From 9469188e3226793f8718ea572f69bd84b961e116 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Tue, 12 May 2015 00:36:22 +0200 Subject: [PATCH 01/43] Work in progress --- libraries/MySensors/MyConfig.h | 8 +- libraries/MySensors/MyGateway.cpp | 99 +++++++++++++++++++ libraries/MySensors/MyGateway.h | 83 ++++++++++++++++ ...yParserSerial.h => MyGatewayTransport.cpp} | 17 +--- libraries/MySensors/MyGatewayTransport.h | 44 +++++++++ .../MySensors/MyGatewayTransportSerial.cpp | 66 +++++++++++++ .../MySensors/MyGatewayTransportSerial.h | 50 ++++++++++ .../{MyParser.cpp => MyProtocol.cpp} | 4 +- .../MySensors/{MyParser.h => MyProtocol.h} | 14 ++- ...ParserSerial.cpp => MyProtocolDefault.cpp} | 16 ++- libraries/MySensors/MyProtocolDefault.h | 42 ++++++++ libraries/MySensors/MySensor.cpp | 91 +++++++++-------- libraries/MySensors/MySensor.h | 16 +-- .../EthernetGateway/EthernetGateway.ino | 2 +- .../examples/EthernetGateway/GatewayUtil.h | 4 +- .../examples/SerialGateway/GatewayUtil.h | 4 +- .../examples/SerialGateway/SerialGateway.ino | 2 +- 17 files changed, 477 insertions(+), 85 deletions(-) create mode 100644 libraries/MySensors/MyGateway.cpp create mode 100644 libraries/MySensors/MyGateway.h rename libraries/MySensors/{MyParserSerial.h => MyGatewayTransport.cpp} (76%) create mode 100644 libraries/MySensors/MyGatewayTransport.h create mode 100644 libraries/MySensors/MyGatewayTransportSerial.cpp create mode 100644 libraries/MySensors/MyGatewayTransportSerial.h rename libraries/MySensors/{MyParser.cpp => MyProtocol.cpp} (94%) rename libraries/MySensors/{MyParser.h => MyProtocol.h} (84%) rename libraries/MySensors/{MyParserSerial.cpp => MyProtocolDefault.cpp} (83%) create mode 100644 libraries/MySensors/MyProtocolDefault.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index c2148ab..020092d 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -56,13 +56,13 @@ // #define WITH_LEDS_BLINKING // default LEDs blinking period in milliseconds -#define DEFAULT_LED_BLINK_PERIOD 300 +#define MY_DEFAULT_LED_BLINK_PERIOD 300 // The RX LED default pin -#define DEFAULT_RX_LED_PIN 8 +#define MY_DEFAULT_RX_LED_PIN 8 // The TX LED default pin -#define DEFAULT_TX_LED_PIN 9 +#define MY_DEFAULT_TX_LED_PIN 9 // The Error LED default pin -#define DEFAULT_ERR_LED_PIN 7 +#define MY_DEFAULT_ERR_LED_PIN 7 /********************************** diff --git a/libraries/MySensors/MyGateway.cpp b/libraries/MySensors/MyGateway.cpp new file mode 100644 index 0000000..93e58be --- /dev/null +++ b/libraries/MySensors/MyGateway.cpp @@ -0,0 +1,99 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "MyGateway.h" + +// Inline function and macros +static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { + msg.sender = sender; + msg.destination = destination; + msg.sensor = sensor; + msg.type = type; + mSetCommand(msg,command); + mSetRequestAck(msg,enableAck); + mSetAck(msg,false); + return msg; +} + +MyGateway::MyGateway(MyGatewayTransport &_transport,MyTransport &_radio, MyHw &_hw +#ifdef MY_SIGNING_FEATURE + , MySigning &_signer +#endif +#ifdef WITH_LEDS_BLINKING + , uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period +#endif + ) : transport(_transport),MySensor(_radio, _hw +#ifdef MY_SIGNING_FEATURE + , _signer +#endif +#ifdef WITH_LEDS_BLINKING + , _rx, _tx, _er, _blink_period +#endif + ) +{ + +} + +boolean MyGateway::sendRoute(MyMessage &message) { + if (message.destination == GATEWAY_ADDRESS) { + // This is a message sent from a sensor attached on the gateway node. + // Pass it directly to the gateway transport layer. + transport.send(message); + } else { + MySensor::sendRoute(message); + } +} + + +boolean MyGateway::process() { + bool newMessage = false; + if (transport.available()) { + MyMessage &gmsg = transport.receive(); + if (msg.destination == GATEWAY_ADDRESS) { + // Check if sender requests an ack back. + if (mGetRequestAck(gmsg)) { + // Copy message + tmpMsg = gmsg; + mSetRequestAck(tmpMsg,false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetAck(tmpMsg,true); + tmpMsg.sender = nc.nodeId; + tmpMsg.destination = msg.sender; + transport.send(tmpMsg); + } + if (mGetCommand(gmsg) == C_INTERNAL) { + if (msg.type == I_VERSION) { + // Request for version. Create the response + transport.send(build(msg, GATEWAY_ADDRESS, GATEWAY_ADDRESS, GATEWAY_ADDRESS, C_INTERNAL, I_VERSION, false).set(LIBRARY_VERSION)); + } else if (msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + //setInclusionMode(atoi(msg.data) == 1); + } else { + processInternalMessages(gmsg); + } + } else { + // Call incoming message callback if available + if (msgCallback != NULL) { + msgCallback(msg); + } + newMessage = true; + } + } + } + return MySensor::process() || newMessage; +} diff --git a/libraries/MySensors/MyGateway.h b/libraries/MySensors/MyGateway.h new file mode 100644 index 0000000..a7cc319 --- /dev/null +++ b/libraries/MySensors/MyGateway.h @@ -0,0 +1,83 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyGateway_h +#define MyGateway_h + + +#include "MyConfig.h" +#include "MySensor.h" +#include "MyHw.h" +#include "MyTransport.h" +#include "MyTransportNRF24.h" +#ifdef MY_SIGNING_FEATURE +#include "MySigning.h" +#include "MySigningNone.h" +#endif +#include "MyMessage.h" +#ifdef MY_OTA_FIRMWARE_FEATURE +#include "utility/SPIFlash.h" +#endif + +#include "MyProtocol.h" +#include "MyGatewayTransport.h" +#include "MyGatewayTransportSerial.h" + +#include +#include + + +class MyGateway : public MySensor +{ +public: + // MyProtocolSerial constructor + MyGateway(MyGatewayTransport &transport=*new MyGatewayTransportSerial(), MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() +#ifdef MY_SIGNING_FEATURE + , MySigning &signer=*new MySigningNone() +#endif +#ifdef WITH_LEDS_BLINKING + , uint8_t _rx=MY_DEFAULT_RX_LED_PIN + , uint8_t _tx=MY_DEFAULT_TX_LED_PIN + , uint8_t _er=MY_DEFAULT_ERR_LED_PIN + , unsigned long _blink_period=MY_DEFAULT_LED_BLINK_PERIOD +#endif + ); + + + void enableInclusionModeFeature(uint8_t inclusionModeButtonPin, uint8_t inclusionModeDuration); + + /** + * See MySensor.h + * + * Overloaded to handle local sensor data sent to controller. + */ + boolean sendRoute(MyMessage &message); + + /** + * Processes incoming messages to this node. + * Returns true if there is a message addressed for this node was received. + * Preferred way of handling incoming messages is to use the callback defined in begin(). + */ + boolean process(); + +private: + MyGatewayTransport &transport; +}; + +#endif diff --git a/libraries/MySensors/MyParserSerial.h b/libraries/MySensors/MyGatewayTransport.cpp similarity index 76% rename from libraries/MySensors/MyParserSerial.h rename to libraries/MySensors/MyGatewayTransport.cpp index 80d315d..2306d5f 100644 --- a/libraries/MySensors/MyParserSerial.h +++ b/libraries/MySensors/MyGatewayTransport.cpp @@ -17,18 +17,9 @@ * version 2 as published by the Free Software Foundation. */ -#ifndef MyParserSerial_h -#define MyParserSerial_h +#include "MyGatewayTransport.h" -#include "MyConfig.h" -#include "MyParser.h" -class MyParserSerial : public MyParser -{ -public: - MyParserSerial(); - bool parse(MyMessage &message, char *inputString); -private: - uint8_t h2i(char c); -}; -#endif +MyGatewayTransport::MyGatewayTransport(MyProtocol &_protocol) : protocol(_protocol) { + +} diff --git a/libraries/MySensors/MyGatewayTransport.h b/libraries/MySensors/MyGatewayTransport.h new file mode 100644 index 0000000..d94006f --- /dev/null +++ b/libraries/MySensors/MyGatewayTransport.h @@ -0,0 +1,44 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyGatewayTransport_h +#define MyGatewayTransport_h + +#include "MyMessage.h" +#include "MyProtocol.h" +#include "MyProtocolDefault.h" + +class MyGatewayTransport +{ +public: + // MyProtocol constructor + MyGatewayTransport(MyProtocol &protocol = *new MyProtocolDefault()); + + // Send message to controller + virtual bool send(MyMessage &message) = 0; + + // Check if a new message is available from controller + virtual bool available() = 0; + + // Pick up last message received from controller + virtual MyMessage& receive() = 0; +protected: + MyProtocol& protocol; +}; +#endif diff --git a/libraries/MySensors/MyGatewayTransportSerial.cpp b/libraries/MySensors/MyGatewayTransportSerial.cpp new file mode 100644 index 0000000..e0f79bf --- /dev/null +++ b/libraries/MySensors/MyGatewayTransportSerial.cpp @@ -0,0 +1,66 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "MyGatewayTransportSerial.h" + + +MyGatewayTransportSerial::MyGatewayTransportSerial(MyProtocol &_protocol) : MyGatewayTransport(_protocol),inputPos(0) +{ + +} + +bool MyGatewayTransportSerial::send(MyMessage &message) { + Serial.print(protocol.format(message)); + // Serial print is always successful + return true; +} + +bool MyGatewayTransportSerial::available() { + bool available = false; + while (Serial.available()) { + // get the new byte: + char inChar = (char) Serial.read(); + // if the incoming character is a newline, set a flag + // so the main loop can do something about it: + if (inputPos < MAX_RECEIVE_LENGTH - 1 && !available) { + if (inChar == '\n') { + inputString[inputPos] = 0; + available = true; + } else { + // add it to the inputString: + inputString[inputPos] = inChar; + inputPos++; + } + } else { + // Incoming message too long. Throw away + inputPos = 0; + } + } + if (available) { + // Parse message and return parse result + available = protocol.parse(msg, inputString); + inputPos = 0; + } + return available; +} + +MyMessage & MyGatewayTransportSerial::receive() { + // Return the last parsed message + return msg; +} diff --git a/libraries/MySensors/MyGatewayTransportSerial.h b/libraries/MySensors/MyGatewayTransportSerial.h new file mode 100644 index 0000000..678e932 --- /dev/null +++ b/libraries/MySensors/MyGatewayTransportSerial.h @@ -0,0 +1,50 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyGatewayTransportSerial_h +#define MyGatewayTransportSerial_h + +#include "MyMessage.h" +#include "MyProtocol.h" +#include "MyGatewayTransport.h" +#include "MyProtocolDefault.h" + +#define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller + +class MyGatewayTransportSerial : public MyGatewayTransport +{ +public: + // MyGateway constructor + MyGatewayTransportSerial(MyProtocol &protocol = *new MyProtocolDefault()); + + // Send message to controller + bool send(MyMessage &message); + + // Check if a new message is available from controller + bool available(); + + // Pick up last message received from controller + MyMessage& receive(); +private: + char inputString[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface + int inputPos; + MyMessage msg; +}; + +#endif diff --git a/libraries/MySensors/MyParser.cpp b/libraries/MySensors/MyProtocol.cpp similarity index 94% rename from libraries/MySensors/MyParser.cpp rename to libraries/MySensors/MyProtocol.cpp index 2011d16..f0a473a 100644 --- a/libraries/MySensors/MyParser.cpp +++ b/libraries/MySensors/MyProtocol.cpp @@ -17,7 +17,7 @@ * version 2 as published by the Free Software Foundation. */ -#include "MyParser.h" +#include "MyProtocol.h" -MyParser::MyParser() { +MyProtocol::MyProtocol() { } diff --git a/libraries/MySensors/MyParser.h b/libraries/MySensors/MyProtocol.h similarity index 84% rename from libraries/MySensors/MyParser.h rename to libraries/MySensors/MyProtocol.h index 39e2975..5b0298f 100644 --- a/libraries/MySensors/MyParser.h +++ b/libraries/MySensors/MyProtocol.h @@ -17,19 +17,23 @@ * version 2 as published by the Free Software Foundation. */ -#ifndef MyParser_h -#define MyParser_h +#ifndef MyProtocol_h +#define MyProtocol_h #include "MyMessage.h" -class MyParser +class MyProtocol { public: - // MyParser constructor - MyParser(); + // MyProtocol constructor + MyProtocol(); // parse(message, inputString) // parse a string into a message element // returns true if successfully parsed the input string virtual bool parse(MyMessage &message, char *inputString) = 0; + + // Format MyMessage to the protocol represenataion + virtual char *format(MyMessage &message) = 0; + }; #endif diff --git a/libraries/MySensors/MyParserSerial.cpp b/libraries/MySensors/MyProtocolDefault.cpp similarity index 83% rename from libraries/MySensors/MyParserSerial.cpp rename to libraries/MySensors/MyProtocolDefault.cpp index e2ee52a..f410abe 100644 --- a/libraries/MySensors/MyParserSerial.cpp +++ b/libraries/MySensors/MyProtocolDefault.cpp @@ -17,13 +17,13 @@ * version 2 as published by the Free Software Foundation. */ -#include "MyParser.h" -#include "MyParserSerial.h" +#include "MyProtocol.h" +#include "MyProtocolDefault.h" #include "MyTransport.h" -MyParserSerial::MyParserSerial() : MyParser() {} +MyProtocolDefault::MyProtocolDefault() : MyProtocol() {} -bool MyParserSerial::parse(MyMessage &message, char *inputString) { +bool MyProtocolDefault::parse(MyMessage &message, char *inputString) { char *str, *p, *value=NULL; uint8_t bvalue[MAX_PAYLOAD]; uint8_t blen = 0; @@ -89,7 +89,13 @@ bool MyParserSerial::parse(MyMessage &message, char *inputString) { return true; } -uint8_t MyParserSerial::h2i(char c) { +char * MyProtocolDefault::format(MyMessage &message) { + snprintf_P(fmtBuffer, MAX_FORMAT_BUFFER_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuffer)); + return fmtBuffer; +} + + +uint8_t MyProtocolDefault::h2i(char c) { uint8_t i = 0; if (c <= '9') i += c - '0'; diff --git a/libraries/MySensors/MyProtocolDefault.h b/libraries/MySensors/MyProtocolDefault.h new file mode 100644 index 0000000..8d35609 --- /dev/null +++ b/libraries/MySensors/MyProtocolDefault.h @@ -0,0 +1,42 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyProtocolDefault_h +#define MyProtocolDefault_h + +#include "MyConfig.h" +#include "MyProtocol.h" +#include "MyTransport.h" + +#define MAX_FORMAT_BUFFER_LENGTH 120 // Max buffersize when formatting messages + + +class MyProtocolDefault : public MyProtocol +{ +public: + MyProtocolDefault(); + bool parse(MyMessage &message, char *inputString); + char *format(MyMessage &message); +private: + char fmtBuffer[MAX_FORMAT_BUFFER_LENGTH]; + char convBuffer[MAX_PAYLOAD*2+1]; + + uint8_t h2i(char c); +}; +#endif diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp index cb0e026..8929282 100644 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -667,50 +667,19 @@ boolean MySensor::process() { return true; // Just pass along nonce silently (no need to call callback for these) #endif } else if (sender == GATEWAY_ADDRESS) { - bool isMetric; - - if (type == I_REBOOT) { - // Requires MySensors or other bootloader with watchdogs enabled - hw_reboot(); - } else if (type == I_ID_RESPONSE) { + if (type == I_ID_RESPONSE && nc.nodeId == AUTO) { + nc.nodeId = msg.getByte(); if (nc.nodeId == AUTO) { - nc.nodeId = msg.getByte(); - if (nc.nodeId == AUTO) { - // sensor net gateway will return max id if all sensor id are taken - debug(PSTR("full\n")); - while (1); // Wait here. Nothing else we can do... - } - setupNode(); - // Write id to EEPROM - hw_writeConfig(EEPROM_NODE_ID_ADDRESS, nc.nodeId); - debug(PSTR("id=%d\n"), nc.nodeId); - } - } else if (type == I_CONFIG) { - // Pick up configuration from controller (currently only metric/imperial) - // and store it in eeprom if changed - isMetric = msg.getString()[0] == 'M' ; - cc.isMetric = isMetric; - hw_writeConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); - } else if (type == I_CHILDREN) { - if (repeaterMode && msg.getString()[0] == 'C') { - // Clears child relay data for this node - debug(PSTR("clear\n")); - uint8_t i = 255; - do { - hw_writeConfig(EEPROM_ROUTES_ADDRESS+i, 0xff); - } while (i--); - // Clear parent node id & distance to gw - hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF); - hw_writeConfig(EEPROM_DISTANCE_ADDRESS, 0xFF); - // Find parent node - findParentNode(); - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); - } - } else if (type == I_TIME) { - if (timeCallback != NULL) { - // Deliver time to callback - timeCallback(msg.getULong()); + // sensor net gateway will return max id if all sensor id are taken + debug(PSTR("full\n")); + while (1); // Wait here. Nothing else we can do... } + setupNode(); + // Write id to EEPROM + hw_writeConfig(EEPROM_NODE_ID_ADDRESS, nc.nodeId); + debug(PSTR("id=%d\n"), nc.nodeId); + } else { + processInternalMessages(msg); } return false; } @@ -791,6 +760,44 @@ boolean MySensor::process() { return false; } + +void MySensor::processInternalMessages(MyMessage &msg) { + bool isMetric; + uint8_t type = msg.type; + + if (type == I_REBOOT) { + // Requires MySensors or other bootloader with watchdogs enabled + hw_reboot(); + } else if (type == I_CONFIG) { + // Pick up configuration from controller (currently only metric/imperial) + // and store it in eeprom if changed + isMetric = msg.getString()[0] == 'M' ; + cc.isMetric = isMetric; + hw_writeConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); + } else if (type == I_CHILDREN) { + if (repeaterMode && msg.getString()[0] == 'C') { + // Clears child relay data for this node + debug(PSTR("clear\n")); + uint8_t i = 255; + do { + hw_writeConfig(EEPROM_ROUTES_ADDRESS+i, 0xff); + } while (i--); + // Clear parent node id & distance to gw + hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF); + hw_writeConfig(EEPROM_DISTANCE_ADDRESS, 0xFF); + // Find parent node + findParentNode(); + sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); + } + } else if (type == I_TIME) { + if (timeCallback != NULL) { + // Deliver time to callback + timeCallback(msg.getULong()); + } + } +} + + MyMessage& MySensor::getLastMessage() { return msg; } diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 9917b66..dfc762c 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -26,7 +26,6 @@ #include "MyHw.h" #include "MyTransport.h" #include "MyTransportNRF24.h" -#include "MyParser.h" #ifdef MY_SIGNING_FEATURE #include "MySigning.h" #include "MySigningNone.h" @@ -147,10 +146,10 @@ class MySensor , MySigning &signer=*new MySigningNone() #endif #ifdef WITH_LEDS_BLINKING - , uint8_t _rx=DEFAULT_RX_LED_PIN, - uint8_t _tx=DEFAULT_TX_LED_PIN, - uint8_t _er=DEFAULT_ERR_LED_PIN, - unsigned long _blink_period=DEFAULT_LED_BLINK_PERIOD + , uint8_t _rx=MY_DEFAULT_RX_LED_PIN, + uint8_t _tx=MY_DEFAULT_TX_LED_PIN, + uint8_t _er=MY_DEFAULT_ERR_LED_PIN, + unsigned long _blink_period=MY_DEFAULT_LED_BLINK_PERIOD #endif ); @@ -199,7 +198,6 @@ class MySensor */ bool send(MyMessage &msg, bool ack=false); - boolean sendRoute(MyMessage &message); /** * Send this nodes battery level to gateway. @@ -315,6 +313,8 @@ class MySensor void errBlink(uint8_t cnt); #endif + boolean sendRoute(MyMessage &message); + protected: NodeConfig nc; // Essential settings for node to work ControllerConfig cc; // Configuration coming from controller @@ -357,8 +357,7 @@ class MySensor MyHw& hw; boolean sendWrite(uint8_t dest, MyMessage &message); - - private: + void processInternalMessages(MyMessage &msg); #ifdef DEBUG char convBuf[MAX_PAYLOAD*2+1]; #endif @@ -371,6 +370,7 @@ class MySensor bool isValidFirmware(); #endif + private: void requestNodeId(); void setupNode(); diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 383cbdf..dcbb32f 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -66,7 +66,7 @@ #include #include -#include +#include #include #include #include diff --git a/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h b/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h index 64730f2..4547446 100644 --- a/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h +++ b/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h @@ -17,7 +17,7 @@ volatile boolean buttonTriggeredInclusion; boolean inclusionMode; // Keeps track on inclusion mode void (*serial)(const char *fmt, ... ); -MyParserSerial parser; +MyProtocolDefault protocol; void setInclusionMode(boolean newMode); @@ -79,7 +79,7 @@ void parseAndSend(MySensor &gw, char *commandBuffer) { boolean ok; MyMessage &msg = gw.getLastMessage(); - if (parser.parse(msg, commandBuffer)) { + if (protocol.parse(msg, commandBuffer)) { uint8_t command = mGetCommand(msg); if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { diff --git a/libraries/MySensors/examples/SerialGateway/GatewayUtil.h b/libraries/MySensors/examples/SerialGateway/GatewayUtil.h index bf24038..e3cb90a 100644 --- a/libraries/MySensors/examples/SerialGateway/GatewayUtil.h +++ b/libraries/MySensors/examples/SerialGateway/GatewayUtil.h @@ -37,7 +37,7 @@ volatile boolean buttonTriggeredInclusion; boolean inclusionMode; // Keeps track on inclusion mode void (*serial)(const char *fmt, ... ); -MyParserSerial parser; +MyProtocolDefault protocol; void setInclusionMode(boolean newMode); @@ -99,7 +99,7 @@ void parseAndSend(MySensor &gw, char *commandBuffer) { boolean ok; MyMessage &msg = gw.getLastMessage(); - if (parser.parse(msg, commandBuffer)) { + if (protocol.parse(msg, commandBuffer)) { uint8_t command = mGetCommand(msg); if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { diff --git a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino index 7478665..ad75280 100644 --- a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino +++ b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino @@ -46,7 +46,7 @@ #include #include -#include +#include #include #include #include From 01d13f0ca42b288fe4851fffdeb93ea2ec96881a Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Tue, 12 May 2015 23:28:49 +0200 Subject: [PATCH 02/43] Serial Gateway in a working state --- libraries/MySensors/MyConfig.h | 24 ++- libraries/MySensors/MyGateway.cpp | 109 ++++++++++--- libraries/MySensors/MyGateway.h | 35 ++++- libraries/MySensors/MySensor.cpp | 32 ++-- libraries/MySensors/MySensor.h | 6 +- .../EthernetGateway/EthernetGateway.ino | 4 +- .../examples/EthernetGateway/GatewayUtil.h | 4 +- .../examples/SerialGateway/GatewayUtil.h | 146 ------------------ .../examples/SerialGateway/SerialGateway.ino | 97 +++--------- 9 files changed, 185 insertions(+), 272 deletions(-) delete mode 100644 libraries/MySensors/examples/SerialGateway/GatewayUtil.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 020092d..0e07a5a 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -49,22 +49,36 @@ * Information LEDs blinking ***********************************/ // This feature enables LEDs blinking on message receive, transmit -// or if some error occured. This was commonly used only in gateways, +// or if some error occurred. This was commonly used only in gateways, // but now can be used in any sensor node. Also the LEDs can now be // disabled in the gateway. -// #define WITH_LEDS_BLINKING +// #define MY_LEDS_BLINKING_FEATURE // default LEDs blinking period in milliseconds #define MY_DEFAULT_LED_BLINK_PERIOD 300 // The RX LED default pin -#define MY_DEFAULT_RX_LED_PIN 8 +#define MY_DEFAULT_RX_LED_PIN 6 // The TX LED default pin -#define MY_DEFAULT_TX_LED_PIN 9 +#define MY_DEFAULT_TX_LED_PIN 5 // The Error LED default pin -#define MY_DEFAULT_ERR_LED_PIN 7 +#define MY_DEFAULT_ERR_LED_PIN 4 +/********************************************** +* Gateway inclusion button/mode configuration +**********************************************/ +// Enabled inclusion mode feature +#define MY_INCLUSION_MODE_FEATURE + +// Enables inclusion-mode button feature on the gateway device +#define MY_INCLUSION_BUTTON_FEATURE + +// The default input pin used for the inclusion mode button +#define MY_INCLUSION_MODE_BUTTON_PIN 3 +// Number of seconds (default one minute) inclusion mode should be enabled +#define MY_INCLUSION_MODE_DURATION 60 + /********************************** * Message Signing Settings ***********************************/ diff --git a/libraries/MySensors/MyGateway.cpp b/libraries/MySensors/MyGateway.cpp index 93e58be..db4e4ee 100644 --- a/libraries/MySensors/MyGateway.cpp +++ b/libraries/MySensors/MyGateway.cpp @@ -20,33 +20,64 @@ #include "MyGateway.h" // Inline function and macros -static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { - msg.sender = sender; - msg.destination = destination; - msg.sensor = sensor; +static inline MyMessage& build(MyMessage &msg, uint8_t type) { + msg.sender = GATEWAY_ADDRESS; + msg.destination = GATEWAY_ADDRESS; + msg.sensor = 0; msg.type = type; - mSetCommand(msg,command); - mSetRequestAck(msg,enableAck); - mSetAck(msg,false); + mSetCommand(msg, C_INTERNAL); + mSetRequestAck(msg, false); + mSetAck(msg, false); return msg; } -MyGateway::MyGateway(MyGatewayTransport &_transport,MyTransport &_radio, MyHw &_hw +MyGateway::MyGateway(MyGatewayTransport &_transport, MyTransport &_radio, + MyHw &_hw #ifdef MY_SIGNING_FEATURE - , MySigning &_signer + , MySigning &_signer #endif -#ifdef WITH_LEDS_BLINKING - , uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period +#ifdef MY_LEDS_BLINKING_FEATURE + , uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period #endif - ) : transport(_transport),MySensor(_radio, _hw + ) : + transport(_transport), MySensor(_radio, _hw #ifdef MY_SIGNING_FEATURE - , _signer + , _signer #endif -#ifdef WITH_LEDS_BLINKING - , _rx, _tx, _er, _blink_period +#ifdef MY_LEDS_BLINKING_FEATURE + , _rx, _tx, _er, _blink_period #endif ) { +#ifdef MY_INCLUSION_MODE_FEATURE + inclusionMode = false; +#endif +} + +void MyGateway::begin(void (*_msgCallback)(const MyMessage &) +#ifdef MY_INCLUSION_MODE_FEATURE + , int _inclusionModeDuration +#ifdef MY_INCLUSION_BUTTON_FEATURE + , uint8_t _inclusionModeButtonPin +#endif +#endif + +) { + // Setup digital in that triggers inclusion mode +#ifdef MY_INCLUSION_MODE_FEATURE + inclusionDuration = _inclusionModeDuration*1000; +#ifdef MY_INCLUSION_BUTTON_FEATURE + inclusionButtonPin = _inclusionModeButtonPin; + pinMode(inclusionButtonPin, INPUT); + digitalWrite(inclusionButtonPin, HIGH); +#endif +#endif + + // Start MySensors in repeater mode + MySensor::begin(_msgCallback, GATEWAY_ADDRESS, true, GATEWAY_ADDRESS); + + // Startup complete + transport.send(build(msg, I_GATEWAY_READY).set("Gateway startup complete.")); } @@ -60,8 +91,8 @@ boolean MyGateway::sendRoute(MyMessage &message) { } } - boolean MyGateway::process() { + checkInclusionMode(); bool newMessage = false; if (transport.available()) { MyMessage &gmsg = transport.receive(); @@ -70,8 +101,8 @@ boolean MyGateway::process() { if (mGetRequestAck(gmsg)) { // Copy message tmpMsg = gmsg; - mSetRequestAck(tmpMsg,false); // Reply without ack flag (otherwise we would end up in an eternal loop) - mSetAck(tmpMsg,true); + mSetRequestAck(tmpMsg, false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetAck(tmpMsg, true); tmpMsg.sender = nc.nodeId; tmpMsg.destination = msg.sender; transport.send(tmpMsg); @@ -79,10 +110,12 @@ boolean MyGateway::process() { if (mGetCommand(gmsg) == C_INTERNAL) { if (msg.type == I_VERSION) { // Request for version. Create the response - transport.send(build(msg, GATEWAY_ADDRESS, GATEWAY_ADDRESS, GATEWAY_ADDRESS, C_INTERNAL, I_VERSION, false).set(LIBRARY_VERSION)); + transport.send(build(msg, I_VERSION).set(LIBRARY_VERSION)); +#ifdef MY_INCLUSION_MODE_FEATURE } else if (msg.type == I_INCLUSION_MODE) { // Request to change inclusion mode - //setInclusionMode(atoi(msg.data) == 1); + setInclusionMode(atoi(msg.data) == 1); +#endif } else { processInternalMessages(gmsg); } @@ -97,3 +130,39 @@ boolean MyGateway::process() { } return MySensor::process() || newMessage; } + +#ifdef MY_INCLUSION_MODE_FEATURE +void MyGateway::setInclusionMode(boolean newMode) { + if (newMode != inclusionMode) { + inclusionMode = newMode; + // Send back mode change to controller + transport.send(build(msg, I_INCLUSION_MODE).set(inclusionMode?1:0)); + if (inclusionMode) { + + inclusionStartTime = hw_millis(); + Serial.println(inclusionStartTime); + Serial.println(inclusionDuration); + + } + } +} + +void MyGateway::checkInclusionMode() { + + #ifdef MY_INCLUSION_BUTTON_FEATURE + if (!inclusionMode && digitalRead(inclusionButtonPin) == LOW) { + // Start inclusion mode + setInclusionMode(true); + } + #endif + + if (inclusionMode && hw_millis()-inclusionStartTime>inclusionDuration) { + // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode + setInclusionMode(false); + } +} + + +#endif + + diff --git a/libraries/MySensors/MyGateway.h b/libraries/MySensors/MyGateway.h index a7cc319..7ec55dc 100644 --- a/libraries/MySensors/MyGateway.h +++ b/libraries/MySensors/MyGateway.h @@ -51,7 +51,7 @@ public: #ifdef MY_SIGNING_FEATURE , MySigning &signer=*new MySigningNone() #endif -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE , uint8_t _rx=MY_DEFAULT_RX_LED_PIN , uint8_t _tx=MY_DEFAULT_TX_LED_PIN , uint8_t _er=MY_DEFAULT_ERR_LED_PIN @@ -60,7 +60,24 @@ public: ); - void enableInclusionModeFeature(uint8_t inclusionModeButtonPin, uint8_t inclusionModeDuration); + /** + * Begin operation of the MySensors library + * + * Call this in setup(), before calling any other sensor net library methods. + * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. + * @param inclusionModeDuration Number of milliseconds inclusion mode should be enabled + * @param inclusionModeButtonPin Button pin used for enabling inclusion mode + */ + + void begin(void (* msgCallback)(const MyMessage &)=NULL +#ifdef MY_INCLUSION_MODE_FEATURE + , int inclusionModeDuration=MY_INCLUSION_MODE_DURATION +#ifdef MY_INCLUSION_BUTTON_FEATURE + , uint8_t inclusionModeButtonPin=MY_INCLUSION_MODE_BUTTON_PIN +#endif +#endif + ); + /** * See MySensor.h @@ -77,7 +94,21 @@ public: boolean process(); private: + MyGatewayTransport &transport; + +#ifdef MY_INCLUSION_MODE_FEATURE + + void setInclusionMode(bool newMode); + void checkInclusionMode(); + unsigned long inclusionStartTime; + bool inclusionMode; + unsigned long inclusionDuration; + + #ifdef MY_INCLUSION_BUTTON_FEATURE + uint8_t inclusionButtonPin; + #endif +#endif }; #endif diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/MySensor.cpp index 8929282..0a35016 100644 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/MySensor.cpp @@ -53,7 +53,7 @@ MySensor::MySensor(MyTransport &_radio, MyHw &_hw #ifdef MY_SIGNING_FEATURE , MySigning &_signer #endif -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE , uint8_t _rx, uint8_t _tx, uint8_t _er, unsigned long _blink_period #endif ) @@ -62,7 +62,7 @@ MySensor::MySensor(MyTransport &_radio, MyHw &_hw #ifdef MY_SIGNING_FEATURE signer(_signer), #endif -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE pinRx(_rx), pinTx(_tx), pinEr(_er), ledBlinkPeriod(_blink_period), #endif #ifdef MY_OTA_FIRMWARE_FEATURE @@ -96,7 +96,7 @@ bool MySensor::isValidFirmware() { #endif -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE void MySensor::handleLedsBlinking() { static unsigned long next_time = hw_millis() + ledBlinkPeriod; @@ -175,7 +175,7 @@ void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, b hw_readConfigBlock((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign)); #endif -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE // Setup led pins pinMode(pinRx, OUTPUT); pinMode(pinTx, OUTPUT); @@ -327,7 +327,7 @@ boolean MySensor::sendRoute(MyMessage &message) { // If we still don't have any parent id, re-request and skip this message. if (nc.parentNodeId == AUTO) { findParentNode(); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; @@ -336,7 +336,7 @@ boolean MySensor::sendRoute(MyMessage &message) { // If we still don't have any node id, re-request and skip this message. if (nc.nodeId == AUTO) { requestNodeId(); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; @@ -375,14 +375,14 @@ boolean MySensor::sendRoute(MyMessage &message) { } if (hw_millis() - enter > MY_VERIFICATION_TIMEOUT_MS) { debug(PSTR("nonce tmo\n")); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; } if (!signOk) { debug(PSTR("sign fail\n")); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; @@ -443,7 +443,7 @@ boolean MySensor::sendRoute(MyMessage &message) { if (!ok) { // Failure when sending to parent node. The parent node might be down and we // need to find another route to gateway. -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif failedTransmissions++; @@ -460,7 +460,7 @@ boolean MySensor::sendWrite(uint8_t to, MyMessage &message) { mSetVersion(message, PROTOCOL_VERSION); uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message); message.last = nc.nodeId; -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE txBlink(1); #endif bool ok = radio.send(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length)); @@ -508,7 +508,7 @@ void MySensor::requestTime(void (* _timeCallback)(unsigned long)) { boolean MySensor::process() { hw_watchdogReset(); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE handleLedsBlinking(); #endif @@ -522,7 +522,7 @@ boolean MySensor::process() { debug(PSTR("fw upd fail\n")); // Give up. We have requested MY_OTA_RETRY times without any packet in return. fwUpdateOngoing = false; -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; @@ -546,7 +546,7 @@ boolean MySensor::process() { #endif uint8_t len = radio.receive((uint8_t *)&msg); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE rxBlink(1); #endif @@ -561,14 +561,14 @@ boolean MySensor::process() { if (!mGetSigned(msg)) { // Got unsigned message that should have been signed debug(PSTR("no sign\n")); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; } else if (!signer.verifyMsg(msg)) { debug(PSTR("verify fail\n")); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; // This signed message has been tampered with! @@ -584,7 +584,7 @@ boolean MySensor::process() { if(!(mGetVersion(msg) == PROTOCOL_VERSION)) { debug(PSTR("ver mismatch\n")); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE errBlink(1); #endif return false; diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index dfc762c..ad8e8f8 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -145,7 +145,7 @@ class MySensor #ifdef MY_SIGNING_FEATURE , MySigning &signer=*new MySigningNone() #endif -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE , uint8_t _rx=MY_DEFAULT_RX_LED_PIN, uint8_t _tx=MY_DEFAULT_TX_LED_PIN, uint8_t _er=MY_DEFAULT_ERR_LED_PIN, @@ -303,7 +303,7 @@ class MySensor */ int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE /** * Blink with LEDs * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms @@ -339,7 +339,7 @@ class MySensor MySigning& signer; #endif -#ifdef WITH_LEDS_BLINKING +#ifdef MY_LEDS_BLINKING_FEATURE uint8_t pinRx; // Rx led pin uint8_t pinTx; // Tx led pin uint8_t pinEr; // Err led pin diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index dcbb32f..dbfdcd6 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -104,8 +104,8 @@ MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); MyHwATMega328 hw; // Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) -// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h -#ifdef WITH_LEDS_BLINKING +// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h +#ifdef MY_WITH_LEDS_BLINKING MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); #else MySensor gw(transport, hw /*, signer*/); diff --git a/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h b/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h index 4547446..b0aea73 100644 --- a/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h +++ b/libraries/MySensors/examples/EthernetGateway/GatewayUtil.h @@ -92,12 +92,12 @@ void parseAndSend(MySensor &gw, char *commandBuffer) { setInclusionMode(atoi(msg.data) == 1); } } else { - #ifdef WITH_LEDS_BLINKING + #ifdef MY_LEDS_BLINKING_FEATURE gw.txBlink(1); #endif ok = gw.sendRoute(msg); if (!ok) { - #ifdef WITH_LEDS_BLINKING + #ifdef MY_LEDS_BLINKING_FEATURE gw.errBlink(1); #endif } diff --git a/libraries/MySensors/examples/SerialGateway/GatewayUtil.h b/libraries/MySensors/examples/SerialGateway/GatewayUtil.h deleted file mode 100644 index e3cb90a..0000000 --- a/libraries/MySensors/examples/SerialGateway/GatewayUtil.h +++ /dev/null @@ -1,146 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - */ - -#ifndef __GATEWAYUTIL_H__ -#define __GATEWAYUTIL_H__ - -#include - - -#ifdef ARDUINO - - -uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled -uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode - -#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller -#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller - -volatile boolean buttonTriggeredInclusion; -boolean inclusionMode; // Keeps track on inclusion mode -void (*serial)(const char *fmt, ... ); - -MyProtocolDefault protocol; - -void setInclusionMode(boolean newMode); - -char convBuf[MAX_PAYLOAD*2+1]; -char serialBuffer[MAX_SEND_LENGTH]; // Buffer for building string when sending data to vera -unsigned long inclusionStartTime; - -void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) { - inclusionMode = 0; - buttonTriggeredInclusion = false; - serial = _serial; - - pinInclusion = _inc; - inclusionTime = _incTime; - - // Setup digital in that triggers inclusion mode - pinMode(pinInclusion, INPUT); - digitalWrite(pinInclusion, HIGH); -} - - - -void startInclusionInterrupt() { - buttonTriggeredInclusion = true; -} - -void incomingMessage(const MyMessage &message) { -// if (mGetCommand(message) == C_PRESENTATION && inclusionMode) { -// gw.rxBlink(3); -// } else { -// gw.rxBlink(1); -// } - // Pass along the message from sensors to serial line - serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf)); -} - - - -void checkButtonTriggeredInclusion() { - if (buttonTriggeredInclusion) { - // Ok, someone pressed the inclusion button on the gateway - // start inclusion mode for 1 munute. -#ifdef DEBUG - serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE); -#endif - buttonTriggeredInclusion = false; - setInclusionMode(true); - } -} - -void checkInclusionFinished() { - if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) { - // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode - setInclusionMode(false); - } -} - -void parseAndSend(MySensor &gw, char *commandBuffer) { - boolean ok; - MyMessage &msg = gw.getLastMessage(); - - if (protocol.parse(msg, commandBuffer)) { - uint8_t command = mGetCommand(msg); - - if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { - // Handle messages directed to gateway - if (msg.type == I_VERSION) { - // Request for version - serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); - } else if (msg.type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(msg.data) == 1); - } - } else { - #ifdef WITH_LEDS_BLINKING - gw.txBlink(1); - #endif - ok = gw.sendRoute(msg); - if (!ok) { - #ifdef WITH_LEDS_BLINKING - gw.errBlink(1); - #endif - } - } - } -} - -void setInclusionMode(boolean newMode) { - if (newMode != inclusionMode) { - inclusionMode = newMode; - // Send back mode change on serial line to ack command - serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0); - - if (inclusionMode) { - inclusionStartTime = millis(); - } - } -} - - -#else -#error This example is only for use on Arduino. -#endif // ARDUINO - -#endif - diff --git a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino index ad75280..cbf52d7 100644 --- a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino +++ b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino @@ -29,15 +29,13 @@ * - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series * * LEDs (OPTIONAL): - * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h + * - To use the feature, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly * - ERR (red) - fast blink on error during transmission error or recieve crc error * */ -#define NO_PORTB_PINCHANGES - #include #include #include @@ -46,13 +44,11 @@ #include #include +#include #include -#include -#include -#include -#include "GatewayUtil.h" +#include -#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled +#define INCLUSION_MODE_TIME 60 // Number of seconds inclusion mode is enabled #define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button #define RADIO_ERROR_LED_PIN 4 // Error led pin #define RADIO_RX_LED_PIN 6 // Receive led pin @@ -70,88 +66,37 @@ MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); // Hardware profile MyHwATMega328 hw; +// Controller Transport profile +MyProtocolDefault protocol; +MyGatewayTransportSerial ctrlTransport(protocol); + // Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) -// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h -#ifdef WITH_LEDS_BLINKING -MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); +// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h +#ifdef MY_LEDS_BLINKING_FEATURE +MyGateway gw(ctrlTransport, transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); #else -MySensor gw(transport, hw /*, signer*/); +MyGateway gw(ctrlTransport, transport, hw /*, signer*/); #endif -char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface -int inputPos = 0; -boolean commandComplete = false; // whether the string is complete - -void parseAndSend(char *commandBuffer); - -void output(const char *fmt, ... ) { - va_list args; - va_start (args, fmt ); - vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args); - va_end (args); - Serial.print(serialBuffer); -} - - void setup() { - gw.begin(incomingMessage, 0, true, 0); + gw.begin(NULL + #ifdef MY_INCLUSION_MODE_FEATURE + , INCLUSION_MODE_TIME + #ifdef MY_INCLUSION_BUTTON_FEATURE + , INCLUSION_MODE_PIN + #endif + #endif + ); - setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output); - - // Add interrupt for inclusion button to pin - PCintPort::attachInterrupt(pinInclusion, startInclusionInterrupt, RISING); - - - // Send startup log message on serial - serial(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY); } void loop() { gw.process(); - - checkButtonTriggeredInclusion(); - checkInclusionFinished(); - - if (commandComplete) { - // A command wass issued from serial interface - // We will now try to send it to the actuator - parseAndSend(gw, inputString); - commandComplete = false; - inputPos = 0; - } -} - - -/* - SerialEvent occurs whenever a new data comes in the - hardware serial RX. This routine is run between each - time loop() runs, so using delay inside loop can delay - response. Multiple bytes of data may be available. - */ -void serialEvent() { - while (Serial.available()) { - // get the new byte: - char inChar = (char)Serial.read(); - // if the incoming character is a newline, set a flag - // so the main loop can do something about it: - if (inputPos Date: Sat, 23 May 2015 21:41:53 +0200 Subject: [PATCH 03/43] Add begin function to the GatewayTransport class Signed-off-by: Tomas Hozza --- libraries/MySensors/MyGateway.cpp | 6 ++++++ libraries/MySensors/MyGatewayTransport.h | 3 +++ libraries/MySensors/MyGatewayTransportSerial.cpp | 4 ++++ libraries/MySensors/MyGatewayTransportSerial.h | 3 +++ 4 files changed, 16 insertions(+) diff --git a/libraries/MySensors/MyGateway.cpp b/libraries/MySensors/MyGateway.cpp index db4e4ee..404b5b4 100644 --- a/libraries/MySensors/MyGateway.cpp +++ b/libraries/MySensors/MyGateway.cpp @@ -73,6 +73,12 @@ void MyGateway::begin(void (*_msgCallback)(const MyMessage &) #endif #endif + // initialize the transport driver + if (!transport.begin()) { + debug(PSTR("transport driver init fail\n")); + while(1); // Nothing more we can do + } + // Start MySensors in repeater mode MySensor::begin(_msgCallback, GATEWAY_ADDRESS, true, GATEWAY_ADDRESS); diff --git a/libraries/MySensors/MyGatewayTransport.h b/libraries/MySensors/MyGatewayTransport.h index d94006f..da03ff5 100644 --- a/libraries/MySensors/MyGatewayTransport.h +++ b/libraries/MySensors/MyGatewayTransport.h @@ -30,6 +30,9 @@ public: // MyProtocol constructor MyGatewayTransport(MyProtocol &protocol = *new MyProtocolDefault()); + // initialize the transport driver + virtual bool begin() = 0; + // Send message to controller virtual bool send(MyMessage &message) = 0; diff --git a/libraries/MySensors/MyGatewayTransportSerial.cpp b/libraries/MySensors/MyGatewayTransportSerial.cpp index e0f79bf..f5acbed 100644 --- a/libraries/MySensors/MyGatewayTransportSerial.cpp +++ b/libraries/MySensors/MyGatewayTransportSerial.cpp @@ -25,6 +25,10 @@ MyGatewayTransportSerial::MyGatewayTransportSerial(MyProtocol &_protocol) : MyGa } +bool MyGatewayTransportSerial::begin() { + return true; +} + bool MyGatewayTransportSerial::send(MyMessage &message) { Serial.print(protocol.format(message)); // Serial print is always successful diff --git a/libraries/MySensors/MyGatewayTransportSerial.h b/libraries/MySensors/MyGatewayTransportSerial.h index 678e932..44434cf 100644 --- a/libraries/MySensors/MyGatewayTransportSerial.h +++ b/libraries/MySensors/MyGatewayTransportSerial.h @@ -33,6 +33,9 @@ public: // MyGateway constructor MyGatewayTransportSerial(MyProtocol &protocol = *new MyProtocolDefault()); + // initialize the transport driver + bool begin(); + // Send message to controller bool send(MyMessage &message); From 0c9b2b738d295f56a36097a4bfa564ea0060b960 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Sat, 23 May 2015 22:20:03 +0200 Subject: [PATCH 04/43] Don't call checkInclusionMode() if the feature is not turned on Signed-off-by: Tomas Hozza --- libraries/MySensors/MyGateway.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/MySensors/MyGateway.cpp b/libraries/MySensors/MyGateway.cpp index 404b5b4..906823b 100644 --- a/libraries/MySensors/MyGateway.cpp +++ b/libraries/MySensors/MyGateway.cpp @@ -98,7 +98,9 @@ boolean MyGateway::sendRoute(MyMessage &message) { } boolean MyGateway::process() { +#ifdef MY_INCLUSION_MODE_FEATURE checkInclusionMode(); +#endif bool newMessage = false; if (transport.available()) { MyMessage &gmsg = transport.receive(); From cc47409f1aecd3fa7eefca33647e2bca0d46b089 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Sat, 23 May 2015 22:40:10 +0200 Subject: [PATCH 05/43] Send messages from sensor nodes using the GatewayTransport driver Signed-off-by: Tomas Hozza --- libraries/MySensors/MyGateway.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/MySensors/MyGateway.cpp b/libraries/MySensors/MyGateway.cpp index 906823b..2eeb039 100644 --- a/libraries/MySensors/MyGateway.cpp +++ b/libraries/MySensors/MyGateway.cpp @@ -136,7 +136,15 @@ boolean MyGateway::process() { } } } - return MySensor::process() || newMessage; + + // new message from sensor node + if (MySensor::process()) { + MyMessage &msg = MySensor::getLastMessage(); + newMessage = true; + transport.send(msg); + } + + return newMessage; } #ifdef MY_INCLUSION_MODE_FEATURE From ceb8f5969fbe97b20ffe5fa9a7cbc264ead7a1e2 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Sat, 23 May 2015 23:15:03 +0200 Subject: [PATCH 06/43] Add tested draft of MyGatewayTransportEthernet working as client Signed-off-by: Tomas Hozza --- libraries/MySensors/MyConfig.h | 12 ++ .../MySensors/MyGatewayTransportEthernet.cpp | 189 ++++++++++++++++++ .../MySensors/MyGatewayTransportEthernet.h | 100 +++++++++ 3 files changed, 301 insertions(+) create mode 100644 libraries/MySensors/MyGatewayTransportEthernet.cpp create mode 100644 libraries/MySensors/MyGatewayTransportEthernet.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 0e07a5a..871e269 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -74,6 +74,11 @@ // Enables inclusion-mode button feature on the gateway device #define MY_INCLUSION_BUTTON_FEATURE +// Disable inclusion mode button if inclusion mode feature is not enabled +#ifndef MY_INCLUSION_MODE_FEATURE +#undef MY_INCLUSION_BUTTON_FEATURE +#endif + // The default input pin used for the inclusion mode button #define MY_INCLUSION_MODE_BUTTON_PIN 3 // Number of seconds (default one minute) inclusion mode should be enabled @@ -152,6 +157,13 @@ #define RFM69_ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! +/************************************** +* Gateway Transport Ethernet Defaults +***************************************/ +// Enable to use DHCP for getting IP address. If not defined, static IP is expected +//#define IP_ADDRESS_DHCP +// Enable to use UDP instead of plain Ethernet +#define USE_UDP #endif diff --git a/libraries/MySensors/MyGatewayTransportEthernet.cpp b/libraries/MySensors/MyGatewayTransportEthernet.cpp new file mode 100644 index 0000000..7d5e948 --- /dev/null +++ b/libraries/MySensors/MyGatewayTransportEthernet.cpp @@ -0,0 +1,189 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Tomas Hozza + * Copyright (C) 2015 Tomas Hozza + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "MyGatewayTransportEthernet.h" + +MyGatewayTransportEthernet::MyGatewayTransportEthernet( + MyProtocol &protocol, + uint8_t *gw_mac +#ifndef IP_ADDRESS_DHCP + , IPAddress gw_ip +#endif /* not IP_ADDRESS_DHCP */ + , uint16_t gw_port +#ifdef IP_ADDRESS_DHCP + , unsigned long ip_renew_interval +#endif /* IP_ADDRESS_DHCP */ + , IPAddress controller_IP + , uint16_t controller_port) : + MyGatewayTransport(protocol), + gatewayMAC(gw_mac), +#ifndef IP_ADDRESS_DHCP + gatewayIP(gw_ip), +#endif /* not IP_ADDRESS_DHCP */ + gatewayPort(gw_port), +#ifdef IP_ADDRESS_DHCP + ip_renewal_period(ip_renew_interval), +#endif /* IP_ADDRESS_DHCP */ + controllerIP(controller_IP), + controllerPort(controller_port) +{ + ; +} + +bool MyGatewayTransportEthernet::begin() { +#ifdef IP_ADDRESS_DHCP + // Get IP address from DHCP + Ethernet.begin(gatewayMAC); +#else + Ethernet.begin(gatewayMAC, gatewayIP); +#endif /* IP_ADDRESS_DHCP */ + + // give the Ethernet interface a second to initialize + // TODO: use HW delay + delay(1000); + +#ifdef USE_UDP + server = new EthernetUDP(); + server->begin(gatewayPort); +#else + // we have to use pointers due to the constructor of EthernetServer + server = new EthernetServer(gatewayPort); + server->begin(); +#endif /* USE_UDP */ +} + +bool MyGatewayTransportEthernet::send(MyMessage &message) +{ + char *msg = NULL; + + if (controllerIP == INADDR_NONE) { + // no controller IP address set! + return false; + } + else { + msg = protocol.format(message); +#ifdef USE_UDP + server->beginPacket(controllerIP, controllerPort); + server->write(msg, strlen(msg)); + // returns 1 if the packet was sent successfully + return server->endPacket(); +#else + EthernetClient client; + if (client.connect(controllerIP, controllerPort)) { + client.write(msg, strlen(msg)); + client.stop(); + return true; + } + else { + // connecting to the server failed! + return false; + } +#endif /* USE_UDP */ + } +} + +bool MyGatewayTransportEthernet::available() +{ + bool available = false; + +#ifdef IP_ADDRESS_DHCP + // renew IP address using DHCP + renewIP(); +#endif + +#ifdef USE_UDP + int packet_size = server->parsePacket(); + + if (server->available()) { + server->read(inputBuffer, MAX_RECEIVE_LENGTH); + available = true; + } +#else + // if an incoming client connects, there will be + // bytes available to read via the client object + EthernetClient client = server->available(); + + if (client) { + while (client.available()) { + // read the bytes incoming from the client + char inChar = client.read(); + + if (inputPos < MAX_RECEIVE_LENGTH - 1) { + // if newline then command is complete + if (inChar == '\n') { + inputBuffer[inputPos] = 0; + available = true; + } else { + inputBuffer[inputPos] = inChar; + inputPos++; + } + } + } + } + inputPos = 0; +#endif + + if (available) { + // Parse message and return parse result + available = protocol.parse(msg, inputBuffer); + } + + return available; +} + +MyMessage& MyGatewayTransportEthernet::receive() +{ + // Return the last parsed message + return msg; +} + +void MyGatewayTransportEthernet::setControllerIPPort(const IPAddress& addr, const uint16_t port) { + controllerIP = addr; + + /* set the port if some legal value passed */ + if (port > 0) + controllerPort = port; +} + +#ifdef IP_ADDRESS_DHCP +void MyGatewayTransportEthernet::renewIP() +{ + /* renew/rebind IP address + 0 - nothing happened + 1 - renew failed + 2 - renew success + 3 - rebinf failed + 4 - rebind success + */ + // TODO: Use millis from MyHw ?? + static unsigned long next_time = millis() + ip_renewal_period; + unsigned long now = millis(); + + // http://playground.arduino.cc/Code/TimingRollover + if ((long)(now - next_time) < 0) + return; + + if (Ethernet.maintain() & ~(0x06)) { + /* Error occured -> IP was not renewed */ + return; + } + + next_time = now + ip_renewal_period; +} +#endif /* IP_ADDRESS_DHCP */ diff --git a/libraries/MySensors/MyGatewayTransportEthernet.h b/libraries/MySensors/MyGatewayTransportEthernet.h new file mode 100644 index 0000000..fefda1c --- /dev/null +++ b/libraries/MySensors/MyGatewayTransportEthernet.h @@ -0,0 +1,100 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Tomas Hozza + * Copyright (C) 2015 Tomas Hozza + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyGatewayTransportEthernet_h +#define MyGatewayTransportEthernet_h + +#include "MyConfig.h" +#include "MyMessage.h" +#include "MyProtocol.h" +#include "MyGatewayTransport.h" +#include "MyProtocolDefault.h" + +#include + +// Use this if you have attached a Ethernet ENC28J60 shields +//#include + +// Use this fo WizNET W5100 module and Arduino Ethernet Shield +#include + +#ifdef USE_UDP +#include +#endif /* USE_UDP */ + +#define CONTROLLER_PORT 5003 +#define IP_RENEWAL_INTERVAL 60000 // in milliseconds +#define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller + + +class MyGatewayTransportEthernet : public MyGatewayTransport +{ + public: + MyGatewayTransportEthernet(MyProtocol &protocol, + uint8_t *gw_mac +#ifndef IP_ADDRESS_DHCP + , IPAddress gw_ip +#endif /* not IP_ADDRESS_DHCP */ + , uint16_t gw_port +#ifdef IP_ADDRESS_DHCP + , unsigned long ip_renew_interval +#endif /* IP_ADDRESS_DHCP */ + , IPAddress controller_IP + , uint16_t controller_port + ); + + // initialize the driver + bool begin(); + + // Send message to controller + bool send(MyMessage &message); + + // Check if a new message is available from controller + bool available(); + + // Pick up last message received from controller + MyMessage& receive(); + + // Set the controller IP and Port + void setControllerIPPort(const IPAddress& addr, const uint16_t port); + +protected: + IPAddress controllerIP; + uint16_t controllerPort; + +#ifdef IP_ADDRESS_DHCP + void renewIP(); + unsigned long ip_renewal_period; +#endif /* IP_ADDRESS_DHCP */ + uint8_t *gatewayMAC; + IPAddress gatewayIP; + uint16_t gatewayPort; + +#ifndef USE_UDP + EthernetServer *server; + uint8_t inputPos; +#else + EthernetUDP *server; +#endif + + char inputBuffer[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface + MyMessage msg; +}; + +#endif /* MyGatewayTransportEthernet_h */ From e16cb028e97986dd0c5d77200fda733c975f74a6 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Sat, 23 May 2015 23:16:24 +0200 Subject: [PATCH 07/43] Rework Ethernet Gateway to use MyGatewayTransportEthernet Signed-off-by: Tomas Hozza --- .../EthernetGateway/EthernetGateway.ino | 184 ++++++------------ .../examples/EthernetGateway/GatewayUtil.h | 125 ------------ 2 files changed, 57 insertions(+), 252 deletions(-) delete mode 100644 libraries/MySensors/examples/EthernetGateway/GatewayUtil.h diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index dbfdcd6..6b38f89 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -20,67 +20,60 @@ * * REVISION HISTORY * Version 1.0 - Henrik EKblad - * Contribution by a-lurker and Anticimex, + * Contribution by a-lurker and Anticimex, * Contribution by Norbert Truchsess + * Contribution by Tomas Hozza + * * - * * DESCRIPTION - * The EthernetGateway sends data received from sensors to the ethernet link. + * The EthernetGateway sends data received from sensors to the ethernet link. * The gateway also accepts input on ethernet interface, which is then sent out to the radio network. * * The GW code is designed for Arduino 328p / 16MHz. ATmega168 does not have enough memory to run this program. - * + * * * COMPILING WIZNET (W5100) ETHERNET MODULE * > Edit MyConfig.h in (libraries\MySensors\) to enable softspi (remove // before "#define SOFTSPI"). * * COMPILING ENC28J60 ETHERNET MODULE - * > Use Arduino IDE 1.5.7 (or later) - * > Disable DEBUG in Sensor.h before compiling this sketch. Othervise the sketch will probably not fit in program space when downloading. - * > Remove Ethernet.h include below and include UIPEthernet.h - * > Remove DigitalIO include + * > Use Arduino IDE 1.5.7 (or later) + * > Disable DEBUG in Sensor.h before compiling this sketch. Othervise the sketch will probably not fit in program space when downloading. + * > Remove Ethernet.h include below and include UIPEthernet.h + * > Remove DigitalIO include * Note that I had to disable UDP and DHCP support in uipethernet-conf.h to reduce space. (which means you have to choose a static IP for that module) * * VERA CONFIGURATION: - * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. + * Enter "ip-number:port" in the ip-field of the Arduino GW device. This will temporarily override any serial configuration for the Vera plugin. * E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003 * * LED purposes: * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly - * - ERR (red) - fast blink on error during transmission error or recieve crc error - * + * - ERR (red) - fast blink on error during transmission error or recieve crc error + * * See http://www.mysensors.org/build/ethernet_gateway for wiring instructions. * */ -#define NO_PORTB_PINCHANGES #include // This include can be removed when using UIPEthernet module -#include +#include #include +#include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include "GatewayUtil.h" +#include +#include +#include +// needed due to Arduino IDE +#include -// Use this if you have attached a Ethernet ENC28J60 shields -// #include - -// Use this for WizNET W5100 module and Arduino Ethernet Shield -#include - - -#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled +#define INCLUSION_MODE_TIME 60 // Number of minutes inclusion mode is enabled #define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button #define RADIO_CE_PIN 5 // radio chip enable @@ -90,6 +83,11 @@ #define RADIO_RX_LED_PIN 8 // Receive led pin #define RADIO_TX_LED_PIN 9 // the PCB, on board LED +#define IP_PORT 5003 // The port you want to open +#ifndef IP_ADDRESS_DHCP +// Gateway IP address if not using DHCP +IPAddress myIp (192, 168, 178, 66); // Configure your static ip-address here COMPILE ERROR HERE? Use Arduino IDE 1.5.7 or later! +#endif /* IP_ADDRESS_DHCP */ // NRFRF24L01 radio driver (set low transmit power by default) MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); @@ -100,117 +98,49 @@ MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); //MySigningAtsha204Soft signer; //MySigningAtsha204 signer; -// Hardware profile +// Hardware profile MyHwATMega328 hw; -// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) -// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h -#ifdef MY_WITH_LEDS_BLINKING -MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); -#else -MySensor gw(transport, hw /*, signer*/); -#endif - - -#define IP_PORT 5003 // The port you want to open -IPAddress myIp (192, 168, 178, 66); // Configure your static ip-address here COMPILE ERROR HERE? Use Arduino IDE 1.5.7 or later! +// Controller protocol +MyProtocolDefault protocol; // The MAC address can be anything you want but should be unique on your network. // Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. // Note that most of the Ardunio examples use "DEAD BEEF FEED" for the MAC address. byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // DEAD BEEF FEED -// a R/W server on the port -EthernetServer server = EthernetServer(IP_PORT); -// handle to open connection -EthernetClient client = EthernetClient(); +// Controller IP +IPAddress controllerIP = IPAddress(192, 168, 178, 254); -char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface -int inputPos = 0; -bool sentReady = false; +// Gateway transport driver +#ifdef IP_ADDRESS_DHCP +MyGatewayTransportEthernet ctrlTransport(protocol, mac, /* gw port */ CONTROLLER_PORT, IP_RENEWAL_INTERVAL, controllerIP, CONTROLLER_PORT); +#else +MyGatewayTransportEthernet ctrlTransport(protocol, mac, myIp, /* gw port */ CONTROLLER_PORT, controllerIP, CONTROLLER_PORT); +#endif -void output(const char *fmt, ... ) { - va_list args; - va_start (args, fmt ); - vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args); - va_end (args); - Serial.print(serialBuffer); - client.write(serialBuffer); + +// Construct MyGateway library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) +// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h +#ifdef MY_WITH_LEDS_BLINKING +MyGateway gw(ctrlTransport, transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); +#else +MyGateway gw(ctrlTransport, transport, hw /*, signer*/); +#endif + +void setup() +{ + gw.begin(NULL +#ifdef MY_INCLUSION_MODE_FEATURE + , INCLUSION_MODE_TIME +#ifdef MY_INCLUSION_BUTTON_FEATURE + , INCLUSION_MODE_PIN +#endif +#endif + ); } -void setup() -{ - Ethernet.begin(mac, myIp); - - setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output); - - // Add interrupt for inclusion button to pin - PCintPort::attachInterrupt(pinInclusion, startInclusionInterrupt, RISING); - - // give the Ethernet interface a second to initialize - delay(1000); - - // Initialize gateway at maximum PA level, channel 70 and callback for write operations - gw.begin(incomingMessage, 0, true, 0); - - - // start listening for clients - server.begin(); - -} - - void loop() { - gw.process(); - - checkButtonTriggeredInclusion(); - checkInclusionFinished(); - - // if an incoming client connects, there will be - // bytes available to read via the client object - EthernetClient newclient = server.available(); - // if a new client connects make sure to dispose any previous existing sockets - if (newclient) { - if (client != newclient) { - client.stop(); - client = newclient; - output(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY); - } - } - - if (client) { - if (!client.connected()) { - client.stop(); - } else if (client.available()) { - // read the bytes incoming from the client - char inChar = client.read(); - if (inputPos - - -#ifdef ARDUINO - - -uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled -uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode - -#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller -#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller - -volatile boolean buttonTriggeredInclusion; -boolean inclusionMode; // Keeps track on inclusion mode -void (*serial)(const char *fmt, ... ); - -MyProtocolDefault protocol; - -void setInclusionMode(boolean newMode); - -char convBuf[MAX_PAYLOAD*2+1]; -char serialBuffer[MAX_SEND_LENGTH]; // Buffer for building string when sending data to vera -unsigned long inclusionStartTime; - -void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) { - inclusionMode = 0; - buttonTriggeredInclusion = false; - serial = _serial; - - pinInclusion = _inc; - inclusionTime = _incTime; - - // Setup digital in that triggers inclusion mode - pinMode(pinInclusion, INPUT); - digitalWrite(pinInclusion, HIGH); -} - - - -void startInclusionInterrupt() { - buttonTriggeredInclusion = true; -} - -void incomingMessage(const MyMessage &message) { -// if (mGetCommand(message) == C_PRESENTATION && inclusionMode) { -// gw.rxBlink(3); -// } else { -// gw.rxBlink(1); -// } - // Pass along the message from sensors to serial line - serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf)); -} - - - -void checkButtonTriggeredInclusion() { - if (buttonTriggeredInclusion) { - // Ok, someone pressed the inclusion button on the gateway - // start inclusion mode for 1 munute. -#ifdef DEBUG - serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE); -#endif - buttonTriggeredInclusion = false; - setInclusionMode(true); - } -} - -void checkInclusionFinished() { - if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) { - // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode - setInclusionMode(false); - } -} - -void parseAndSend(MySensor &gw, char *commandBuffer) { - boolean ok; - MyMessage &msg = gw.getLastMessage(); - - if (protocol.parse(msg, commandBuffer)) { - uint8_t command = mGetCommand(msg); - - if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) { - // Handle messages directed to gateway - if (msg.type == I_VERSION) { - // Request for version - serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION); - } else if (msg.type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(msg.data) == 1); - } - } else { - #ifdef MY_LEDS_BLINKING_FEATURE - gw.txBlink(1); - #endif - ok = gw.sendRoute(msg); - if (!ok) { - #ifdef MY_LEDS_BLINKING_FEATURE - gw.errBlink(1); - #endif - } - } - } -} - -void setInclusionMode(boolean newMode) { - if (newMode != inclusionMode) { - inclusionMode = newMode; - // Send back mode change on serial line to ack command - serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0); - - if (inclusionMode) { - inclusionStartTime = millis(); - } - } -} - - -#else -#error This example is only for use on Arduino. -#endif // ARDUINO - -#endif From bdae50886bb0d7726fa13fa14fc2052507860b90 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Sat, 12 Sep 2015 00:34:44 +0200 Subject: [PATCH 08/43] MotionSensor working --- libraries/MySensors/MyConfig.h | 78 +- libraries/MySensors/MySensor.h | 437 +--- .../{ => core}/MyGatewayTransport.cpp | 0 .../MySensors/{ => core}/MyGatewayTransport.h | 0 .../{ => core}/MyGatewayTransportEthernet.cpp | 0 .../{ => core}/MyGatewayTransportEthernet.h | 0 .../{ => core}/MyGatewayTransportSerial.cpp | 0 .../{ => core}/MyGatewayTransportSerial.h | 0 libraries/MySensors/{ => core}/MyHw.cpp | 0 libraries/MySensors/{ => core}/MyHw.h | 0 .../MySensors/{ => core}/MyHwATMega328.cpp | 6 +- .../MySensors/{ => core}/MyHwATMega328.h | 1 - .../MySensors/{ => core}/MyHwESP8266.cpp | 0 libraries/MySensors/{ => core}/MyHwESP8266.h | 0 libraries/MySensors/{ => core}/MyMessage.cpp | 0 libraries/MySensors/{ => core}/MyMessage.h | 0 libraries/MySensors/{ => core}/MyProtocol.cpp | 0 libraries/MySensors/{ => core}/MyProtocol.h | 0 .../{ => core}/MyProtocolDefault.cpp | 0 .../MySensors/{ => core}/MyProtocolDefault.h | 0 .../{MySensor.cpp => core/MySensorCore.cpp} | 24 +- libraries/MySensors/core/MySensorCore.h | 448 ++++ libraries/MySensors/{ => core}/MySigning.cpp | 0 libraries/MySensors/{ => core}/MySigning.h | 0 .../{ => core}/MySigningAtsha204.cpp | 0 .../MySensors/{ => core}/MySigningAtsha204.h | 0 .../{ => core}/MySigningAtsha204Soft.cpp | 0 .../{ => core}/MySigningAtsha204Soft.h | 0 .../MySensors/{ => core}/MySigningNone.cpp | 0 .../MySensors/{ => core}/MySigningNone.h | 0 .../MySensors/{ => core}/MyTransport.cpp | 0 libraries/MySensors/{ => core}/MyTransport.h | 0 .../MySensors/{ => core}/MyTransportNRF24.cpp | 0 .../MySensors/{ => core}/MyTransportNRF24.h | 0 .../MySensors/{ => core}/MyTransportRFM69.cpp | 2 +- .../MySensors/{ => core}/MyTransportRFM69.h | 4 +- libraries/MySensors/{ => core}/Version.h | 0 .../drivers}/DigitalIO/DigitalIO.h | 0 .../drivers}/DigitalIO/DigitalPin.h | 0 .../drivers}/DigitalIO/I2cConstants.h | 0 .../drivers}/DigitalIO/PinIO.cpp | 0 .../{ => MySensors/drivers}/DigitalIO/PinIO.h | 0 .../drivers}/DigitalIO/SoftI2cMaster.cpp | 0 .../drivers}/DigitalIO/SoftI2cMaster.h | 0 .../drivers}/DigitalIO/SoftSPI.h | 0 .../drivers}/DigitalIO/attic/ADS7818.h | 0 .../drivers}/DigitalIO/attic/MCP320X.h | 0 .../drivers}/DigitalIO/attic/MCP355X.h | 0 .../DigitalPinBlink/DigitalPinBlink.ino | 0 .../DigitalPinConfigToggle.ino | 0 .../DigitalPinReadWrite.ino | 0 .../DigitalPinShiftOut/DigitalPinShiftOut.ino | 0 .../examples/PinIOBegin/PinIOBegin.ino | 0 .../PinIOConfigToggle/PinIOConfigToggle.ino | 0 .../PinIOReadWrite/PinIOReadWrite.ino | 0 .../examples/ScanI2cBus/ScanI2cBus.ino | 0 .../SoftDS1307Utility/SoftDS1307Utility.ino | 0 .../examples/testArduino/testArduino.ino | 0 .../testDigitalPin/testDigitalPin.ino | 0 .../testFastDigital/testFastDigital.ino | 0 .../examples/testPinIO/testPinIO.ino | 0 .../examples/testSoftSPI/testSoftSPI.ino | 0 .../MySensors/drivers/Ethernet_UIP/Dhcp.cpp | 478 +++++ .../MySensors/drivers/Ethernet_UIP/Dhcp.h | 178 ++ .../MySensors/drivers/Ethernet_UIP/Dns.cpp | 422 ++++ .../MySensors/drivers/Ethernet_UIP/Dns.h | 41 + .../MySensors/drivers/Ethernet_UIP/README | 227 ++ .../drivers/Ethernet_UIP/UIPClient.cpp | 583 +++++ .../drivers/Ethernet_UIP/UIPClient.h | 112 + .../drivers/Ethernet_UIP/UIPEthernet.cpp | 485 +++++ .../drivers/Ethernet_UIP/UIPEthernet.h | 127 ++ .../drivers/Ethernet_UIP/UIPServer.cpp | 63 + .../drivers/Ethernet_UIP/UIPServer.h | 40 + .../MySensors/drivers/Ethernet_UIP/UIPUdp.cpp | 383 ++++ .../MySensors/drivers/Ethernet_UIP/UIPUdp.h | 126 ++ .../drivers/Ethernet_UIP/ethernet_comp.h | 9 + .../AdvancedChatServer/AdvancedChatServer.ino | 104 + .../examples/EchoServer/EchoServer.ino | 58 + .../examples/TcpClient/TcpClient.ino | 76 + .../examples/TcpServer/TcpServer.ino | 53 + .../examples/UdpClient/UdpClient.ino | 93 + .../examples/UdpServer/UdpServer.ino | 88 + .../drivers/Ethernet_UIP/keywords.txt | 58 + .../drivers/Ethernet_UIP/library.properties | 10 + .../Ethernet_UIP/tests/perl/tcpclient.pl | 34 + .../Ethernet_UIP/tests/perl/tcpserver.pl | 53 + .../Ethernet_UIP/tests/perl/udpclient.pl | 26 + .../Ethernet_UIP/tests/perl/udpserver.pl | 40 + .../Ethernet_UIP/utility/Enc28J60Network.cpp | 612 ++++++ .../Ethernet_UIP/utility/Enc28J60Network.h | 91 + .../drivers/Ethernet_UIP/utility/clock-arch.c | 28 + .../drivers/Ethernet_UIP/utility/clock-arch.h | 27 + .../drivers/Ethernet_UIP/utility/enc28j60.h | 257 +++ .../drivers/Ethernet_UIP/utility/mempool.cpp | 168 ++ .../drivers/Ethernet_UIP/utility/mempool.h | 54 + .../Ethernet_UIP/utility/mempool_conf.h | 34 + .../drivers/Ethernet_UIP/utility/uip-conf.h | 185 ++ .../drivers/Ethernet_UIP/utility/uip.c | 1897 +++++++++++++++++ .../drivers/Ethernet_UIP/utility/uip.h | 1601 ++++++++++++++ .../drivers/Ethernet_UIP/utility/uip_arch.h | 138 ++ .../drivers/Ethernet_UIP/utility/uip_arp.c | 423 ++++ .../drivers/Ethernet_UIP/utility/uip_arp.h | 144 ++ .../drivers/Ethernet_UIP/utility/uip_clock.h | 88 + .../Ethernet_UIP/utility/uip_debug.cpp | 170 ++ .../drivers/Ethernet_UIP/utility/uip_debug.h | 18 + .../drivers/Ethernet_UIP/utility/uip_timer.c | 127 ++ .../drivers/Ethernet_UIP/utility/uip_timer.h | 86 + .../Ethernet_UIP/utility/uipethernet-conf.h | 29 + .../drivers/Ethernet_UIP/utility/uipopt.h | 543 +++++ .../drivers/Ethernet_UIP/utility/util.h | 13 + .../MySensors/drivers/Ethernet_W5100/Client.h | 45 + .../MySensors/drivers/Ethernet_W5100/Dhcp.cpp | 471 ++++ .../MySensors/drivers/Ethernet_W5100/Dhcp.h | 177 ++ .../MySensors/drivers/Ethernet_W5100/Dns.cpp | 423 ++++ .../MySensors/drivers/Ethernet_W5100/Dns.h | 41 + .../drivers/Ethernet_W5100/Ethernet.cpp | 136 ++ .../drivers/Ethernet_W5100/Ethernet.h | 41 + .../drivers/Ethernet_W5100/EthernetClient.cpp | 177 ++ .../drivers/Ethernet_W5100/EthernetClient.h | 42 + .../drivers/Ethernet_W5100/EthernetServer.cpp | 92 + .../drivers/Ethernet_W5100/EthernetServer.h | 22 + .../drivers/Ethernet_W5100/EthernetUdp.cpp | 252 +++ .../drivers/Ethernet_W5100/EthernetUdp.h | 102 + .../drivers/Ethernet_W5100/IPAddress.cpp | 74 + .../drivers/Ethernet_W5100/IPAddress.h | 75 + .../MySensors/drivers/Ethernet_W5100/Server.h | 30 + .../drivers/Ethernet_W5100/utility/socket.cpp | 469 ++++ .../drivers/Ethernet_W5100/utility/socket.h | 44 + .../drivers/Ethernet_W5100/utility/util.h | 14 + .../drivers/Ethernet_W5100/utility/w5100.cpp | 225 ++ .../drivers/Ethernet_W5100/utility/w5100.h | 422 ++++ libraries/MySensors/drivers/RF24/RF24.h | 4 +- .../MySensors/drivers/RF24/RF24_config.h | 20 +- libraries/MySensors/drivers/RFM69/RFM69.cpp | 2 +- libraries/MySensors/drivers/SPI/SPI.cpp | 201 ++ libraries/MySensors/drivers/SPI/SPI.h | 324 +++ .../BarometricPressureSensor.ino | 143 ++ .../DigitalPotControl/DigitalPotControl.ino | 71 + libraries/MySensors/drivers/SPI/keywords.txt | 36 + .../MySensors/drivers/SPI/library.properties | 9 + .../MySensors/drivers/SPIFlash/SPIFlash.h | 4 +- .../EthernetGateway/EthernetGateway.ino | 21 +- .../examples/MotionSensor/MotionSensor.ino | 8 +- 143 files changed, 15417 insertions(+), 500 deletions(-) rename libraries/MySensors/{ => core}/MyGatewayTransport.cpp (100%) rename libraries/MySensors/{ => core}/MyGatewayTransport.h (100%) rename libraries/MySensors/{ => core}/MyGatewayTransportEthernet.cpp (100%) rename libraries/MySensors/{ => core}/MyGatewayTransportEthernet.h (100%) rename libraries/MySensors/{ => core}/MyGatewayTransportSerial.cpp (100%) rename libraries/MySensors/{ => core}/MyGatewayTransportSerial.h (100%) rename libraries/MySensors/{ => core}/MyHw.cpp (100%) rename libraries/MySensors/{ => core}/MyHw.h (100%) rename libraries/MySensors/{ => core}/MyHwATMega328.cpp (98%) rename libraries/MySensors/{ => core}/MyHwATMega328.h (99%) rename libraries/MySensors/{ => core}/MyHwESP8266.cpp (100%) rename libraries/MySensors/{ => core}/MyHwESP8266.h (100%) rename libraries/MySensors/{ => core}/MyMessage.cpp (100%) rename libraries/MySensors/{ => core}/MyMessage.h (100%) rename libraries/MySensors/{ => core}/MyProtocol.cpp (100%) rename libraries/MySensors/{ => core}/MyProtocol.h (100%) rename libraries/MySensors/{ => core}/MyProtocolDefault.cpp (100%) rename libraries/MySensors/{ => core}/MyProtocolDefault.h (100%) rename libraries/MySensors/{MySensor.cpp => core/MySensorCore.cpp} (98%) create mode 100644 libraries/MySensors/core/MySensorCore.h rename libraries/MySensors/{ => core}/MySigning.cpp (100%) rename libraries/MySensors/{ => core}/MySigning.h (100%) rename libraries/MySensors/{ => core}/MySigningAtsha204.cpp (100%) rename libraries/MySensors/{ => core}/MySigningAtsha204.h (100%) rename libraries/MySensors/{ => core}/MySigningAtsha204Soft.cpp (100%) rename libraries/MySensors/{ => core}/MySigningAtsha204Soft.h (100%) rename libraries/MySensors/{ => core}/MySigningNone.cpp (100%) rename libraries/MySensors/{ => core}/MySigningNone.h (100%) rename libraries/MySensors/{ => core}/MyTransport.cpp (100%) rename libraries/MySensors/{ => core}/MyTransport.h (100%) rename libraries/MySensors/{ => core}/MyTransportNRF24.cpp (100%) rename libraries/MySensors/{ => core}/MyTransportNRF24.h (100%) rename libraries/MySensors/{ => core}/MyTransportRFM69.cpp (98%) rename libraries/MySensors/{ => core}/MyTransportRFM69.h (83%) rename libraries/MySensors/{ => core}/Version.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/DigitalIO.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/DigitalPin.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/I2cConstants.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/PinIO.cpp (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/PinIO.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/SoftI2cMaster.cpp (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/SoftI2cMaster.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/SoftSPI.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/attic/ADS7818.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/attic/MCP320X.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/attic/MCP355X.h (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/PinIOBegin/PinIOBegin.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/testArduino/testArduino.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/testDigitalPin/testDigitalPin.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/testFastDigital/testFastDigital.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/testPinIO/testPinIO.ino (100%) rename libraries/{ => MySensors/drivers}/DigitalIO/examples/testSoftSPI/testSoftSPI.ino (100%) create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/Dhcp.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/Dhcp.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/Dns.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/Dns.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/README create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPClient.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPClient.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPServer.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPServer.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/ethernet_comp.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/examples/EchoServer/EchoServer.ino create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/examples/TcpClient/TcpClient.ino create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/examples/TcpServer/TcpServer.ino create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/examples/UdpClient/UdpClient.ino create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/examples/UdpServer/UdpServer.ino create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/keywords.txt create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/library.properties create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpclient.pl create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpserver.pl create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpclient.pl create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpserver.pl create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.c create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/enc28j60.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/mempool_conf.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip-conf.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip.c create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arch.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.c create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_clock.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.c create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uipethernet-conf.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/uipopt.h create mode 100644 libraries/MySensors/drivers/Ethernet_UIP/utility/util.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Client.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Dhcp.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Dhcp.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Dns.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Dns.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Ethernet.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Ethernet.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/IPAddress.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/IPAddress.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/Server.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/utility/socket.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/utility/socket.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/utility/util.h create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.cpp create mode 100644 libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.h create mode 100644 libraries/MySensors/drivers/SPI/SPI.cpp create mode 100644 libraries/MySensors/drivers/SPI/SPI.h create mode 100644 libraries/MySensors/drivers/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino create mode 100644 libraries/MySensors/drivers/SPI/examples/DigitalPotControl/DigitalPotControl.ino create mode 100644 libraries/MySensors/drivers/SPI/keywords.txt create mode 100644 libraries/MySensors/drivers/SPI/library.properties diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 9731a71..71d87c0 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -24,10 +24,10 @@ // Enable debug flag for debug prints. This will add a lot to the size of the final sketch but good // to see what is actually is happening when developing -#define MY_DEBUG +//#define MY_DEBUG -// Disable this line, If you are using TX(1), RX(0) as normal I/O pin -#define MY_ENABLED_SERIAL +// Enable this line, If you are using TX(1), RX(0) as normal I/O pin +// #define MY_DISABLED_SERIAL // Serial output baud rate (for debug prints and serial gateway) #ifndef MY_BAUD_RATE @@ -112,33 +112,41 @@ /********************************** * Message Signing Settings ***********************************/ -// Disable to completly disable signing functionality in library +// Disable to completely disable signing functionality in library //#define MY_SIGNING_FEATURE // Define a suitable timeout for a signature verification session -// Consider the turnaround from a nonce being generated to a signed message being received +// Consider the turn-around from a nonce being generated to a signed message being received // which might vary, especially in networks with many hops. 5s ought to be enough for anyone. +#ifndef MY_VERIFICATION_TIMEOUT_MS #define MY_VERIFICATION_TIMEOUT_MS 5000 +#endif -// Enable to turn on whitelisting +// Enable to turn on white-listing // When enabled, a signing node will salt the signature with it's unique signature and nodeId. // The verifying node will look up the sender in a local table of trusted nodes and // do the corresponding salting in order to verify the signature. -// For this reason, if whitelisting is enabled on one of the nodes in a sign-verify pair, both -// nodes have to implement whitelisting for this to work. -// Note that a node can still transmit a non-salted message (i.e. have whitelisting disabled) -// to a node that has whitelisting enabled (assuming the receiver does not have a matching entry -// for the sender in it's whitelist) +// For this reason, if white listing is enabled on one of the nodes in a sign-verify pair, both +// nodes have to implement white listing for this to work. +// Note that a node can still transmit a non-salted message (i.e. have white listing disabled) +// to a node that has white listing enabled (assuming the receiver does not have a matching entry +// for the sender in it's white list) //#define MY_SECURE_NODE_WHITELISTING // MySigningAtsha204 default setting +#ifndef MY_ATSHA204_PIN #define MY_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached +#endif // MySigningAtsha204Soft default settings +#ifndef MY_RANDOMSEED_PIN #define MY_RANDOMSEED_PIN 7 // A7 - Pin used for random generation (do not connect anything to this) +#endif // Key to use for HMAC calculation in MySigningAtsha204Soft (32 bytes) +#ifndef MY_HMAC_KEY #define MY_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +#endif /********************************** * NRF24L01 Driver Defaults @@ -155,30 +163,48 @@ #define RF24_BASE_RADIO_ID ((uint64_t)0xA8A8E1FC00LL) // Enable SOFTSPI for NRF24L01 when using the W5100 Ethernet module -//#define SOFTSPI -#ifdef SOFTSPI - // Define the soft SPI pins used for NRF radio - const uint8_t SOFT_SPI_MISO_PIN = 16; - const uint8_t SOFT_SPI_MOSI_PIN = 15; - const uint8_t SOFT_SPI_SCK_PIN = 14; -#endif +//#define MY_SOFTSPI +#ifndef MY_SOFT_SPI_SCK_PIN +#define MY_SOFT_SPI_SCK_PIN 14 +#endif +#ifndef MY_SOFT_SPI_MISO_PIN +#define MY_SOFT_SPI_MISO_PIN 16 +#endif +#ifndef MY_SOFT_SPI_MOSI_PIN +#define MY_SOFT_SPI_MOSI_PIN 15 +#endif /********************************** * RFM69 Driver Defaults ***********************************/ -// Default network id. Use the same for all nodes that will talk to each other -#define RFM69_NETWORKID 100 // Default frequency to use. This must match the hardware version of the RFM69 radio (uncomment one): -// #define RFM69_FREQUENCY RF69_433MHZ -#define RFM69_FREQUENCY RF69_868MHZ -//#define FREQUENCY RF69_915MHZ +#ifndef MY_RFM69_FREQUENCY +// #define MY_RFM69_FREQUENCY RF69_433MHZ +#define MY_RFM69_FREQUENCY RF69_868MHZ +//#define MY_RFM69_FREQUENCY RF69_915MHZ +#endif + +// Default network id. Use the same for all nodes that will talk to each other +#ifndef MY_RFM69_NETWORKID +#define MY_RFM69_NETWORKID 100 +#endif +#ifndef MY_RF69_IRQ_PIN +#define MY_RF69_IRQ_PIN RF69_IRQ_PIN +#endif +#ifndef MY_RF69_SPI_CS +#define MY_RF69_SPI_CS RF69_SPI_CS +#endif +#ifndef MY_RF69_IRQ_NUM +#define MY_RF69_IRQ_NUM RF69_IRQ_NUM +#endif // Enable this for encryption of packets -//#define RFM69_ENABLE_ENCRYPTION -#define RFM69_ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! - +//#define MY_RFM69_ENABLE_ENCRYPTION +#ifndef MY_RFM69_ENCRYPTKEY +#define MY_RFM69_ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! +#endif /************************************** * Gateway Transport Ethernet Defaults diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index b1d3795..94f7e45 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -21,430 +21,45 @@ #ifndef MySensor_h #define MySensor_h -#include "Version.h" // Auto generated by bot #include "MyConfig.h" -#include "MyHw.h" -#include "MyTransport.h" -#include "MyTransportNRF24.h" -#ifdef MY_SIGNING_FEATURE -#include "MySigning.h" -#include "MySigningNone.h" -#endif -#include "MyMessage.h" -#ifdef MY_OTA_FIRMWARE_FEATURE -#include "drivers/SPIFlash/SPIFlash.h" -#endif -#include "MyGatewayTransport.h" -#include "MyGatewayTransportSerial.h" +// Include drivers +#include "drivers/SPI/SPI.cpp" -#include -#include +#include "drivers/RF24/RF24.cpp" +#include "drivers/RFM69/RFM69.cpp" -// Set the hardware driver to use (initialized by MySensor-class) -//#if defined __AVR_ATmega328P__ -#if defined(ARDUINO_ARCH_ESP8266) -#include "MyHwESP8266.h" -typedef MyHwESP8266 MyHwDriver; -#elif defined(ARDUINO_ARCH_AVR) -#include "MyHwATMega328.h" -typedef MyHwATMega328 MyHwDriver; -#endif -//#endif +#include "drivers/ATSHA204/ATSHA204.cpp" +#include "drivers/ATSHA204/sha256.cpp" +#include "drivers/SPIFlash/SPIFlash.cpp" -#ifdef MY_DEBUG -#define debug(x,...) hw.debugPrint(isGateway, x, ##__VA_ARGS__) -#else -#define debug(x,...) -#endif +#include "drivers/Ethernet_W5100/utility/socket.cpp" +#include "drivers/Ethernet_W5100/utility/w5100.cpp" +#include "drivers/Ethernet_W5100/DNS.cpp" +#include "drivers/Ethernet_W5100/Ethernet.cpp" +#include "drivers/Ethernet_W5100/EthernetUdp.cpp" +#include "drivers/Ethernet_W5100/IPAddress.cpp" -#ifdef WITH_LEDS_BLINKING_INVERSE -#define LED_ON 0x1 -#define LED_OFF 0x0 -#else -#define LED_ON 0x0 -#define LED_OFF 0x1 -#endif -// EEPROM start address for mysensors library data -#define EEPROM_START 0 -// EEPROM location of node id -#define EEPROM_NODE_ID_ADDRESS EEPROM_START -// EEPROM location of parent id -#define EEPROM_PARENT_NODE_ID_ADDRESS (EEPROM_START+1) -// EEPROM location of distance to gateway -#define EEPROM_DISTANCE_ADDRESS (EEPROM_PARENT_NODE_ID_ADDRESS+1) -#define EEPROM_ROUTES_ADDRESS (EEPROM_DISTANCE_ADDRESS+1) // Where to start storing routing information in EEPROM. Will allocate 256 bytes. -#define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS+256) // Location of controller sent configuration (we allow one payload of config data from controller) -#define EEPROM_FIRMWARE_TYPE_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24) -#define EEPROM_FIRMWARE_VERSION_ADDRESS (EEPROM_FIRMWARE_TYPE_ADDRESS+2) -#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS+2) -#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS+2) -#define EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2) -#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS+32) // First free address for sketch static configuration +// Include core classes +#include "core/MyHw.cpp" +#include "core/MyHwATMega328.cpp" +#include "core/MyTransport.cpp" +#include "core/MyTransportNRF24.cpp" +#include "core/MyTransportRFM69.cpp" -// Search for a new parent node after this many transmission failures -#define SEARCH_FAILURES 5 +#include "core/MyGatewayTransport.cpp" +#include "core/MyGatewayTransportSerial.cpp" +#include "core/MyMessage.cpp" +#include "core/MySensorCore.cpp" -struct NodeConfig -{ - uint8_t nodeId; // Current node id - uint8_t parentNodeId; // Where this node sends its messages - uint8_t distance; // This nodes distance to sensor net gateway (number of hops) -}; - -struct ControllerConfig { - uint8_t isMetric; -}; - - -// Size of each firmware block -#define FIRMWARE_BLOCK_SIZE 16 -// Number of times a firmware block should be requested before giving up -#define FIRMWARE_MAX_REQUESTS 5 -// Number of times to request a fw block before giving up -#define MY_OTA_RETRY 5 -// Number of millisecons before re-request a fw block -#define MY_OTA_RETRY_DELAY 500 -// Start offset for firmware in flash (DualOptiboot wants to keeps a signature first) -#define FIRMWARE_START_OFFSET 10 -// Bootloader version -#define MY_OTA_BOOTLOADER_MAJOR_VERSION 3 -#define MY_OTA_BOOTLOADER_MINOR_VERSION 0 -#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION) - - -// FW config structure, stored in eeprom -typedef struct { - uint16_t type; - uint16_t version; - uint16_t blocks; - uint16_t crc; -} __attribute__((packed)) NodeFirmwareConfig; - -typedef struct { - uint16_t type; - uint16_t version; - uint16_t blocks; - uint16_t crc; - uint16_t BLVersion; -} __attribute__((packed)) RequestFirmwareConfig; - -typedef struct { - uint16_t type; - uint16_t version; - uint16_t block; -} __attribute__((packed)) RequestFWBlock; - -typedef struct { - uint16_t type; - uint16_t version; - uint16_t block; - uint8_t data[FIRMWARE_BLOCK_SIZE]; -} __attribute__((packed)) ReplyFWBlock; - - -#ifdef __cplusplus -class MySensor -{ - public: - /** - * Constructor - * - * Creates a new instance of Sensor class. - * - */ - MySensor(MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() -#ifdef MY_SIGNING_FEATURE - , MySigning &signer=*new MySigningNone() -#endif - ); - - /** - * Begin operation of the MySensors library - * - * Call this in setup(), before calling any other sensor net library methods. - * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. - * @param nodeId The unique id (1-254) for this sensor. Default is AUTO(255) which means sensor tries to fetch an id from controller. - * @param repeaterMode Activate repeater mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false - * @param parentNodeId Use this to force node to always communicate with a certain parent node. Default is AUTO which means node automatically tries to find a parent. - */ - - void begin(void (* msgCallback)(const MyMessage &)=NULL, uint8_t nodeId=AUTO, boolean repeaterMode=false, uint8_t parentNodeId=AUTO); - - /** - * Return the nodes nodeId. - */ - uint8_t getNodeId(); - - /** - * Each node must present all attached sensors before any values can be handled correctly by the controller. - * It is usually good to present all attached sensors after power-up in setup(). - * - * @param sensorId Select a unique sensor id for this sensor. Choose a number between 0-254. - * @param sensorType The sensor type. See sensor typedef in MyMessage.h. - * @param description A textual description of the sensor. - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * @param description A textual description of the sensor. - */ - void present(uint8_t sensorId, uint8_t sensorType, const char *description="", bool ack=false); - - /** - * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. - * @param name String containing a short Sketch name or NULL if not applicable - * @param version String containing a short Sketch version or NULL if not applicable - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * - */ - void sendSketchInfo(const char *name, const char *version, bool ack=false); - - /** - * Sends a message to gateway or one of the other nodes in the radio network - * - * @param msg Message to send - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * @return true Returns true if message reached the first stop on its way to destination. - */ - bool send(MyMessage &msg, bool ack=false); - - - /** - * Send this nodes battery level to gateway. - * @param level Level between 0-100(%) - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * - */ - void sendBatteryLevel(uint8_t level, bool ack=false); - - /** - * Send a heartbeat message (I'm alive!) to the gateway/controller. - * The payload will be an incremental 16 bit integer value starting at 1 when sensor is powered on. - */ - void sendHeartbeat(void); - - /** - * Requests a value from gateway or some other sensor in the radio network. - * Make sure to add callback-method in begin-method to handle request responses. - * - * @param childSensorId The unique child id for the different sensors connected to this Arduino. 0-254. - * @param variableType The variableType to fetch - * @param destination The nodeId of other node in radio network. Default is gateway - */ - void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination=GATEWAY_ADDRESS); - - /** - * Requests time from controller. Answer will be delivered to callback. - * - * @param callback for time request. Incoming argument is seconds since 1970. - */ - void requestTime(void (* timeCallback)(unsigned long)); - - - /** - * Processes incoming messages to this node. If this is a relaying node it will - * Returns true if there is a message addressed for this node just was received. - * Use callback to handle incoming messages. - */ - boolean process(); - - /** - * Returns the most recent node configuration received from controller - */ - ControllerConfig getConfig(); - - /** - * Save a state (in local EEPROM). Good for actuators to "remember" state between - * power cycles. - * - * You have 256 bytes to play with. Note that there is a limitation on the number - * of writes the EEPROM can handle (~100 000 cycles on ATMega328). - * - * @param pos The position to store value in (0-255) - * @param Value to store in position - */ - void saveState(uint8_t pos, uint8_t value); - - /** - * Load a state (from local EEPROM). - * - * @param pos The position to fetch value from (0-255) - * @return Value to store in position - */ - uint8_t loadState(uint8_t pos); - - /** - * Returns the last received message - */ - MyMessage& getLastMessage(void); - - - - /** - * Wait for a specified amount of time to pass. Keeps process()ing. - * This does not power-down the radio nor the Arduino. - * Because this calls process() in a loop, it is a good way to wait - * in your loop() on a repeater node or sensor that listens to messages. - * @param ms Number of milliseconds to sleep. - */ - void wait(unsigned long ms); - - /** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. - * @param ms Number of milliseconds to sleep. - */ - void sleep(unsigned long ms); - - /** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change. - * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin - * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 - * @param interrupt Interrupt that should trigger the wakeup - * @param mode RISING, FALLING, CHANGE - * @param ms Number of milliseconds to sleep or 0 to sleep forever - * @return true if wake up was triggered by pin change and false means timer woke it up. - */ - bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); - - /** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. - * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin - * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 - * @param interrupt1 First interrupt that should trigger the wakeup - * @param mode1 Mode for first interrupt (RISING, FALLING, CHANGE) - * @param interrupt2 Second interrupt that should trigger the wakeup - * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) - * @param ms Number of milliseconds to sleep or 0 to sleep forever - * @return Interrupt number wake up was triggered by pin change and negative if timer woke it up. - */ - int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); - -#ifdef MY_LEDS_BLINKING_FEATURE - /** - * Blink with LEDs - * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms - */ - void rxBlink(uint8_t cnt); - void txBlink(uint8_t cnt); - void errBlink(uint8_t cnt); -#endif - - boolean sendRoute(MyMessage &message); - - protected: - NodeConfig nc; // Essential settings for node to work - ControllerConfig cc; // Configuration coming from controller -#ifdef MY_OTA_FIRMWARE_FEATURE - NodeFirmwareConfig fc; - bool fwUpdateOngoing; - unsigned long fwLastRequestTime; - uint16_t fwBlock; - uint8_t fwRetry; - SPIFlash flash; -#endif - - bool repeaterMode; - bool autoFindParent; - bool isGateway; - - MyMessage msg; // Buffer for incoming messages. - MyMessage tmpMsg ; // Buffer for temporary messages (acks and nonces among others). - -#ifdef MY_LEDS_BLINKING_FEATURE - // these variables don't need to be volatile, since we are not using interrupts - uint8_t countRx; - uint8_t countTx; - uint8_t countErr; - - void handleLedsBlinking(); // do the actual blinking - unsigned long blink_next_time; -#endif - - MyTransport& radio; -#ifdef MY_SIGNING_FEATURE - uint16_t doSign[16]; // Bitfield indicating which sensors require signed communication - MyMessage msgSign; // Buffer for message to sign. - MySigning& signer; -#endif - MyHw& hw; - - boolean sendWrite(uint8_t dest, MyMessage &message); - void processInternalMessages(MyMessage &msg); -#ifdef MY_DEBUG - char convBuf[MAX_PAYLOAD*2+1]; -#endif - uint8_t failedTransmissions; - uint16_t heartbeat; - void (*timeCallback)(unsigned long); // Callback for requested time messages - void (*msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. - -#ifdef MY_OTA_FIRMWARE_FEATURE -// do a crc16 on the whole received firmware - bool isValidFirmware(); -#endif - - private: - - void requestNodeId(); - void setupNode(); - void findParentNode(); - uint8_t crc8Message(MyMessage &message); -}; -#endif - - -class MyGateway : public MySensor -{ -public: - // MyProtocolSerial constructor - MyGateway(MyGatewayTransport &transport=*new MyGatewayTransportSerial(), MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() -#ifdef MY_SIGNING_FEATURE - , MySigning &signer=*new MySigningNone() -#endif - ); - - - /** - * Begin operation of the MySensors library - * - * Call this in setup(), before calling any other sensor net library methods. - * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. - * @param inclusionModeDuration Number of milliseconds inclusion mode should be enabled - * @param inclusionModeButtonPin Button pin used for enabling inclusion mode - */ - - void begin(void (* msgCallback)(const MyMessage &)=NULL); - - - /** - * See MySensor.h - * - * Overloaded to handle local sensor data sent to controller. - */ - boolean sendRoute(MyMessage &message); - - /** - * Processes incoming messages to this node. - * Returns true if there is a message addressed for this node was received. - * Preferred way of handling incoming messages is to use the callback defined in begin(). - */ - boolean process(); - -private: - - MyGatewayTransport& transport; - -#ifdef MY_INCLUSION_MODE_FEATURE - - void setInclusionMode(bool newMode); - void checkInclusionMode(); - unsigned long inclusionStartTime; - bool inclusionMode; -#endif -}; +// Initialize library +MyTransportRFM69 transport; +MySensor gw; #endif diff --git a/libraries/MySensors/MyGatewayTransport.cpp b/libraries/MySensors/core/MyGatewayTransport.cpp similarity index 100% rename from libraries/MySensors/MyGatewayTransport.cpp rename to libraries/MySensors/core/MyGatewayTransport.cpp diff --git a/libraries/MySensors/MyGatewayTransport.h b/libraries/MySensors/core/MyGatewayTransport.h similarity index 100% rename from libraries/MySensors/MyGatewayTransport.h rename to libraries/MySensors/core/MyGatewayTransport.h diff --git a/libraries/MySensors/MyGatewayTransportEthernet.cpp b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp similarity index 100% rename from libraries/MySensors/MyGatewayTransportEthernet.cpp rename to libraries/MySensors/core/MyGatewayTransportEthernet.cpp diff --git a/libraries/MySensors/MyGatewayTransportEthernet.h b/libraries/MySensors/core/MyGatewayTransportEthernet.h similarity index 100% rename from libraries/MySensors/MyGatewayTransportEthernet.h rename to libraries/MySensors/core/MyGatewayTransportEthernet.h diff --git a/libraries/MySensors/MyGatewayTransportSerial.cpp b/libraries/MySensors/core/MyGatewayTransportSerial.cpp similarity index 100% rename from libraries/MySensors/MyGatewayTransportSerial.cpp rename to libraries/MySensors/core/MyGatewayTransportSerial.cpp diff --git a/libraries/MySensors/MyGatewayTransportSerial.h b/libraries/MySensors/core/MyGatewayTransportSerial.h similarity index 100% rename from libraries/MySensors/MyGatewayTransportSerial.h rename to libraries/MySensors/core/MyGatewayTransportSerial.h diff --git a/libraries/MySensors/MyHw.cpp b/libraries/MySensors/core/MyHw.cpp similarity index 100% rename from libraries/MySensors/MyHw.cpp rename to libraries/MySensors/core/MyHw.cpp diff --git a/libraries/MySensors/MyHw.h b/libraries/MySensors/core/MyHw.h similarity index 100% rename from libraries/MySensors/MyHw.h rename to libraries/MySensors/core/MyHw.h diff --git a/libraries/MySensors/MyHwATMega328.cpp b/libraries/MySensors/core/MyHwATMega328.cpp similarity index 98% rename from libraries/MySensors/MyHwATMega328.cpp rename to libraries/MySensors/core/MyHwATMega328.cpp index ad05033..b20d337 100644 --- a/libraries/MySensors/MyHwATMega328.cpp +++ b/libraries/MySensors/core/MyHwATMega328.cpp @@ -121,7 +121,7 @@ void powerDown(period_t period) { void MyHwATMega328::internalSleep(unsigned long ms) { // Let serial prints finish (debug, log etc) - #ifdef MY_ENABLED_SERIAL + #ifndef MY_DISABLED_SERIAL Serial.flush(); #endif pinIntTrigger = 0; @@ -152,7 +152,7 @@ bool MyHwATMega328::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { pinTriggeredWakeup = false; } } else { - #ifdef MY_ENABLED_SERIAL + #ifndef MY_DISABLED_SERIAL Serial.flush(); #endif powerDown(SLEEP_FOREVER); @@ -172,7 +172,7 @@ inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t i retVal = -1; } } else { - #ifdef MY_ENABLED_SERIAL + #ifndef MY_DISABLED_SERIAL Serial.flush(); #endif powerDown(SLEEP_FOREVER); diff --git a/libraries/MySensors/MyHwATMega328.h b/libraries/MySensors/core/MyHwATMega328.h similarity index 99% rename from libraries/MySensors/MyHwATMega328.h rename to libraries/MySensors/core/MyHwATMega328.h index a992ff2..3468db6 100644 --- a/libraries/MySensors/MyHwATMega328.h +++ b/libraries/MySensors/core/MyHwATMega328.h @@ -36,7 +36,6 @@ #ifdef __cplusplus #include -#include #endif #if defined __AVR_ATmega328P__ diff --git a/libraries/MySensors/MyHwESP8266.cpp b/libraries/MySensors/core/MyHwESP8266.cpp similarity index 100% rename from libraries/MySensors/MyHwESP8266.cpp rename to libraries/MySensors/core/MyHwESP8266.cpp diff --git a/libraries/MySensors/MyHwESP8266.h b/libraries/MySensors/core/MyHwESP8266.h similarity index 100% rename from libraries/MySensors/MyHwESP8266.h rename to libraries/MySensors/core/MyHwESP8266.h diff --git a/libraries/MySensors/MyMessage.cpp b/libraries/MySensors/core/MyMessage.cpp similarity index 100% rename from libraries/MySensors/MyMessage.cpp rename to libraries/MySensors/core/MyMessage.cpp diff --git a/libraries/MySensors/MyMessage.h b/libraries/MySensors/core/MyMessage.h similarity index 100% rename from libraries/MySensors/MyMessage.h rename to libraries/MySensors/core/MyMessage.h diff --git a/libraries/MySensors/MyProtocol.cpp b/libraries/MySensors/core/MyProtocol.cpp similarity index 100% rename from libraries/MySensors/MyProtocol.cpp rename to libraries/MySensors/core/MyProtocol.cpp diff --git a/libraries/MySensors/MyProtocol.h b/libraries/MySensors/core/MyProtocol.h similarity index 100% rename from libraries/MySensors/MyProtocol.h rename to libraries/MySensors/core/MyProtocol.h diff --git a/libraries/MySensors/MyProtocolDefault.cpp b/libraries/MySensors/core/MyProtocolDefault.cpp similarity index 100% rename from libraries/MySensors/MyProtocolDefault.cpp rename to libraries/MySensors/core/MyProtocolDefault.cpp diff --git a/libraries/MySensors/MyProtocolDefault.h b/libraries/MySensors/core/MyProtocolDefault.h similarity index 100% rename from libraries/MySensors/MyProtocolDefault.h rename to libraries/MySensors/core/MyProtocolDefault.h diff --git a/libraries/MySensors/MySensor.cpp b/libraries/MySensors/core/MySensorCore.cpp similarity index 98% rename from libraries/MySensors/MySensor.cpp rename to libraries/MySensors/core/MySensorCore.cpp index 6a8f96e..32b4e8e 100644 --- a/libraries/MySensors/MySensor.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -19,27 +19,7 @@ -#include "MySensor.h" - - - -#include "drivers/RF24/RF24.cpp" - -#include "drivers/RFM69/RFM69.cpp" - -#include "drivers/ATSHA204/ATSHA204.cpp" -#include "drivers/ATSHA204/sha256.cpp" - -#include "drivers/SPIFlash/SPIFlash.cpp" - - -#include "drivers/Ethernet_W5100/utility/socket.cpp" -#include "drivers/Ethernet_W5100/utility/w5100.cpp" -#include "drivers/Ethernet_W5100/DNS.cpp" -#include "drivers/Ethernet_W5100/Ethernet.cpp" -#include "drivers/Ethernet_W5100/EthernetUdp.cpp" -#include "drivers/Ethernet_W5100/IPAddress.cpp" - +#include "MySensorCore.h" #define DISTANCE_INVALID (0xFF) @@ -168,7 +148,7 @@ void MySensor::errBlink(uint8_t cnt) { #endif void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, uint8_t _parentNodeId) { - #ifdef MY_ENABLED_SERIAL + #ifndef MY_DISABLED_SERIAL hw_init(); #endif repeaterMode = _repeaterMode; diff --git a/libraries/MySensors/core/MySensorCore.h b/libraries/MySensors/core/MySensorCore.h new file mode 100644 index 0000000..5636b29 --- /dev/null +++ b/libraries/MySensors/core/MySensorCore.h @@ -0,0 +1,448 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + + +#ifndef MySensorCore_h +#define MySensorCore_h + +#include "Version.h" // Auto generated by bot +#include "MyConfig.h" +#include "MyHw.h" +#include "MyTransport.h" +#include "MyTransportNRF24.h" +#ifdef MY_SIGNING_FEATURE +#include "MySigning.h" +#include "MySigningNone.h" +#endif +#include "MyMessage.h" +#ifdef MY_OTA_FIRMWARE_FEATURE +#include "drivers/SPIFlash/SPIFlash.h" +#endif + +#include "MyGatewayTransport.h" +#include "MyGatewayTransportSerial.h" + +#include +#include + + +// Set the hardware driver to use (initialized by MySensor-class) +#if defined(ARDUINO_ARCH_ESP8266) +#include "MyHwESP8266.h" +typedef MyHwESP8266 MyHwDriver; +#elif defined(ARDUINO_ARCH_AVR) +#include "MyHwATMega328.h" +typedef MyHwATMega328 MyHwDriver; +#endif + + +#ifdef MY_DEBUG +#define debug(x,...) hw.debugPrint(isGateway, x, ##__VA_ARGS__) +#else +#define debug(x,...) +#endif + +#ifdef WITH_LEDS_BLINKING_INVERSE +#define LED_ON 0x1 +#define LED_OFF 0x0 +#else +#define LED_ON 0x0 +#define LED_OFF 0x1 +#endif + + +// EEPROM start address for mysensors library data +#define EEPROM_START 0 +// EEPROM location of node id +#define EEPROM_NODE_ID_ADDRESS EEPROM_START +// EEPROM location of parent id +#define EEPROM_PARENT_NODE_ID_ADDRESS (EEPROM_START+1) +// EEPROM location of distance to gateway +#define EEPROM_DISTANCE_ADDRESS (EEPROM_PARENT_NODE_ID_ADDRESS+1) +#define EEPROM_ROUTES_ADDRESS (EEPROM_DISTANCE_ADDRESS+1) // Where to start storing routing information in EEPROM. Will allocate 256 bytes. +#define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS+256) // Location of controller sent configuration (we allow one payload of config data from controller) +#define EEPROM_FIRMWARE_TYPE_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24) +#define EEPROM_FIRMWARE_VERSION_ADDRESS (EEPROM_FIRMWARE_TYPE_ADDRESS+2) +#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS+2) +#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS+2) +#define EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2) +#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS+32) // First free address for sketch static configuration + +// Search for a new parent node after this many transmission failures +#define SEARCH_FAILURES 5 + + +struct NodeConfig +{ + uint8_t nodeId; // Current node id + uint8_t parentNodeId; // Where this node sends its messages + uint8_t distance; // This nodes distance to sensor net gateway (number of hops) +}; + +struct ControllerConfig { + uint8_t isMetric; +}; + + +// Size of each firmware block +#define FIRMWARE_BLOCK_SIZE 16 +// Number of times a firmware block should be requested before giving up +#define FIRMWARE_MAX_REQUESTS 5 +// Number of times to request a fw block before giving up +#define MY_OTA_RETRY 5 +// Number of millisecons before re-request a fw block +#define MY_OTA_RETRY_DELAY 500 +// Start offset for firmware in flash (DualOptiboot wants to keeps a signature first) +#define FIRMWARE_START_OFFSET 10 +// Bootloader version +#define MY_OTA_BOOTLOADER_MAJOR_VERSION 3 +#define MY_OTA_BOOTLOADER_MINOR_VERSION 0 +#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION) + + +// FW config structure, stored in eeprom +typedef struct { + uint16_t type; + uint16_t version; + uint16_t blocks; + uint16_t crc; +} __attribute__((packed)) NodeFirmwareConfig; + +typedef struct { + uint16_t type; + uint16_t version; + uint16_t blocks; + uint16_t crc; + uint16_t BLVersion; +} __attribute__((packed)) RequestFirmwareConfig; + +typedef struct { + uint16_t type; + uint16_t version; + uint16_t block; +} __attribute__((packed)) RequestFWBlock; + +typedef struct { + uint16_t type; + uint16_t version; + uint16_t block; + uint8_t data[FIRMWARE_BLOCK_SIZE]; +} __attribute__((packed)) ReplyFWBlock; + + +#ifdef __cplusplus +class MySensor +{ + public: + /** + * Constructor + * + * Creates a new instance of Sensor class. + * + */ + MySensor(MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() +#ifdef MY_SIGNING_FEATURE + , MySigning &signer=*new MySigningNone() +#endif + ); + + /** + * Begin operation of the MySensors library + * + * Call this in setup(), before calling any other sensor net library methods. + * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. + * @param nodeId The unique id (1-254) for this sensor. Default is AUTO(255) which means sensor tries to fetch an id from controller. + * @param repeaterMode Activate repeater mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false + * @param parentNodeId Use this to force node to always communicate with a certain parent node. Default is AUTO which means node automatically tries to find a parent. + */ + + void begin(void (* msgCallback)(const MyMessage &)=NULL, uint8_t nodeId=AUTO, boolean repeaterMode=false, uint8_t parentNodeId=AUTO); + + /** + * Return the nodes nodeId. + */ + uint8_t getNodeId(); + + /** + * Each node must present all attached sensors before any values can be handled correctly by the controller. + * It is usually good to present all attached sensors after power-up in setup(). + * + * @param sensorId Select a unique sensor id for this sensor. Choose a number between 0-254. + * @param sensorType The sensor type. See sensor typedef in MyMessage.h. + * @param description A textual description of the sensor. + * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. + * @param description A textual description of the sensor. + */ + void present(uint8_t sensorId, uint8_t sensorType, const char *description="", bool ack=false); + + /** + * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. + * @param name String containing a short Sketch name or NULL if not applicable + * @param version String containing a short Sketch version or NULL if not applicable + * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. + * + */ + void sendSketchInfo(const char *name, const char *version, bool ack=false); + + /** + * Sends a message to gateway or one of the other nodes in the radio network + * + * @param msg Message to send + * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. + * @return true Returns true if message reached the first stop on its way to destination. + */ + bool send(MyMessage &msg, bool ack=false); + + + /** + * Send this nodes battery level to gateway. + * @param level Level between 0-100(%) + * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. + * + */ + void sendBatteryLevel(uint8_t level, bool ack=false); + + /** + * Send a heartbeat message (I'm alive!) to the gateway/controller. + * The payload will be an incremental 16 bit integer value starting at 1 when sensor is powered on. + */ + void sendHeartbeat(void); + + /** + * Requests a value from gateway or some other sensor in the radio network. + * Make sure to add callback-method in begin-method to handle request responses. + * + * @param childSensorId The unique child id for the different sensors connected to this Arduino. 0-254. + * @param variableType The variableType to fetch + * @param destination The nodeId of other node in radio network. Default is gateway + */ + void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination=GATEWAY_ADDRESS); + + /** + * Requests time from controller. Answer will be delivered to callback. + * + * @param callback for time request. Incoming argument is seconds since 1970. + */ + void requestTime(void (* timeCallback)(unsigned long)); + + + /** + * Processes incoming messages to this node. If this is a relaying node it will + * Returns true if there is a message addressed for this node just was received. + * Use callback to handle incoming messages. + */ + boolean process(); + + /** + * Returns the most recent node configuration received from controller + */ + ControllerConfig getConfig(); + + /** + * Save a state (in local EEPROM). Good for actuators to "remember" state between + * power cycles. + * + * You have 256 bytes to play with. Note that there is a limitation on the number + * of writes the EEPROM can handle (~100 000 cycles on ATMega328). + * + * @param pos The position to store value in (0-255) + * @param Value to store in position + */ + void saveState(uint8_t pos, uint8_t value); + + /** + * Load a state (from local EEPROM). + * + * @param pos The position to fetch value from (0-255) + * @return Value to store in position + */ + uint8_t loadState(uint8_t pos); + + /** + * Returns the last received message + */ + MyMessage& getLastMessage(void); + + + + /** + * Wait for a specified amount of time to pass. Keeps process()ing. + * This does not power-down the radio nor the Arduino. + * Because this calls process() in a loop, it is a good way to wait + * in your loop() on a repeater node or sensor that listens to messages. + * @param ms Number of milliseconds to sleep. + */ + void wait(unsigned long ms); + + /** + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. + * @param ms Number of milliseconds to sleep. + */ + void sleep(unsigned long ms); + + /** + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change. + * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin + * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 + * @param interrupt Interrupt that should trigger the wakeup + * @param mode RISING, FALLING, CHANGE + * @param ms Number of milliseconds to sleep or 0 to sleep forever + * @return true if wake up was triggered by pin change and false means timer woke it up. + */ + bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); + + /** + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. + * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin + * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 + * @param interrupt1 First interrupt that should trigger the wakeup + * @param mode1 Mode for first interrupt (RISING, FALLING, CHANGE) + * @param interrupt2 Second interrupt that should trigger the wakeup + * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) + * @param ms Number of milliseconds to sleep or 0 to sleep forever + * @return Interrupt number wake up was triggered by pin change and negative if timer woke it up. + */ + int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); + +#ifdef MY_LEDS_BLINKING_FEATURE + /** + * Blink with LEDs + * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms + */ + void rxBlink(uint8_t cnt); + void txBlink(uint8_t cnt); + void errBlink(uint8_t cnt); +#endif + + boolean sendRoute(MyMessage &message); + + protected: + NodeConfig nc; // Essential settings for node to work + ControllerConfig cc; // Configuration coming from controller +#ifdef MY_OTA_FIRMWARE_FEATURE + NodeFirmwareConfig fc; + bool fwUpdateOngoing; + unsigned long fwLastRequestTime; + uint16_t fwBlock; + uint8_t fwRetry; + SPIFlash flash; +#endif + + bool repeaterMode; + bool autoFindParent; + bool isGateway; + + MyMessage msg; // Buffer for incoming messages. + MyMessage tmpMsg ; // Buffer for temporary messages (acks and nonces among others). + +#ifdef MY_LEDS_BLINKING_FEATURE + // these variables don't need to be volatile, since we are not using interrupts + uint8_t countRx; + uint8_t countTx; + uint8_t countErr; + + void handleLedsBlinking(); // do the actual blinking + unsigned long blink_next_time; +#endif + + MyTransport& radio; +#ifdef MY_SIGNING_FEATURE + uint16_t doSign[16]; // Bitfield indicating which sensors require signed communication + MyMessage msgSign; // Buffer for message to sign. + MySigning& signer; +#endif + MyHw& hw; + + boolean sendWrite(uint8_t dest, MyMessage &message); + void processInternalMessages(MyMessage &msg); +#ifdef MY_DEBUG + char convBuf[MAX_PAYLOAD*2+1]; +#endif + uint8_t failedTransmissions; + uint16_t heartbeat; + void (*timeCallback)(unsigned long); // Callback for requested time messages + void (*msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. + +#ifdef MY_OTA_FIRMWARE_FEATURE +// do a crc16 on the whole received firmware + bool isValidFirmware(); +#endif + + private: + + void requestNodeId(); + void setupNode(); + void findParentNode(); + uint8_t crc8Message(MyMessage &message); +}; +#endif + + +class MyGateway : public MySensor +{ +public: + // MyProtocolSerial constructor + MyGateway(MyGatewayTransport &transport=*new MyGatewayTransportSerial(), MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() +#ifdef MY_SIGNING_FEATURE + , MySigning &signer=*new MySigningNone() +#endif + ); + + + /** + * Begin operation of the MySensors library + * + * Call this in setup(), before calling any other sensor net library methods. + * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. + * @param inclusionModeDuration Number of milliseconds inclusion mode should be enabled + * @param inclusionModeButtonPin Button pin used for enabling inclusion mode + */ + + void begin(void (* msgCallback)(const MyMessage &)=NULL); + + + /** + * See MySensor.h + * + * Overloaded to handle local sensor data sent to controller. + */ + boolean sendRoute(MyMessage &message); + + /** + * Processes incoming messages to this node. + * Returns true if there is a message addressed for this node was received. + * Preferred way of handling incoming messages is to use the callback defined in begin(). + */ + boolean process(); + +private: + + MyGatewayTransport& transport; + +#ifdef MY_INCLUSION_MODE_FEATURE + + void setInclusionMode(bool newMode); + void checkInclusionMode(); + unsigned long inclusionStartTime; + bool inclusionMode; +#endif +}; + + +#endif diff --git a/libraries/MySensors/MySigning.cpp b/libraries/MySensors/core/MySigning.cpp similarity index 100% rename from libraries/MySensors/MySigning.cpp rename to libraries/MySensors/core/MySigning.cpp diff --git a/libraries/MySensors/MySigning.h b/libraries/MySensors/core/MySigning.h similarity index 100% rename from libraries/MySensors/MySigning.h rename to libraries/MySensors/core/MySigning.h diff --git a/libraries/MySensors/MySigningAtsha204.cpp b/libraries/MySensors/core/MySigningAtsha204.cpp similarity index 100% rename from libraries/MySensors/MySigningAtsha204.cpp rename to libraries/MySensors/core/MySigningAtsha204.cpp diff --git a/libraries/MySensors/MySigningAtsha204.h b/libraries/MySensors/core/MySigningAtsha204.h similarity index 100% rename from libraries/MySensors/MySigningAtsha204.h rename to libraries/MySensors/core/MySigningAtsha204.h diff --git a/libraries/MySensors/MySigningAtsha204Soft.cpp b/libraries/MySensors/core/MySigningAtsha204Soft.cpp similarity index 100% rename from libraries/MySensors/MySigningAtsha204Soft.cpp rename to libraries/MySensors/core/MySigningAtsha204Soft.cpp diff --git a/libraries/MySensors/MySigningAtsha204Soft.h b/libraries/MySensors/core/MySigningAtsha204Soft.h similarity index 100% rename from libraries/MySensors/MySigningAtsha204Soft.h rename to libraries/MySensors/core/MySigningAtsha204Soft.h diff --git a/libraries/MySensors/MySigningNone.cpp b/libraries/MySensors/core/MySigningNone.cpp similarity index 100% rename from libraries/MySensors/MySigningNone.cpp rename to libraries/MySensors/core/MySigningNone.cpp diff --git a/libraries/MySensors/MySigningNone.h b/libraries/MySensors/core/MySigningNone.h similarity index 100% rename from libraries/MySensors/MySigningNone.h rename to libraries/MySensors/core/MySigningNone.h diff --git a/libraries/MySensors/MyTransport.cpp b/libraries/MySensors/core/MyTransport.cpp similarity index 100% rename from libraries/MySensors/MyTransport.cpp rename to libraries/MySensors/core/MyTransport.cpp diff --git a/libraries/MySensors/MyTransport.h b/libraries/MySensors/core/MyTransport.h similarity index 100% rename from libraries/MySensors/MyTransport.h rename to libraries/MySensors/core/MyTransport.h diff --git a/libraries/MySensors/MyTransportNRF24.cpp b/libraries/MySensors/core/MyTransportNRF24.cpp similarity index 100% rename from libraries/MySensors/MyTransportNRF24.cpp rename to libraries/MySensors/core/MyTransportNRF24.cpp diff --git a/libraries/MySensors/MyTransportNRF24.h b/libraries/MySensors/core/MyTransportNRF24.h similarity index 100% rename from libraries/MySensors/MyTransportNRF24.h rename to libraries/MySensors/core/MyTransportNRF24.h diff --git a/libraries/MySensors/MyTransportRFM69.cpp b/libraries/MySensors/core/MyTransportRFM69.cpp similarity index 98% rename from libraries/MySensors/MyTransportRFM69.cpp rename to libraries/MySensors/core/MyTransportRFM69.cpp index 757c9a5..ca29585 100644 --- a/libraries/MySensors/MyTransportRFM69.cpp +++ b/libraries/MySensors/core/MyTransportRFM69.cpp @@ -32,7 +32,7 @@ MyTransportRFM69::MyTransportRFM69(uint8_t freqBand, uint8_t networkId, uint8_t bool MyTransportRFM69::init() { // Start up the radio library (_address will be set later by the MySensors library) radio.initialize(_freqBand, _address, _networkId); -#ifdef RFM69_ENABLE_ENCRYPTION +#ifdef MY_RFM69_ENABLE_ENCRYPTION radio.encrypt(RFM69_ENCRYPTKEY); #endif return true; diff --git a/libraries/MySensors/MyTransportRFM69.h b/libraries/MySensors/core/MyTransportRFM69.h similarity index 83% rename from libraries/MySensors/MyTransportRFM69.h rename to libraries/MySensors/core/MyTransportRFM69.h index ea9eaa6..affbb25 100644 --- a/libraries/MySensors/MyTransportRFM69.h +++ b/libraries/MySensors/core/MyTransportRFM69.h @@ -24,13 +24,13 @@ #include "MyTransport.h" #include #include "drivers/RFM69/RFM69.h" -#include +#include "drivers/SPI/SPI.h" class MyTransportRFM69 : public MyTransport { public: - MyTransportRFM69(uint8_t freqBand=RFM69_FREQUENCY, uint8_t networkId=RFM69_NETWORKID, uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM); + MyTransportRFM69(uint8_t freqBand=MY_RFM69_FREQUENCY, uint8_t networkId=MY_RFM69_NETWORKID, uint8_t slaveSelectPin=MY_RF69_SPI_CS, uint8_t interruptPin=MY_RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=MY_RF69_IRQ_NUM); bool init(); void setAddress(uint8_t address); uint8_t getAddress(); diff --git a/libraries/MySensors/Version.h b/libraries/MySensors/core/Version.h similarity index 100% rename from libraries/MySensors/Version.h rename to libraries/MySensors/core/Version.h diff --git a/libraries/DigitalIO/DigitalIO.h b/libraries/MySensors/drivers/DigitalIO/DigitalIO.h similarity index 100% rename from libraries/DigitalIO/DigitalIO.h rename to libraries/MySensors/drivers/DigitalIO/DigitalIO.h diff --git a/libraries/DigitalIO/DigitalPin.h b/libraries/MySensors/drivers/DigitalIO/DigitalPin.h similarity index 100% rename from libraries/DigitalIO/DigitalPin.h rename to libraries/MySensors/drivers/DigitalIO/DigitalPin.h diff --git a/libraries/DigitalIO/I2cConstants.h b/libraries/MySensors/drivers/DigitalIO/I2cConstants.h similarity index 100% rename from libraries/DigitalIO/I2cConstants.h rename to libraries/MySensors/drivers/DigitalIO/I2cConstants.h diff --git a/libraries/DigitalIO/PinIO.cpp b/libraries/MySensors/drivers/DigitalIO/PinIO.cpp similarity index 100% rename from libraries/DigitalIO/PinIO.cpp rename to libraries/MySensors/drivers/DigitalIO/PinIO.cpp diff --git a/libraries/DigitalIO/PinIO.h b/libraries/MySensors/drivers/DigitalIO/PinIO.h similarity index 100% rename from libraries/DigitalIO/PinIO.h rename to libraries/MySensors/drivers/DigitalIO/PinIO.h diff --git a/libraries/DigitalIO/SoftI2cMaster.cpp b/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp similarity index 100% rename from libraries/DigitalIO/SoftI2cMaster.cpp rename to libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp diff --git a/libraries/DigitalIO/SoftI2cMaster.h b/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h similarity index 100% rename from libraries/DigitalIO/SoftI2cMaster.h rename to libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h diff --git a/libraries/DigitalIO/SoftSPI.h b/libraries/MySensors/drivers/DigitalIO/SoftSPI.h similarity index 100% rename from libraries/DigitalIO/SoftSPI.h rename to libraries/MySensors/drivers/DigitalIO/SoftSPI.h diff --git a/libraries/DigitalIO/attic/ADS7818.h b/libraries/MySensors/drivers/DigitalIO/attic/ADS7818.h similarity index 100% rename from libraries/DigitalIO/attic/ADS7818.h rename to libraries/MySensors/drivers/DigitalIO/attic/ADS7818.h diff --git a/libraries/DigitalIO/attic/MCP320X.h b/libraries/MySensors/drivers/DigitalIO/attic/MCP320X.h similarity index 100% rename from libraries/DigitalIO/attic/MCP320X.h rename to libraries/MySensors/drivers/DigitalIO/attic/MCP320X.h diff --git a/libraries/DigitalIO/attic/MCP355X.h b/libraries/MySensors/drivers/DigitalIO/attic/MCP355X.h similarity index 100% rename from libraries/DigitalIO/attic/MCP355X.h rename to libraries/MySensors/drivers/DigitalIO/attic/MCP355X.h diff --git a/libraries/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino b/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino similarity index 100% rename from libraries/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino rename to libraries/MySensors/drivers/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino diff --git a/libraries/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino b/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino similarity index 100% rename from libraries/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino rename to libraries/MySensors/drivers/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino diff --git a/libraries/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino b/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino similarity index 100% rename from libraries/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino rename to libraries/MySensors/drivers/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino diff --git a/libraries/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino b/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino similarity index 100% rename from libraries/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino rename to libraries/MySensors/drivers/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino diff --git a/libraries/DigitalIO/examples/PinIOBegin/PinIOBegin.ino b/libraries/MySensors/drivers/DigitalIO/examples/PinIOBegin/PinIOBegin.ino similarity index 100% rename from libraries/DigitalIO/examples/PinIOBegin/PinIOBegin.ino rename to libraries/MySensors/drivers/DigitalIO/examples/PinIOBegin/PinIOBegin.ino diff --git a/libraries/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino b/libraries/MySensors/drivers/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino similarity index 100% rename from libraries/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino rename to libraries/MySensors/drivers/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino diff --git a/libraries/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino b/libraries/MySensors/drivers/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino similarity index 100% rename from libraries/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino rename to libraries/MySensors/drivers/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino diff --git a/libraries/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino b/libraries/MySensors/drivers/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino similarity index 100% rename from libraries/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino rename to libraries/MySensors/drivers/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino diff --git a/libraries/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino b/libraries/MySensors/drivers/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino similarity index 100% rename from libraries/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino rename to libraries/MySensors/drivers/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino diff --git a/libraries/DigitalIO/examples/testArduino/testArduino.ino b/libraries/MySensors/drivers/DigitalIO/examples/testArduino/testArduino.ino similarity index 100% rename from libraries/DigitalIO/examples/testArduino/testArduino.ino rename to libraries/MySensors/drivers/DigitalIO/examples/testArduino/testArduino.ino diff --git a/libraries/DigitalIO/examples/testDigitalPin/testDigitalPin.ino b/libraries/MySensors/drivers/DigitalIO/examples/testDigitalPin/testDigitalPin.ino similarity index 100% rename from libraries/DigitalIO/examples/testDigitalPin/testDigitalPin.ino rename to libraries/MySensors/drivers/DigitalIO/examples/testDigitalPin/testDigitalPin.ino diff --git a/libraries/DigitalIO/examples/testFastDigital/testFastDigital.ino b/libraries/MySensors/drivers/DigitalIO/examples/testFastDigital/testFastDigital.ino similarity index 100% rename from libraries/DigitalIO/examples/testFastDigital/testFastDigital.ino rename to libraries/MySensors/drivers/DigitalIO/examples/testFastDigital/testFastDigital.ino diff --git a/libraries/DigitalIO/examples/testPinIO/testPinIO.ino b/libraries/MySensors/drivers/DigitalIO/examples/testPinIO/testPinIO.ino similarity index 100% rename from libraries/DigitalIO/examples/testPinIO/testPinIO.ino rename to libraries/MySensors/drivers/DigitalIO/examples/testPinIO/testPinIO.ino diff --git a/libraries/DigitalIO/examples/testSoftSPI/testSoftSPI.ino b/libraries/MySensors/drivers/DigitalIO/examples/testSoftSPI/testSoftSPI.ino similarity index 100% rename from libraries/DigitalIO/examples/testSoftSPI/testSoftSPI.ino rename to libraries/MySensors/drivers/DigitalIO/examples/testSoftSPI/testSoftSPI.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.cpp b/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.cpp new file mode 100644 index 0000000..d34e8e2 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.cpp @@ -0,0 +1,478 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#include +#include +#include "Dhcp.h" +#include "Arduino.h" +#include "utility/util.h" + +int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) +{ + _dhcpLeaseTime=0; + _dhcpT1=0; + _dhcpT2=0; + _lastCheck=0; + _timeout = timeout; + _responseTimeout = responseTimeout; + + // zero out _dhcpMacAddr + memset(_dhcpMacAddr, 0, 6); + reset_DHCP_lease(); + + memcpy((void*)_dhcpMacAddr, (void*)mac, 6); + _dhcp_state = STATE_DHCP_START; + return request_DHCP_lease(); +} + +void DhcpClass::reset_DHCP_lease(){ + // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp + memset(_dhcpLocalIp, 0, 20); +} + +//return:0 on error, 1 if request is sent and response is received +int DhcpClass::request_DHCP_lease(){ + + uint8_t messageType = 0; + + + + // Pick an initial transaction ID + _dhcpTransactionId = random(1UL, 2000UL); + _dhcpInitialTransactionId = _dhcpTransactionId; + + _dhcpUdpSocket.stop(); + if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) + { + // Couldn't get a socket + return 0; + } + + presend_DHCP(); + + int result = 0; + + unsigned long startTime = millis(); + + while(_dhcp_state != STATE_DHCP_LEASED) + { + if(_dhcp_state == STATE_DHCP_START) + { + _dhcpTransactionId++; + + send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_DISCOVER; + } + else if(_dhcp_state == STATE_DHCP_REREQUEST){ + _dhcpTransactionId++; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + else if(_dhcp_state == STATE_DHCP_DISCOVER) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_OFFER) + { + // We'll use the transaction ID that the offer came with, + // rather than the one we were up to + _dhcpTransactionId = respId; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + } + else if(_dhcp_state == STATE_DHCP_REQUEST) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_ACK) + { + _dhcp_state = STATE_DHCP_LEASED; + result = 1; + //use default lease time if we didn't get it + if(_dhcpLeaseTime == 0){ + _dhcpLeaseTime = DEFAULT_LEASE; + } + //calculate T1 & T2 if we didn't get it + if(_dhcpT1 == 0){ + //T1 should be 50% of _dhcpLeaseTime + _dhcpT1 = _dhcpLeaseTime >> 1; + } + if(_dhcpT2 == 0){ + //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime + _dhcpT2 = _dhcpT1 << 1; + } + _renewInSec = _dhcpT1; + _rebindInSec = _dhcpT2; + } + else if(messageType == DHCP_NAK) + _dhcp_state = STATE_DHCP_START; + } + + if(messageType == 255) + { + messageType = 0; + _dhcp_state = STATE_DHCP_START; + } + + if(result != 1 && ((millis() - startTime) > _timeout)) + break; + } + + // We're done with the socket now + _dhcpUdpSocket.stop(); + _dhcpTransactionId++; + + return result; +} + +void DhcpClass::presend_DHCP() +{ +} + +void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) +{ + uint8_t buffer[32]; + memset(buffer, 0, 32); + IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address + + if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) + { + // FIXME Need to return errors + return; + } + + buffer[0] = DHCP_BOOTREQUEST; // op + buffer[1] = DHCP_HTYPE10MB; // htype + buffer[2] = DHCP_HLENETHERNET; // hlen + buffer[3] = DHCP_HOPS; // hops + + // xid + unsigned long xid = htonl(_dhcpTransactionId); + memcpy(buffer + 4, &(xid), 4); + + // 8, 9 - seconds elapsed + buffer[8] = ((secondsElapsed & 0xff00) >> 8); + buffer[9] = (secondsElapsed & 0x00ff); + + // flags + unsigned short flags = htons(DHCP_FLAGSBROADCAST); + memcpy(buffer + 10, &(flags), 2); + + // ciaddr: already zeroed + // yiaddr: already zeroed + // siaddr: already zeroed + // giaddr: already zeroed + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 28); + + memset(buffer, 0, 32); // clear local buffer + + memcpy(buffer, _dhcpMacAddr, 6); // chaddr + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 16); + + memset(buffer, 0, 32); // clear local buffer + + // leave zeroed out for sname && file + // put in W5100 transmit buffer x 6 (192 bytes) + + for(int i = 0; i < 6; i++) { + _dhcpUdpSocket.write(buffer, 32); + } + + // OPT - Magic Cookie + buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); + buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); + buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); + buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); + + // OPT - message type + buffer[4] = dhcpMessageType; + buffer[5] = 0x01; + buffer[6] = messageType; //DHCP_REQUEST; + + // OPT - client identifier + buffer[7] = dhcpClientIdentifier; + buffer[8] = 0x07; + buffer[9] = 0x01; + memcpy(buffer + 10, _dhcpMacAddr, 6); + + // OPT - host name + buffer[16] = hostName; + buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address + strcpy((char*)&(buffer[18]), HOST_NAME); + + printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); + printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); + printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 30); + + if(messageType == DHCP_REQUEST) + { + buffer[0] = dhcpRequestedIPaddr; + buffer[1] = 0x04; + buffer[2] = _dhcpLocalIp[0]; + buffer[3] = _dhcpLocalIp[1]; + buffer[4] = _dhcpLocalIp[2]; + buffer[5] = _dhcpLocalIp[3]; + + buffer[6] = dhcpServerIdentifier; + buffer[7] = 0x04; + buffer[8] = _dhcpDhcpServerIp[0]; + buffer[9] = _dhcpDhcpServerIp[1]; + buffer[10] = _dhcpDhcpServerIp[2]; + buffer[11] = _dhcpDhcpServerIp[3]; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 12); + } + + buffer[0] = dhcpParamRequest; + buffer[1] = 0x06; + buffer[2] = subnetMask; + buffer[3] = routersOnSubnet; + buffer[4] = dns; + buffer[5] = domainName; + buffer[6] = dhcpT1value; + buffer[7] = dhcpT2value; + buffer[8] = endOption; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 9); + + _dhcpUdpSocket.endPacket(); +} + +uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) +{ + uint8_t type = 0; + uint8_t opt_len = 0; + + unsigned long startTime = millis(); + + while(_dhcpUdpSocket.parsePacket() <= 0) + { + if((millis() - startTime) > responseTimeout) + { + return 255; + } + delay(50); + } + // start reading in the packet + RIP_MSG_FIXED fixedMsg; + _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); + + if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) + { + transactionId = ntohl(fixedMsg.xid); + if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) + { + // Need to read the rest of the packet here regardless + _dhcpUdpSocket.flush(); + return 0; + } + + memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); + + // Skip to the option part + // Doing this a byte at a time so we don't have to put a big buffer + // on the stack (as we don't have lots of memory lying around) + for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) + { + _dhcpUdpSocket.read(); // we don't care about the returned byte + } + + while (_dhcpUdpSocket.available() > 0) + { + switch (_dhcpUdpSocket.read()) + { + case endOption : + break; + + case padOption : + break; + + case dhcpMessageType : + opt_len = _dhcpUdpSocket.read(); + type = _dhcpUdpSocket.read(); + break; + + case subnetMask : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpSubnetMask, 4); + break; + + case routersOnSubnet : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpGatewayIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dns : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpDnsServerIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dhcpServerIdentifier : + opt_len = _dhcpUdpSocket.read(); + if( *((uint32_t*)_dhcpDhcpServerIp) == 0 || + IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() ) + { + _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); + } + else + { + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + } + break; + + case dhcpT1value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); + _dhcpT1 = ntohl(_dhcpT1); + break; + + case dhcpT2value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); + _dhcpT2 = ntohl(_dhcpT2); + break; + + case dhcpIPaddrLeaseTime : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); + _dhcpLeaseTime = ntohl(_dhcpLeaseTime); + _renewInSec = _dhcpLeaseTime; + break; + + default : + opt_len = _dhcpUdpSocket.read(); + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + break; + } + } + } + + // Need to skip to end of the packet regardless here + _dhcpUdpSocket.flush(); + + return type; +} + + +/* + returns: + 0/DHCP_CHECK_NONE: nothing happened + 1/DHCP_CHECK_RENEW_FAIL: renew failed + 2/DHCP_CHECK_RENEW_OK: renew success + 3/DHCP_CHECK_REBIND_FAIL: rebind fail + 4/DHCP_CHECK_REBIND_OK: rebind success +*/ +int DhcpClass::checkLease(){ + //this uses a signed / unsigned trick to deal with millis overflow + unsigned long now = millis(); + signed long snow = (long)now; + int rc=DHCP_CHECK_NONE; + if (_lastCheck != 0){ + signed long factor; + //calc how many ms past the timeout we are + factor = snow - (long)_secTimeout; + //if on or passed the timeout, reduce the counters + if ( factor >= 0 ){ + //next timeout should be now plus 1000 ms minus parts of second in factor + _secTimeout = snow + 1000 - factor % 1000; + //how many seconds late are we, minimum 1 + factor = factor / 1000 +1; + + //reduce the counters by that mouch + //if we can assume that the cycle time (factor) is fairly constant + //and if the remainder is less than cycle time * 2 + //do it early instead of late + if(_renewInSec < factor*2 ) + _renewInSec = 0; + else + _renewInSec -= factor; + + if(_rebindInSec < factor*2 ) + _rebindInSec = 0; + else + _rebindInSec -= factor; + } + + //if we have a lease but should renew, do it + if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ + _dhcp_state = STATE_DHCP_REREQUEST; + rc = 1 + request_DHCP_lease(); + } + + //if we have a lease or is renewing but should bind, do it + if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ + //this should basically restart completely + _dhcp_state = STATE_DHCP_START; + reset_DHCP_lease(); + rc = 3 + request_DHCP_lease(); + } + } + else{ + _secTimeout = snow + 1000; + } + + _lastCheck = now; + return rc; +} + +IPAddress DhcpClass::getLocalIp() +{ + return IPAddress(_dhcpLocalIp); +} + +IPAddress DhcpClass::getSubnetMask() +{ + return IPAddress(_dhcpSubnetMask); +} + +IPAddress DhcpClass::getGatewayIp() +{ + return IPAddress(_dhcpGatewayIp); +} + +IPAddress DhcpClass::getDhcpServerIp() +{ + return IPAddress(_dhcpDhcpServerIp); +} + +IPAddress DhcpClass::getDnsServerIp() +{ + return IPAddress(_dhcpDnsServerIp); +} + +void DhcpClass::printByte(char * buf, uint8_t n ) { + char *str = &buf[1]; + buf[0]='0'; + do { + unsigned long m = n; + n /= 16; + char c = m - 16 * n; + *str-- = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.h b/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.h new file mode 100644 index 0000000..01405d7 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.h @@ -0,0 +1,178 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#ifndef Dhcp_h +#define Dhcp_h + +#include "UIPUdp.h" + +/* DHCP state machine. */ +#define STATE_DHCP_START 0 +#define STATE_DHCP_DISCOVER 1 +#define STATE_DHCP_REQUEST 2 +#define STATE_DHCP_LEASED 3 +#define STATE_DHCP_REREQUEST 4 +#define STATE_DHCP_RELEASE 5 + +#define DHCP_FLAGSBROADCAST 0x8000 + +/* UDP port numbers for DHCP */ +#define DHCP_SERVER_PORT 67 /* from server to client */ +#define DHCP_CLIENT_PORT 68 /* from client to server */ + +/* DHCP message OP code */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_HTYPE10MB 1 +#define DHCP_HTYPE100MB 2 + +#define DHCP_HLENETHERNET 6 +#define DHCP_HOPS 0 +#define DHCP_SECS 0 + +#define MAGIC_COOKIE 0x63825363 +#define MAX_DHCP_OPT 16 + +#define HOST_NAME "ENC28J" +#define DEFAULT_LEASE (900) //default lease time in seconds + +#define DHCP_CHECK_NONE (0) +#define DHCP_CHECK_RENEW_FAIL (1) +#define DHCP_CHECK_RENEW_OK (2) +#define DHCP_CHECK_REBIND_FAIL (3) +#define DHCP_CHECK_REBIND_OK (4) + +enum +{ + padOption = 0, + subnetMask = 1, + timerOffset = 2, + routersOnSubnet = 3, + /* timeServer = 4, + nameServer = 5,*/ + dns = 6, + /*logServer = 7, + cookieServer = 8, + lprServer = 9, + impressServer = 10, + resourceLocationServer = 11,*/ + hostName = 12, + /*bootFileSize = 13, + meritDumpFile = 14,*/ + domainName = 15, + /*swapServer = 16, + rootPath = 17, + extentionsPath = 18, + IPforwarding = 19, + nonLocalSourceRouting = 20, + policyFilter = 21, + maxDgramReasmSize = 22, + defaultIPTTL = 23, + pathMTUagingTimeout = 24, + pathMTUplateauTable = 25, + ifMTU = 26, + allSubnetsLocal = 27, + broadcastAddr = 28, + performMaskDiscovery = 29, + maskSupplier = 30, + performRouterDiscovery = 31, + routerSolicitationAddr = 32, + staticRoute = 33, + trailerEncapsulation = 34, + arpCacheTimeout = 35, + ethernetEncapsulation = 36, + tcpDefaultTTL = 37, + tcpKeepaliveInterval = 38, + tcpKeepaliveGarbage = 39, + nisDomainName = 40, + nisServers = 41, + ntpServers = 42, + vendorSpecificInfo = 43, + netBIOSnameServer = 44, + netBIOSdgramDistServer = 45, + netBIOSnodeType = 46, + netBIOSscope = 47, + xFontServer = 48, + xDisplayManager = 49,*/ + dhcpRequestedIPaddr = 50, + dhcpIPaddrLeaseTime = 51, + /*dhcpOptionOverload = 52,*/ + dhcpMessageType = 53, + dhcpServerIdentifier = 54, + dhcpParamRequest = 55, + /*dhcpMsg = 56, + dhcpMaxMsgSize = 57,*/ + dhcpT1value = 58, + dhcpT2value = 59, + /*dhcpClassIdentifier = 60,*/ + dhcpClientIdentifier = 61, + endOption = 255 +}; + +typedef struct _RIP_MSG_FIXED +{ + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint8_t ciaddr[4]; + uint8_t yiaddr[4]; + uint8_t siaddr[4]; + uint8_t giaddr[4]; + uint8_t chaddr[6]; +}RIP_MSG_FIXED; + +class DhcpClass { +private: + uint32_t _dhcpInitialTransactionId; + uint32_t _dhcpTransactionId; + uint8_t _dhcpMacAddr[6]; + uint8_t _dhcpLocalIp[4]; + uint8_t _dhcpSubnetMask[4]; + uint8_t _dhcpGatewayIp[4]; + uint8_t _dhcpDhcpServerIp[4]; + uint8_t _dhcpDnsServerIp[4]; + uint32_t _dhcpLeaseTime; + uint32_t _dhcpT1, _dhcpT2; + signed long _renewInSec; + signed long _rebindInSec; + signed long _lastCheck; + unsigned long _timeout; + unsigned long _responseTimeout; + unsigned long _secTimeout; + uint8_t _dhcp_state; + UIPUDP _dhcpUdpSocket; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + void presend_DHCP(); + void send_DHCP_MESSAGE(uint8_t, uint16_t); + void printByte(char *, uint8_t); + + uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); +public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dns.cpp b/libraries/MySensors/drivers/Ethernet_UIP/Dns.cpp new file mode 100644 index 0000000..2b97fb7 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/Dns.cpp @@ -0,0 +1,422 @@ +// Arduino DNS client for Enc28J60-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#include "Udp.h" +#include "utility/util.h" + +#include "Dns.h" +#include +//#include +#include "Arduino.h" + + +#define SOCKET_NONE 255 +// Various flags and header field values for a DNS message +#define UDP_HEADER_SIZE 8 +#define DNS_HEADER_SIZE 12 +#define TTL_SIZE 4 +#define QUERY_FLAG (0) +#define RESPONSE_FLAG (1<<15) +#define QUERY_RESPONSE_MASK (1<<15) +#define OPCODE_STANDARD_QUERY (0) +#define OPCODE_INVERSE_QUERY (1<<11) +#define OPCODE_STATUS_REQUEST (2<<11) +#define OPCODE_MASK (15<<11) +#define AUTHORITATIVE_FLAG (1<<10) +#define TRUNCATION_FLAG (1<<9) +#define RECURSION_DESIRED_FLAG (1<<8) +#define RECURSION_AVAILABLE_FLAG (1<<7) +#define RESP_NO_ERROR (0) +#define RESP_FORMAT_ERROR (1) +#define RESP_SERVER_FAILURE (2) +#define RESP_NAME_ERROR (3) +#define RESP_NOT_IMPLEMENTED (4) +#define RESP_REFUSED (5) +#define RESP_MASK (15) +#define TYPE_A (0x0001) +#define CLASS_IN (0x0001) +#define LABEL_COMPRESSION_MASK (0xC0) +// Port number that DNS servers listen on +#define DNS_PORT 53 + +// Possible return codes from ProcessResponse +#define SUCCESS 1 +#define TIMED_OUT -1 +#define INVALID_SERVER -2 +#define TRUNCATED -3 +#define INVALID_RESPONSE -4 + +void DNSClient::begin(const IPAddress& aDNSServer) +{ + iDNSServer = aDNSServer; + iRequestId = 0; +} + + +int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult) +{ + // See if we've been given a valid IP address + const char* p =aIPAddrString; + while (*p && + ( (*p == '.') || (*p >= '0') || (*p <= '9') )) + { + p++; + } + + if (*p == '\0') + { + // It's looking promising, we haven't found any invalid characters + p = aIPAddrString; + int segment =0; + int segmentValue =0; + while (*p && (segment < 4)) + { + if (*p == '.') + { + // We've reached the end of a segment + if (segmentValue > 255) + { + // You can't have IP address segments that don't fit in a byte + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + segment++; + segmentValue = 0; + } + } + else + { + // Next digit + segmentValue = (segmentValue*10)+(*p - '0'); + } + p++; + } + // We've reached the end of address, but there'll still be the last + // segment to deal with + if ((segmentValue > 255) || (segment > 3)) + { + // You can't have IP address segments that don't fit in a byte, + // or more than four segments + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + return 1; + } + } + else + { + return 0; + } +} + +int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) +{ + int ret =0; + + // See if it's a numeric IP address + if (inet_aton(aHostname, aResult)) + { + // It is, our work here is done + return 1; + } + + // Check we've got a valid DNS server to use + if (iDNSServer == INADDR_NONE) + { + return INVALID_SERVER; + } + + // Find a socket to use + if (iUdp.begin(1024+(millis() & 0xF)) == 1) + { + // Try up to three times + int retries = 0; +// while ((retries < 3) && (ret <= 0)) + { + // Send DNS request + ret = iUdp.beginPacket(iDNSServer, DNS_PORT); + if (ret != 0) + { + // Now output the request data + ret = BuildRequest(aHostname); + if (ret != 0) + { + // And finally send the request + ret = iUdp.endPacket(); + if (ret != 0) + { + // Now wait for a response + int wait_retries = 0; + ret = TIMED_OUT; + while ((wait_retries < 3) && (ret == TIMED_OUT)) + { + ret = ProcessResponse(5000, aResult); + wait_retries++; + } + } + } + } + retries++; + } + + // We're done with the socket now + iUdp.stop(); + } + + return ret; +} + +uint16_t DNSClient::BuildRequest(const char* aName) +{ + // Build header + // 1 1 1 1 1 1 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ID | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | QDCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ANCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | NSCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ARCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // As we only support one request at a time at present, we can simplify + // some of this header + iRequestId = millis(); // generate a random ID + uint16_t twoByteBuffer; + + // FIXME We should also check that there's enough space available to write to, rather + // FIXME than assume there's enough space (as the code does at present) + iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId)); + + twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(1); // One question record + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = 0; // Zero answer records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // and zero additional records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + // Build question + const char* start =aName; + const char* end =start; + uint8_t len; + // Run through the name being requested + while (*end) + { + // Find out how long this section of the name is + end = start; + while (*end && (*end != '.') ) + { + end++; + } + + if (end-start > 0) + { + // Write out the size of this section + len = end-start; + iUdp.write(&len, sizeof(len)); + // And then write out the section + iUdp.write((uint8_t*)start, end-start); + } + start = end+1; + } + + // We've got to the end of the question name, so + // terminate it with a zero-length section + len = 0; + iUdp.write(&len, sizeof(len)); + // Finally the type and class of question + twoByteBuffer = htons(TYPE_A); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(CLASS_IN); // Internet class of question + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // Success! Everything buffered okay + return 1; +} + + +uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) +{ + uint32_t startTime = millis(); + + // Wait for a response packet + while(iUdp.parsePacket() <= 0) + { + if((millis() - startTime) > aTimeout) + return TIMED_OUT; + delay(50); + } + + // We've had a reply! + // Read the UDP header + uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header + // Check that it's a response from the right server and the right port + if ( (iDNSServer != iUdp.remoteIP()) || + (iUdp.remotePort() != DNS_PORT) ) + { + // It's not from who we expected + return INVALID_SERVER; + } + + // Read through the rest of the response + if (iUdp.available() < DNS_HEADER_SIZE) + { + return TRUNCATED; + } + iUdp.read(header, DNS_HEADER_SIZE); + + uint16_t header_flags = htons(*((uint16_t*)&header[2])); + // Check that it's a response to this request + if ( ( iRequestId != (*((uint16_t*)&header[0])) ) || + ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) ) + { + // Mark the entire packet as read + iUdp.flush(); + return INVALID_RESPONSE; + } + // Check for any errors in the response (or in our request) + // although we don't do anything to get round these + if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) ) + { + // Mark the entire packet as read + iUdp.flush(); + return -5; //INVALID_RESPONSE; + } + + // And make sure we've got (at least) one answer + uint16_t answerCount = htons(*((uint16_t*)&header[6])); + if (answerCount == 0 ) + { + // Mark the entire packet as read + iUdp.flush(); + return -6; //INVALID_RESPONSE; + } + + // Skip over any questions + for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++) + { + // Skip over the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if (len > 0) + { + // Don't need to actually read the data out for the string, just + // advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } while (len != 0); + + // Now jump over the type and class + for (int i =0; i < 4; i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + + // Now we're up to the bit we're interested in, the answer + // There might be more than one answer (although we'll just use the first + // type A answer) and some authority and additional resource records but + // we're going to ignore all of them. + + for (uint16_t i =0; i < answerCount; i++) + { + // Skip the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if ((len & LABEL_COMPRESSION_MASK) == 0) + { + // It's just a normal label + if (len > 0) + { + // And it's got a length + // Don't need to actually read the data out for the string, + // just advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + else + { + // This is a pointer to a somewhere else in the message for the + // rest of the name. We don't care about the name, and RFC1035 + // says that a name is either a sequence of labels ended with a + // 0 length octet or a pointer or a sequence of labels ending in + // a pointer. Either way, when we get here we're at the end of + // the name + // Skip over the pointer + iUdp.read(); // we don't care about the returned byte + // And set len so that we drop out of the name loop + len = 0; + } + } while (len != 0); + + // Check the type and class + uint16_t answerType; + uint16_t answerClass; + iUdp.read((uint8_t*)&answerType, sizeof(answerType)); + iUdp.read((uint8_t*)&answerClass, sizeof(answerClass)); + + // Ignore the Time-To-Live as we don't do any caching + for (int i =0; i < TTL_SIZE; i++) + { + iUdp.read(); // we don't care about the returned byte + } + + // And read out the length of this answer + // Don't need header_flags anymore, so we can reuse it here + iUdp.read((uint8_t*)&header_flags, sizeof(header_flags)); + + if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) ) + { + if (htons(header_flags) != 4) + { + // It's a weird size + // Mark the entire packet as read + iUdp.flush(); + return -9;//INVALID_RESPONSE; + } + iUdp.read(aAddress.raw_address(), 4); + return SUCCESS; + } + else + { + // This isn't an answer type we're after, move onto the next one + for (uint16_t i =0; i < htons(header_flags); i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + + // Mark the entire packet as read + iUdp.flush(); + + // If we get here then we haven't found an answer + return -10;//INVALID_RESPONSE; +} + diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dns.h b/libraries/MySensors/drivers/Ethernet_UIP/Dns.h new file mode 100644 index 0000000..4913ca8 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/Dns.h @@ -0,0 +1,41 @@ +// Arduino DNS client for Enc28J60-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#ifndef DNSClient_h +#define DNSClient_h + +#include + +class DNSClient +{ +public: + // ctor + void begin(const IPAddress& aDNSServer); + + /** Convert a numeric IP address string into a four-byte IP address. + @param aIPAddrString IP address to convert + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int inet_aton(const char *aIPAddrString, IPAddress& aResult); + + /** Resolve the given hostname to an IP address. + @param aHostname Name to be resolved + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int getHostByName(const char* aHostname, IPAddress& aResult); + +protected: + uint16_t BuildRequest(const char* aName); + uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); + + IPAddress iDNSServer; + uint16_t iRequestId; + UIPUDP iUdp; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/README b/libraries/MySensors/drivers/Ethernet_UIP/README new file mode 100644 index 0000000..321b334 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/README @@ -0,0 +1,227 @@ +This is UIPEthernet version 1.09 + +An plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. +Just include 'UIPEthernet.h' instead of 'Ethernet.h' and use all your code written for the stock Arduino Ethernet lib! + +UIPEthernet is written as a wrapper around the mature uIP Stack by Adam Dunkels, which provides the low-level implementation for all supported protocols. To overcome the memory-constrains (a 'regular' uIP-application does all processing in RAM) the ENC28J60 internal memory is used for all stream buffers (in and out). Only 400-600 Bytes of Arduinos RAM are used (depending on the number of concurrently open connections). As of Flash-memory a ATmega368-based Arduino is the minimum requirenment. + +This library is written by Norbert Truchsess + +uIP was written by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science. + +This library was inspired by the SerialIP implementation by Adam Nielsen , actually I took this code as a starting point, but in the latest versions there are very few lines left. + +Installation +------------ + +To install the libraries, you need to place them into your "libraries" folder. You can find it within your Arduino IDE distribution within the "hardware" folder. + + C:\> cd [path to Arduino distribution]\libraries + C:\> git clone https://github.com/ntruchsess/arduino_uip UIPEthernet + +Be sure to restart the IDE if it was running. + +On a Mac, you will want to create a folder named "libraries" in in the "Documents" -> "Arduino" folder within your home directory. Clone the project there (and restart the IDE, if it was running during this process). + + $ cd ~/Documents/Arduino/libraries + $ git clone https://github.com/ntruchsess/arduino_uip UIPEthernet + +Or you download the zipped version of the library from https://github.com/ntruchsess/arduino_uip/releases, and copy the contained directory UIPEthernet to [path to Arduino distribution]\libraries\UIPEthernet. + +If you are running Arduino-IDE 1.5.x use release-version 1.59 or checkout branch 'Arduino_1.5.x' + +Additional information can be found on the Arduino website: http://www.arduino.cc/en/Hacking/Libraries + +Documentation +------------- + +For more information visit: + + - UIPEthernet Repository on github: + https://github.com/ntruchsess/arduino_uip + + - Arduino Ethernet library description + http://arduino.cc/en/Reference/Ethernet + (Arduino_uip uses the same API as that, just include "UIPEthernet.h", "UIPClient.h", "UIPServer.h" and "UIPUDP.h" instead of the stock "Ethernet.h", "EthernetClient.h", "EthernetServer.h " and "EthernetUDP.h") + + - uIP API reference: + http://www.sics.se/~adam/uip/uip-1.0-refman/ + + - Arduino forums + http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl + + - uIP homepage: + http://www.sics.se/~adam/uip/index.php/Main_Page + +Licenses +------------- + +UIPEthernet.h +UIPEthernet.cpp +UIPServer.h +UIPServer.cpp +UIPClient.h +UIPClient.cpp +UIPUdp.h +UIPUdp.cpp +utility/mempool.h +utility/mempool.cpp + +Copyright (c) 2013 Norbert Truchsess +All rights reserved. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +-------------- + +utility/enc28j60.h + +Author : Pascal Stang (c)2005 +Modified by Norbert Truchsess +Copyright: GPL V2 + +-------------- + +utility/Enc28J60Network.h +utility/Enc28J60Network.cpp + +Copyright (c) 2013 Norbert Truchsess +All rights reserved. + +inspired and based on enc28j60.c file from the AVRlib library by Pascal Stang. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program 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 General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +-------------- + +utility/uip.c +utility/uip_arp.h +utility/uip_arp.c +utility/uip_arch.h +utility/uip.h +utility/uipopt.h + +Copyright (c) 2001-2003, Adam Dunkels , . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +-------------- + +uip-conf.h +utility/uip-neighbor.h +utility/uip-neighbor.c +utility/uip_timer.h +utility/uip_timer.c +utility/uip_clock.h + +Author Adam Dunkels Adam Dunkels , +Copyright (c) 2004,2006, Swedish Institute of Computer Science. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the Institute nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +-------------- + +Dhcp.h +Dhcp.cpp + +DHCP Library v0.3 - April 25, 2009 +Author: Jordan Terrell - blog.jordanterrell.com +- as included in Arduinos stock Ethernet-library, no special licence mentioned here + +-------------- + +Dns.h +Dns.cpp + +(c) Copyright 2009-2010 MCQN Ltd. +Released under Apache License, version 2.0 + +-------------- + +clock-arch.h +clock-arch.c + +Copyright (c) 2010 Adam Nielsen +All rights 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 diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.cpp b/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.cpp new file mode 100644 index 0000000..d199cfe --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.cpp @@ -0,0 +1,583 @@ +/* + UIPClient.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +extern "C" +{ +#import "utility/uip-conf.h" +#import "utility/uip.h" +#import "utility/uip_arp.h" +#import "string.h" +} +#include "UIPEthernet.h" +#include "UIPClient.h" +#include "Dns.h" + +#ifdef UIPETHERNET_DEBUG_CLIENT +#include "HardwareSerial.h" +#endif + +#define UIP_TCP_PHYH_LEN UIP_LLH_LEN+UIP_IPTCPH_LEN + +uip_userdata_t UIPClient::all_data[UIP_CONNS]; + +UIPClient::UIPClient() : + data(NULL) +{ +} + +UIPClient::UIPClient(uip_userdata_t* conn_data) : + data(conn_data) +{ +} + +int +UIPClient::connect(IPAddress ip, uint16_t port) +{ + stop(); + uip_ipaddr_t ipaddr; + uip_ip_addr(ipaddr, ip); + struct uip_conn* conn = uip_connect(&ipaddr, htons(port)); + if (conn) + { +#if UIP_CONNECT_TIMEOUT > 0 + int32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT; +#endif + while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) + { + UIPEthernetClass::tick(); + if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) + { + data = (uip_userdata_t*) conn->appstate; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("connected, state: ")); + Serial.print(data->state); + Serial.print(F(", first packet in: ")); + Serial.println(data->packets_in[0]); +#endif + return 1; + } +#if UIP_CONNECT_TIMEOUT > 0 + if (((int32_t)(millis() - timeout)) > 0) + { + conn->tcpstateflags = UIP_CLOSED; + break; + } +#endif + } + } + return 0; +} + +int +UIPClient::connect(const char *host, uint16_t port) +{ + // Look up the host first + int ret = 0; +#if UIP_UDP + DNSClient dns; + IPAddress remote_addr; + + dns.begin(UIPEthernetClass::_dnsServerAddress); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return connect(remote_addr, port); + } +#endif + return ret; +} + +void +UIPClient::stop() +{ + if (data && data->state) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("before stop(), with data")); + _dumpAllData(); +#endif + _flushBlocks(&data->packets_in[0]); + if (data->state & UIP_CLIENT_REMOTECLOSED) + { + data->state = 0; + } + else + { + data->state |= UIP_CLIENT_CLOSE; + } +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after stop()")); + _dumpAllData(); +#endif + } +#ifdef UIPETHERNET_DEBUG_CLIENT + else + { + Serial.println(F("stop(), data: NULL")); + } +#endif + data = NULL; + UIPEthernetClass::tick(); +} + +uint8_t +UIPClient::connected() +{ + return (data && (data->packets_in[0] != NOBLOCK || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0; +} + +bool +UIPClient::operator==(const UIPClient& rhs) +{ + return data && rhs.data && (data == rhs.data); +} + +UIPClient::operator bool() +{ + UIPEthernetClass::tick(); + return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK); +} + +size_t +UIPClient::write(uint8_t c) +{ + return _write(data, &c, 1); +} + +size_t +UIPClient::write(const uint8_t *buf, size_t size) +{ + return _write(data, buf, size); +} + +size_t +UIPClient::_write(uip_userdata_t* u, const uint8_t *buf, size_t size) +{ + int remain = size; + uint16_t written; +#if UIP_ATTEMPTS_ON_WRITE > 0 + uint16_t attempts = UIP_ATTEMPTS_ON_WRITE; +#endif + repeat: + UIPEthernetClass::tick(); + if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) + { + uint8_t p = _currentBlock(&u->packets_out[0]); + if (u->packets_out[p] == NOBLOCK) + { +newpacket: + u->packets_out[p] = Enc28J60Network::allocBlock(UIP_SOCKET_DATALEN); + if (u->packets_out[p] == NOBLOCK) + { +#if UIP_ATTEMPTS_ON_WRITE > 0 + if ((--attempts)>0) +#endif +#if UIP_ATTEMPTS_ON_WRITE != 0 + goto repeat; +#endif + goto ready; + } + u->out_pos = 0; + } +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient.write: writePacket(")); + Serial.print(u->packets_out[p]); + Serial.print(F(") pos: ")); + Serial.print(u->out_pos); + Serial.print(F(", buf[")); + Serial.print(size-remain); + Serial.print(F("-")); + Serial.print(remain); + Serial.print(F("]: '")); + Serial.write((uint8_t*)buf+size-remain,remain); + Serial.println(F("'")); +#endif + written = Enc28J60Network::writePacket(u->packets_out[p],u->out_pos,(uint8_t*)buf+size-remain,remain); + remain -= written; + u->out_pos+=written; + if (remain > 0) + { + if (p == UIP_SOCKET_NUMPACKETS-1) + { +#if UIP_ATTEMPTS_ON_WRITE > 0 + if ((--attempts)>0) +#endif +#if UIP_ATTEMPTS_ON_WRITE != 0 + goto repeat; +#endif + goto ready; + } + p++; + goto newpacket; + } +ready: +#if UIP_CLIENT_TIMER >= 0 + u->timer = millis()+UIP_CLIENT_TIMER; +#endif + return size-remain; + } + return -1; +} + +int +UIPClient::available() +{ + if (*this) + return _available(data); + return 0; +} + +int +UIPClient::_available(uip_userdata_t *u) +{ + int len = 0; + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + len += Enc28J60Network::blockSize(u->packets_in[i]); + } + return len; +} + +int +UIPClient::read(uint8_t *buf, size_t size) +{ + if (*this) + { + uint16_t remain = size; + if (data->packets_in[0] == NOBLOCK) + return 0; + uint16_t read; + do + { + read = Enc28J60Network::readPacket(data->packets_in[0],0,buf+size-remain,remain); + if (read == Enc28J60Network::blockSize(data->packets_in[0])) + { + remain -= read; + _eatBlock(&data->packets_in[0]); + if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) + data->state |= UIP_CLIENT_RESTART; + if (data->packets_in[0] == NOBLOCK) + { + if (data->state & UIP_CLIENT_REMOTECLOSED) + { + data->state = 0; + data = NULL; + } + return size-remain; + } + } + else + { + Enc28J60Network::resizeBlock(data->packets_in[0],read); + break; + } + } + while(remain > 0); + return size; + } + return -1; +} + +int +UIPClient::read() +{ + uint8_t c; + if (read(&c,1) < 0) + return -1; + return c; +} + +int +UIPClient::peek() +{ + if (*this) + { + if (data->packets_in[0] != NOBLOCK) + { + uint8_t c; + Enc28J60Network::readPacket(data->packets_in[0],0,&c,1); + return c; + } + } + return -1; +} + +void +UIPClient::flush() +{ + if (*this) + { + _flushBlocks(&data->packets_in[0]); + } +} + +void +uipclient_appcall(void) +{ + uint16_t send_len = 0; + uip_userdata_t *u = (uip_userdata_t*)uip_conn->appstate; + if (!u && uip_connected()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient uip_connected")); + UIPClient::_dumpAllData(); +#endif + u = (uip_userdata_t*) UIPClient::_allocateData(); + if (u) + { + uip_conn->appstate = u; +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient allocated state: ")); + Serial.println(u->state,BIN); +#endif + } +#ifdef UIPETHERNET_DEBUG_CLIENT + else + Serial.println(F("UIPClient allocation failed")); +#endif + } + if (u) + { + if (uip_newdata()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.print(F("UIPClient uip_newdata, uip_len:")); + Serial.println(uip_len); +#endif + if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) + { + for (uint8_t i=0; i < UIP_SOCKET_NUMPACKETS; i++) + { + if (u->packets_in[i] == NOBLOCK) + { + u->packets_in[i] = Enc28J60Network::allocBlock(uip_len); + if (u->packets_in[i] != NOBLOCK) + { + Enc28J60Network::copyPacket(u->packets_in[i],0,UIPEthernetClass::in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len); + if (i == UIP_SOCKET_NUMPACKETS-1) + uip_stop(); + goto finish_newdata; + } + } + } + UIPEthernetClass::packetstate &= ~UIPETHERNET_FREEPACKET; + uip_stop(); + } + } +finish_newdata: + if (u->state & UIP_CLIENT_RESTART) + { + u->state &= ~UIP_CLIENT_RESTART; + uip_restart(); + } + // If the connection has been closed, save received but unread data. + if (uip_closed() || uip_timedout()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient uip_closed")); + UIPClient::_dumpAllData(); +#endif + // drop outgoing packets not sent yet: + UIPClient::_flushBlocks(&u->packets_out[0]); + if (u->packets_in[0] != NOBLOCK) + { + ((uip_userdata_closed_t *)u)->lport = uip_conn->lport; + u->state |= UIP_CLIENT_REMOTECLOSED; + } + else + u->state = 0; + // disassociate appdata. +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("after UIPClient uip_closed")); + UIPClient::_dumpAllData(); +#endif + uip_conn->appstate = NULL; + goto finish; + } + if (uip_acked()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient uip_acked")); +#endif + UIPClient::_eatBlock(&u->packets_out[0]); + } + if (uip_poll() || uip_rexmit()) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + //Serial.println(F("UIPClient uip_poll")); +#endif + if (u->packets_out[0] != NOBLOCK) + { + if (u->packets_out[1] == NOBLOCK) + { + send_len = u->out_pos; + if (send_len > 0) + { + Enc28J60Network::resizeBlock(u->packets_out[0],0,send_len); + } + } + else + send_len = Enc28J60Network::blockSize(u->packets_out[0]); + if (send_len > 0) + { + UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf; + UIPEthernetClass::uip_packet = Enc28J60Network::allocBlock(UIPEthernetClass::uip_hdrlen+send_len); + if (UIPEthernetClass::uip_packet != NOBLOCK) + { + Enc28J60Network::copyPacket(UIPEthernetClass::uip_packet,UIPEthernetClass::uip_hdrlen,u->packets_out[0],0,send_len); + UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; + } + } + goto finish; + } + } + // don't close connection unless all outgoing packets are sent + if (u->state & UIP_CLIENT_CLOSE) + { +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("UIPClient state UIP_CLIENT_CLOSE")); + UIPClient::_dumpAllData(); +#endif + if (u->packets_out[0] == NOBLOCK) + { + u->state = 0; + uip_conn->appstate = NULL; + uip_close(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("no blocks out -> free userdata")); + UIPClient::_dumpAllData(); +#endif + } + else + { + uip_stop(); +#ifdef UIPETHERNET_DEBUG_CLIENT + Serial.println(F("blocks outstanding transfer -> uip_stop()")); +#endif + } + } + } + finish: + uip_send(uip_appdata,send_len); + uip_len = send_len; +} + +uip_userdata_t * +UIPClient::_allocateData() +{ + for ( uint8_t sock = 0; sock < UIP_CONNS; sock++ ) + { + uip_userdata_t* data = &UIPClient::all_data[sock]; + if (!data->state) + { + data->state = sock | UIP_CLIENT_CONNECTED; + memset(&data->packets_in[0],0,sizeof(uip_userdata_t)-sizeof(data->state)); + return data; + } + } + return NULL; +} + +uint8_t +UIPClient::_currentBlock(memhandle* block) +{ + for (uint8_t i = 1; i < UIP_SOCKET_NUMPACKETS; i++) + { + if (block[i] == NOBLOCK) + return i-1; + } + return UIP_SOCKET_NUMPACKETS-1; +} + +void +UIPClient::_eatBlock(memhandle* block) +{ +#ifdef UIPETHERNET_DEBUG_CLIENT + memhandle* start = block; + Serial.print(F("eatblock(")); + Serial.print(*block); + Serial.print(F("): ")); + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + Serial.print(start[i]); + Serial.print(F(" ")); + } + Serial.print(F("-> ")); +#endif + Enc28J60Network::freeBlock(block[0]); + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS-1; i++) + { + block[i] = block[i+1]; + } + block[UIP_SOCKET_NUMPACKETS-1] = NOBLOCK; +#ifdef UIPETHERNET_DEBUG_CLIENT + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + Serial.print(start[i]); + Serial.print(F(" ")); + } + Serial.println(); +#endif +} + +void +UIPClient::_flushBlocks(memhandle* block) +{ + for (uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) + { + Enc28J60Network::freeBlock(block[i]); + block[i] = NOBLOCK; + } +} + +#ifdef UIPETHERNET_DEBUG_CLIENT +void +UIPClient::_dumpAllData() { + for (uint8_t i=0; i < UIP_CONNS; i++) + { + Serial.print(F("UIPClient::all_data[")); + Serial.print(i); + Serial.print(F("], state:")); + Serial.println(all_data[i].state, BIN); + Serial.print(F("packets_in: ")); + for (uint8_t j=0; j < UIP_SOCKET_NUMPACKETS; j++) + { + Serial.print(all_data[i].packets_in[j]); + Serial.print(F(" ")); + } + Serial.println(); + if (all_data[i].state & UIP_CLIENT_REMOTECLOSED) + { + Serial.print(F("state remote closed, local port: ")); + Serial.println(htons(((uip_userdata_closed_t *)(&all_data[i]))->lport)); + } + else + { + Serial.print(F("packets_out: ")); + for (uint8_t j=0; j < UIP_SOCKET_NUMPACKETS; j++) + { + Serial.print(all_data[i].packets_out[j]); + Serial.print(F(" ")); + } + Serial.println(); + Serial.print(F("out_pos: ")); + Serial.println(all_data[i].out_pos); + } + } +} +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.h b/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.h new file mode 100644 index 0000000..6c0c006 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.h @@ -0,0 +1,112 @@ +/* + UIPClient.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef UIPCLIENT_H +#define UIPCLIENT_H + +#include "ethernet_comp.h" +#include "Print.h" +#import "Client.h" +#import "utility/mempool.h" + +extern "C" { + #import "utility/uip.h" +} + +#define UIP_SOCKET_DATALEN UIP_TCP_MSS +//#define UIP_SOCKET_NUMPACKETS UIP_RECEIVE_WINDOW/UIP_TCP_MSS+1 +#ifndef UIP_SOCKET_NUMPACKETS +#define UIP_SOCKET_NUMPACKETS 5 +#endif + +#define UIP_CLIENT_CONNECTED 0x10 +#define UIP_CLIENT_CLOSE 0x20 +#define UIP_CLIENT_REMOTECLOSED 0x40 +#define UIP_CLIENT_RESTART 0x80 +#define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED | UIP_CLIENT_RESTART) +#define UIP_CLIENT_SOCKETS ~UIP_CLIENT_STATEFLAGS + +typedef uint8_t uip_socket_ptr; + +typedef struct { + uint8_t state; + memhandle packets_in[UIP_SOCKET_NUMPACKETS]; + uint16_t lport; /**< The local TCP port, in network byte order. */ +} uip_userdata_closed_t; + +typedef struct { + uint8_t state; + memhandle packets_in[UIP_SOCKET_NUMPACKETS]; + memhandle packets_out[UIP_SOCKET_NUMPACKETS]; + memaddress out_pos; +#if UIP_CLIENT_TIMER >= 0 + unsigned long timer; +#endif +} uip_userdata_t; + +class UIPClient : public Client { + +public: + UIPClient(); + int connect(IPAddress ip, uint16_t port); + int connect(const char *host, uint16_t port); + int read(uint8_t *buf, size_t size); + void stop(); + uint8_t connected(); + operator bool(); + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; + + size_t write(uint8_t); + size_t write(const uint8_t *buf, size_t size); + int available(); + int read(); + int peek(); + void flush(); + + using Print::write; + +private: + UIPClient(struct uip_conn *_conn); + UIPClient(uip_userdata_t* conn_data); + + uip_userdata_t* data; + + static uip_userdata_t all_data[UIP_CONNS]; + static uip_userdata_t* _allocateData(); + + static size_t _write(uip_userdata_t *,const uint8_t *buf, size_t size); + static int _available(uip_userdata_t *); + + static uint8_t _currentBlock(memhandle* blocks); + static void _eatBlock(memhandle* blocks); + static void _flushBlocks(memhandle* blocks); + +#ifdef UIPETHERNET_DEBUG_CLIENT + static void _dumpAllData(); +#endif + + friend class UIPEthernetClass; + friend class UIPServer; + + friend void uipclient_appcall(void); + +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.cpp b/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.cpp new file mode 100644 index 0000000..91ec70a --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.cpp @@ -0,0 +1,485 @@ +/* + UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include +#include "UIPEthernet.h" +#include "utility/Enc28J60Network.h" + +#if(defined UIPETHERNET_DEBUG || defined UIPETHERNET_DEBUG_CHKSUM) +#include "HardwareSerial.h" +#endif + +#include "UIPUdp.h" + +extern "C" +{ +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +#include "utility/uip_timer.h" +} + +#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0]) + +memhandle UIPEthernetClass::in_packet(NOBLOCK); +memhandle UIPEthernetClass::uip_packet(NOBLOCK); +uint8_t UIPEthernetClass::uip_hdrlen(0); +uint8_t UIPEthernetClass::packetstate(0); + +IPAddress UIPEthernetClass::_dnsServerAddress; +DhcpClass* UIPEthernetClass::_dhcp(NULL); + +unsigned long UIPEthernetClass::periodic_timer; + +// Because uIP isn't encapsulated within a class we have to use global +// variables, so we can only have one TCP/IP stack per program. + +UIPEthernetClass::UIPEthernetClass() +{ +} + +#if UIP_UDP +int +UIPEthernetClass::begin(const uint8_t* mac) +{ + static DhcpClass s_dhcp; + _dhcp = &s_dhcp; + + // Initialise the basic info + init(mac); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP((uint8_t*)mac); + if(ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); + } + return ret; +} +#endif + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) +{ + IPAddress dns = ip; + dns[3] = 1; + begin(mac, ip, dns); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) +{ + IPAddress gateway = ip; + gateway[3] = 1; + begin(mac, ip, dns, gateway); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) +{ + IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) +{ + init(mac); + configure(ip,dns,gateway,subnet); +} + +int UIPEthernetClass::maintain(){ + tick(); + int rc = DHCP_CHECK_NONE; +#if UIP_UDP + if(_dhcp != NULL){ + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + switch ( rc ){ + case DHCP_CHECK_NONE: + //nothing done + break; + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); + break; + default: + //this is actually a error, it will retry though + break; + } + } + return rc; +#endif +} + +IPAddress UIPEthernetClass::localIP() +{ + IPAddress ret; + uip_ipaddr_t a; + uip_gethostaddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::subnetMask() +{ + IPAddress ret; + uip_ipaddr_t a; + uip_getnetmask(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::gatewayIP() +{ + IPAddress ret; + uip_ipaddr_t a; + uip_getdraddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::dnsServerIP() +{ + return _dnsServerAddress; +} + +void +UIPEthernetClass::tick() +{ + if (in_packet == NOBLOCK) + { + in_packet = Enc28J60Network::receivePacket(); +#ifdef UIPETHERNET_DEBUG + if (in_packet != NOBLOCK) + { + Serial.print(F("--------------\nreceivePacket: ")); + Serial.println(in_packet); + } +#endif + } + if (in_packet != NOBLOCK) + { + packetstate = UIPETHERNET_FREEPACKET; + uip_len = Enc28J60Network::blockSize(in_packet); + if (uip_len > 0) + { + Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE); + if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) + { + uip_packet = in_packet; //required for upper_layer_checksum of in_packet! +#ifdef UIPETHERNET_DEBUG + Serial.print(F("readPacket type IP, uip_len: ")); + Serial.println(uip_len); +#endif + uip_arp_ipin(); + uip_input(); + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } + else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP)) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("readPacket type ARP, uip_len: ")); + Serial.println(uip_len); +#endif + uip_arp_arpin(); + if (uip_len > 0) + { + network_send(); + } + } + } + if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("freeing packet: ")); + Serial.println(in_packet); +#endif + Enc28J60Network::freePacket(); + in_packet = NOBLOCK; + } + } + + unsigned long now = millis(); + +#if UIP_CLIENT_TIMER >= 0 + boolean periodic = (long)( now - periodic_timer ) >= 0; + for (int i = 0; i < UIP_CONNS; i++) + { +#else + if ((long)( now - periodic_timer ) >= 0) + { + periodic_timer = now + UIP_PERIODIC_TIMER; + + for (int i = 0; i < UIP_CONNS; i++) + { +#endif + uip_conn = &uip_conns[i]; +#if UIP_CLIENT_TIMER >= 0 + if (periodic) + { +#endif + uip_process(UIP_TIMER); +#if UIP_CLIENT_TIMER >= 0 + } + else + { + if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) + uip_process(UIP_POLL_REQUEST); + else + continue; + } +#endif + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } +#if UIP_CLIENT_TIMER >= 0 + if (periodic) + { + periodic_timer = now + UIP_PERIODIC_TIMER; +#endif +#if UIP_UDP + for (int i = 0; i < UIP_UDP_CONNS; i++) + { + uip_udp_periodic(i); + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. */ + if (uip_len > 0) + { + UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate)); + } + } +#endif /* UIP_UDP */ + } +} + +boolean UIPEthernetClass::network_send() +{ + if (packetstate & UIPETHERNET_SENDPACKET) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("Enc28J60Network_send uip_packet: ")); + Serial.print(uip_packet); + Serial.print(F(", hdrlen: ")); + Serial.println(uip_hdrlen); +#endif + Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_hdrlen); + packetstate &= ~ UIPETHERNET_SENDPACKET; + goto sendandfree; + } + uip_packet = Enc28J60Network::allocBlock(uip_len); + if (uip_packet != NOBLOCK) + { +#ifdef UIPETHERNET_DEBUG + Serial.print(F("Enc28J60Network_send uip_buf (uip_len): ")); + Serial.print(uip_len); + Serial.print(F(", packet: ")); + Serial.println(uip_packet); +#endif + Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_len); + goto sendandfree; + } + return false; +sendandfree: + Enc28J60Network::sendPacket(uip_packet); + Enc28J60Network::freeBlock(uip_packet); + uip_packet = NOBLOCK; + return true; +} + +void UIPEthernetClass::init(const uint8_t* mac) { + periodic_timer = millis() + UIP_PERIODIC_TIMER; + + Enc28J60Network::init((uint8_t*)mac); + uip_seteth_addr(mac); + + uip_init(); + uip_arp_init(); +} + +void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { + uip_ipaddr_t ipaddr; + + uip_ip_addr(ipaddr, ip); + uip_sethostaddr(ipaddr); + + uip_ip_addr(ipaddr, gateway); + uip_setdraddr(ipaddr); + + uip_ip_addr(ipaddr, subnet); + uip_setnetmask(ipaddr); + + _dnsServerAddress = dns; +} + +UIPEthernetClass UIPEthernet; + +/*---------------------------------------------------------------------------*/ +uint16_t +UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) +{ + uint16_t t; + const uint8_t *dataptr; + const uint8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) { /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + dataptr += 2; + } + + if(dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} + +/*---------------------------------------------------------------------------*/ + +uint16_t +UIPEthernetClass::ipchksum(void) +{ + uint16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + return (sum == 0) ? 0xffff : htons(sum); +} + +/*---------------------------------------------------------------------------*/ +uint16_t +#if UIP_UDP +UIPEthernetClass::upper_layer_chksum(uint8_t proto) +#else +uip_tcpchksum(void) +#endif +{ + uint16_t upper_layer_len; + uint16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ +#if UIP_UDP + sum = upper_layer_len + proto; +#else + sum = upper_layer_len + UIP_PROTO_TCP; +#endif + /* Sum IP source and destination addresses. */ + sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + uint8_t upper_layer_memlen; +#if UIP_UDP + switch(proto) + { +// case UIP_PROTO_ICMP: +// case UIP_PROTO_ICMP6: +// upper_layer_memlen = upper_layer_len; +// break; + case UIP_PROTO_UDP: + upper_layer_memlen = UIP_UDPH_LEN; + break; + default: +// case UIP_PROTO_TCP: +#endif + upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; +#if UIP_UDP + break; + } +#endif + sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); +#ifdef UIPETHERNET_DEBUG_CHKSUM + Serial.print(F("chksum uip_buf[")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN); + Serial.print(F("-")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + Serial.print(F("]: ")); + Serial.println(htons(sum),HEX); +#endif + if (upper_layer_memlen < upper_layer_len) + { + sum = Enc28J60Network::chksum( + sum, + UIPEthernetClass::uip_packet, + UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, + upper_layer_len - upper_layer_memlen + ); +#ifdef UIPETHERNET_DEBUG_CHKSUM + Serial.print(F("chksum uip_packet(")); + Serial.print(uip_packet); + Serial.print(F(")[")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + Serial.print(F("-")); + Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); + Serial.print(F("]: ")); + Serial.println(htons(sum),HEX); +#endif + } + return (sum == 0) ? 0xffff : htons(sum); +} + +uint16_t +uip_ipchksum(void) +{ + return UIPEthernet.ipchksum(); +} + +#if UIP_UDP +uint16_t +uip_tcpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); + return sum; +} + +uint16_t +uip_udpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); + return sum; +} +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.h b/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.h new file mode 100644 index 0000000..c68d578 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.h @@ -0,0 +1,127 @@ +/* + UIPEthernet.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef UIPETHERNET_H +#define UIPETHERNET_H + +//#define UIPETHERNET_DEBUG +//#define UIPETHERNET_DEBUG_CHKSUM +//#define UIPETHERNET_DEBUG_UDP +//#define UIPETHERNET_DEBUG_CLIENT + +#include "ethernet_comp.h" +#include +#include "Dhcp.h" +#include "IPAddress.h" +#include "utility/Enc28J60Network.h" +#include "UIPClient.h" +#include "UIPServer.h" +#include "UIPUdp.h" + +extern "C" +{ +#include "utility/uip_timer.h" +#include "utility/uip.h" +} + +#define UIPETHERNET_FREEPACKET 1 +#define UIPETHERNET_SENDPACKET 2 +#define UIPETHERNET_BUFFERREAD 4 + +#define uip_ip_addr(addr, ip) do { \ + ((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ + ((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ + } while(0) + +#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable + +#define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \ + uip_ethaddr.addr[1] = eaddr[1];\ + uip_ethaddr.addr[2] = eaddr[2];\ + uip_ethaddr.addr[3] = eaddr[3];\ + uip_ethaddr.addr[4] = eaddr[4];\ + uip_ethaddr.addr[5] = eaddr[5];} while(0) + +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +class UIPEthernetClass +{ +public: + UIPEthernetClass(); + + int begin(const uint8_t* mac); + void begin(const uint8_t* mac, IPAddress ip); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + // maintain() must be called at regular intervals to process the incoming serial + // data and issue IP events to the sketch. It does not return until all IP + // events have been processed. Renews dhcp-lease if required. + int maintain(); + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + +private: + static memhandle in_packet; + static memhandle uip_packet; + static uint8_t uip_hdrlen; + static uint8_t packetstate; + + static IPAddress _dnsServerAddress; + static DhcpClass* _dhcp; + + static unsigned long periodic_timer; + + static void init(const uint8_t* mac); + static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + static void tick(); + + static boolean network_send(); + + friend class UIPServer; + + friend class UIPClient; + + friend class UIPUDP; + + static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); + static uint16_t ipchksum(void); +#if UIP_UDP + static uint16_t upper_layer_chksum(uint8_t proto); +#endif + friend uint16_t uip_ipchksum(void); + friend uint16_t uip_tcpchksum(void); + friend uint16_t uip_udpchksum(void); + + friend void uipclient_appcall(void); + friend void uipudp_appcall(void); + +#if UIP_CONF_IPV6 + uint16_t uip_icmp6chksum(void); +#endif /* UIP_CONF_IPV6 */ +}; + +extern UIPEthernetClass UIPEthernet; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.cpp b/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.cpp new file mode 100644 index 0000000..21c7ef5 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.cpp @@ -0,0 +1,63 @@ +/* + UIPServer.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#include "UIPEthernet.h" +#include "UIPServer.h" +extern "C" { + #include "utility/uip-conf.h" +} + +UIPServer::UIPServer(uint16_t port) : _port(htons(port)) +{ +} + +UIPClient UIPServer::available() +{ + UIPEthernetClass::tick(); + for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ ) + { + if (data->packets_in[0] != NOBLOCK + && (((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port) + || ((data->state & UIP_CLIENT_REMOTECLOSED) && ((uip_userdata_closed_t *)data)->lport == _port))) + return UIPClient(data); + } + return UIPClient(); +} + +void UIPServer::begin() +{ + uip_listen(_port); + UIPEthernetClass::tick(); +} + +size_t UIPServer::write(uint8_t c) +{ + return write(&c,1); +} + +size_t UIPServer::write(const uint8_t *buf, size_t size) +{ + size_t ret = 0; + for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ ) + { + if ((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port) + ret += UIPClient::_write(data,buf,size); + } + return ret; +} + diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.h b/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.h new file mode 100644 index 0000000..0cc0619 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.h @@ -0,0 +1,40 @@ +/* + UIPServer.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +#ifndef UIPSERVER_H +#define UIPSERVER_H + +#include "ethernet_comp.h" +#import "Server.h" +#import "UIPClient.h" + +class UIPServer : public Server { + +public: + UIPServer(uint16_t); + UIPClient available(); + void begin(); + size_t write(uint8_t); + size_t write(const uint8_t *buf, size_t size); + using Print::write; + +private: + uint16_t _port; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.cpp b/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.cpp new file mode 100644 index 0000000..3deb2c4 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.cpp @@ -0,0 +1,383 @@ +/* + UIPUdp.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "UIPEthernet.h" +#include "UIPUdp.h" +#include "Dns.h" + +#ifdef UIPETHERNET_DEBUG_UDP +#include "HardwareSerial.h" +#endif + +extern "C" { +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +} + +#if UIP_UDP +#define UIP_ARPHDRSIZE 42 +#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +// Constructor +UIPUDP::UIPUDP() : + _uip_udp_conn(NULL) +{ + memset(&appdata,0,sizeof(appdata)); +} + +// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use +uint8_t +UIPUDP::begin(uint16_t port) +{ + if (!_uip_udp_conn) + { + _uip_udp_conn = uip_udp_new(NULL, 0); + } + if (_uip_udp_conn) + { + uip_udp_bind(_uip_udp_conn,htons(port)); + _uip_udp_conn->appstate = &appdata; + return 1; + } + return 0; +} + +// Finish with the UDP socket +void +UIPUDP::stop() +{ + if (_uip_udp_conn) + { + uip_udp_remove(_uip_udp_conn); + _uip_udp_conn->appstate = NULL; + _uip_udp_conn=NULL; + Enc28J60Network::freeBlock(appdata.packet_in); + Enc28J60Network::freeBlock(appdata.packet_next); + Enc28J60Network::freeBlock(appdata.packet_out); + memset(&appdata,0,sizeof(appdata)); + } +} + +// Sending UDP packets + +// Start building up a packet to send to the remote host specific in ip and port +// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port +int +UIPUDP::beginPacket(IPAddress ip, uint16_t port) +{ + UIPEthernetClass::tick(); + if (ip && port) + { + uip_ipaddr_t ripaddr; + uip_ip_addr(&ripaddr, ip); +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp beginPacket, ")); +#endif + if (_uip_udp_conn) + { + _uip_udp_conn->rport = htons(port); + uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr); + } + else + { + _uip_udp_conn = uip_udp_new(&ripaddr,htons(port)); + if (_uip_udp_conn) + { +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("new connection, ")); +#endif + _uip_udp_conn->appstate = &appdata; + } + else + { +#ifdef UIPETHERNET_DEBUG_UDP + Serial.println(F("failed to allocate new connection")); +#endif + return 0; + } + } +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("rip: ")); + Serial.print(ip); + Serial.print(F(", port: ")); + Serial.println(port); +#endif + } + if (_uip_udp_conn) + { + if (appdata.packet_out == NOBLOCK) + { + appdata.packet_out = Enc28J60Network::allocBlock(UIP_UDP_MAXPACKETSIZE); + appdata.out_pos = UIP_UDP_PHYH_LEN; + if (appdata.packet_out != NOBLOCK) + return 1; +#ifdef UIPETHERNET_DEBUG_UDP + else + Serial.println(F("failed to allocate memory for packet")); +#endif + } +#ifdef UIPETHERNET_DEBUG_UDP + else + Serial.println(F("previous packet on that connection not sent yet")); +#endif + } + return 0; +} + +// Start building up a packet to send to the remote host specific in host and port +// Returns 1 if successful, 0 if there was a problem resolving the hostname or port +int +UIPUDP::beginPacket(const char *host, uint16_t port) +{ + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(UIPEthernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return beginPacket(remote_addr, port); + } else { + return ret; + } +} + +// Finish off this packet and send it +// Returns 1 if the packet was sent successfully, 0 if there was an error +int +UIPUDP::endPacket() +{ + if (_uip_udp_conn && appdata.packet_out != NOBLOCK) + { + appdata.send = true; + Enc28J60Network::resizeBlock(appdata.packet_out,0,appdata.out_pos); + uip_udp_periodic_conn(_uip_udp_conn); + if (uip_len > 0) + { + _send(&appdata); + return 1; + } + } + return 0; +} + +// Write a single byte into the packet +size_t +UIPUDP::write(uint8_t c) +{ + return write(&c,1); +} + +// Write size bytes from buffer into the packet +size_t +UIPUDP::write(const uint8_t *buffer, size_t size) +{ + if (appdata.packet_out != NOBLOCK) + { + size_t ret = Enc28J60Network::writePacket(appdata.packet_out,appdata.out_pos,(uint8_t*)buffer,size); + appdata.out_pos += ret; + return ret; + } + return 0; +} + +// Start processing the next available incoming packet +// Returns the size of the packet in bytes, or 0 if no packets are available +int +UIPUDP::parsePacket() +{ + UIPEthernetClass::tick(); +#ifdef UIPETHERNET_DEBUG_UDP + if (appdata.packet_in != NOBLOCK) + { + Serial.print(F("udp parsePacket freeing previous packet: ")); + Serial.println(appdata.packet_in); + } +#endif + Enc28J60Network::freeBlock(appdata.packet_in); + + appdata.packet_in = appdata.packet_next; + appdata.packet_next = NOBLOCK; + +#ifdef UIPETHERNET_DEBUG_UDP + if (appdata.packet_in != NOBLOCK) + { + Serial.print(F("udp parsePacket received packet: ")); + Serial.print(appdata.packet_in); + } +#endif + int size = Enc28J60Network::blockSize(appdata.packet_in); +#ifdef UIPETHERNET_DEBUG_UDP + if (appdata.packet_in != NOBLOCK) + { + Serial.print(F(", size: ")); + Serial.println(size); + } +#endif + return size; +} + +// Number of bytes remaining in the current packet +int +UIPUDP::available() +{ + UIPEthernetClass::tick(); + return Enc28J60Network::blockSize(appdata.packet_in); +} + +// Read a single byte from the current packet +int +UIPUDP::read() +{ + unsigned char c; + if (read(&c,1) > 0) + { + return c; + } + return -1; +} + +// Read up to len bytes from the current packet and place them into buffer +// Returns the number of bytes read, or 0 if none are available +int +UIPUDP::read(unsigned char* buffer, size_t len) +{ + UIPEthernetClass::tick(); + if (appdata.packet_in != NOBLOCK) + { + memaddress read = Enc28J60Network::readPacket(appdata.packet_in,0,buffer,len); + if (read == Enc28J60Network::blockSize(appdata.packet_in)) + { + Enc28J60Network::freeBlock(appdata.packet_in); + appdata.packet_in = NOBLOCK; + } + else + Enc28J60Network::resizeBlock(appdata.packet_in,read); + return read; + } + return 0; +} + +// Return the next byte from the current packet without moving on to the next byte +int +UIPUDP::peek() +{ + UIPEthernetClass::tick(); + if (appdata.packet_in != NOBLOCK) + { + unsigned char c; + if (Enc28J60Network::readPacket(appdata.packet_in,0,&c,1) == 1) + return c; + } + return -1; +} + +// Finish reading the current packet +void +UIPUDP::flush() +{ + UIPEthernetClass::tick(); + Enc28J60Network::freeBlock(appdata.packet_in); + appdata.packet_in = NOBLOCK; +} + +// Return the IP address of the host who sent the current incoming packet +IPAddress +UIPUDP::remoteIP() +{ + return _uip_udp_conn ? ip_addr_uip(_uip_udp_conn->ripaddr) : IPAddress(); +} + +// Return the port of the host who sent the current incoming packet +uint16_t +UIPUDP::remotePort() +{ + return _uip_udp_conn ? ntohs(_uip_udp_conn->rport) : 0; +} + +// uIP callback function + +void +uipudp_appcall(void) { + if (uip_udp_userdata_t *data = (uip_udp_userdata_t *)(uip_udp_conn->appstate)) + { + if (uip_newdata()) + { + if (data->packet_next == NOBLOCK) + { + uip_udp_conn->rport = UDPBUF->srcport; + uip_ipaddr_copy(uip_udp_conn->ripaddr,UDPBUF->srcipaddr); + data->packet_next = Enc28J60Network::allocBlock(ntohs(UDPBUF->udplen)-UIP_UDPH_LEN); + //if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery + if (data->packet_next != NOBLOCK) + { + //discard Linklevel and IP and udp-header and any trailing bytes: + Enc28J60Network::copyPacket(data->packet_next,0,UIPEthernetClass::in_packet,UIP_UDP_PHYH_LEN,Enc28J60Network::blockSize(data->packet_next)); + #ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_newdata received packet: ")); + Serial.print(data->packet_next); + Serial.print(F(", size: ")); + Serial.println(Enc28J60Network::blockSize(data->packet_next)); + #endif + } + } + } + if (uip_poll() && data->send) + { + //set uip_slen (uip private) by calling uip_udp_send +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_poll preparing packet to send: ")); + Serial.print(data->packet_out); + Serial.print(F(", size: ")); + Serial.println(Enc28J60Network::blockSize(data->packet_out)); +#endif + UIPEthernetClass::uip_packet = data->packet_out; + UIPEthernetClass::uip_hdrlen = UIP_UDP_PHYH_LEN; + uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN)); + } + } +} + +void +UIPUDP::_send(uip_udp_userdata_t *data) { + uip_arp_out(); //add arp + if (uip_len == UIP_ARPHDRSIZE) + { + UIPEthernetClass::uip_packet = NOBLOCK; + UIPEthernetClass::packetstate &= ~UIPETHERNET_SENDPACKET; +#ifdef UIPETHERNET_DEBUG_UDP + Serial.println(F("udp, uip_poll results in ARP-packet")); +#endif + } + else + //arp found ethaddr for ip (otherwise packet is replaced by arp-request) + { + data->send = false; + data->packet_out = NOBLOCK; + UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; +#ifdef UIPETHERNET_DEBUG_UDP + Serial.print(F("udp, uip_packet to send: ")); + Serial.println(UIPEthernetClass::uip_packet); +#endif + } + UIPEthernetClass::network_send(); +} +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.h b/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.h new file mode 100644 index 0000000..b007a3c --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.h @@ -0,0 +1,126 @@ +/* + UIPUdp.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef UIPUDP_H +#define UIPUDP_H + +#include "ethernet_comp.h" +#include "Arduino.h" +#include +#include "utility/mempool.h" +extern "C" { + #include "utility/uip.h" +} + +#define UIP_UDP_MAXDATALEN 1500 +#define UIP_UDP_PHYH_LEN UIP_LLH_LEN+UIP_IPUDPH_LEN +#define UIP_UDP_MAXPACKETSIZE UIP_UDP_MAXDATALEN+UIP_UDP_PHYH_LEN + +typedef struct { + memaddress out_pos; + memhandle packet_next; + memhandle packet_in; + memhandle packet_out; + boolean send; +} uip_udp_userdata_t; + +class UIPUDP : public UDP +{ + +private: + struct uip_udp_conn *_uip_udp_conn; + + uip_udp_userdata_t appdata; + +public: + UIPUDP(); // Constructor + uint8_t + begin(uint16_t);// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + void + stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + int + beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + int + beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + int + endPacket(); + // Write a single byte into the packet + size_t + write(uint8_t); + // Write size bytes from buffer into the packet + size_t + write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + int + parsePacket(); + // Number of bytes remaining in the current packet + int + available(); + // Read a single byte from the current packet + int + read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + int + read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + int + read(char* buffer, size_t len) + { + return read((unsigned char*) buffer, len); + } + ; + // Return the next byte from the current packet without moving on to the next byte + int + peek(); + void + flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + IPAddress + remoteIP(); + + // Return the port of the host who sent the current incoming packet + uint16_t + remotePort(); + +private: + + friend void uipudp_appcall(void); + + friend class UIPEthernetClass; + static void _send(uip_udp_userdata_t *data); + +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/ethernet_comp.h b/libraries/MySensors/drivers/Ethernet_UIP/ethernet_comp.h new file mode 100644 index 0000000..4cec2ab --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/ethernet_comp.h @@ -0,0 +1,9 @@ +#ifndef ETHERNET_COMP_H +#define ETHERNET_COMP_H + +#define Ethernet UIPEthernet +#define EthernetClient UIPClient +#define EthernetServer UIPServer +#define EthernetUDP UIPUDP + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino b/libraries/MySensors/drivers/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino new file mode 100644 index 0000000..bc2f094 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -0,0 +1,104 @@ +/* + Advanced Chat Server + + A simple server that distributes any incoming messages to all + connected clients but the client the message comes from. + To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + redesigned to make use of operator== 25 Nov 2013 + by Norbert Truchsess + + */ + +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. + +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +IPAddress ip(192,168,0,6); + +// telnet defaults to port 23 +EthernetServer server(23); + +EthernetClient clients[4]; + +void setup() { + // initialize the ethernet device + Ethernet.begin(mac, ip); + // start listening for clients + server.begin(); + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + Serial.print("Chat server address:"); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + if (client) { + + boolean newClient = true; + for (byte i=0;i<4;i++) { + //check whether this client refers to the same socket as one of the existing instances: + if (clients[i]==client) { + newClient = false; + break; + } + } + + if (newClient) { + //check which of the existing clients can be overridden: + for (byte i=0;i<4;i++) { + if (!clients[i] && clients[i]!=client) { + clients[i] = client; + // clead out the input buffer: + client.flush(); + // clead out the input buffer: + client.flush(); + Serial.println("We have a new client"); + client.println("Hello, client!"); + client.print("my IP: "); + client.println(Ethernet.localIP()); + break; + } + } + } + + if (client.available() > 0) { + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to all other connected clients: + for (byte i=0;i<4;i++) { + if (clients[i] && clients[i]!=client) { + clients[i].write(thisChar); + } + } + // echo the bytes to the server as well: + Serial.write(thisChar); + } + } + for (byte i=0;i<4;i++) { + if (!(clients[i].connected())) { + // client.stop() invalidates the internal socket-descriptor, so next use of == will allways return false; + clients[i].stop(); + } + } +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/EchoServer/EchoServer.ino b/libraries/MySensors/drivers/Ethernet_UIP/examples/EchoServer/EchoServer.ino new file mode 100644 index 0000000..62d66e4 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/examples/EchoServer/EchoServer.ino @@ -0,0 +1,58 @@ +/* + * UIPEthernet EchoServer example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This Hello World example sets up a server at 192.168.1.6 on port 1000. + * Telnet here to access the service. The uIP stack will also respond to + * pings to test if you have successfully established a TCP connection to + * the Arduino. + * + * This example was based upon uIP hello-world by Adam Dunkels + * Ported to the Arduino IDE by Adam Nielsen + * Adaption to Enc28J60 by Norbert Truchsess + */ + +#include +// The connection_data struct needs to be defined in an external file. +#include +#include + +EthernetServer server = EthernetServer(1000); + +void setup() +{ + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + IPAddress myIP(192,168,0,6); + + Ethernet.begin(mac,myIP); + + server.begin(); +} + +void loop() +{ + size_t size; + + if (EthernetClient client = server.available()) + { + if (client) + { + while((size = client.available()) > 0) + { + uint8_t* msg = (uint8_t*)malloc(size); + size = client.read(msg,size); + Serial.write(msg,size); + client.write(msg,size); + free(msg); + } + } + } +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpClient/TcpClient.ino b/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpClient/TcpClient.ino new file mode 100644 index 0000000..dca685c --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpClient/TcpClient.ino @@ -0,0 +1,76 @@ +/* + * UIPEthernet TcpClient example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This TcpClient example gets its local ip-address via dhcp and sets + * up a tcp socket-connection to 192.168.0.1 port 5000 every 5 Seconds. + * After sending a message it waits for a response. After receiving the + * response the client disconnects and tries to reconnect after 5 seconds. + * + * Copyright (C) 2013 by Norbert Truchsess + */ + +#include + +EthernetClient client; +signed long next; + +void setup() { + + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + Ethernet.begin(mac); + + Serial.print("localIP: "); + Serial.println(Ethernet.localIP()); + Serial.print("subnetMask: "); + Serial.println(Ethernet.subnetMask()); + Serial.print("gatewayIP: "); + Serial.println(Ethernet.gatewayIP()); + Serial.print("dnsServerIP: "); + Serial.println(Ethernet.dnsServerIP()); + + next = 0; +} + +void loop() { + + if (((signed long)(millis() - next)) > 0) + { + next = millis() + 5000; + Serial.println("Client connect"); + // replace hostname with name of machine running tcpserver.pl +// if (client.connect("server.local",5000)) + if (client.connect(IPAddress(192,168,0,1),5000)) + { + Serial.println("Client connected"); + client.println("DATA from Client"); + while(client.available()==0) + { + if (next - millis() < 0) + goto close; + } + int size; + while((size = client.available()) > 0) + { + uint8_t* msg = (uint8_t*)malloc(size); + size = client.read(msg,size); + Serial.write(msg,size); + free(msg); + } +close: + //disconnect client + Serial.println("Client disconnect"); + client.stop(); + } + else + Serial.println("Client connect failed"); + } +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpServer/TcpServer.ino b/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpServer/TcpServer.ino new file mode 100644 index 0000000..10512ec --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpServer/TcpServer.ino @@ -0,0 +1,53 @@ +/* + * UIPEthernet EchoServer example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This Hello World example sets up a server at 192.168.1.6 on port 1000. + * Telnet here to access the service. The uIP stack will also respond to + * pings to test if you have successfully established a TCP connection to + * the Arduino. + * + * This example was based upon uIP hello-world by Adam Dunkels + * Ported to the Arduino IDE by Adam Nielsen + * Adaption to Enc28J60 by Norbert Truchsess + */ + +#include + +EthernetServer server = EthernetServer(1000); + +void setup() +{ + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + IPAddress myIP(192,168,0,6); + + Ethernet.begin(mac,myIP); + + server.begin(); +} + +void loop() +{ + size_t size; + + if (EthernetClient client = server.available()) + { + while((size = client.available()) > 0) + { + uint8_t* msg = (uint8_t*)malloc(size); + size = client.read(msg,size); + Serial.write(msg,size); + free(msg); + } + client.println("DATA from Server!"); + client.stop(); + } +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpClient/UdpClient.ino b/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpClient/UdpClient.ino new file mode 100644 index 0000000..aad56b4 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpClient/UdpClient.ino @@ -0,0 +1,93 @@ +/* + * UIPEthernet UdpClient example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This UdpClient example tries to send a packet via udp to 192.168.0.1 + * on port 5000 every 5 seconds. After successfully sending the packet it + * waits for up to 5 seconds for a response on the local port that has been + * implicitly opened when sending the packet. + * + * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) + */ + +#include + +EthernetUDP udp; +unsigned long next; + +void setup() { + + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + + Ethernet.begin(mac,IPAddress(192,168,0,6)); + + next = millis()+5000; +} + +void loop() { + + int success; + int len = 0; + + if (((signed long)(millis()-next))>0) + { + do + { + success = udp.beginPacket(IPAddress(192,168,0,1),5000); + Serial.print("beginPacket: "); + Serial.println(success ? "success" : "failed"); + //beginPacket fails if remote ethaddr is unknown. In this case an + //arp-request is send out first and beginPacket succeeds as soon + //the arp-response is received. + } + while (!success && ((signed long)(millis()-next))<0); + if (!success ) + goto stop; + + success = udp.write("hello world from arduino"); + + Serial.print("bytes written: "); + Serial.println(success); + + success = udp.endPacket(); + + Serial.print("endPacket: "); + Serial.println(success ? "success" : "failed"); + + do + { + //check for new udp-packet: + success = udp.parsePacket(); + } + while (!success && ((signed long)(millis()-next))<0); + if (!success ) + goto stop; + + Serial.print("received: '"); + do + { + int c = udp.read(); + Serial.write(c); + len++; + } + while ((success = udp.available())>0); + Serial.print("', "); + Serial.print(len); + Serial.println(" bytes"); + + //finish reading this packet: + udp.flush(); + + stop: + udp.stop(); + next = millis()+5000; + } +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpServer/UdpServer.ino b/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpServer/UdpServer.ino new file mode 100644 index 0000000..3b12d75 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpServer/UdpServer.ino @@ -0,0 +1,88 @@ +/* + * UIPEthernet UdpServer example. + * + * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based + * Ethernet-shield. + * + * UIPEthernet uses the fine uIP stack by Adam Dunkels + * + * ----------------- + * + * This UdpServer example sets up a udp-server at 192.168.0.6 on port 5000. + * send packet via upd to test + * + * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) + */ + +#include + +EthernetUDP udp; + +void setup() { + + Serial.begin(9600); + + uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; + + Ethernet.begin(mac,IPAddress(192,168,0,6)); + + int success = udp.begin(5000); + + Serial.print("initialize: "); + Serial.println(success ? "success" : "failed"); + +} + +void loop() { + + //check for new udp-packet: + int size = udp.parsePacket(); + if (size > 0) { + do + { + char* msg = (char*)malloc(size+1); + int len = udp.read(msg,size+1); + msg[len]=0; + Serial.print("received: '"); + Serial.print(msg); + free(msg); + } + while ((size = udp.available())>0); + //finish reading this packet: + udp.flush(); + Serial.println("'"); + int success; + do + { + Serial.print("remote ip: "); + Serial.println(udp.remoteIP()); + Serial.print("remote port: "); + Serial.println(udp.remotePort()); + //send new packet back to ip/port of client. This also + //configures the current connection to ignore packets from + //other clients! + success = udp.beginPacket(udp.remoteIP(),udp.remotePort()); + Serial.print("beginPacket: "); + Serial.println(success ? "success" : "failed"); + //beginPacket fails if remote ethaddr is unknown. In this case an + //arp-request is send out first and beginPacket succeeds as soon + //the arp-response is received. + } + while (!success); + + success = udp.println("hello world from arduino"); + + Serial.print("bytes written: "); + Serial.println(success); + + success = udp.endPacket(); + + Serial.print("endPacket: "); + Serial.println(success ? "success" : "failed"); + + udp.stop(); + //restart with new connection to receive packets from other clients + Serial.print("restart connection: "); + Serial.println (udp.begin(5000) ? "success" : "failed"); + } +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/keywords.txt b/libraries/MySensors/drivers/Ethernet_UIP/keywords.txt new file mode 100644 index 0000000..83ff854 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/keywords.txt @@ -0,0 +1,58 @@ +####################################### +# Syntax Coloring Map for SerialIP +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +UIPEthernet KEYWORD1 +UIPServer KEYWORD1 +UIPClient KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +PSOCK_BEGIN KEYWORD2 +PSOCK_CLOSE KEYWORD2 +PSOCK_END KEYWORD2 +PSOCK_EXIT KEYWORD2 +PSOCK_INIT KEYWORD2 +PSOCK_READBUF KEYWORD2 +PSOCK_READTO KEYWORD2 +PSOCK_SEND KEYWORD2 +PSOCK_SEND_STR KEYWORD2 + +uip_listen KEYWORD2 +uip_unlisten KEYWORD2 +uip_connect KEYWORD2 +uip_outstanding KEYWORD2 +uip_send KEYWORD2 +uip_datalen KEYWORD2 +uip_close KEYWORD2 +uip_abort KEYWORD2 +uip_stop KEYWORD2 +uip_stopped KEYWORD2 +uip_restart KEYWORD2 +uip_acked KEYWORD2 +uip_connected KEYWORD2 +uip_closed KEYWORD2 +uip_aborted KEYWORD2 +uip_timedout KEYWORD2 +uip_rexmit KEYWORD2 +uip_poll KEYWORD2 +uip_initialmss KEYWORD2 +uip_mss KEYWORD2 +uip_ipaddr KEYWORD2 +uip_ipaddr_maskcmp KEYWORD2 +uip_ipaddr_mask KEYWORD2 +HTONS KEYWORD2 +htons KEYWORD2 + +use_device KEYWORD2 +set_uip_callback KEYWORD2 +set_gateway KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/MySensors/drivers/Ethernet_UIP/library.properties b/libraries/MySensors/drivers/Ethernet_UIP/library.properties new file mode 100644 index 0000000..158ae31 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/library.properties @@ -0,0 +1,10 @@ +name=UIPEthernet +author=ntruchsess +email=Norbert Truchsess +sentence=Ethernet library for ENC28J60 +paragraph=implements the same API as stock Ethernet-lib. Just replace the include of Ethernet.h with UIPEthernet.h +url=https://github.com/ntruchsess/arduino_uip +architectures=avr +version=1.04 +dependencies= +core-dependencies=arduino (>=1.5.0) diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpclient.pl b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpclient.pl new file mode 100644 index 0000000..e6884dc --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpclient.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl +#tcpclient.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$client_socket); + +# creating object interface of IO::Socket::INET modules which internally creates +# socket, binds and connects to the TCP server running on the specific port. +$socket = new IO::Socket::INET ( +PeerHost => '192.168.0.6', +PeerPort => '1000', +Proto => 'tcp', +) or die "ERROR in Socket Creation : $!\n"; + +print "TCP Connection Success.\n"; + +# write on the socket to server. +$data = "DATA from Client"; +print $socket "$data\n"; +# we can also send the data through IO::Socket::INET module, +# $socket->send($data); + +# read the socket data sent by server. +$data = <$socket>; +# we can also read from socket through recv() in IO::Socket::INET +# $socket->recv($data,1024); +print "Received from Server : $data\n"; + +sleep (10); +$socket->close(); \ No newline at end of file diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpserver.pl b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpserver.pl new file mode 100644 index 0000000..17405a3 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpserver.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +#tcpserver.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$client_socket); +my ($peeraddress,$peerport); + +# creating object interface of IO::Socket::INET modules which internally does +# socket creation, binding and listening at the specified port address. +$socket = new IO::Socket::INET ( +LocalHost => '192.168.0.1', +LocalPort => '5000', +Proto => 'tcp', +Listen => 5, +Reuse => 1 +) or die "ERROR in Socket Creation : $!\n"; + +print "SERVER Waiting for client connection on port 5000\n"; + +while(1) +{ + # waiting for new client connection. + $client_socket = $socket->accept(); + + # get the host and port number of newly connected client. + $peer_address = $client_socket->peerhost(); + $peer_port = $client_socket->peerport(); + + print "Accepted New Client Connection From : $peer_address, $peer_port\n "; + + # read operation on the newly accepted client + $data = <$client_socket>; + # we can also read from socket through recv() in IO::Socket::INET + # $client_socket->recv($data,1024); + print "Received from Client : $data\n"; + + # write operation on the newly accepted client. + $data = "DATA from Server"; + print $client_socket "$data\n"; + # we can also send the data through IO::Socket::INET module, + # $client_socket->send($data); + + sleep(1); + + $client_socket->close(); +} + +$socket->close(); + diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpclient.pl b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpclient.pl new file mode 100644 index 0000000..bc9e6a2 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpclient.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl +#udpclient.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$data); + +# We call IO::Socket::INET->new() to create the UDP Socket +# and bind with the PeerAddr. +$socket = new IO::Socket::INET ( +PeerAddr => '192.168.0.6:5000', +Proto => 'udp' +) or die "ERROR in Socket Creation : $!\n"; +#send operation +$data = "data from client"; +$socket->send($data); + +#read operation +$data = <$socket>; +print "Data received from socket : $data\n "; + +sleep(10); +$socket->close(); diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpserver.pl b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpserver.pl new file mode 100644 index 0000000..e728a46 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpserver.pl @@ -0,0 +1,40 @@ +#!/usr/bin/perl +#udpserver.pl + +use IO::Socket::INET; + +# flush after every write +$| = 1; + +my ($socket,$received_data); +my ($peeraddress,$peerport); + +# we call IO::Socket::INET->new() to create the UDP Socket and bound +# to specific port number mentioned in LocalPort and there is no need to provide +# LocalAddr explicitly as in TCPServer. +$socket = new IO::Socket::INET ( +LocalPort => '5000', +Proto => 'udp', +) or die "ERROR in Socket Creation : $!\n"; + +while(1) +{ +# read operation on the socket +$socket->recv($recieved_data,1024); + +#get the peerhost and peerport at which the recent data received. +$peer_address = $socket->peerhost(); +$peer_port = $socket->peerport(); +print "($peer_address , $peer_port) said : $recieved_data\n"; + +#send the data to the client at which the read/write operations done recently. +$data = "data from server\n"; + +$socket->send($data); + +print $socket "$data"; + +} + +$socket->close(); + diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.cpp b/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.cpp new file mode 100644 index 0000000..c7c66fb --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.cpp @@ -0,0 +1,612 @@ +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "Enc28J60Network.h" +#include "Arduino.h" + +extern "C" { +#include +#include "enc28j60.h" +#include "uip.h" +} + +#ifdef ENC28J60DEBUG +#include "HardwareSerial.h" +#endif + +// set CS to 0 = active +#define CSACTIVE digitalWrite(ENC28J60_CONTROL_CS, LOW) +// set CS to 1 = passive +#define CSPASSIVE digitalWrite(ENC28J60_CONTROL_CS, HIGH) +// +#define waitspi() while(!(SPSR&(1< ip checksum for theses bytes=f7f9 + // in binary these poitions are:11 0000 0011 1111 + // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 + //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! + writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN); + writeRegPair(EPMM0, 0x303f); + writeRegPair(EPMCSL, 0xf7f9); + // + // + // do bank 2 stuff + // enable MAC receive + // and bring MAC out of reset (writes 0x00 to MACON2) + writeRegPair(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); + // enable automatic padding to 60bytes and CRC operations + writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); + // set inter-frame gap (non-back-to-back) + writeRegPair(MAIPGL, 0x0C12); + // set inter-frame gap (back-to-back) + writeReg(MABBIPG, 0x12); + // Set the maximum packet size which the controller will accept + // Do not send packets longer than MAX_FRAMELEN: + writeRegPair(MAMXFLL, MAX_FRAMELEN); + // do bank 3 stuff + // write MAC address + // NOTE: MAC address in ENC28J60 is byte-backward + writeReg(MAADR5, macaddr[0]); + writeReg(MAADR4, macaddr[1]); + writeReg(MAADR3, macaddr[2]); + writeReg(MAADR2, macaddr[3]); + writeReg(MAADR1, macaddr[4]); + writeReg(MAADR0, macaddr[5]); + // no loopback of transmitted frames + phyWrite(PHCON2, PHCON2_HDLDIS); + // switch to bank 0 + setBank(ECON1); + // enable interrutps + writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); + // enable packet reception + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + //Configure leds + phyWrite(PHLCON,0x476); +} + +memhandle +Enc28J60Network::receivePacket() +{ + uint8_t rxstat; + uint16_t len; + // check if a packet has been received and buffered + //if( !(readReg(EIR) & EIR_PKTIF) ){ + // The above does not work. See Rev. B4 Silicon Errata point 6. + if (readReg(EPKTCNT) != 0) + { + uint16_t readPtr = nextPacketPtr+6 > RXSTOP_INIT ? nextPacketPtr+6-RXSTOP_INIT+RXSTART_INIT : nextPacketPtr+6; + // Set the read pointer to the start of the received packet + writeRegPair(ERDPTL, nextPacketPtr); + // read the next packet pointer + nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); + nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + // read the packet length (see datasheet page 43) + len = readOp(ENC28J60_READ_BUF_MEM, 0); + len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + len -= 4; //remove the CRC count + // read the receive status (see datasheet page 43) + rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); + //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; +#ifdef ENC28J60DEBUG + Serial.print("receivePacket ["); + Serial.print(readPtr,HEX); + Serial.print("-"); + Serial.print((readPtr+len) % (RXSTOP_INIT+1),HEX); + Serial.print("], next: "); + Serial.print(nextPacketPtr,HEX); + Serial.print(", stat: "); + Serial.print(rxstat,HEX); + Serial.print(", count: "); + Serial.print(readReg(EPKTCNT)); + Serial.print(" -> "); + Serial.println((rxstat & 0x80)!=0 ? "OK" : "failed"); +#endif + // decrement the packet counter indicate we are done with this packet + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); + // check CRC and symbol errors (see datasheet page 44, table 7-3): + // The ERXFCON.CRCEN is set by default. Normally we should not + // need to check this. + if ((rxstat & 0x80) != 0) + { + receivePkt.begin = readPtr; + receivePkt.size = len; + return UIP_RECEIVEBUFFERHANDLE; + } + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); + } + return (NOBLOCK); +} + +void +Enc28J60Network::setERXRDPT() +{ + writeRegPair(ERXRDPTL, nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr-1); +} + +memaddress +Enc28J60Network::blockSize(memhandle handle) +{ + return handle == NOBLOCK ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; +} + +void +Enc28J60Network::sendPacket(memhandle handle) +{ + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin-1; + uint16_t end = start + packet->size; + + // backup data at control-byte position + uint8_t data = readByte(start); + // write control-byte (if not 0 anyway) + if (data) + writeByte(start, 0); + +#ifdef ENC28J60DEBUG + Serial.print("sendPacket("); + Serial.print(handle); + Serial.print(") ["); + Serial.print(start,HEX); + Serial.print("-"); + Serial.print(end,HEX); + Serial.print("]: "); + for (uint16_t i=start; i<=end; i++) + { + Serial.print(readByte(i),HEX); + Serial.print(" "); + } + Serial.println(); +#endif + + // TX start + writeRegPair(ETXSTL, start); + // Set the TXND pointer to correspond to the packet size given + writeRegPair(ETXNDL, end); + // send the contents of the transmit buffer onto the network + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); + // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. + if( (readReg(EIR) & EIR_TXERIF) ) + { + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); + } + + //restore data on control-byte position + if (data) + writeByte(start, data); +} + +uint16_t +Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) +{ + memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; + memaddress start = handle == UIP_RECEIVEBUFFERHANDLE && packet->begin + position > RXSTOP_INIT ? packet->begin + position-RXSTOP_INIT+RXSTART_INIT : packet->begin + position; + + writeRegPair(ERDPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + return len; +} + +uint16_t +Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ + len = setReadPtr(handle, position, len); + readBuffer(len, buffer); + return len; +} + +uint16_t +Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin + position; + + writeRegPair(EWRPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + writeBuffer(len, buffer); + return len; +} + +uint8_t Enc28J60Network::readByte(uint16_t addr) +{ + writeRegPair(ERDPTL, addr); + + CSACTIVE; + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + CSPASSIVE; + return (SPDR); +} + +void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) +{ + writeRegPair(EWRPTL, addr); + + CSACTIVE; + // issue write command + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); + // write data + SPDR = data; + waitspi(); + CSPASSIVE; +} + +void +Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) +{ + memblock *dest = &blocks[dest_pkt]; + memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; + memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE && src->begin + src_pos > RXSTOP_INIT ? src->begin + src_pos-RXSTOP_INIT+RXSTART_INIT : src->begin + src_pos; + enc28J60_mempool_block_move_callback(dest->begin+dest_pos,start,len); + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); +} + +void +enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) +{ +//void +//Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) +//{ + //as ENC28J60 DMA is unable to copy single bytes: + if (len == 1) + { + Enc28J60Network::writeByte(dest,Enc28J60Network::readByte(src)); + } + else + { + // calculate address of last byte + len += src - 1; + + /* 1. Appropriately program the EDMAST, EDMAND + and EDMADST register pairs. The EDMAST + registers should point to the first byte to copy + from, the EDMAND registers should point to the + last byte to copy and the EDMADST registers + should point to the first byte in the destination + range. The destination range will always be + linear, never wrapping at any values except from + 8191 to 0 (the 8-Kbyte memory boundary). + Extreme care should be taken when + programming the start and end pointers to + prevent a never ending DMA operation which + would overwrite the entire 8-Kbyte buffer. + */ + Enc28J60Network::writeRegPair(EDMASTL, src); + Enc28J60Network::writeRegPair(EDMADSTL, dest); + + if ((src <= RXSTOP_INIT)&& (len > RXSTOP_INIT))len -= (RXSTOP_INIT-RXSTART_INIT); + Enc28J60Network::writeRegPair(EDMANDL, len); + + /* + 2. If an interrupt at the end of the copy process is + desired, set EIE.DMAIE and EIE.INTIE and + clear EIR.DMAIF. + + 3. Verify that ECON1.CSUMEN is clear. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); + + /* 4. Start the DMA copy by setting ECON1.DMAST. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + + // wait until runnig DMA is completed + while (Enc28J60Network::readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST); + } +} + +void +Enc28J60Network::freePacket() +{ + setERXRDPT(); +} + +uint8_t +Enc28J60Network::readOp(uint8_t op, uint8_t address) +{ + CSACTIVE; + // issue read command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + // do dummy read if needed (for mac and mii, see datasheet page 29) + if(address & 0x80) + { + SPDR = 0x00; + waitspi(); + } + // release CS + CSPASSIVE; + return(SPDR); +} + +void +Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) +{ + CSACTIVE; + // issue write command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // write data + SPDR = data; + waitspi(); + CSPASSIVE; +} + +void +Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) +{ + CSACTIVE; + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + while(len) + { + len--; + // read data + SPDR = 0x00; + waitspi(); + *data = SPDR; + data++; + } + //*data='\0'; + CSPASSIVE; +} + +void +Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) +{ + CSACTIVE; + // issue write command + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); + while(len) + { + len--; + // write data + SPDR = *data; + data++; + waitspi(); + } + CSPASSIVE; +} + +void +Enc28J60Network::setBank(uint8_t address) +{ + // set the bank (if needed) + if((address & BANK_MASK) != bank) + { + // set the bank + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); + bank = (address & BANK_MASK); + } +} + +uint8_t +Enc28J60Network::readReg(uint8_t address) +{ + // set the bank + setBank(address); + // do the read + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +void +Enc28J60Network::writeReg(uint8_t address, uint8_t data) +{ + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +void +Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) +{ + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, (data&0xFF)); + writeOp(ENC28J60_WRITE_CTRL_REG, address+1, (data) >> 8); +} + +void +Enc28J60Network::phyWrite(uint8_t address, uint16_t data) +{ + // set the PHY register address + writeReg(MIREGADR, address); + // write the PHY data + writeRegPair(MIWRL, data); + // wait until the PHY write completes + while(readReg(MISTAT) & MISTAT_BUSY){ + delayMicroseconds(15); + } +} + +uint16_t +Enc28J60Network::phyRead(uint8_t address) +{ + writeReg(MIREGADR,address); + writeReg(MICMD, MICMD_MIIRD); + // wait until the PHY read completes + while(readReg(MISTAT) & MISTAT_BUSY){ + delayMicroseconds(15); + } //and MIRDH + writeReg(MICMD, 0); + return (readReg(MIRDL) | readReg(MIRDH) << 8); +} + +void +Enc28J60Network::clkout(uint8_t clk) +{ + //setup clkout: 2 is 12.5MHz: + writeReg(ECOCON, clk & 0x7); +} + +// read the revision of the chip: +uint8_t +Enc28J60Network::getrev(void) +{ + return(readReg(EREVID)); +} + +uint16_t +Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) +{ + uint16_t t; + len = setReadPtr(handle, pos, len)-1; + CSACTIVE; + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + uint16_t i; + for (i = 0; i < len; i+=2) + { + // read data + SPDR = 0x00; + waitspi(); + t = SPDR << 8; + SPDR = 0x00; + waitspi(); + t += SPDR; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + if(i == len) { + SPDR = 0x00; + waitspi(); + t = (SPDR << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + CSPASSIVE; + + /* Return sum in host byte order. */ + return sum; +} + +void +Enc28J60Network::powerOff() +{ + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); +} + +void +Enc28J60Network::powerOn() +{ + writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + delay(50); +} + +bool +Enc28J60Network::linkStatus() +{ + return (phyRead(PHSTAT2) & 0x0400) > 0; +} + +Enc28J60Network Enc28J60; diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.h new file mode 100644 index 0000000..7346e47 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.h @@ -0,0 +1,91 @@ +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + inspired by enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef Enc28J60Network_H_ +#define Enc28J60Network_H_ + +#include "mempool.h" + +#define ENC28J60_CONTROL_CS SS +#define SPI_MOSI MOSI +#define SPI_MISO MISO +#define SPI_SCK SCK +#define SPI_SS SS + +#define UIP_RECEIVEBUFFERHANDLE 0xff + +//#define ENC28J60DEBUG + +/* + * Empfangen von ip-header, arp etc... + * wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection + */ + +class Enc28J60Network : public MemoryPool +{ + +private: + static uint16_t nextPacketPtr; + static uint8_t bank; + + static struct memblock receivePkt; + + static uint8_t readOp(uint8_t op, uint8_t address); + static void writeOp(uint8_t op, uint8_t address, uint8_t data); + static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); + static void setERXRDPT(); + static void readBuffer(uint16_t len, uint8_t* data); + static void writeBuffer(uint16_t len, uint8_t* data); + static uint8_t readByte(uint16_t addr); + static void writeByte(uint16_t addr, uint8_t data); + static void setBank(uint8_t address); + static uint8_t readReg(uint8_t address); + static void writeReg(uint8_t address, uint8_t data); + static void writeRegPair(uint8_t address, uint16_t data); + static void phyWrite(uint8_t address, uint16_t data); + static uint16_t phyRead(uint8_t address); + static void clkout(uint8_t clk); + + friend void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); + +public: + + uint8_t getrev(void); + void powerOn(); + void powerOff(); + bool linkStatus(); + + static void init(uint8_t* macaddr); + static memhandle receivePacket(); + static void freePacket(); + static memaddress blockSize(memhandle handle); + static void sendPacket(memhandle handle); + static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); + static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); +}; + +extern Enc28J60Network Enc28J60; +#endif /* Enc28J60NetworkClass_H_ */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.c b/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.c new file mode 100644 index 0000000..13b886d --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.c @@ -0,0 +1,28 @@ +/* + clock-arch.c - Arduino implementation of uIP clock device. + Copyright (c) 2010 Adam Nielsen + All rights 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 + */ + +#include +#include "clock-arch.h" + +clock_time_t +clock_time(void) +{ + return (clock_time_t) millis(); +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.h new file mode 100644 index 0000000..d7a828b --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.h @@ -0,0 +1,27 @@ +/* + clock-arch.h - Arduino implementation of uIP clock device. + Copyright (c) 2010 Adam Nielsen + All rights 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 + */ + +#ifndef clock_h_ +#define clock_h_ + +typedef unsigned long clock_time_t; +#define CLOCK_CONF_SECOND 1000 + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/enc28j60.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/enc28j60.h new file mode 100644 index 0000000..3a45c59 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/enc28j60.h @@ -0,0 +1,257 @@ +/***************************************************************************** +* +* Title : Microchip ENC28J60 Ethernet Interface Driver +* Author : Pascal Stang (c)2005 +* Modified by Norbert Truchsess +* Copyright: GPL V2 +* +*This driver provides initialization and transmit/receive +*functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY. +*This chip is novel in that it is a full MAC+PHY interface all in a 28-pin +*chip, using an SPI interface to the host processor. +* +* +*****************************************************************************/ + +#ifndef ENC28J60_H +#define ENC28J60_H +#include + +// ENC28J60 Control Registers +// Control register definitions are a combination of address, +// bank number, and Ethernet/MAC/PHY indicator bits. +// - Register address (bits 0-4) +// - Bank number (bits 5-6) +// - MAC/PHY indicator (bit 7) +#define ADDR_MASK 0x1F +#define BANK_MASK 0x60 +#define SPRD_MASK 0x80 +// All-bank registers +#define EIE 0x1B +#define EIR 0x1C +#define ESTAT 0x1D +#define ECON2 0x1E +#define ECON1 0x1F +// Bank 0 registers +#define ERDPTL (0x00|0x00) +#define ERDPTH (0x01|0x00) +#define EWRPTL (0x02|0x00) +#define EWRPTH (0x03|0x00) +#define ETXSTL (0x04|0x00) +#define ETXSTH (0x05|0x00) +#define ETXNDL (0x06|0x00) +#define ETXNDH (0x07|0x00) +#define ERXSTL (0x08|0x00) +#define ERXSTH (0x09|0x00) +#define ERXNDL (0x0A|0x00) +#define ERXNDH (0x0B|0x00) +#define ERXRDPTL (0x0C|0x00) +#define ERXRDPTH (0x0D|0x00) +#define ERXWRPTL (0x0E|0x00) +#define ERXWRPTH (0x0F|0x00) +#define EDMASTL (0x10|0x00) +#define EDMASTH (0x11|0x00) +#define EDMANDL (0x12|0x00) +#define EDMANDH (0x13|0x00) +#define EDMADSTL (0x14|0x00) +#define EDMADSTH (0x15|0x00) +#define EDMACSL (0x16|0x00) +#define EDMACSH (0x17|0x00) +// Bank 1 registers +#define EHT0 (0x00|0x20) +#define EHT1 (0x01|0x20) +#define EHT2 (0x02|0x20) +#define EHT3 (0x03|0x20) +#define EHT4 (0x04|0x20) +#define EHT5 (0x05|0x20) +#define EHT6 (0x06|0x20) +#define EHT7 (0x07|0x20) +#define EPMM0 (0x08|0x20) +#define EPMM1 (0x09|0x20) +#define EPMM2 (0x0A|0x20) +#define EPMM3 (0x0B|0x20) +#define EPMM4 (0x0C|0x20) +#define EPMM5 (0x0D|0x20) +#define EPMM6 (0x0E|0x20) +#define EPMM7 (0x0F|0x20) +#define EPMCSL (0x10|0x20) +#define EPMCSH (0x11|0x20) +#define EPMOL (0x14|0x20) +#define EPMOH (0x15|0x20) +#define EWOLIE (0x16|0x20) +#define EWOLIR (0x17|0x20) +#define ERXFCON (0x18|0x20) +#define EPKTCNT (0x19|0x20) +// Bank 2 registers +#define MACON1 (0x00|0x40|0x80) +#define MACON2 (0x01|0x40|0x80) +#define MACON3 (0x02|0x40|0x80) +#define MACON4 (0x03|0x40|0x80) +#define MABBIPG (0x04|0x40|0x80) +#define MAIPGL (0x06|0x40|0x80) +#define MAIPGH (0x07|0x40|0x80) +#define MACLCON1 (0x08|0x40|0x80) +#define MACLCON2 (0x09|0x40|0x80) +#define MAMXFLL (0x0A|0x40|0x80) +#define MAMXFLH (0x0B|0x40|0x80) +#define MAPHSUP (0x0D|0x40|0x80) +#define MICON (0x11|0x40|0x80) +#define MICMD (0x12|0x40|0x80) +#define MIREGADR (0x14|0x40|0x80) +#define MIWRL (0x16|0x40|0x80) +#define MIWRH (0x17|0x40|0x80) +#define MIRDL (0x18|0x40|0x80) +#define MIRDH (0x19|0x40|0x80) +// Bank 3 registers +#define MAADR1 (0x00|0x60|0x80) +#define MAADR0 (0x01|0x60|0x80) +#define MAADR3 (0x02|0x60|0x80) +#define MAADR2 (0x03|0x60|0x80) +#define MAADR5 (0x04|0x60|0x80) +#define MAADR4 (0x05|0x60|0x80) +#define EBSTSD (0x06|0x60) +#define EBSTCON (0x07|0x60) +#define EBSTCSL (0x08|0x60) +#define EBSTCSH (0x09|0x60) +#define MISTAT (0x0A|0x60|0x80) +#define EREVID (0x12|0x60) +#define ECOCON (0x15|0x60) +#define EFLOCON (0x17|0x60) +#define EPAUSL (0x18|0x60) +#define EPAUSH (0x19|0x60) +// PHY registers +#define PHCON1 0x00 +#define PHSTAT1 0x01 +#define PHHID1 0x02 +#define PHHID2 0x03 +#define PHCON2 0x10 +#define PHSTAT2 0x11 +#define PHIE 0x12 +#define PHIR 0x13 +#define PHLCON 0x14 + +// ENC28J60 ERXFCON Register Bit Definitions +#define ERXFCON_UCEN 0x80 +#define ERXFCON_ANDOR 0x40 +#define ERXFCON_CRCEN 0x20 +#define ERXFCON_PMEN 0x10 +#define ERXFCON_MPEN 0x08 +#define ERXFCON_HTEN 0x04 +#define ERXFCON_MCEN 0x02 +#define ERXFCON_BCEN 0x01 +// ENC28J60 EIE Register Bit Definitions +#define EIE_INTIE 0x80 +#define EIE_PKTIE 0x40 +#define EIE_DMAIE 0x20 +#define EIE_LINKIE 0x10 +#define EIE_TXIE 0x08 +#define EIE_WOLIE 0x04 +#define EIE_TXERIE 0x02 +#define EIE_RXERIE 0x01 +// ENC28J60 EIR Register Bit Definitions +#define EIR_PKTIF 0x40 +#define EIR_DMAIF 0x20 +#define EIR_LINKIF 0x10 +#define EIR_TXIF 0x08 +#define EIR_WOLIF 0x04 +#define EIR_TXERIF 0x02 +#define EIR_RXERIF 0x01 +// ENC28J60 ESTAT Register Bit Definitions +#define ESTAT_INT 0x80 +#define ESTAT_LATECOL 0x10 +#define ESTAT_RXBUSY 0x04 +#define ESTAT_TXABRT 0x02 +#define ESTAT_CLKRDY 0x01 +// ENC28J60 ECON2 Register Bit Definitions +#define ECON2_AUTOINC 0x80 +#define ECON2_PKTDEC 0x40 +#define ECON2_PWRSV 0x20 +#define ECON2_VRPS 0x08 +// ENC28J60 ECON1 Register Bit Definitions +#define ECON1_TXRST 0x80 +#define ECON1_RXRST 0x40 +#define ECON1_DMAST 0x20 +#define ECON1_CSUMEN 0x10 +#define ECON1_TXRTS 0x08 +#define ECON1_RXEN 0x04 +#define ECON1_BSEL1 0x02 +#define ECON1_BSEL0 0x01 +// ENC28J60 MACON1 Register Bit Definitions +#define MACON1_LOOPBK 0x10 +#define MACON1_TXPAUS 0x08 +#define MACON1_RXPAUS 0x04 +#define MACON1_PASSALL 0x02 +#define MACON1_MARXEN 0x01 +// ENC28J60 MACON2 Register Bit Definitions +#define MACON2_MARST 0x80 +#define MACON2_RNDRST 0x40 +#define MACON2_MARXRST 0x08 +#define MACON2_RFUNRST 0x04 +#define MACON2_MATXRST 0x02 +#define MACON2_TFUNRST 0x01 +// ENC28J60 MACON3 Register Bit Definitions +#define MACON3_PADCFG2 0x80 +#define MACON3_PADCFG1 0x40 +#define MACON3_PADCFG0 0x20 +#define MACON3_TXCRCEN 0x10 +#define MACON3_PHDRLEN 0x08 +#define MACON3_HFRMLEN 0x04 +#define MACON3_FRMLNEN 0x02 +#define MACON3_FULDPX 0x01 +// ENC28J60 MICMD Register Bit Definitions +#define MICMD_MIISCAN 0x02 +#define MICMD_MIIRD 0x01 +// ENC28J60 MISTAT Register Bit Definitions +#define MISTAT_NVALID 0x04 +#define MISTAT_SCAN 0x02 +#define MISTAT_BUSY 0x01 +// ENC28J60 PHY PHCON1 Register Bit Definitions +#define PHCON1_PRST 0x8000 +#define PHCON1_PLOOPBK 0x4000 +#define PHCON1_PPWRSV 0x0800 +#define PHCON1_PDPXMD 0x0100 +// ENC28J60 PHY PHSTAT1 Register Bit Definitions +#define PHSTAT1_PFDPX 0x1000 +#define PHSTAT1_PHDPX 0x0800 +#define PHSTAT1_LLSTAT 0x0004 +#define PHSTAT1_JBSTAT 0x0002 +// ENC28J60 PHY PHCON2 Register Bit Definitions +#define PHCON2_FRCLINK 0x4000 +#define PHCON2_TXDIS 0x2000 +#define PHCON2_JABBER 0x0400 +#define PHCON2_HDLDIS 0x0100 + +// ENC28J60 Packet Control Byte Bit Definitions +#define PKTCTRL_PHUGEEN 0x08 +#define PKTCTRL_PPADEN 0x04 +#define PKTCTRL_PCRCEN 0x02 +#define PKTCTRL_POVERRIDE 0x01 + +// SPI operation codes +#define ENC28J60_READ_CTRL_REG 0x00 +#define ENC28J60_READ_BUF_MEM 0x3A +#define ENC28J60_WRITE_CTRL_REG 0x40 +#define ENC28J60_WRITE_BUF_MEM 0x7A +#define ENC28J60_BIT_FIELD_SET 0x80 +#define ENC28J60_BIT_FIELD_CLR 0xA0 +#define ENC28J60_SOFT_RESET 0xFF + + +// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata +// buffer boundaries applied to internal 8K ram +// the entire available packet buffer space is allocated +// +// start with recbuf at 0/ +#define RXSTART_INIT 0x0 +// receive buffer end. make sure this is an odd value ( See Rev. B1,B4,B5,B7 Silicon Errata 'Memory (Ethernet Buffer)') +#define RXSTOP_INIT (0x1FFF-0x1800) +// start TX buffer RXSTOP_INIT+1 +#define TXSTART_INIT (RXSTOP_INIT+1) +// stp TX buffer at end of mem +#define TXSTOP_INIT 0x1FFF +// +// max frame length which the conroller will accept: +#define MAX_FRAMELEN 1500 // (note: maximum ethernet frame length would be 1518) +//#define MAX_FRAMELEN 600 + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.cpp b/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.cpp new file mode 100644 index 0000000..c2f7abf --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.cpp @@ -0,0 +1,168 @@ +/* + mempool.cpp - sleek implementation of a memory pool + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "mempool.h" +#include + +#define POOLOFFSET 1 + +struct memblock MemoryPool::blocks[MEMPOOL_NUM_MEMBLOCKS+1]; + +void +MemoryPool::init() +{ + memset(&blocks[0], 0, sizeof(blocks)); + blocks[POOLSTART].begin = MEMPOOL_STARTADDRESS; + blocks[POOLSTART].size = 0; + blocks[POOLSTART].nextblock = NOBLOCK; +} + +memhandle +MemoryPool::allocBlock(memaddress size) +{ + memblock* best = NULL; + memhandle cur = POOLSTART; + memblock* block = &blocks[POOLSTART]; + memaddress bestsize = MEMPOOL_SIZE + 1; + + do + { + memhandle next = block->nextblock; + memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - block->begin - block->size; + if (freesize == size) + { + best = &blocks[cur]; + goto found; + } + if (freesize > size && freesize < bestsize) + { + bestsize = freesize; + best = &blocks[cur]; + } + if (next == NOBLOCK) + { + if (best) + goto found; + else + goto collect; + } + block = &blocks[next]; + cur = next; + } + while (true); + + collect: + { + cur = POOLSTART; + block = &blocks[POOLSTART]; + memhandle next; + while ((next = block->nextblock) != NOBLOCK) + { + memaddress dest = block->begin + block->size; + memblock* nextblock = &blocks[next]; + memaddress* src = &nextblock->begin; + if (dest != *src) + { +#ifdef MEMPOOL_MEMBLOCK_MV + MEMPOOL_MEMBLOCK_MV(dest,*src,nextblock->size); +#endif + *src = dest; + } + block = nextblock; + } + if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size) + best = block; + else + goto notfound; + } + + found: + { + block = &blocks[POOLOFFSET]; + for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++) + { + if (block->size) + { + block++; + continue; + } + memaddress address = best->begin + best->size; +#ifdef MEMBLOCK_ALLOC + MEMBLOCK_ALLOC(address,size); +#endif + block->begin = address; + block->size = size; + block->nextblock = best->nextblock; + best->nextblock = cur; + return cur; + } + } + + notfound: return NOBLOCK; +} + +void +MemoryPool::freeBlock(memhandle handle) +{ + if (handle == NOBLOCK) + return; + memblock *b = &blocks[POOLSTART]; + + do + { + memhandle next = b->nextblock; + if (next == handle) + { + memblock *f = &blocks[next]; +#ifdef MEMBLOCK_FREE + MEMBLOCK_FREE(f->begin,f->size); +#endif + b->nextblock = f->nextblock; + f->size = 0; + f->nextblock = NOBLOCK; + return; + } + if (next == NOBLOCK) + return; + b = &blocks[next]; + } + while (true); +} + +void +MemoryPool::resizeBlock(memhandle handle, memaddress position) +{ + memblock * block = &blocks[handle]; + block->begin += position; + block->size -= position; +} + +void +MemoryPool::resizeBlock(memhandle handle, memaddress position, memaddress size) +{ + memblock * block = &blocks[handle]; + block->begin += position; + block->size = size; +} + +memaddress +MemoryPool::blockSize(memhandle handle) +{ + return blocks[handle].size; +} diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.h new file mode 100644 index 0000000..2a1db21 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.h @@ -0,0 +1,54 @@ +/* + mempool.h - sleek implementation of a memory pool + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#ifndef MEMPOOL_H +#define MEMPOOL_H + +#include + +#define POOLSTART 0 +#define NOBLOCK 0 + +#include "mempool_conf.h" + +struct memblock +{ + memaddress begin; + memaddress size; + memhandle nextblock; +}; + +class MemoryPool +{ +#ifdef MEMPOOLTEST_H + friend class MemoryPoolTest; +#endif + +protected: + static struct memblock blocks[MEMPOOL_NUM_MEMBLOCKS+1]; + +public: + static void init(); + static memhandle allocBlock(memaddress); + static void freeBlock(memhandle); + static void resizeBlock(memhandle handle, memaddress position); + static void resizeBlock(memhandle handle, memaddress position, memaddress size); + static memaddress blockSize(memhandle); +}; +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool_conf.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool_conf.h new file mode 100644 index 0000000..9615f92 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool_conf.h @@ -0,0 +1,34 @@ +#ifndef MEMPOOLCONF_H +#define MEMPOOLCONF_H +#include "uipethernet-conf.h" +extern "C" { + #include "uipopt.h" + #include "enc28j60.h" +} +#include + +typedef uint16_t memaddress; +typedef uint8_t memhandle; + +#if UIP_SOCKET_NUMPACKETS and UIP_CONNS +#define NUM_TCP_MEMBLOCKS (UIP_SOCKET_NUMPACKETS*2)*UIP_CONNS +#else +#define NUM_TCP_MEMBLOCKS 0 +#endif + +#if UIP_UDP and UIP_UDP_CONNS +#define NUM_UDP_MEMBLOCKS 3*UIP_UDP_CONNS +#else +#define NUM_UDP_MEMBLOCKS 0 +#endif + +#define MEMPOOL_NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS+NUM_UDP_MEMBLOCKS) + +#define MEMPOOL_STARTADDRESS TXSTART_INIT+1 +#define MEMPOOL_SIZE TXSTOP_INIT-TXSTART_INIT + +void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); + +#define MEMPOOL_MEMBLOCK_MV(dest,src,size) enc28J60_mempool_block_move_callback(dest,src,size) + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip-conf.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip-conf.h new file mode 100644 index 0000000..814aeb9 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip-conf.h @@ -0,0 +1,185 @@ +/** + * UIPEthernet Project-specific configuration options + * Copyright (c) 2013 Norbert Truchsess + * @{ + * + * uIP has a number of configuration options that can be overridden + * for each project. These are kept in a project-specific uip-conf.h + * file and all configuration names have the prefix UIP_CONF. + */ + +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + */ + +#ifndef __UIP_CONF_H__ +#define __UIP_CONF_H__ + +#include +#include "uipethernet-conf.h" + +/** + * 8 bit datatype + * + * This typedef defines the 8-bit type used throughout uIP. + * + * \hideinitializer + */ +typedef uint8_t u8_t; + +/** + * 16 bit datatype + * + * This typedef defines the 16-bit type used throughout uIP. + * + * \hideinitializer + */ +typedef uint16_t u16_t; + +/** + * Statistics datatype + * + * This typedef defines the dataype used for keeping statistics in + * uIP. + * + * \hideinitializer + */ +typedef unsigned short uip_stats_t; + +/** + * Maximum number of TCP connections. + * (see uipethernet-conf.h) + * \hideinitializer + * + * #define UIP_CONF_MAX_CONNECTIONS 4 + */ + +/** + * Maximum number of listening TCP ports. + * + * \hideinitializer + */ +#define UIP_CONF_MAX_LISTENPORTS 4 + +/** + * uIP buffer size. + * + * \hideinitializer + */ +#define UIP_CONF_BUFFER_SIZE 98 +//#define UIP_CONF_BUFFER_SIZE 118 + +/** + * The TCP maximum segment size. + * + * This is should not be to set to more than + * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. + */ + +#define UIP_CONF_TCP_MSS 512 + +/** + * The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the uip_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + * + * \hideinitializer + */ +#define UIP_CONF_RECEIVE_WINDOW 512 + +/** + * CPU byte order. + * + * \hideinitializer + */ +#define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN + +/** + * Logging on or off + * + * \hideinitializer + */ +#define UIP_CONF_LOGGING 0 + +/** + * UDP support on or off + * (see uipethernet-conf.h) + * \hideinitializer + * + * #define UIP_CONF_UDP 1 + * + * #define UIP_CONF_UDP_CONNS 4 + */ + +/** + * UDP checksums on or off + * + * \hideinitializer + */ +#define UIP_CONF_UDP_CHECKSUMS 1 + +/** + * UDP Broadcast (receive) on or off + * (see uipethernet-conf.h) + * \hideinitializer + * #define UIP_CONF_BROADCAST 1 + */ + + +/** + * uIP statistics on or off + * + * \hideinitializer + */ +#define UIP_CONF_STATISTICS 0 + +// SLIP +//#define UIP_CONF_LLH_LEN 0 + +typedef void* uip_tcp_appstate_t; + +void uipclient_appcall(void); + +#define UIP_APPCALL uipclient_appcall + +typedef void* uip_udp_appstate_t; + +void uipudp_appcall(void); + +#define UIP_UDP_APPCALL uipudp_appcall + +#define CC_REGISTER_ARG register + +#define UIP_ARCH_CHKSUM 1 + +#endif /* __UIP_CONF_H__ */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.c b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.c new file mode 100644 index 0000000..84ea8c3 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.c @@ -0,0 +1,1897 @@ +#define DEBUG_PRINTF(...) /*printf(__VA_ARGS__)*/ + +/** + * \defgroup uip The uIP TCP/IP stack + * @{ + * + * uIP is an implementation of the TCP/IP protocol stack intended for + * small 8-bit and 16-bit microcontrollers. + * + * uIP provides the necessary protocols for Internet communication, + * with a very small code footprint and RAM requirements - the uIP + * code size is on the order of a few kilobytes and RAM usage is on + * the order of a few hundred bytes. + */ + +/** + * \file + * The uIP TCP/IP stack code. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip.c,v 1.65 2006/06/11 21:46:39 adam Exp $ + * + */ + +/* + * uIP is a small implementation of the IP, UDP and TCP protocols (as + * well as some basic ICMP stuff). The implementation couples the IP, + * UDP, TCP and the application layers very tightly. To keep the size + * of the compiled code down, this code frequently uses the goto + * statement. While it would be possible to break the uip_process() + * function into many smaller functions, this would increase the code + * size because of the overhead of parameter passing and the fact that + * the optimier would not be as efficient. + * + * The principle is that we have a small buffer, called the uip_buf, + * in which the device driver puts an incoming packet. The TCP/IP + * stack parses the headers in the packet, and calls the + * application. If the remote host has sent data to the application, + * this data is present in the uip_buf and the application read the + * data from there. It is up to the application to put this data into + * a byte stream if needed. The application will not be fed with data + * that is out of sequence. + * + * If the application whishes to send data to the peer, it should put + * its data into the uip_buf. The uip_appdata pointer points to the + * first available byte. The TCP/IP stack will calculate the + * checksums, and fill in the necessary header fields and finally send + * the packet back to the peer. +*/ + +#include "uip.h" +#include "uipopt.h" +#include "uip_arch.h" + +#if UIP_CONF_IPV6 +#include "uip-neighbor.h" +#endif /* UIP_CONF_IPV6 */ + +#include + +/*---------------------------------------------------------------------------*/ +/* Variable definitions. */ + + +/* The IP address of this host. If it is defined to be fixed (by + setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set + here. Otherwise, the address */ +#if UIP_FIXEDADDR > 0 +const uip_ipaddr_t uip_hostaddr = + {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), + HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; +const uip_ipaddr_t uip_draddr = + {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), + HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; +const uip_ipaddr_t uip_netmask = + {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), + HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; +#else +uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; +#endif /* UIP_FIXEDADDR */ + +static const uip_ipaddr_t all_ones_addr = +#if UIP_CONF_IPV6 + {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; +#else /* UIP_CONF_IPV6 */ + {0xffff,0xffff}; +#endif /* UIP_CONF_IPV6 */ +static const uip_ipaddr_t all_zeroes_addr = +#if UIP_CONF_IPV6 + {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; +#else /* UIP_CONF_IPV6 */ + {0x0000,0x0000}; +#endif /* UIP_CONF_IPV6 */ + + +#if UIP_FIXEDETHADDR +const struct uip_eth_addr uip_ethaddr = {{UIP_ETHADDR0, + UIP_ETHADDR1, + UIP_ETHADDR2, + UIP_ETHADDR3, + UIP_ETHADDR4, + UIP_ETHADDR5}}; +#else +struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; +#endif + +#ifndef UIP_CONF_EXTERNAL_BUFFER +u8_t uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains + incoming packets. */ +#endif /* UIP_CONF_EXTERNAL_BUFFER */ + +void *uip_appdata; /* The uip_appdata pointer points to + application data. */ +void *uip_sappdata; /* The uip_appdata pointer points to + the application data which is to + be sent. */ +#if UIP_URGDATA > 0 +void *uip_urgdata; /* The uip_urgdata pointer points to + urgent data (out-of-band data), if + present. */ +u16_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + +u16_t uip_len, uip_slen; + /* The uip_len is either 8 or 16 bits, + depending on the maximum packet + size. */ + +u8_t uip_flags; /* The uip_flags variable is used for + communication between the TCP/IP stack + and the application program. */ +struct uip_conn *uip_conn; /* uip_conn always points to the current + connection. */ + +struct uip_conn uip_conns[UIP_CONNS]; + /* The uip_conns array holds all TCP + connections. */ +u16_t uip_listenports[UIP_LISTENPORTS]; + /* The uip_listenports list all currently + listning ports. */ +#if UIP_UDP +struct uip_udp_conn *uip_udp_conn; +struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +static u16_t ipid; /* Ths ipid variable is an increasing + number that is used for the IP ID + field. */ + +void uip_setipid(u16_t id) { ipid = id; } + +static u8_t iss[4]; /* The iss variable is used for the TCP + initial sequence number. */ + +#if UIP_ACTIVE_OPEN +static u16_t lastport; /* Keeps track of the last port used for + a new connection. */ +#endif /* UIP_ACTIVE_OPEN */ + +/* Temporary variables. */ +u8_t uip_acc32[4]; +static u8_t c, opt; +static u16_t tmp16; + +/* Structures and definitions. */ +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 +#define TCP_CTL 0x3f + +#define TCP_OPT_END 0 /* End of TCP options list */ +#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */ +#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */ + +#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ + +#define ICMP_ECHO_REPLY 0 +#define ICMP_ECHO 8 + +#define ICMP6_ECHO_REPLY 129 +#define ICMP6_ECHO 128 +#define ICMP6_NEIGHBOR_SOLICITATION 135 +#define ICMP6_NEIGHBOR_ADVERTISEMENT 136 + +#define ICMP6_FLAG_S (1 << 6) + +#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1 +#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2 + + +/* Macros. */ +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) +#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) + + +#if UIP_STATISTICS == 1 +struct uip_stats uip_stat; +#define UIP_STAT(s) s +#else +#define UIP_STAT(s) +#endif /* UIP_STATISTICS == 1 */ + +#if UIP_LOGGING == 1 +#include +void uip_log(char *msg); +#define UIP_LOG(m) uip_log(m) +#else +#define UIP_LOG(m) +#endif /* UIP_LOGGING == 1 */ + +#if ! UIP_ARCH_ADD32 +void +uip_add32(u8_t *op32, u16_t op16) +{ + uip_acc32[3] = op32[3] + (op16 & 0xff); + uip_acc32[2] = op32[2] + (op16 >> 8); + uip_acc32[1] = op32[1]; + uip_acc32[0] = op32[0]; + + if(uip_acc32[2] < (op16 >> 8)) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + + + if(uip_acc32[3] < (op16 & 0xff)) { + ++uip_acc32[2]; + if(uip_acc32[2] == 0) { + ++uip_acc32[1]; + if(uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + } +} + +#endif /* UIP_ARCH_ADD32 */ + +#if ! UIP_ARCH_CHKSUM +/*---------------------------------------------------------------------------*/ +static u16_t +chksum(u16_t sum, const u8_t *data, u16_t len) +{ + u16_t t; + const u8_t *dataptr; + const u8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) { /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + dataptr += 2; + } + + if(dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if(sum < t) { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} +/*---------------------------------------------------------------------------*/ +u16_t +uip_chksum(u16_t *data, u16_t len) +{ + return htons(chksum(0, (u8_t *)data, len)); +} +/*---------------------------------------------------------------------------*/ +#ifndef UIP_ARCH_IPCHKSUM +u16_t +uip_ipchksum(void) +{ + u16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + DEBUG_PRINTF("uip_ipchksum: sum 0x%04x\n", sum); + return (sum == 0) ? 0xffff : htons(sum); +} +#endif +/*---------------------------------------------------------------------------*/ +static u16_t +upper_layer_chksum(u8_t proto) +{ + u16_t upper_layer_len; + u16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ + sum = upper_layer_len + proto; + /* Sum IP source and destination addresses. */ + sum = chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + /* Sum TCP header and data. */ + sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], + upper_layer_len); + + return (sum == 0) ? 0xffff : htons(sum); +} +/*---------------------------------------------------------------------------*/ +#if UIP_CONF_IPV6 +u16_t +uip_icmp6chksum(void) +{ + return upper_layer_chksum(UIP_PROTO_ICMP6); + +} +#endif /* UIP_CONF_IPV6 */ +/*---------------------------------------------------------------------------*/ +u16_t +uip_tcpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_TCP); +} +/*---------------------------------------------------------------------------*/ +#if UIP_UDP_CHECKSUMS +u16_t +uip_udpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_UDP); +} +#endif /* UIP_UDP_CHECKSUMS */ +#endif /* UIP_ARCH_CHKSUM */ +/*---------------------------------------------------------------------------*/ +void +uip_init(void) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + uip_listenports[c] = 0; + } + for(c = 0; c < UIP_CONNS; ++c) { + uip_conns[c].tcpstateflags = UIP_CLOSED; + } +#if UIP_ACTIVE_OPEN + lastport = 1024; +#endif /* UIP_ACTIVE_OPEN */ + +#if UIP_UDP + for(c = 0; c < UIP_UDP_CONNS; ++c) { + uip_udp_conns[c].lport = 0; + } +#endif /* UIP_UDP */ + + + /* IPv4 initialization. */ +#if UIP_FIXEDADDR == 0 + /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/ +#endif /* UIP_FIXEDADDR */ + +} +/*---------------------------------------------------------------------------*/ +#if UIP_ACTIVE_OPEN +struct uip_conn * +uip_connect(uip_ipaddr_t *ripaddr, u16_t rport) +{ + register struct uip_conn *conn, *cconn; + + /* Find an unused local port. */ + again: + ++lastport; + + if(lastport >= 32000) { + lastport = 4096; + } + + /* Check if this port is already in use, and if so try to find + another one. */ + for(c = 0; c < UIP_CONNS; ++c) { + conn = &uip_conns[c]; + if(conn->tcpstateflags != UIP_CLOSED && + conn->lport == htons(lastport)) { + goto again; + } + } + + conn = 0; + for(c = 0; c < UIP_CONNS; ++c) { + cconn = &uip_conns[c]; + if(cconn->tcpstateflags == UIP_CLOSED) { + conn = cconn; + break; + } + if(cconn->tcpstateflags == UIP_TIME_WAIT) { + if(conn == 0 || + cconn->timer > conn->timer) { + conn = cconn; + } + } + } + + if(conn == 0) { + return 0; + } + + conn->tcpstateflags = UIP_SYN_SENT; + + conn->snd_nxt[0] = iss[0]; + conn->snd_nxt[1] = iss[1]; + conn->snd_nxt[2] = iss[2]; + conn->snd_nxt[3] = iss[3]; + + conn->initialmss = conn->mss = UIP_TCP_MSS; + + conn->len = 1; /* TCP length of the SYN is one. */ + conn->nrtx = 0; + conn->timer = 1; /* Send the SYN next time around. */ + conn->rto = UIP_RTO; + conn->sa = 0; + conn->sv = 16; /* Initial value of the RTT variance. */ + conn->lport = htons(lastport); + conn->rport = rport; + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + + return conn; +} +#endif /* UIP_ACTIVE_OPEN */ +/*---------------------------------------------------------------------------*/ +#if UIP_UDP +struct uip_udp_conn * +uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) +{ + register struct uip_udp_conn *conn; + + /* Find an unused local port. */ + again: + ++lastport; + + if(lastport >= 32000) { + lastport = 4096; + } + + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == htons(lastport)) { + goto again; + } + } + + + conn = 0; + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if(uip_udp_conns[c].lport == 0) { + conn = &uip_udp_conns[c]; + break; + } + } + + if(conn == 0) { + return 0; + } + + conn->lport = HTONS(lastport); + conn->rport = rport; + if(ripaddr == NULL) { + memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t)); + } else { + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + } + conn->ttl = UIP_TTL; + + return conn; +} +#endif /* UIP_UDP */ +/*---------------------------------------------------------------------------*/ +void +uip_unlisten(u16_t port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(uip_listenports[c] == port) { + uip_listenports[c] = 0; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +void +uip_listen(u16_t port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(uip_listenports[c] == 0) { + uip_listenports[c] = port; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +/* XXX: IP fragment reassembly: not well-tested. */ + +#if UIP_REASSEMBLY && !UIP_CONF_IPV6 +#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) +static u8_t uip_reassbuf[UIP_REASS_BUFSIZE]; +static u8_t uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; +static const u8_t bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, + 0x0f, 0x07, 0x03, 0x01}; +static u16_t uip_reasslen; +static u8_t uip_reassflags; +#define UIP_REASS_FLAG_LASTFRAG 0x01 +static u8_t uip_reasstmr; + +#define IP_MF 0x20 + +static u8_t +uip_reass(void) +{ + u16_t offset, len; + u16_t i; + + /* If ip_reasstmr is zero, no packet is present in the buffer, so we + write the IP header of the fragment into the reassembly + buffer. The timer is updated with the maximum age. */ + if(uip_reasstmr == 0) { + memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN); + uip_reasstmr = UIP_REASS_MAXAGE; + uip_reassflags = 0; + /* Clear the bitmap. */ + memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); + } + + /* Check if the incoming fragment matches the one currently present + in the reasembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if(BUF->srcipaddr[0] == FBUF->srcipaddr[0] && + BUF->srcipaddr[1] == FBUF->srcipaddr[1] && + BUF->destipaddr[0] == FBUF->destipaddr[0] && + BUF->destipaddr[1] == FBUF->destipaddr[1] && + BUF->ipid[0] == FBUF->ipid[0] && + BUF->ipid[1] == FBUF->ipid[1]) { + + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; + + /* If the offset or the offset + fragment length overflows the + reassembly buffer, we discard the entire packet. */ + if(offset > UIP_REASS_BUFSIZE || + offset + len > UIP_REASS_BUFSIZE) { + uip_reasstmr = 0; + goto nullreturn; + } + + /* Copy the fragment into the reassembly buffer, at the right + offset. */ + memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], + (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), + len); + + /* Update the bitmap. */ + if(offset / (8 * 8) == (offset + len) / (8 * 8)) { + /* If the two endpoints are in the same byte, we only update + that byte. */ + + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7] & + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } else { + /* If the two endpoints are in different bytes, we update the + bytes in the endpoints and fill the stuff inbetween with + 0xff. */ + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7]; + for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { + uip_reassbitmap[i] = 0xff; + } + uip_reassbitmap[(offset + len) / (8 * 8)] |= + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } + + /* If this fragment has the More Fragments flag set to zero, we + know that this is the last fragment, so we can calculate the + size of the entire packet. We also set the + IP_REASS_FLAG_LASTFRAG flag to indicate that we have received + the final fragment. */ + + if((BUF->ipoffset[0] & IP_MF) == 0) { + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; + uip_reasslen = offset + len; + } + + /* Finally, we check if we have a full packet in the buffer. We do + this by checking if we have the last fragment and if all bits + in the bitmap are set. */ + if(uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { + /* Check all bytes up to and including all but the last byte in + the bitmap. */ + for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { + if(uip_reassbitmap[i] != 0xff) { + goto nullreturn; + } + } + /* Check the last byte in the bitmap. It should contain just the + right amount of bits. */ + if(uip_reassbitmap[uip_reasslen / (8 * 8)] != + (u8_t)~bitmap_bits[uip_reasslen / 8 & 7]) { + goto nullreturn; + } + + /* If we have come this far, we have a full packet in the + buffer, so we allocate a pbuf and copy the packet into it. We + also reset the timer. */ + uip_reasstmr = 0; + memcpy(BUF, FBUF, uip_reasslen); + + /* Pretend to be a "normal" (i.e., not fragmented) IP packet + from now on. */ + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + BUF->len[0] = uip_reasslen >> 8; + BUF->len[1] = uip_reasslen & 0xff; + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + + return uip_reasslen; + } + } + + nullreturn: + return 0; +} +#endif /* UIP_REASSEMBLY */ +/*---------------------------------------------------------------------------*/ +static void +uip_add_rcv_nxt(u16_t n) +{ + uip_add32(uip_conn->rcv_nxt, n); + uip_conn->rcv_nxt[0] = uip_acc32[0]; + uip_conn->rcv_nxt[1] = uip_acc32[1]; + uip_conn->rcv_nxt[2] = uip_acc32[2]; + uip_conn->rcv_nxt[3] = uip_acc32[3]; +} +/*---------------------------------------------------------------------------*/ +void +uip_process(u8_t flag) +{ + register struct uip_conn *uip_connr = uip_conn; + +#if UIP_UDP + if(flag == UIP_UDP_SEND_CONN) { + goto udp_send; + } +#endif /* UIP_UDP */ + + uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + + /* Check if we were invoked because of a poll request for a + particular connection. */ + if(flag == UIP_POLL_REQUEST) { + if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && + !uip_outstanding(uip_connr)) { + uip_flags = UIP_POLL; + UIP_APPCALL(); + goto appsend; + } + goto drop; + + /* Check if we were invoked because of the perodic timer fireing. */ + } else if(flag == UIP_TIMER) { +#if UIP_REASSEMBLY + if(uip_reasstmr != 0) { + --uip_reasstmr; + } +#endif /* UIP_REASSEMBLY */ + /* Increase the initial sequence number. */ + if(++iss[3] == 0) { + if(++iss[2] == 0) { + if(++iss[1] == 0) { + ++iss[0]; + } + } + } + + /* Reset the length variables. */ + uip_len = 0; + uip_slen = 0; + + /* Check if the connection is in a state in which we simply wait + for the connection to time out. If so, we increase the + connection's timer and remove the connection if it times + out. */ + if(uip_connr->tcpstateflags == UIP_TIME_WAIT || + uip_connr->tcpstateflags == UIP_FIN_WAIT_2) { + ++(uip_connr->timer); + if(uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) { + uip_connr->tcpstateflags = UIP_CLOSED; + } + } else if(uip_connr->tcpstateflags != UIP_CLOSED) { + /* If the connection has outstanding data, we increase the + connection's timer and see if it has reached the RTO value + in which case we retransmit. */ + if(uip_outstanding(uip_connr)) { + if(uip_connr->timer-- == 0) { + if(uip_connr->nrtx == UIP_MAXRTX || + ((uip_connr->tcpstateflags == UIP_SYN_SENT || + uip_connr->tcpstateflags == UIP_SYN_RCVD) && + uip_connr->nrtx == UIP_MAXSYNRTX)) { + uip_connr->tcpstateflags = UIP_CLOSED; + + /* We call UIP_APPCALL() with uip_flags set to + UIP_TIMEDOUT to inform the application that the + connection has timed out. */ + uip_flags = UIP_TIMEDOUT; + UIP_APPCALL(); + + /* We also send a reset packet to the remote host. */ + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + /* Exponential backoff. */ + uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4? + 4: + uip_connr->nrtx); + ++(uip_connr->nrtx); + + /* Ok, so we need to retransmit. We do this differently + depending on which state we are in. In ESTABLISHED, we + call upon the application so that it may prepare the + data for the retransmit. In SYN_RCVD, we resend the + SYNACK that we sent earlier and in LAST_ACK we have to + retransmit our FINACK. */ + UIP_STAT(++uip_stat.tcp.rexmit); + switch(uip_connr->tcpstateflags & UIP_TS_MASK) { + case UIP_SYN_RCVD: + /* In the SYN_RCVD state, we should retransmit our + SYNACK. */ + goto tcp_send_synack; + +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In the SYN_SENT state, we retransmit out SYN. */ + BUF->flags = 0; + goto tcp_send_syn; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application + to do the actual retransmit after which we jump into + the code for sending out the packet (the apprexmit + label). */ + uip_flags = UIP_REXMIT; + UIP_APPCALL(); + goto apprexmit; + + case UIP_FIN_WAIT_1: + case UIP_CLOSING: + case UIP_LAST_ACK: + /* In all these states we should retransmit a FINACK. */ + goto tcp_send_finack; + + } + } + } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { + /* If there was no need for a retransmission, we poll the + application for new data. */ + uip_flags = UIP_POLL; + UIP_APPCALL(); + goto appsend; + } + } + goto drop; + } +#if UIP_UDP + if(flag == UIP_UDP_TIMER) { + if(uip_udp_conn->lport != 0) { + uip_conn = NULL; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_len = uip_slen = 0; + uip_flags = UIP_POLL; + UIP_UDP_APPCALL(); + goto udp_send; + } else { + goto drop; + } + } +#endif + + /* This is where the input processing starts. */ + UIP_STAT(++uip_stat.ip.recv); + + /* Start of IP input header processing code. */ + +#if UIP_CONF_IPV6 + /* Check validity of the IP header. */ + if((BUF->vtc & 0xf0) != 0x60) { /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ipv6: invalid version."); + goto drop; + } +#else /* UIP_CONF_IPV6 */ + /* Check validity of the IP header. */ + if(BUF->vhl != 0x45) { /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ip: invalid version or header length."); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + + /* Check the size of the packet. If the size reported to us in + uip_len is smaller the size reported in the IP header, we assume + that the packet has been corrupted in transit. If the size of + uip_len is larger than the size reported in the IP packet header, + the packet has been padded and we set uip_len to the correct + value.. */ + + if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) { + uip_len = (BUF->len[0] << 8) + BUF->len[1]; +#if UIP_CONF_IPV6 + uip_len += 40; /* The length reported in the IPv6 header is the + length of the payload that follows the + header. However, uIP uses the uip_len variable + for holding the size of the entire packet, + including the IP header. For IPv4 this is not a + problem as the length field in the IPv4 header + contains the length of the entire packet. But + for IPv6 we need to add the size of the IPv6 + header (40 bytes). */ +#endif /* UIP_CONF_IPV6 */ + } else { + UIP_LOG("ip: packet shorter than reported in IP header."); + goto drop; + } + +#if !UIP_CONF_IPV6 + /* Check the fragment flag. */ + if((BUF->ipoffset[0] & 0x3f) != 0 || + BUF->ipoffset[1] != 0) { +#if UIP_REASSEMBLY + uip_len = uip_reass(); + if(uip_len == 0) { + goto drop; + } +#else /* UIP_REASSEMBLY */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.fragerr); + UIP_LOG("ip: fragment dropped."); + goto drop; +#endif /* UIP_REASSEMBLY */ + } +#endif /* UIP_CONF_IPV6 */ + + if(uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) { + /* If we are configured to use ping IP address configuration and + hasn't been assigned an IP address yet, we accept all ICMP + packets. */ +#if UIP_PINGADDRCONF && !UIP_CONF_IPV6 + if(BUF->proto == UIP_PROTO_ICMP) { + UIP_LOG("ip: possible ping config packet received."); + goto icmp_input; + } else { + UIP_LOG("ip: packet dropped since no address assigned."); + goto drop; + } +#endif /* UIP_PINGADDRCONF */ + + } else { + /* If IP broadcast support is configured, we check for a broadcast + UDP packet, which may be destined to us. */ +#if UIP_BROADCAST + DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum()); + if(BUF->proto == UIP_PROTO_UDP && + uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) + /*&& + uip_ipchksum() == 0xffff*/) { + goto udp_input; + } +#endif /* UIP_BROADCAST */ + + /* Check if the packet is destined for our IP address. */ +#if !UIP_CONF_IPV6 + if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#else /* UIP_CONF_IPV6 */ + /* For IPv6, packet reception is a little trickier as we need to + make sure that we listen to certain multicast addresses (all + hosts multicast address, and the solicited-node multicast + address) as well. However, we will cheat here and accept all + multicast packets that are sent to the ff02::/16 addresses. */ + if(!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) && + BUF->destipaddr[0] != HTONS(0xff02)) { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + } + +#if !UIP_CONF_IPV6 + if(uip_ipchksum() != 0xffff) { /* Compute and check the IP header + checksum. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.chkerr); + UIP_LOG("ip: bad checksum."); + goto drop; + } +#endif /* UIP_CONF_IPV6 */ + + if(BUF->proto == UIP_PROTO_TCP) { /* Check for TCP packet. If so, + proceed with TCP input + processing. */ + goto tcp_input; + } + +#if UIP_UDP + if(BUF->proto == UIP_PROTO_UDP) { + goto udp_input; + } +#endif /* UIP_UDP */ + +#if !UIP_CONF_IPV6 + /* ICMPv4 processing code follows. */ + if(BUF->proto != UIP_PROTO_ICMP) { /* We only allow ICMP packets from + here. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp."); + goto drop; + } + +#if UIP_PINGADDRCONF + icmp_input: +#endif /* UIP_PINGADDRCONF */ + UIP_STAT(++uip_stat.icmp.recv); + + /* ICMP echo (i.e., ping) processing. This is simple, we only change + the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP + checksum before we return the packet. */ + if(ICMPBUF->type != ICMP_ECHO) { + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: not icmp echo."); + goto drop; + } + + /* If we are configured to use ping IP address assignment, we use + the destination IP address of this ping packet and assign it to + ourself. */ +#if UIP_PINGADDRCONF + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0) { + uip_hostaddr[0] = BUF->destipaddr[0]; + uip_hostaddr[1] = BUF->destipaddr[1]; + } +#endif /* UIP_PINGADDRCONF */ + + ICMPBUF->type = ICMP_ECHO_REPLY; + + if(ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; + } else { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); + } + + /* Swap IP addresses. */ + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + + /* End of IPv4 input header processing code. */ +#else /* !UIP_CONF_IPV6 */ + + /* This is IPv6 ICMPv6 processing code. */ + DEBUG_PRINTF("icmp6_input: length %d\n", uip_len); + + if(BUF->proto != UIP_PROTO_ICMP6) { /* We only allow ICMPv6 packets from + here. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp6."); + goto drop; + } + + UIP_STAT(++uip_stat.icmp.recv); + + /* If we get a neighbor solicitation for our address we should send + a neighbor advertisement message back. */ + if(ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) { + if(uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) { + + if(ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) { + /* Save the sender's address in our neighbor list. */ + uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); + } + + /* We should now send a neighbor advertisement back to where the + neighbor solicication came from. */ + ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; + ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ + + ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; + + uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr); + uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr); + ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; + ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ + memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr)); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + goto send; + + } + goto drop; + } else if(ICMPBUF->type == ICMP6_ECHO) { + /* ICMP echo (i.e., ping) processing. This is simple, we only + change the ICMP type from ECHO to ECHO_REPLY and update the + ICMP checksum before we return the packet. */ + + ICMPBUF->type = ICMP6_ECHO_REPLY; + + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + } else { + DEBUG_PRINTF("Unknown icmp6 message type %d\n", ICMPBUF->type); + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: unknown ICMP message."); + goto drop; + } + + /* End of IPv6 ICMP processing. */ + +#endif /* !UIP_CONF_IPV6 */ + +#if UIP_UDP + /* UDP input processing. */ + udp_input: + /* UDP processing is really just a hack. We don't do anything to the + UDP/IP headers, but let the UDP application do all the hard + work. If the application sets uip_slen, it has a packet to + send. */ +#if UIP_UDP_CHECKSUMS + uip_len = uip_len - UIP_IPUDPH_LEN; + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + if(UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) { + UIP_STAT(++uip_stat.udp.drop); + UIP_STAT(++uip_stat.udp.chkerr); + UIP_LOG("udp: bad checksum."); + goto drop; + } +#else /* UIP_UDP_CHECKSUMS */ + uip_len = uip_len - UIP_IPUDPH_LEN; +#endif /* UIP_UDP_CHECKSUMS */ + + /* Demultiplex this UDP packet between the UDP "connections". */ + for(uip_udp_conn = &uip_udp_conns[0]; + uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; + ++uip_udp_conn) { + /* If the local UDP port is non-zero, the connection is considered + to be used. If so, the local port number is checked against the + destination port number in the received packet. If the two port + numbers match, the remote port number is checked if the + connection is bound to a remote port. Finally, if the + connection is bound to a remote IP address, the source IP + address of the packet is checked. */ + if(uip_udp_conn->lport != 0 && + UDPBUF->destport == uip_udp_conn->lport && + (uip_udp_conn->rport == 0 || + UDPBUF->srcport == uip_udp_conn->rport) && + (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) || + uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || + uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) { + goto udp_found; + } + } + UIP_LOG("udp: no matching connection found"); + goto drop; + + udp_found: + uip_conn = NULL; + uip_flags = UIP_NEWDATA; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_slen = 0; + UIP_UDP_APPCALL(); + udp_send: + if(uip_slen == 0) { + goto drop; + } + uip_len = uip_slen + UIP_IPUDPH_LEN; + +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* UIP_CONF_IPV6 */ + + BUF->ttl = uip_udp_conn->ttl; + BUF->proto = UIP_PROTO_UDP; + + UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN); + UDPBUF->udpchksum = 0; + + BUF->srcport = uip_udp_conn->lport; + BUF->destport = uip_udp_conn->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr); + + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; + +#if UIP_UDP_CHECKSUMS + /* Calculate UDP checksum. */ + UDPBUF->udpchksum = ~(uip_udpchksum()); + if(UDPBUF->udpchksum == 0) { + UDPBUF->udpchksum = 0xffff; + } +#endif /* UIP_UDP_CHECKSUMS */ + + goto ip_send_nolen; +#endif /* UIP_UDP */ + + /* TCP input processing. */ + tcp_input: + UIP_STAT(++uip_stat.tcp.recv); + + /* Start of TCP input header processing code. */ + + if(uip_tcpchksum() != 0xffff) { /* Compute and check the TCP + checksum. */ + UIP_STAT(++uip_stat.tcp.drop); + UIP_STAT(++uip_stat.tcp.chkerr); + UIP_LOG("tcp: bad checksum."); + goto drop; + } + + + /* Demultiplex this segment. */ + /* First check any active connections. */ + for(uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; + ++uip_connr) { + if(uip_connr->tcpstateflags != UIP_CLOSED && + BUF->destport == uip_connr->lport && + BUF->srcport == uip_connr->rport && + uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) { + goto found; + } + } + + /* If we didn't find and active connection that expected the packet, + either this packet is an old duplicate, or this is a SYN packet + destined for a connection in LISTEN. If the SYN flag isn't set, + it is an old packet and we send a RST. */ + if((BUF->flags & TCP_CTL) != TCP_SYN) { + goto reset; + } + + tmp16 = BUF->destport; + /* Next, check listening connections. */ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if(tmp16 == uip_listenports[c]) + goto found_listen; + } + + /* No matching connection found, so we send a RST packet. */ + UIP_STAT(++uip_stat.tcp.synrst); + reset: + + /* We do not send resets in response to resets. */ + if(BUF->flags & TCP_RST) { + goto drop; + } + + UIP_STAT(++uip_stat.tcp.rst); + + BUF->flags = TCP_RST | TCP_ACK; + uip_len = UIP_IPTCPH_LEN; + BUF->tcpoffset = 5 << 4; + + /* Flip the seqno and ackno fields in the TCP header. */ + c = BUF->seqno[3]; + BUF->seqno[3] = BUF->ackno[3]; + BUF->ackno[3] = c; + + c = BUF->seqno[2]; + BUF->seqno[2] = BUF->ackno[2]; + BUF->ackno[2] = c; + + c = BUF->seqno[1]; + BUF->seqno[1] = BUF->ackno[1]; + BUF->ackno[1] = c; + + c = BUF->seqno[0]; + BUF->seqno[0] = BUF->ackno[0]; + BUF->ackno[0] = c; + + /* We also have to increase the sequence number we are + acknowledging. If the least significant byte overflowed, we need + to propagate the carry to the other bytes as well. */ + if(++BUF->ackno[3] == 0) { + if(++BUF->ackno[2] == 0) { + if(++BUF->ackno[1] == 0) { + ++BUF->ackno[0]; + } + } + } + + /* Swap port numbers. */ + tmp16 = BUF->srcport; + BUF->srcport = BUF->destport; + BUF->destport = tmp16; + + /* Swap IP addresses. */ + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + /* And send out the RST packet! */ + goto tcp_send_noconn; + + /* This label will be jumped to if we matched the incoming packet + with a connection in LISTEN. In that case, we should create a new + connection and send a SYNACK in return. */ + found_listen: + /* First we check if there are any connections avaliable. Unused + connections are kept in the same table as used connections, but + unused ones have the tcpstate set to CLOSED. Also, connections in + TIME_WAIT are kept track of and we'll use the oldest one if no + CLOSED connections are found. Thanks to Eddie C. Dost for a very + nice algorithm for the TIME_WAIT search. */ + uip_connr = 0; + for(c = 0; c < UIP_CONNS; ++c) { + if(uip_conns[c].tcpstateflags == UIP_CLOSED) { + uip_connr = &uip_conns[c]; + break; + } + if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) { + if(uip_connr == 0 || + uip_conns[c].timer > uip_connr->timer) { + uip_connr = &uip_conns[c]; + } + } + } + + if(uip_connr == 0) { + /* All connections are used already, we drop packet and hope that + the remote end will retransmit the packet at a time when we + have more spare connections. */ + UIP_STAT(++uip_stat.tcp.syndrop); + UIP_LOG("tcp: found no unused connections."); + goto drop; + } + uip_conn = uip_connr; + + /* Fill in the necessary fields for the new connection. */ + uip_connr->rto = uip_connr->timer = UIP_RTO; + uip_connr->sa = 0; + uip_connr->sv = 4; + uip_connr->nrtx = 0; + uip_connr->lport = BUF->destport; + uip_connr->rport = BUF->srcport; + uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr); + uip_connr->tcpstateflags = UIP_SYN_RCVD; + + uip_connr->snd_nxt[0] = iss[0]; + uip_connr->snd_nxt[1] = iss[1]; + uip_connr->snd_nxt[2] = iss[2]; + uip_connr->snd_nxt[3] = iss[3]; + uip_connr->len = 1; + + /* rcv_nxt should be the seqno from the incoming packet + 1. */ + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_add_rcv_nxt(1); + + /* Parse the TCP MSS option, if present. */ + if((BUF->tcpoffset & 0xf0) > 0x50) { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; + if(opt == TCP_OPT_END) { + /* End of options. */ + break; + } else if(opt == TCP_OPT_NOOP) { + ++c; + /* NOP option. */ + } else if(opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + /* An MSS option with the right option length. */ + tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = uip_connr->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } else { + /* All other options have a length field, so that we easily + can skip past them. */ + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + + /* Our response will be a SYNACK. */ +#if UIP_ACTIVE_OPEN + tcp_send_synack: + BUF->flags = TCP_ACK; + + tcp_send_syn: + BUF->flags |= TCP_SYN; +#else /* UIP_ACTIVE_OPEN */ + tcp_send_synack: + BUF->flags = TCP_SYN | TCP_ACK; +#endif /* UIP_ACTIVE_OPEN */ + + /* We send out the TCP Maximum Segment Size option with our + SYNACK. */ + BUF->optdata[0] = TCP_OPT_MSS; + BUF->optdata[1] = TCP_OPT_MSS_LEN; + BUF->optdata[2] = (UIP_TCP_MSS) / 256; + BUF->optdata[3] = (UIP_TCP_MSS) & 255; + uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; + BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; + goto tcp_send; + + /* This label will be jumped to if we found an active connection. */ + found: + uip_conn = uip_connr; + uip_flags = 0; + /* We do a very naive form of TCP reset processing; we just accept + any RST and kill our connection. We should in fact check if the + sequence number of this reset is wihtin our advertised window + before we accept the reset. */ + if(BUF->flags & TCP_RST) { + uip_connr->tcpstateflags = UIP_CLOSED; + UIP_LOG("tcp: got reset, aborting connection."); + uip_flags = UIP_ABORT; + UIP_APPCALL(); + goto drop; + } + /* Calculated the length of the data, if the application has sent + any data to us. */ + c = (BUF->tcpoffset >> 4) << 2; + /* uip_len will contain the length of the actual TCP data. This is + calculated by subtracing the length of the TCP header (in + c) and the length of the IP header (20 bytes). */ + uip_len = uip_len - c - UIP_IPH_LEN; + + /* First, check if the sequence number of the incoming packet is + what we're expecting next. If not, we send out an ACK with the + correct numbers in. */ + if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && + ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) { + if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) && + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || + BUF->seqno[1] != uip_connr->rcv_nxt[1] || + BUF->seqno[2] != uip_connr->rcv_nxt[2] || + BUF->seqno[3] != uip_connr->rcv_nxt[3])) { + goto tcp_send_ack; + } + } + + /* Next, check if the incoming segment acknowledges any outstanding + data. If so, we update the sequence number, reset the length of + the outstanding data, calculate RTT estimations, and reset the + retransmission timer. */ + if((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) { + uip_add32(uip_connr->snd_nxt, uip_connr->len); + + if(BUF->ackno[0] == uip_acc32[0] && + BUF->ackno[1] == uip_acc32[1] && + BUF->ackno[2] == uip_acc32[2] && + BUF->ackno[3] == uip_acc32[3]) { + /* Update sequence number. */ + uip_connr->snd_nxt[0] = uip_acc32[0]; + uip_connr->snd_nxt[1] = uip_acc32[1]; + uip_connr->snd_nxt[2] = uip_acc32[2]; + uip_connr->snd_nxt[3] = uip_acc32[3]; + + + /* Do RTT estimation, unless we have done retransmissions. */ + if(uip_connr->nrtx == 0) { + signed char m; + m = uip_connr->rto - uip_connr->timer; + /* This is taken directly from VJs original code in his paper */ + m = m - (uip_connr->sa >> 3); + uip_connr->sa += m; + if(m < 0) { + m = -m; + } + m = m - (uip_connr->sv >> 2); + uip_connr->sv += m; + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; + + } + /* Set the acknowledged flag. */ + uip_flags = UIP_ACKDATA; + /* Reset the retransmission timer. */ + uip_connr->timer = uip_connr->rto; + + /* Reset length of outstanding data. */ + uip_connr->len = 0; + } + + } + + /* Do different things depending on in what state the connection is. */ + switch(uip_connr->tcpstateflags & UIP_TS_MASK) { + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not + implemented, since we force the application to close when the + peer sends a FIN (hence the application goes directly from + ESTABLISHED to LAST_ACK). */ + case UIP_SYN_RCVD: + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and + we are waiting for an ACK that acknowledges the data we sent + out the last time. Therefore, we want to have the UIP_ACKDATA + flag set. If so, we enter the ESTABLISHED state. */ + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_flags = UIP_CONNECTED; + uip_connr->len = 0; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + uip_slen = 0; + UIP_APPCALL(); + goto appsend; + } + goto drop; +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In SYN_SENT, we wait for a SYNACK that is sent in response to + our SYN. The rcv_nxt is set to sequence number in the SYNACK + plus one, and we send an ACK. We move into the ESTABLISHED + state. */ + if((uip_flags & UIP_ACKDATA) && + (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) { + + /* Parse the TCP MSS option, if present. */ + if((BUF->tcpoffset & 0xf0) > 0x50) { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; + if(opt == TCP_OPT_END) { + /* End of options. */ + break; + } else if(opt == TCP_OPT_NOOP) { + ++c; + /* NOP option. */ + } else if(opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + /* An MSS option with the right option length. */ + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = + uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } else { + /* All other options have a length field, so that we easily + can skip past them. */ + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_add_rcv_nxt(1); + uip_flags = UIP_CONNECTED | UIP_NEWDATA; + uip_connr->len = 0; + uip_len = 0; + uip_slen = 0; + UIP_APPCALL(); + goto appsend; + } + /* Inform the application that the connection failed */ + uip_flags = UIP_ABORT; + UIP_APPCALL(); + /* The connection is closed after we send the RST */ + uip_conn->tcpstateflags = UIP_CLOSED; + goto reset; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application to feed + data into the uip_buf. If the UIP_ACKDATA flag is set, the + application should put new data into the buffer, otherwise we are + retransmitting an old segment, and the application should put that + data into the buffer. + + If the incoming packet is a FIN, we should close the connection on + this side as well, and we send out a FIN and enter the LAST_ACK + state. We require that there is no outstanding data; otherwise the + sequence numbers will be screwed up. */ + + if(BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + if(uip_outstanding(uip_connr)) { + goto drop; + } + uip_add_rcv_nxt(1 + uip_len); + uip_flags |= UIP_CLOSE; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + } + UIP_APPCALL(); + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_LAST_ACK; + uip_connr->nrtx = 0; + tcp_send_finack: + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* Check the URG flag. If this is set, the segment carries urgent + data that we must pass to the application. */ + if((BUF->flags & TCP_URG) != 0) { +#if UIP_URGDATA > 0 + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; + if(uip_urglen > uip_len) { + /* There is more urgent data in the next segment to come. */ + uip_urglen = uip_len; + } + uip_add_rcv_nxt(uip_urglen); + uip_len -= uip_urglen; + uip_urgdata = uip_appdata; + uip_appdata += uip_urglen; + } else { + uip_urglen = 0; +#else /* UIP_URGDATA > 0 */ + uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]); + uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; +#endif /* UIP_URGDATA > 0 */ + } + + /* If uip_len > 0 we have TCP data in the packet, and we flag this + by setting the UIP_NEWDATA flag and update the sequence number + we acknowledge. If the application has stopped the dataflow + using uip_stop(), we must not accept any data packets from the + remote host. */ + if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + + /* Check if the available buffer space advertised by the other end + is smaller than the initial MSS for this connection. If so, we + set the current MSS to the window size to ensure that the + application does not send more data than the other end can + handle. + + If the remote host advertises a zero window, we set the MSS to + the initial MSS so that the application will send an entire MSS + of data. This data will not be acknowledged by the receiver, + and the application will retransmit it. This is called the + "persistent timer" and uses the retransmission mechanim. + */ + tmp16 = ((u16_t)BUF->wnd[0] << 8) + (u16_t)BUF->wnd[1]; + if(tmp16 > uip_connr->initialmss || + tmp16 == 0) { + tmp16 = uip_connr->initialmss; + } + uip_connr->mss = tmp16; + + /* If this packet constitutes an ACK for outstanding data (flagged + by the UIP_ACKDATA flag, we should call the application since it + might want to send more data. If the incoming packet had data + from the peer (as flagged by the UIP_NEWDATA flag), the + application must also be notified. + + When the application is called, the global variable uip_len + contains the length of the incoming data. The application can + access the incoming data through the global pointer + uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN + bytes into the uip_buf array. + + If the application wishes to send any data, this data should be + put into the uip_appdata and the length of the data should be + put into uip_len. If the application don't have any data to + send, uip_len must be set to 0. */ + if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { + uip_slen = 0; + UIP_APPCALL(); + + appsend: + + if(uip_flags & UIP_ABORT) { + uip_slen = 0; + uip_connr->tcpstateflags = UIP_CLOSED; + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + if(uip_flags & UIP_CLOSE) { + uip_slen = 0; + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_FIN_WAIT_1; + uip_connr->nrtx = 0; + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* If uip_slen > 0, the application has data to be sent. */ + if(uip_slen > 0) { + + /* If the connection has acknowledged data, the contents of + the ->len variable should be discarded. */ + if((uip_flags & UIP_ACKDATA) != 0) { + uip_connr->len = 0; + } + + /* If the ->len variable is non-zero the connection has + already data in transit and cannot send anymore right + now. */ + if(uip_connr->len == 0) { + + /* The application cannot send more than what is allowed by + the mss (the minumum of the MSS and the available + window). */ + if(uip_slen > uip_connr->mss) { + uip_slen = uip_connr->mss; + } + + /* Remember how much data we send out now so that we know + when everything has been acknowledged. */ + uip_connr->len = uip_slen; + } else { + + /* If the application already had unacknowledged data, we + make sure that the application does not send (i.e., + retransmit) out more than it previously sent out. */ + uip_slen = uip_connr->len; + } + } + uip_connr->nrtx = 0; + apprexmit: + uip_appdata = uip_sappdata; + + /* If the application has data to be sent, or if the incoming + packet had new data in it, we must send out a packet. */ + if(uip_slen > 0 && uip_connr->len > 0) { + /* Add the length of the IP and TCP headers. */ + uip_len = uip_connr->len + UIP_TCPIP_HLEN; + /* We always set the ACK flag in response packets. */ + BUF->flags = TCP_ACK | TCP_PSH; + /* Send the packet. */ + goto tcp_send_noopts; + } + /* If there is no data to send, just send out a pure ACK if + there is newdata. */ + if(uip_flags & UIP_NEWDATA) { + uip_len = UIP_TCPIP_HLEN; + BUF->flags = TCP_ACK; + goto tcp_send_noopts; + } + } + goto drop; + case UIP_LAST_ACK: + /* We can close this connection if the peer has acknowledged our + FIN. This is indicated by the UIP_ACKDATA flag. */ + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_CLOSED; + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + } + break; + + case UIP_FIN_WAIT_1: + /* The application has closed the connection, but the remote host + hasn't closed its end yet. Thus we do nothing but wait for a + FIN from the other side. */ + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(BUF->flags & TCP_FIN) { + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_connr->len = 0; + } else { + uip_connr->tcpstateflags = UIP_CLOSING; + } + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } else if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_FIN_WAIT_2; + uip_connr->len = 0; + goto drop; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_FIN_WAIT_2: + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(BUF->flags & TCP_FIN) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_TIME_WAIT: + goto tcp_send_ack; + + case UIP_CLOSING: + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + } + } + goto drop; + + + /* We jump here when we are ready to send the packet, and just want + to set the appropriate TCP sequence numbers in the TCP header. */ + tcp_send_ack: + BUF->flags = TCP_ACK; + tcp_send_nodata: + uip_len = UIP_IPTCPH_LEN; + tcp_send_noopts: + BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; + tcp_send: + /* We're done with the input processing. We are now ready to send a + reply. Our job is to fill in all the fields of the TCP and IP + headers before calculating the checksum and finally send the + packet. */ + BUF->ackno[0] = uip_connr->rcv_nxt[0]; + BUF->ackno[1] = uip_connr->rcv_nxt[1]; + BUF->ackno[2] = uip_connr->rcv_nxt[2]; + BUF->ackno[3] = uip_connr->rcv_nxt[3]; + + BUF->seqno[0] = uip_connr->snd_nxt[0]; + BUF->seqno[1] = uip_connr->snd_nxt[1]; + BUF->seqno[2] = uip_connr->snd_nxt[2]; + BUF->seqno[3] = uip_connr->snd_nxt[3]; + + BUF->proto = UIP_PROTO_TCP; + + BUF->srcport = uip_connr->lport; + BUF->destport = uip_connr->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr); + + if(uip_connr->tcpstateflags & UIP_STOPPED) { + /* If the connection has issued uip_stop(), we advertise a zero + window so that the remote host will stop sending data. */ + BUF->wnd[0] = BUF->wnd[1] = 0; + } else { + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); + } + + tcp_send_noconn: + BUF->ttl = UIP_TTL; +#if UIP_CONF_IPV6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* UIP_CONF_IPV6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* UIP_CONF_IPV6 */ + + BUF->urgp[0] = BUF->urgp[1] = 0; + + /* Calculate TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + + ip_send_nolen: + +#if UIP_CONF_IPV6 + BUF->vtc = 0x60; + BUF->tcflow = 0x00; + BUF->flow = 0x00; +#else /* UIP_CONF_IPV6 */ + BUF->vhl = 0x45; + BUF->tos = 0; + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + ++ipid; + BUF->ipid[0] = ipid >> 8; + BUF->ipid[1] = ipid & 0xff; + /* Calculate IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + DEBUG_PRINTF("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum()); +#endif /* UIP_CONF_IPV6 */ + + UIP_STAT(++uip_stat.tcp.sent); + send: + DEBUG_PRINTF("Sending packet with length %d (%d)\n", uip_len, + (BUF->len[0] << 8) | BUF->len[1]); + + UIP_STAT(++uip_stat.ip.sent); + /* Return and let the caller do the actual transmission. */ + uip_flags = 0; + return; + drop: + uip_len = 0; + uip_flags = 0; + return; +} +/*---------------------------------------------------------------------------*/ +u16_t +htons(u16_t val) +{ + return HTONS(val); +} +/*---------------------------------------------------------------------------*/ +void +uip_send(const void *data, int len) +{ + uip_slen = len; + if(len > 0) { + if(data != uip_sappdata) { + memcpy(uip_sappdata, (data), uip_slen); + } + } +} +/** @} */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.h new file mode 100644 index 0000000..4fc0452 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.h @@ -0,0 +1,1601 @@ + +/** + * \addtogroup uip + * @{ + */ + +/** + * \file + * Header file for the uIP TCP/IP stack. + * \author Adam Dunkels + * + * The uIP TCP/IP stack header file contains definitions for a number + * of C macros that are used by uIP programs as well as internal uIP + * structures, TCP/IP header structures and function declarations. + * + */ + + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip.h,v 1.40 2006/06/08 07:12:07 adam Exp $ + * + */ + +#ifndef __UIP_H__ +#define __UIP_H__ + +#include "uipopt.h" + +/** + * Repressentation of an IP address. + * + */ +typedef u16_t uip_ip4addr_t[2]; +typedef u16_t uip_ip6addr_t[8]; +#if UIP_CONF_IPV6 +typedef uip_ip6addr_t uip_ipaddr_t; +#else /* UIP_CONF_IPV6 */ +typedef uip_ip4addr_t uip_ipaddr_t; +#endif /* UIP_CONF_IPV6 */ + +/*---------------------------------------------------------------------------*/ +/* First, the functions that should be called from the + * system. Initialization, the periodic timer and incoming packets are + * handled by the following three functions. + */ + +/** + * \defgroup uipconffunc uIP configuration functions + * @{ + * + * The uIP configuration functions are used for setting run-time + * parameters in uIP such as IP addresses. + */ + +/** + * Set the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + \code + + uip_ipaddr_t addr; + + uip_ipaddr(&addr, 192,168,1,2); + uip_sethostaddr(&addr); + + \endcode + * \param addr A pointer to an IP address of type uip_ipaddr_t; + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr)) + +/** + * Get the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + \code + uip_ipaddr_t hostaddr; + + uip_gethostaddr(&hostaddr); + \endcode + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the currently configured IP address. + * + * \hideinitializer + */ +#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr) + +/** + * Set the default router's IP address. + * + * \param addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the default router. + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr)) + +/** + * Set the netmask. + * + * \param addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the netmask. + * + * \sa uip_ipaddr() + * + * \hideinitializer + */ +#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr)) + + +/** + * Get the default router's IP address. + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address of the default router. + * + * \hideinitializer + */ +#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr) + +/** + * Get the netmask. + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the value of the netmask. + * + * \hideinitializer + */ +#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask) + +/** @} */ + +/** + * \defgroup uipinit uIP initialization functions + * @{ + * + * The uIP initialization functions are used for booting uIP. + */ + +/** + * uIP initialization function. + * + * This function should be called at boot up to initilize the uIP + * TCP/IP stack. + */ +void uip_init(void); + +/** + * uIP initialization function. + * + * This function may be used at boot time to set the initial ip_id. + */ +void uip_setipid(u16_t id); + +/** @} */ + +/** + * \defgroup uipdevfunc uIP device driver functions + * @{ + * + * These functions are used by a network device driver for interacting + * with uIP. + */ + +/** + * Process an incoming packet. + * + * This function should be called when the device driver has received + * a packet from the network. The packet from the device driver must + * be present in the uip_buf buffer, and the length of the packet + * should be placed in the uip_len variable. + * + * When the function returns, there may be an outbound packet placed + * in the uip_buf packet buffer. If so, the uip_len variable is set to + * the length of the packet. If no packet is to be sent out, the + * uip_len variable is set to 0. + * + * The usual way of calling the function is presented by the source + * code below. + \code + uip_len = devicedriver_poll(); + if(uip_len > 0) { + uip_input(); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uIP ARP code before calling + * this function: + \code + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + uip_len = ethernet_devicedrver_poll(); + if(uip_len > 0) { + if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { + uip_arp_ipin(); + uip_input(); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(); + if(uip_len > 0) { + ethernet_devicedriver_send(); + } + } + \endcode + * + * \hideinitializer + */ +#define uip_input() uip_process(UIP_DATA) + +/** + * Periodic processing for a connection identified by its number. + * + * This function does the necessary periodic processing (timers, + * polling) for a uIP TCP conneciton, and should be called when the + * periodic uIP timer goes off. It should be called for every + * connection, regardless of whether they are open of closed. + * + * When the function returns, it may have an outbound packet waiting + * for service in the uIP packet buffer, and if so the uip_len + * variable is set to a value larger than zero. The device driver + * should be called to send out the packet. + * + * The ususal way of calling the function is through a for() loop like + * this: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uip_arp_out() function before + * calling the device driver: + \code + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the connection which is to be periodically polled. + * + * \hideinitializer + */ +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ + uip_process(UIP_TIMER); } while (0) + +/** + * + * + */ +#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) + +/** + * Perform periodic processing for a connection identified by a pointer + * to its structure. + * + * Same as uip_periodic() but takes a pointer to the actual uip_conn + * struct instead of an integer as its argument. This function can be + * used to force periodic processing of a specific connection. + * + * \param conn A pointer to the uip_conn struct for the connection to + * be processed. + * + * \hideinitializer + */ +#define uip_periodic_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_TIMER); } while (0) + +/** + * Reuqest that a particular connection should be polled. + * + * Similar to uip_periodic_conn() but does not perform any timer + * processing. The application is polled for new data. + * + * \param conn A pointer to the uip_conn struct for the connection to + * be processed. + * + * \hideinitializer + */ +#define uip_poll_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_POLL_REQUEST); } while (0) + + +#if UIP_UDP +/** + * Periodic processing for a UDP connection identified by its number. + * + * This function is essentially the same as uip_periodic(), but for + * UDP connections. It is called in a similar fashion as the + * uip_periodic() function: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } + \endcode + * + * \note As for the uip_periodic() function, special care has to be + * taken when using uIP together with ARP and Ethernet: + \code + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } + \endcode + * + * \param conn The number of the UDP connection to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ + uip_process(UIP_UDP_TIMER); } while (0) + +/** + * Periodic processing for a UDP connection identified by a pointer to + * its structure. + * + * Same as uip_udp_periodic() but takes a pointer to the actual + * uip_conn struct instead of an integer as its argument. This + * function can be used to force periodic processing of a specific + * connection. + * + * \param conn A pointer to the uip_udp_conn struct for the connection + * to be processed. + * + * \hideinitializer + */ +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ + uip_process(UIP_UDP_TIMER); } while (0) + + +#endif /* UIP_UDP */ + +/** + * The uIP packet buffer. + * + * The uip_buf array is used to hold incoming and outgoing + * packets. The device driver should place incoming data into this + * buffer. When sending data, the device driver should read the link + * level headers and the TCP/IP headers from this buffer. The size of + * the link level headers is configured by the UIP_LLH_LEN define. + * + * \note The application data need not be placed in this buffer, so + * the device driver must read it from the place pointed to by the + * uip_appdata pointer as illustrated by the following example: + \code + void + devicedriver_send(void) + { + hwsend(&uip_buf[0], UIP_LLH_LEN); + if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) { + hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN); + } else { + hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN); + hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN); + } + } + \endcode + */ +extern u8_t uip_buf[UIP_BUFSIZE+2]; + +/** @} */ + +/*---------------------------------------------------------------------------*/ +/* Functions that are used by the uIP application program. Opening and + * closing connections, sending and receiving data, etc. is all + * handled by the functions below. +*/ +/** + * \defgroup uipappfunc uIP application functions + * @{ + * + * Functions used by an application running of top of uIP. + */ + +/** + * Start listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_listen(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. + */ +void uip_listen(u16_t port); + +/** + * Stop listening to the specified port. + * + * \note Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_unlisten(HTONS(80)); + \endcode + * + * \param port A 16-bit port number in network byte order. + */ +void uip_unlisten(u16_t port); + +/** + * Connect to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It allocates a new connection identifier, + * sets the connection to the SYN_SENT state and sets the + * retransmission timer to 0. This will cause a TCP SYN segment to be + * sent out the next time this connection is periodically processed, + * which usually is done within 0.5 seconds after the call to + * uip_connect(). + * + * \note This function is avaliable only if support for active open + * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. + * + * \note Since this function requires the port number to be in network + * byte order, a conversion using HTONS() or htons() is necessary. + * + \code + uip_ipaddr_t ipaddr; + + uip_ipaddr(&ipaddr, 192,168,1,2); + uip_connect(&ipaddr, HTONS(80)); + \endcode + * + * \param ripaddr The IP address of the remote hot. + * + * \param port A 16-bit port number in network byte order. + * + * \return A pointer to the uIP connection identifier for the new connection, + * or NULL if no connection could be allocated. + * + */ +struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, u16_t port); + + + +/** + * \internal + * + * Check if a connection has outstanding (i.e., unacknowledged) data. + * + * \param conn A pointer to the uip_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_outstanding(conn) ((conn)->len) + +/** + * Send data on the current connection. + * + * This function is used to send out a single segment of TCP + * data. Only applications that have been invoked by uIP for event + * processing can send data. + * + * The amount of data that actually is sent out after a call to this + * funcion is determined by the maximum amount of data TCP allows. uIP + * will automatically crop the data so that only the appropriate + * amount of data is sent. The function uip_mss() can be used to query + * uIP for the amount of data that actually will be sent. + * + * \note This function does not guarantee that the sent data will + * arrive at the destination. If the data is lost in the network, the + * application will be invoked with the uip_rexmit() event being + * set. The application will then have to resend the data using this + * function. + * + * \param data A pointer to the data which is to be sent. + * + * \param len The maximum amount of data bytes to be sent. + * + * \hideinitializer + */ +void uip_send(const void *data, int len); + +/** + * The length of any incoming data that is currently avaliable (if avaliable) + * in the uip_appdata buffer. + * + * The test function uip_data() must first be used to check if there + * is any data available at all. + * + * \hideinitializer + */ +/*void uip_datalen(void);*/ +#define uip_datalen() uip_len + +/** + * The length of any out-of-band data (urgent data) that has arrived + * on the connection. + * + * \note The configuration parameter UIP_URGDATA must be set for this + * function to be enabled. + * + * \hideinitializer + */ +#define uip_urgdatalen() uip_urglen + +/** + * Close the current connection. + * + * This function will close the current connection in a nice way. + * + * \hideinitializer + */ +#define uip_close() (uip_flags = UIP_CLOSE) + +/** + * Abort the current connection. + * + * This function will abort (reset) the current connection, and is + * usually used when an error has occured that prevents using the + * uip_close() function. + * + * \hideinitializer + */ +#define uip_abort() (uip_flags = UIP_ABORT) + +/** + * Tell the sending host to stop sending data. + * + * This function will close our receiver's window so that we stop + * receiving data for the current connection. + * + * \hideinitializer + */ +#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) + +/** + * Find out if the current connection has been previously stopped with + * uip_stop(). + * + * \hideinitializer + */ +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) + +/** + * Restart the current connection, if is has previously been stopped + * with uip_stop(). + * + * This function will open the receiver's window again so that we + * start receiving data for the current connection. + * + * \hideinitializer + */ +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ + } while(0) + + +/* uIP tests that can be made to determine in what state the current + connection is, and what the application function should do. */ + +/** + * Is the current connection a UDP connection? + * + * This function checks whether the current connection is a UDP connection. + * + * \hideinitializer + * + */ +#define uip_udpconnection() (uip_conn == NULL) + +/** + * Is new incoming data available? + * + * Will reduce to non-zero if there is new data for the application + * present at the uip_appdata pointer. The size of the data is + * avaliable through the uip_len variable. + * + * \hideinitializer + */ +#define uip_newdata() (uip_flags & UIP_NEWDATA) + +/** + * Has previously sent data been acknowledged? + * + * Will reduce to non-zero if the previously sent data has been + * acknowledged by the remote host. This means that the application + * can send new data. + * + * \hideinitializer + */ +#define uip_acked() (uip_flags & UIP_ACKDATA) + +/** + * Has the connection just been connected? + * + * Reduces to non-zero if the current connection has been connected to + * a remote host. This will happen both if the connection has been + * actively opened (with uip_connect()) or passively opened (with + * uip_listen()). + * + * \hideinitializer + */ +#define uip_connected() (uip_flags & UIP_CONNECTED) + +/** + * Has the connection been closed by the other end? + * + * Is non-zero if the connection has been closed by the remote + * host. The application may then do the necessary clean-ups. + * + * \hideinitializer + */ +#define uip_closed() (uip_flags & UIP_CLOSE) + +/** + * Has the connection been aborted by the other end? + * + * Non-zero if the current connection has been aborted (reset) by the + * remote host. + * + * \hideinitializer + */ +#define uip_aborted() (uip_flags & UIP_ABORT) + +/** + * Has the connection timed out? + * + * Non-zero if the current connection has been aborted due to too many + * retransmissions. + * + * \hideinitializer + */ +#define uip_timedout() (uip_flags & UIP_TIMEDOUT) + +/** + * Do we need to retransmit previously data? + * + * Reduces to non-zero if the previously sent data has been lost in + * the network, and the application should retransmit it. The + * application should send the exact same data as it did the last + * time, using the uip_send() function. + * + * \hideinitializer + */ +#define uip_rexmit() (uip_flags & UIP_REXMIT) + +/** + * Is the connection being polled by uIP? + * + * Is non-zero if the reason the application is invoked is that the + * current connection has been idle for a while and should be + * polled. + * + * The polling event can be used for sending data without having to + * wait for the remote host to send data. + * + * \hideinitializer + */ +#define uip_poll() (uip_flags & UIP_POLL) + +/** + * Get the initial maxium segment size (MSS) of the current + * connection. + * + * \hideinitializer + */ +#define uip_initialmss() (uip_conn->initialmss) + +/** + * Get the current maxium segment size that can be sent on the current + * connection. + * + * The current maxiumum segment size that can be sent on the + * connection is computed from the receiver's window and the MSS of + * the connection (which also is available by calling + * uip_initialmss()). + * + * \hideinitializer + */ +#define uip_mss() (uip_conn->mss) + +/** + * Set up a new UDP connection. + * + * This function sets up a new UDP connection. The function will + * automatically allocate an unused local port for the new + * connection. However, another port can be chosen by using the + * uip_udp_bind() call, after the uip_udp_new() function has been + * called. + * + * Example: + \code + uip_ipaddr_t addr; + struct uip_udp_conn *c; + + uip_ipaddr(&addr, 192,168,2,1); + c = uip_udp_new(&addr, HTONS(12345)); + if(c != NULL) { + uip_udp_bind(c, HTONS(12344)); + } + \endcode + * \param ripaddr The IP address of the remote host. + * + * \param rport The remote port number in network byte order. + * + * \return The uip_udp_conn structure for the new connection or NULL + * if no connection could be allocated. + */ +struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport); + +/** + * Removed a UDP connection. + * + * \param conn A pointer to the uip_udp_conn structure for the connection. + * + * \hideinitializer + */ +#define uip_udp_remove(conn) (conn)->lport = 0 + +/** + * Bind a UDP connection to a local port. + * + * \param conn A pointer to the uip_udp_conn structure for the + * connection. + * + * \param port The local port number, in network byte order. + * + * \hideinitializer + */ +#define uip_udp_bind(conn, port) (conn)->lport = port + +/** + * Send a UDP datagram of length len on the current connection. + * + * This function can only be called in response to a UDP event (poll + * or newdata). The data must be present in the uip_buf buffer, at the + * place pointed to by the uip_appdata pointer. + * + * \param len The length of the data in the uip_buf buffer. + * + * \hideinitializer + */ +#define uip_udp_send(len) uip_send((char *)uip_appdata, len) + +/** @} */ + +/* uIP convenience and converting functions. */ + +/** + * \defgroup uipconvfunc uIP conversion functions + * @{ + * + * These functions can be used for converting between different data + * formats used by uIP. + */ + +/** + * Construct an IP address from four bytes. + * + * This function constructs an IP address of the type that uIP handles + * internally from four bytes. The function is handy for specifying IP + * addresses to use with e.g. the uip_connect() function. + * + * Example: + \code + uip_ipaddr_t ipaddr; + struct uip_conn *c; + + uip_ipaddr(&ipaddr, 192,168,1,2); + c = uip_connect(&ipaddr, HTONS(80)); + \endcode + * + * \param addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address. + * + * \param addr0 The first octet of the IP address. + * \param addr1 The second octet of the IP address. + * \param addr2 The third octet of the IP address. + * \param addr3 The forth octet of the IP address. + * + * \hideinitializer + */ +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ + ((u16_t *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \ + ((u16_t *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \ + } while(0) + +/** + * Construct an IPv6 address from eight 16-bit words. + * + * This function constructs an IPv6 address. + * + * \hideinitializer + */ +#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \ + ((u16_t *)(addr))[0] = HTONS((addr0)); \ + ((u16_t *)(addr))[1] = HTONS((addr1)); \ + ((u16_t *)(addr))[2] = HTONS((addr2)); \ + ((u16_t *)(addr))[3] = HTONS((addr3)); \ + ((u16_t *)(addr))[4] = HTONS((addr4)); \ + ((u16_t *)(addr))[5] = HTONS((addr5)); \ + ((u16_t *)(addr))[6] = HTONS((addr6)); \ + ((u16_t *)(addr))[7] = HTONS((addr7)); \ + } while(0) + +/** + * Copy an IP address to another IP address. + * + * Copies an IP address from one place to another. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr_copy(&ipaddr2, &ipaddr1); + \endcode + * + * \param dest The destination for the copy. + * \param src The source from where to copy. + * + * \hideinitializer + */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_copy(dest, src) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1]; \ + } while(0) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t)) +#endif /* !UIP_CONF_IPV6 */ + +/** + * Compare two IP addresses + * + * Compares two IP addresses. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) { + printf("They are the same"); + } + \endcode + * + * \param addr1 The first IP address. + * \param addr2 The second IP address. + * + * \hideinitializer + */ +#if !UIP_CONF_IPV6 +#define uip_ipaddr_cmp(addr1, addr2) (((u16_t *)addr1)[0] == ((u16_t *)addr2)[0] && \ + ((u16_t *)addr1)[1] == ((u16_t *)addr2)[1]) +#else /* !UIP_CONF_IPV6 */ +#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) +#endif /* !UIP_CONF_IPV6 */ + +/** + * Compare two IP addresses with netmasks + * + * Compares two IP addresses with netmasks. The masks are used to mask + * out the bits that are to be compared. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2, mask; + + uip_ipaddr(&mask, 255,255,255,0); + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr(&ipaddr2, 192,16,1,3); + if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) { + printf("They are the same"); + } + \endcode + * + * \param addr1 The first IP address. + * \param addr2 The second IP address. + * \param mask The netmask. + * + * \hideinitializer + */ +#define uip_ipaddr_maskcmp(addr1, addr2, mask) \ + (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \ + (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \ + ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \ + (((u16_t *)addr2)[1] & ((u16_t *)mask)[1]))) + + +/** + * Mask out the network part of an IP address. + * + * Masks out the network part of an IP address, given the address and + * the netmask. + * + * Example: + \code + uip_ipaddr_t ipaddr1, ipaddr2, netmask; + + uip_ipaddr(&ipaddr1, 192,16,1,2); + uip_ipaddr(&netmask, 255,255,255,0); + uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask); + \endcode + * + * In the example above, the variable "ipaddr2" will contain the IP + * address 192.168.1.0. + * + * \param dest Where the result is to be placed. + * \param src The IP address. + * \param mask The netmask. + * + * \hideinitializer + */ +#define uip_ipaddr_mask(dest, src, mask) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \ + } while(0) + +/** + * Pick the first octet of an IP address. + * + * Picks out the first octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr1(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 1. + * + * \hideinitializer + */ +#define uip_ipaddr1(addr) (htons(((u16_t *)(addr))[0]) >> 8) + +/** + * Pick the second octet of an IP address. + * + * Picks out the second octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr2(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 2. + * + * \hideinitializer + */ +#define uip_ipaddr2(addr) (htons(((u16_t *)(addr))[0]) & 0xff) + +/** + * Pick the third octet of an IP address. + * + * Picks out the third octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr3(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 3. + * + * \hideinitializer + */ +#define uip_ipaddr3(addr) (htons(((u16_t *)(addr))[1]) >> 8) + +/** + * Pick the fourth octet of an IP address. + * + * Picks out the fourth octet of an IP address. + * + * Example: + \code + uip_ipaddr_t ipaddr; + u8_t octet; + + uip_ipaddr(&ipaddr, 1,2,3,4); + octet = uip_ipaddr4(&ipaddr); + \endcode + * + * In the example above, the variable "octet" will contain the value 4. + * + * \hideinitializer + */ +#define uip_ipaddr4(addr) (htons(((u16_t *)(addr))[1]) & 0xff) + +/** + * Convert 16-bit quantity from host byte order to network byte order. + * + * This macro is primarily used for converting constants from host + * byte order to network byte order. For converting variables to + * network byte order, use the htons() function instead. + * + * \hideinitializer + */ +#ifndef HTONS +# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN +# define HTONS(n) (n) +# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +# define HTONS(n) (u16_t)((((u16_t) (n)) << 8) | (((u16_t) (n)) >> 8)) +# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +#else +#error "HTONS already defined!" +#endif /* HTONS */ + +/** + * Convert 16-bit quantity from host byte order to network byte order. + * + * This function is primarily used for converting variables from host + * byte order to network byte order. For converting constants to + * network byte order, use the HTONS() macro instead. + */ +#ifndef htons +u16_t htons(u16_t val); +#endif /* htons */ +#ifndef ntohs +#define ntohs htons +#endif + +/** @} */ + +/** + * Pointer to the application data in the packet buffer. + * + * This pointer points to the application data when the application is + * called. If the application wishes to send data, the application may + * use this space to write the data into before calling uip_send(). + */ +extern void *uip_appdata; + +#if UIP_URGDATA > 0 +/* u8_t *uip_urgdata: + * + * This pointer points to any urgent data that has been received. Only + * present if compiled with support for urgent data (UIP_URGDATA). + */ +extern void *uip_urgdata; +#endif /* UIP_URGDATA > 0 */ + + +/** + * \defgroup uipdrivervars Variables used in uIP device drivers + * @{ + * + * uIP has a few global variables that are used in device drivers for + * uIP. + */ + +/** + * The length of the packet in the uip_buf buffer. + * + * The global variable uip_len holds the length of the packet in the + * uip_buf buffer. + * + * When the network device driver calls the uIP input function, + * uip_len should be set to the length of the packet in the uip_buf + * buffer. + * + * When sending packets, the device driver should use the contents of + * the uip_len variable to determine the length of the outgoing + * packet. + * + */ +extern u16_t uip_len; + +/** @} */ + +#if UIP_URGDATA > 0 +extern u16_t uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + + +/** + * Representation of a uIP TCP connection. + * + * The uip_conn structure is used for identifying a connection. All + * but one field in the structure are to be considered read-only by an + * application. The only exception is the appstate field whos purpose + * is to let the application store application-specific state (e.g., + * file pointers) for the connection. The type of this field is + * configured in the "uipopt.h" header file. + */ +struct uip_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote host. */ + + u16_t lport; /**< The local TCP port, in network byte order. */ + u16_t rport; /**< The local remote TCP port, in network byte + order. */ + + u8_t rcv_nxt[4]; /**< The sequence number that we expect to + receive next. */ + u8_t snd_nxt[4]; /**< The sequence number that was last sent by + us. */ + u16_t len; /**< Length of the data that was previously sent. */ + u16_t mss; /**< Current maximum segment size for the + connection. */ + u16_t initialmss; /**< Initial maximum segment size for the + connection. */ + u8_t sa; /**< Retransmission time-out calculation state + variable. */ + u8_t sv; /**< Retransmission time-out calculation state + variable. */ + u8_t rto; /**< Retransmission time-out. */ + u8_t tcpstateflags; /**< TCP state and flags. */ + u8_t timer; /**< The retransmission timer. */ + u8_t nrtx; /**< The number of retransmissions for the last + segment sent. */ + + /** The application state. */ + uip_tcp_appstate_t appstate; +}; + + +/** + * Pointer to the current TCP connection. + * + * The uip_conn pointer can be used to access the current TCP + * connection. + */ +extern struct uip_conn *uip_conn; +/* The array containing all uIP connections. */ +extern struct uip_conn uip_conns[UIP_CONNS]; +/** + * \addtogroup uiparch + * @{ + */ + +/** + * 4-byte array used for the 32-bit sequence number calculations. + */ +extern u8_t uip_acc32[4]; + +/** @} */ + + +#if UIP_UDP +/** + * Representation of a uIP UDP connection. + */ +struct uip_udp_conn { + uip_ipaddr_t ripaddr; /**< The IP address of the remote peer. */ + u16_t lport; /**< The local port number in network byte order. */ + u16_t rport; /**< The remote port number in network byte order. */ + u8_t ttl; /**< Default time-to-live. */ + + /** The application state. */ + uip_udp_appstate_t appstate; +}; + +/** + * The current UDP connection. + */ +extern struct uip_udp_conn *uip_udp_conn; +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +/** + * The structure holding the TCP/IP statistics that are gathered if + * UIP_STATISTICS is set to 1. + * + */ +struct uip_stats { + struct { + uip_stats_t drop; /**< Number of dropped packets at the IP + layer. */ + uip_stats_t recv; /**< Number of received packets at the IP + layer. */ + uip_stats_t sent; /**< Number of sent packets at the IP + layer. */ + uip_stats_t vhlerr; /**< Number of packets dropped due to wrong + IP version or header length. */ + uip_stats_t hblenerr; /**< Number of packets dropped due to wrong + IP length, high byte. */ + uip_stats_t lblenerr; /**< Number of packets dropped due to wrong + IP length, low byte. */ + uip_stats_t fragerr; /**< Number of packets dropped since they + were IP fragments. */ + uip_stats_t chkerr; /**< Number of packets dropped due to IP + checksum errors. */ + uip_stats_t protoerr; /**< Number of packets dropped since they + were neither ICMP, UDP nor TCP. */ + } ip; /**< IP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped ICMP packets. */ + uip_stats_t recv; /**< Number of received ICMP packets. */ + uip_stats_t sent; /**< Number of sent ICMP packets. */ + uip_stats_t typeerr; /**< Number of ICMP packets with a wrong + type. */ + } icmp; /**< ICMP statistics. */ + struct { + uip_stats_t drop; /**< Number of dropped TCP segments. */ + uip_stats_t recv; /**< Number of recived TCP segments. */ + uip_stats_t sent; /**< Number of sent TCP segments. */ + uip_stats_t chkerr; /**< Number of TCP segments with a bad + checksum. */ + uip_stats_t ackerr; /**< Number of TCP segments with a bad ACK + number. */ + uip_stats_t rst; /**< Number of recevied TCP RST (reset) segments. */ + uip_stats_t rexmit; /**< Number of retransmitted TCP segments. */ + uip_stats_t syndrop; /**< Number of dropped SYNs due to too few + connections was avaliable. */ + uip_stats_t synrst; /**< Number of SYNs for closed ports, + triggering a RST. */ + } tcp; /**< TCP statistics. */ +#if UIP_UDP + struct { + uip_stats_t drop; /**< Number of dropped UDP segments. */ + uip_stats_t recv; /**< Number of recived UDP segments. */ + uip_stats_t sent; /**< Number of sent UDP segments. */ + uip_stats_t chkerr; /**< Number of UDP segments with a bad + checksum. */ + } udp; /**< UDP statistics. */ +#endif /* UIP_UDP */ +}; + +/** + * The uIP TCP/IP statistics. + * + * This is the variable in which the uIP TCP/IP statistics are gathered. + */ +extern struct uip_stats uip_stat; + + +/*---------------------------------------------------------------------------*/ +/* All the stuff below this point is internal to uIP and should not be + * used directly by an application or by a device driver. + */ +/*---------------------------------------------------------------------------*/ +/* u8_t uip_flags: + * + * When the application is called, uip_flags will contain the flags + * that are defined in this file. Please read below for more + * infomation. + */ +extern u8_t uip_flags; + +/* The following flags may be set in the global variable uip_flags + before calling the application callback. The UIP_ACKDATA, + UIP_NEWDATA, and UIP_CLOSE flags may both be set at the same time, + whereas the others are mutualy exclusive. Note that these flags + should *NOT* be accessed directly, but only through the uIP + functions/macros. */ + +#define UIP_ACKDATA 1 /* Signifies that the outstanding data was + acked and the application should send + out new data instead of retransmitting + the last data. */ +#define UIP_NEWDATA 2 /* Flags the fact that the peer has sent + us new data. */ +#define UIP_REXMIT 4 /* Tells the application to retransmit the + data that was last sent. */ +#define UIP_POLL 8 /* Used for polling the application, to + check if the application has data that + it wants to send. */ +#define UIP_CLOSE 16 /* The remote host has closed the + connection, thus the connection has + gone away. Or the application signals + that it wants to close the + connection. */ +#define UIP_ABORT 32 /* The remote host has aborted the + connection, thus the connection has + gone away. Or the application signals + that it wants to abort the + connection. */ +#define UIP_CONNECTED 64 /* We have got a connection from a remote + host and have set up a new connection + for it, or an active connection has + been successfully established. */ + +#define UIP_TIMEDOUT 128 /* The connection has been aborted due to + too many retransmissions. */ + +/* uip_process(flag): + * + * The actual uIP function which does all the work. + */ +void uip_process(u8_t flag); + +/* The following flags are passed as an argument to the uip_process() + function. They are used to distinguish between the two cases where + uip_process() is called. It can be called either because we have + incoming data that should be processed, or because the periodic + timer has fired. These values are never used directly, but only in + the macrose defined in this file. */ + +#define UIP_DATA 1 /* Tells uIP that there is incoming + data in the uip_buf buffer. The + length of the data is stored in the + global variable uip_len. */ +#define UIP_TIMER 2 /* Tells uIP that the periodic timer + has fired. */ +#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should + be polled. */ +#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram + should be constructed in the + uip_buf buffer. */ +#if UIP_UDP +#define UIP_UDP_TIMER 5 +#endif /* UIP_UDP */ + +/* The TCP states used in the uip_conn->tcpstateflags. */ +#define UIP_CLOSED 0 +#define UIP_SYN_RCVD 1 +#define UIP_SYN_SENT 2 +#define UIP_ESTABLISHED 3 +#define UIP_FIN_WAIT_1 4 +#define UIP_FIN_WAIT_2 5 +#define UIP_CLOSING 6 +#define UIP_TIME_WAIT 7 +#define UIP_LAST_ACK 8 +#define UIP_TS_MASK 15 + +#define UIP_STOPPED 16 + +/* The TCP and IP headers. */ +struct uip_tcpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcflow; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* TCP header. */ + u16_t srcport, + destport; + u8_t seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + u16_t tcpchksum; + u8_t urgp[2]; + u8_t optdata[4]; +}; + +/* The ICMP and IP headers. */ +struct uip_icmpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPv4 header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* ICMP (echo) header. */ + u8_t type, icode; + u16_t icmpchksum; +#if !UIP_CONF_IPV6 + u16_t id, seqno; +#else /* !UIP_CONF_IPV6 */ + u8_t flags, reserved1, reserved2, reserved3; + u8_t icmp6data[16]; + u8_t options[1]; +#endif /* !UIP_CONF_IPV6 */ +}; + + +/* The UDP and IP headers. */ +struct uip_udpip_hdr { +#if UIP_CONF_IPV6 + /* IPv6 header. */ + u8_t vtc, + tcf; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +#endif /* UIP_CONF_IPV6 */ + + /* UDP header. */ + u16_t srcport, + destport; + u16_t udplen; + u16_t udpchksum; +}; + + + +/** + * The buffer size available for user data in the \ref uip_buf buffer. + * + * This macro holds the available size for user data in the \ref + * uip_buf buffer. The macro is intended to be used for checking + * bounds of available user data. + * + * Example: + \code + snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i); + \endcode + * + * \hideinitializer + */ +#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + + +#define UIP_PROTO_ICMP 1 +#define UIP_PROTO_TCP 6 +#define UIP_PROTO_UDP 17 +#define UIP_PROTO_ICMP6 58 + +/* Header sizes. */ +#if UIP_CONF_IPV6 +#define UIP_IPH_LEN 40 +#else /* UIP_CONF_IPV6 */ +#define UIP_IPH_LEN 20 /* Size of IP header */ +#endif /* UIP_CONF_IPV6 */ +#define UIP_UDPH_LEN 8 /* Size of UDP header */ +#define UIP_TCPH_LEN 20 /* Size of TCP header */ +#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + + UDP + header */ +#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + + TCP + header */ +#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN + + +#if UIP_FIXEDADDR +extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#else /* UIP_FIXEDADDR */ +extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#endif /* UIP_FIXEDADDR */ + + + +/** + * Representation of a 48-bit Ethernet address. + */ +struct uip_eth_addr { + u8_t addr[6]; +}; + +/** + * Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * \param buf A pointer to the buffer over which the checksum is to be + * computed. + * + * \param len The length of the buffer over which the checksum is to + * be computed. + * + * \return The Internet checksum of the buffer. + */ +u16_t uip_chksum(u16_t *buf, u16_t len); + +/** + * Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * \return The IP header checksum of the IP header in the uip_buf + * buffer. + */ +u16_t uip_ipchksum(void); + +/** + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * \return The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_tcpchksum(void); + +/** + * Calculate the UDP checksum of the packet in uip_buf and uip_appdata. + * + * The UDP checksum is the Internet checksum of data contents of the + * UDP segment, and a pseudo-header as defined in RFC768. + * + * \return The UDP checksum of the UDP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_udpchksum(void); + + +#endif /* __UIP_H__ */ + + +/** @} */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arch.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arch.h new file mode 100644 index 0000000..71fd84b --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arch.h @@ -0,0 +1,138 @@ +/** + * \addtogroup uip + * {@ + */ + +/** + * \defgroup uiparch Architecture specific uIP functions + * @{ + * + * The functions in the architecture specific module implement the IP + * check sum and 32-bit additions. + * + * The IP checksum calculation is the most computationally expensive + * operation in the TCP/IP stack and it therefore pays off to + * implement this in efficient assembler. The purpose of the uip-arch + * module is to let the checksum functions to be implemented in + * architecture specific assembler. + * + */ + +/** + * \file + * Declarations of architecture specific functions. + * \author Adam Dunkels + */ + +/* + * Copyright (c) 2001, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $ + * + */ + +#ifndef __UIP_ARCH_H__ +#define __UIP_ARCH_H__ + +#include "uip.h" + +/** + * Carry out a 32-bit addition. + * + * Because not all architectures for which uIP is intended has native + * 32-bit arithmetic, uIP uses an external C function for doing the + * required 32-bit additions in the TCP protocol processing. This + * function should add the two arguments and place the result in the + * global variable uip_acc32. + * + * \note The 32-bit integer pointed to by the op32 parameter and the + * result in the uip_acc32 variable are in network byte order (big + * endian). + * + * \param op32 A pointer to a 4-byte array representing a 32-bit + * integer in network byte order (big endian). + * + * \param op16 A 16-bit integer in host byte order. + */ +void uip_add32(u8_t *op32, u16_t op16); + +/** + * Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * \note This function is not called in the current version of uIP, + * but future versions might make use of it. + * + * \param buf A pointer to the buffer over which the checksum is to be + * computed. + * + * \param len The length of the buffer over which the checksum is to + * be computed. + * + * \return The Internet checksum of the buffer. + */ +u16_t uip_chksum(u16_t *buf, u16_t len); + +/** + * Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * \return The IP header checksum of the IP header in the uip_buf + * buffer. + */ +u16_t uip_ipchksum(void); + +/** + * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * \note The uip_appdata pointer that points to the packet data may + * point anywhere in memory, so it is not possible to simply calculate + * the Internet checksum of the contents of the uip_buf buffer. + * + * \return The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ +u16_t uip_tcpchksum(void); + +u16_t uip_udpchksum(void); + +/** @} */ +/** @} */ + +#endif /* __UIP_ARCH_H__ */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.c b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.c new file mode 100644 index 0000000..44ca7c4 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.c @@ -0,0 +1,423 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uiparp uIP Address Resolution Protocol + * @{ + * + * The Address Resolution Protocol ARP is used for mapping between IP + * addresses and link level addresses such as the Ethernet MAC + * addresses. ARP uses broadcast queries to ask for the link level + * address of a known IP address and the host which is configured with + * the IP address for which the query was meant, will respond with its + * link level address. + * + * \note This ARP implementation only supports Ethernet. + */ + +/** + * \file + * Implementation of the ARP Address Resolution Protocol. + * \author Adam Dunkels + * + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $ + * + */ + + +#include "uip_arp.h" + +#include + +struct arp_hdr { + struct uip_eth_hdr ethhdr; + u16_t hwtype; + u16_t protocol; + u8_t hwlen; + u8_t protolen; + u16_t opcode; + struct uip_eth_addr shwaddr; + u16_t sipaddr[2]; + struct uip_eth_addr dhwaddr; + u16_t dipaddr[2]; +}; + +struct ethip_hdr { + struct uip_eth_hdr ethhdr; + /* IP header. */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + u16_t srcipaddr[2], + destipaddr[2]; +}; + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#define ARP_HWTYPE_ETH 1 + +struct arp_entry { + u16_t ipaddr[2]; + struct uip_eth_addr ethaddr; + u8_t time; +}; + +static const struct uip_eth_addr broadcast_ethaddr = + {{0xff,0xff,0xff,0xff,0xff,0xff}}; +static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff}; + +static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; +static u16_t ipaddr[2]; +static u8_t i, c; + +static u8_t arptime; +static u8_t tmpage; + +#define BUF ((struct arp_hdr *)&uip_buf[0]) +#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) +/*-----------------------------------------------------------------------------------*/ +/** + * Initialize the ARP module. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_init(void) +{ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + memset(arp_table[i].ipaddr, 0, 4); + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Periodic ARP processing function. + * + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_timer(void) +{ + struct arp_entry *tabptr; + + ++arptime; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && + arptime - tabptr->time >= UIP_ARP_MAXAGE) { + memset(tabptr->ipaddr, 0, 4); + } + } + +} +/*-----------------------------------------------------------------------------------*/ +static void +uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) +{ + register struct arp_entry *tabptr; + /* Walk through the ARP mapping table and try to find an entry to + update. If none is found, the IP -> MAC address mapping is + inserted in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + + tabptr = &arp_table[i]; + /* Only check those entries that are actually in use. */ + if(tabptr->ipaddr[0] != 0 && + tabptr->ipaddr[1] != 0) { + + /* Check if the source IP address of the incoming packet matches + the IP address in this ARP table entry. */ + if(ipaddr[0] == tabptr->ipaddr[0] && + ipaddr[1] == tabptr->ipaddr[1]) { + + /* An old entry found, update this and return. */ + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; + + return; + } + } + } + + /* If we get here, no existing ARP table entry was found, so we + create one. */ + + /* First, we try to find an unused entry in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(tabptr->ipaddr[0] == 0 && + tabptr->ipaddr[1] == 0) { + break; + } + } + + /* If no unused entry is found, we try to find the oldest entry and + throw it away. */ + if(i == UIP_ARPTAB_SIZE) { + tmpage = 0; + c = 0; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(arptime - tabptr->time > tmpage) { + tmpage = arptime - tabptr->time; + c = i; + } + } + i = c; + tabptr = &arp_table[i]; + } + + /* Now, i is the ARP table entry which we will fill with the new + information. */ + memcpy(tabptr->ipaddr, ipaddr, 4); + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; +} +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming IP packets + * + * This function should be called by the device driver when an IP + * packet has been received. The function will check if the address is + * in the ARP cache, and if so the ARP cache entry will be + * refreshed. If no ARP cache entry was found, a new one is created. + * + * This function expects an IP packet with a prepended Ethernet header + * in the uip_buf[] buffer, and the length of the packet in the global + * variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +//#if 0 +void +uip_arp_ipin(void) +{ + uip_len -= sizeof(struct uip_eth_hdr); + + /* Only insert/update an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + if((IPBUF->srcipaddr[0] & uip_netmask[0]) != + (uip_hostaddr[0] & uip_netmask[0])) { + return; + } + if((IPBUF->srcipaddr[1] & uip_netmask[1]) != + (uip_hostaddr[1] & uip_netmask[1])) { + return; + } + uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); + + return; +} +//#endif /* 0 */ +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming ARP packets. + * + * This function should be called by the device driver when an ARP + * packet has been received. The function will act differently + * depending on the ARP packet type: if it is a reply for a request + * that we previously sent out, the ARP cache will be filled in with + * the values from the ARP reply. If the incoming ARP packet is an ARP + * request for our IP address, an ARP reply packet is created and put + * into the uip_buf[] buffer. + * + * When the function returns, the value of the global variable uip_len + * indicates whether the device driver should send out a packet or + * not. If uip_len is zero, no packet should be sent. If uip_len is + * non-zero, it contains the length of the outbound packet that is + * present in the uip_buf[] buffer. + * + * This function expects an ARP packet with a prepended Ethernet + * header in the uip_buf[] buffer, and the length of the packet in the + * global variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_arpin(void) +{ + + if(uip_len < sizeof(struct arp_hdr)) { + uip_len = 0; + return; + } + uip_len = 0; + + switch(BUF->opcode) { + case HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + reply. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + /* First, we register the one who made the request in our ARP + table, since it is likely that we will do more communication + with this host in the future. */ + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + + /* The reply opcode is 2. */ + BUF->opcode = HTONS(2); + + memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); + + BUF->dipaddr[0] = BUF->sipaddr[0]; + BUF->dipaddr[1] = BUF->sipaddr[1]; + BUF->sipaddr[0] = uip_hostaddr[0]; + BUF->sipaddr[1] = uip_hostaddr[1]; + + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + uip_len = sizeof(struct arp_hdr); + } + break; + case HTONS(ARP_REPLY): + /* ARP reply. We insert or update the ARP table if it was meant + for us. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + } + break; + } + + return; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Prepend Ethernet header to an outbound IP packet and see if we need + * to send out an ARP request. + * + * This function should be called before sending out an IP packet. The + * function checks the destination IP address of the IP packet to see + * what Ethernet MAC address that should be used as a destination MAC + * address on the Ethernet. + * + * If the destination IP address is in the local network (determined + * by logical ANDing of netmask and our IP address), the function + * checks the ARP cache to see if an entry for the destination IP + * address is found. If so, an Ethernet header is prepended and the + * function returns. If no ARP cache entry is found for the + * destination IP address, the packet in the uip_buf[] is replaced by + * an ARP request packet for the IP address. The IP packet is dropped + * and it is assumed that they higher level protocols (e.g., TCP) + * eventually will retransmit the dropped packet. + * + * If the destination IP address is not on the local network, the IP + * address of the default router is used instead. + * + * When the function returns, a packet is present in the uip_buf[] + * buffer, and the length of the packet is in the global variable + * uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_out(void) +{ + struct arp_entry *tabptr; + + /* Find the destination IP address in the ARP table and construct + the Ethernet header. If the destination IP addres isn't on the + local network, we use the default router's IP address instead. + + If not ARP table entry is found, we overwrite the original IP + packet with an ARP request for the IP address. */ + + /* First check if destination is a local broadcast. */ + if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { + memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); + } else { + /* Check if the destination address is on the local network. */ + if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { + /* Destination address was not on the local network, so we need to + use the default router's IP address instead of the destination + address when determining the MAC address. */ + uip_ipaddr_copy(ipaddr, uip_draddr); + } else { + /* Else, we use the destination IP address. */ + uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); + } + + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { + break; + } + } + + if(i == UIP_ARPTAB_SIZE) { + /* The destination address was not in our ARP table, so we + overwrite the IP packet with an ARP request. */ + + memset(BUF->ethhdr.dest.addr, 0xff, 6); + memset(BUF->dhwaddr.addr, 0x00, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + + uip_ipaddr_copy(BUF->dipaddr, ipaddr); + uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); + BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ + BUF->hwtype = HTONS(ARP_HWTYPE_ETH); + BUF->protocol = HTONS(UIP_ETHTYPE_IP); + BUF->hwlen = 6; + BUF->protolen = 4; + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + + uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; + + uip_len = sizeof(struct arp_hdr); + return; + } + + /* Build an ethernet header. */ + memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); + } + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + + IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); + + uip_len += sizeof(struct uip_eth_hdr); +} +/*-----------------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.h new file mode 100644 index 0000000..ef93054 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.h @@ -0,0 +1,144 @@ +/** + * \addtogroup uip + * @{ + */ + +/** + * \addtogroup uiparp + * @{ + */ + +/** + * \file + * Macros and definitions for the ARP module. + * \author Adam Dunkels + */ + + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $ + * + */ + +#ifndef __UIP_ARP_H__ +#define __UIP_ARP_H__ + +#include "uip.h" + + +extern struct uip_eth_addr uip_ethaddr; + +/** + * The Ethernet header. + */ +struct uip_eth_hdr { + struct uip_eth_addr dest; + struct uip_eth_addr src; + u16_t type; +}; + +#define UIP_ETHTYPE_ARP 0x0806 +#define UIP_ETHTYPE_IP 0x0800 +#define UIP_ETHTYPE_IP6 0x86dd + + +/* The uip_arp_init() function must be called before any of the other + ARP functions. */ +void uip_arp_init(void); + +/* The uip_arp_ipin() function should be called whenever an IP packet + arrives from the Ethernet. This function refreshes the ARP table or + inserts a new mapping if none exists. The function assumes that an + IP packet with an Ethernet header is present in the uip_buf buffer + and that the length of the packet is in the uip_len variable. */ +void uip_arp_ipin(void); +//#define uip_arp_ipin() + +/* The uip_arp_arpin() should be called when an ARP packet is received + by the Ethernet driver. This function also assumes that the + Ethernet frame is present in the uip_buf buffer. When the + uip_arp_arpin() function returns, the contents of the uip_buf + buffer should be sent out on the Ethernet if the uip_len variable + is > 0. */ +void uip_arp_arpin(void); + +/* The uip_arp_out() function should be called when an IP packet + should be sent out on the Ethernet. This function creates an + Ethernet header before the IP header in the uip_buf buffer. The + Ethernet header will have the correct Ethernet MAC destination + address filled in if an ARP table entry for the destination IP + address (or the IP address of the default router) is present. If no + such table entry is found, the IP packet is overwritten with an ARP + request and we rely on TCP to retransmit the packet that was + overwritten. In any case, the uip_len variable holds the length of + the Ethernet frame that should be transmitted. */ +void uip_arp_out(void); + +/* The uip_arp_timer() function should be called every ten seconds. It + is responsible for flushing old entries in the ARP table. */ +void uip_arp_timer(void); + +/** @} */ + +/** + * \addtogroup uipconffunc + * @{ + */ + + +/** + * Specifiy the Ethernet MAC address. + * + * The ARP code needs to know the MAC address of the Ethernet card in + * order to be able to respond to ARP queries and to generate working + * Ethernet headers. + * + * \note This macro only specifies the Ethernet MAC address to the ARP + * code. It cannot be used to change the MAC address of the Ethernet + * card. + * + * \param eaddr A pointer to a struct uip_eth_addr containing the + * Ethernet MAC address of the Ethernet card. + * + * \hideinitializer + */ +#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ + uip_ethaddr.addr[1] = eaddr.addr[1];\ + uip_ethaddr.addr[2] = eaddr.addr[2];\ + uip_ethaddr.addr[3] = eaddr.addr[3];\ + uip_ethaddr.addr[4] = eaddr.addr[4];\ + uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) + +/** @} */ +/** @} */ + +#endif /* __UIP_ARP_H__ */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_clock.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_clock.h new file mode 100644 index 0000000..6dd72be --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_clock.h @@ -0,0 +1,88 @@ +/** + * \defgroup clock Clock interface + * + * The clock interface is the interface between the \ref timer "timer library" + * and the platform specific clock functionality. The clock + * interface must be implemented for each platform that uses the \ref + * timer "timer library". + * + * The clock interface does only one this: it measures time. The clock + * interface provides a macro, CLOCK_SECOND, which corresponds to one + * second of system time. + * + * \sa \ref timer "Timer library" + * + * @{ + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $ + */ +#ifndef __UIP_CLOCK_H__ +#define __UIP_CLOCK_H__ + +#include "clock-arch.h" + +/** + * Initialize the clock library. + * + * This function initializes the clock library and should be called + * from the main() function of the system. + * + */ +void uip_clock_init(void); + +/** + * Get the current clock time. + * + * This function returns the current system clock time. + * + * \return The current clock time, measured in system ticks. + */ +clock_time_t clock_time(void); + +/** + * A second, measured in system clock time. + * + * \hideinitializer + */ +#ifdef CLOCK_CONF_SECOND +#define CLOCK_SECOND CLOCK_CONF_SECOND +#else +#define CLOCK_SECOND (clock_time_t)32 +#endif + +#endif /* __CLOCK_H__ */ + +/** @} */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.cpp b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.cpp new file mode 100644 index 0000000..444bd0e --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.cpp @@ -0,0 +1,170 @@ +#include +#include +#include +#include +extern "C" { + #import "utility/uip.h" +} + +struct uip_conn con[UIP_CONNS]; + +void +UIPDebug::uip_debug_printconns() +{ + for(uint8_t i=0;iripaddr,rhs->ripaddr)) + { + Serial.print(" ripaddr: "); + uip_debug_printbytes((const uint8_t *)lhs->ripaddr,4); + Serial.print(" -> "); + uip_debug_printbytes((const uint8_t *)rhs->ripaddr,4); + Serial.println(); + uip_ipaddr_copy(lhs->ripaddr,rhs->ripaddr); + changed = true; + } + if (lhs->lport != rhs->lport) + { + Serial.print(" lport: "); + Serial.print(htons(lhs->lport)); + Serial.print(" -> "); + Serial.println(htons(rhs->lport)); + lhs->lport = rhs->lport; + changed = true; + } + if (lhs->rport != rhs->rport) + { + Serial.print(" rport: "); + Serial.print(htons(lhs->rport)); + Serial.print(" -> "); + Serial.println(htons(rhs->rport)); + lhs->rport = rhs->rport; + changed = true; + } + if ((uint32_t)lhs->rcv_nxt[0] != (uint32_t)rhs->rcv_nxt[0]) + { + Serial.print(" rcv_nxt: "); + uip_debug_printbytes(lhs->rcv_nxt,4); + Serial.print(" -> "); + uip_debug_printbytes(rhs->rcv_nxt,4); + *((uint32_t *)&lhs->rcv_nxt[0]) = (uint32_t)rhs->rcv_nxt[0]; + Serial.println(); + changed = true; + } + if ((uint32_t)lhs->snd_nxt[0] != (uint32_t)rhs->snd_nxt[0]) + { + Serial.print(" snd_nxt: "); + uip_debug_printbytes(lhs->snd_nxt,4); + Serial.print(" -> "); + uip_debug_printbytes(rhs->snd_nxt,4); + *((uint32_t *)&lhs->snd_nxt[0]) = (uint32_t)rhs->snd_nxt[0]; + Serial.println(); + changed = true; + } + if (lhs->len != rhs->len) + { + Serial.print(" len: "); + Serial.print(lhs->len); + Serial.print(" -> "); + Serial.println(rhs->len); + lhs->len = rhs->len; + changed = true; + } + if (lhs->mss != rhs->mss) + { + Serial.print(" mss: "); + Serial.print(lhs->mss); + Serial.print(" -> "); + Serial.println(rhs->mss); + lhs->mss = rhs->mss; + changed = true; + } + if (lhs->initialmss != rhs->initialmss) + { + Serial.print(" initialmss: "); + Serial.print(lhs->initialmss); + Serial.print(" -> "); + Serial.println(rhs->initialmss); + lhs->initialmss = rhs->initialmss; + changed = true; + } + if (lhs->sa != rhs->sa) + { + Serial.print(" sa: "); + Serial.print(lhs->sa); + Serial.print(" -> "); + Serial.println(rhs->sa); + lhs->sa = rhs->sa; + changed = true; + } + if (lhs->sv != rhs->sv) + { + Serial.print(" sv: "); + Serial.print(lhs->sv); + Serial.print(" -> "); + Serial.println(rhs->sv); + lhs->sv = rhs->sv; + changed = true; + } + if (lhs->rto != rhs->rto) + { + Serial.print(" rto: "); + Serial.print(lhs->rto); + Serial.print(" -> "); + Serial.println(rhs->rto); + lhs->rto = rhs->rto; + changed = true; + } + if (lhs->tcpstateflags != rhs->tcpstateflags) + { + Serial.print(" tcpstateflags: "); + Serial.print(lhs->tcpstateflags); + Serial.print(" -> "); + Serial.println(rhs->tcpstateflags); + lhs->tcpstateflags = rhs->tcpstateflags; + changed = true; + } + if (lhs->timer != rhs->timer) + { + Serial.print(" timer: "); + Serial.print(lhs->timer); + Serial.print(" -> "); + Serial.println(rhs->timer); + lhs->timer = rhs->timer; + changed = true; + } + if (lhs->nrtx != rhs->nrtx) + { + Serial.print(" nrtx: "); + Serial.print(lhs->nrtx); + Serial.print(" -> "); + Serial.println(rhs->nrtx); + lhs->nrtx = rhs->nrtx; + changed = true; + } + return changed; +} + +void +UIPDebug::uip_debug_printbytes(const uint8_t *data, uint8_t len) +{ + for(uint8_t i=0;i + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $ + */ + +#include "uip_clock.h" +#include "uip_timer.h" + +/*---------------------------------------------------------------------------*/ +/** + * Set a timer. + * + * This function is used to set a timer for a time sometime in the + * future. The function timer_expired() will evaluate to true after + * the timer has expired. + * + * \param t A pointer to the timer + * \param interval The interval before the timer expires. + * + */ +void +uip_timer_set(struct uip_timer *t, clock_time_t interval) +{ + t->interval = interval; + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Reset the timer with the same interval. + * + * This function resets the timer with the same interval that was + * given to the timer_set() function. The start point of the interval + * is the exact time that the timer last expired. Therefore, this + * function will cause the timer to be stable over time, unlike the + * timer_rester() function. + * + * \param t A pointer to the timer. + * + * \sa timer_restart() + */ +void +uip_timer_reset(struct uip_timer *t) +{ + t->start += t->interval; +} +/*---------------------------------------------------------------------------*/ +/** + * Restart the timer from the current point in time + * + * This function restarts a timer with the same interval that was + * given to the timer_set() function. The timer will start at the + * current time. + * + * \note A periodic timer will drift if this function is used to reset + * it. For preioric timers, use the timer_reset() function instead. + * + * \param t A pointer to the timer. + * + * \sa timer_reset() + */ +void +uip_timer_restart(struct uip_timer *t) +{ + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Check if a timer has expired. + * + * This function tests if a timer has expired and returns true or + * false depending on its status. + * + * \param t A pointer to the timer + * + * \return Non-zero if the timer has expired, zero otherwise. + * + */ +int +uip_timer_expired(struct uip_timer *t) +{ + return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; +} +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.h new file mode 100644 index 0000000..f260349 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.h @@ -0,0 +1,86 @@ +/** + * \defgroup timer Timer library + * + * The timer library provides functions for setting, resetting and + * restarting timers, and for checking if a timer has expired. An + * application must "manually" check if its timers have expired; this + * is not done automatically. + * + * A timer is declared as a \c struct \c timer and all access to the + * timer is made by a pointer to the declared timer. + * + * \note The timer library uses the \ref clock "Clock library" to + * measure time. Intervals should be specified in the format used by + * the clock library. + * + * @{ + */ + + +/** + * \file + * Timer library header file. + * \author + * Adam Dunkels + */ + +/* + * Copyright (c) 2004, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels + * + * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $ + */ +#ifndef __UIP_TIMER_H__ +#define __UIP_TIMER_H__ + +#include "uip_clock.h" + +/** + * A timer. + * + * This structure is used for declaring a timer. The timer must be set + * with timer_set() before it can be used. + * + * \hideinitializer + */ +struct uip_timer { + clock_time_t start; + clock_time_t interval; +}; + +void uip_timer_set(struct uip_timer *t, clock_time_t interval); +void uip_timer_reset(struct uip_timer *t); +void uip_timer_restart(struct uip_timer *t); +int uip_timer_expired(struct uip_timer *t); + +#endif /* __UIP_TIMER_H__ */ + +/** @} */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uipethernet-conf.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uipethernet-conf.h new file mode 100644 index 0000000..b9c8d73 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uipethernet-conf.h @@ -0,0 +1,29 @@ +#ifndef UIPETHERNET_CONF_H +#define UIPETHERNET_CONF_H + +/* for TCP */ +#define UIP_SOCKET_NUMPACKETS 5 +#define UIP_CONF_MAX_CONNECTIONS 1 + +/* for UDP + * set UIP_CONF_UDP to 0 to disable UDP (saves aprox. 5kb flash) */ +#define UIP_CONF_UDP 0 +#define UIP_CONF_BROADCAST 1 +#define UIP_CONF_UDP_CONNS 4 + +/* number of attempts on write before returning number of bytes sent so far + * set to -1 to block until connection is closed by timeout */ +#define UIP_ATTEMPTS_ON_WRITE -1 + +/* timeout after which UIPClient::connect gives up. The timeout is specified in seconds. + * if set to a number <= 0 connect will timeout when uIP does (which might be longer than you expect...) */ +#define UIP_CONNECT_TIMEOUT -1 + +/* periodic timer for uip (in ms) */ +#define UIP_PERIODIC_TIMER 250 + +/* timer to poll client for data after last write (in ms) + * set to -1 to disable fast polling and rely on periodic only (saves 100 bytes flash) */ +#define UIP_CLIENT_TIMER 10 + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uipopt.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/uipopt.h new file mode 100644 index 0000000..42badf8 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/uipopt.h @@ -0,0 +1,543 @@ +/** + * \defgroup uipopt Configuration options for uIP + * @{ + * + * uIP is configured using the per-project configuration file + * uipopt.h. This file contains all compile-time options for uIP and + * should be tweaked to match each specific project. The uIP + * distribution contains a documented example "uipopt.h" that can be + * copied and modified for each project. + * + * \note Most of the configuration options in the uipopt.h should not + * be changed, but rather the per-project uip-conf.h file. + */ + +/** + * \file + * Configuration options for uIP. + * \author Adam Dunkels + * + * This file is used for tweaking various configuration options for + * uIP. You should make a copy of this file into one of your project's + * directories instead of editing this example "uipopt.h" file that + * comes with the uIP distribution. + */ + +/* + * Copyright (c) 2001-2003, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $ + * + */ + +#ifndef __UIPOPT_H__ +#define __UIPOPT_H__ + +#ifndef UIP_LITTLE_ENDIAN +#define UIP_LITTLE_ENDIAN 3412 +#endif /* UIP_LITTLE_ENDIAN */ +#ifndef UIP_BIG_ENDIAN +#define UIP_BIG_ENDIAN 1234 +#endif /* UIP_BIG_ENDIAN */ + +#include "uip-conf.h" + +/*------------------------------------------------------------------------------*/ + +/** + * \name Static configuration options + * @{ + * + * These configuration options can be used for setting the IP address + * settings statically, but only if UIP_FIXEDADDR is set to 1. The + * configuration options for a specific node includes IP address, + * netmask and default router as well as the Ethernet address. The + * netmask, default router and Ethernet address are appliciable only + * if uIP should be run over Ethernet. + * + * All of these should be changed to suit your project. +*/ + +/** + * Determines if uIP should use a fixed IP address or not. + * + * If uIP should use a fixed IP address, the settings are set in the + * uipopt.h file. If not, the macros uip_sethostaddr(), + * uip_setdraddr() and uip_setnetmask() should be used instead. + * + * \hideinitializer + */ +#define UIP_FIXEDADDR 0 + +/** + * Ping IP address asignment. + * + * uIP uses a "ping" packets for setting its own IP address if this + * option is set. If so, uIP will start with an empty IP address and + * the destination IP address of the first incoming "ping" (ICMP echo) + * packet will be used for setting the hosts IP address. + * + * \note This works only if UIP_FIXEDADDR is 0. + * + * \hideinitializer + */ +#ifdef UIP_CONF_PINGADDRCONF +#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF +#else /* UIP_CONF_PINGADDRCONF */ +#define UIP_PINGADDRCONF 0 +#endif /* UIP_CONF_PINGADDRCONF */ + + +/** + * Specifies if the uIP ARP module should be compiled with a fixed + * Ethernet MAC address or not. + * + * If this configuration option is 0, the macro uip_setethaddr() can + * be used to specify the Ethernet address at run-time. + * + * \hideinitializer + */ +#define UIP_FIXEDETHADDR 0 + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name IP configuration options + * @{ + * + */ +/** + * The IP TTL (time to live) of IP packets sent by uIP. + * + * This should normally not be changed. + */ +#define UIP_TTL 64 + +/** + * Turn on support for IP packet reassembly. + * + * uIP supports reassembly of fragmented IP packets. This features + * requires an additonal amount of RAM to hold the reassembly buffer + * and the reassembly code size is approximately 700 bytes. The + * reassembly buffer is of the same size as the uip_buf buffer + * (configured by UIP_BUFSIZE). + * + * \note IP packet reassembly is not heavily tested. + * + * \hideinitializer + */ +#define UIP_REASSEMBLY 0 + +/** + * The maximum time an IP fragment should wait in the reassembly + * buffer before it is dropped. + * + */ +#define UIP_REASS_MAXAGE 40 + +/** @} */ + +/*------------------------------------------------------------------------------*/ +/** + * \name UDP configuration options + * @{ + */ + +/** + * Toggles wether UDP support should be compiled in or not. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP +#define UIP_UDP UIP_CONF_UDP +#else /* UIP_CONF_UDP */ +#define UIP_UDP 0 +#endif /* UIP_CONF_UDP */ + +/** + * Toggles if UDP checksums should be used or not. + * + * \note Support for UDP checksums is currently not included in uIP, + * so this option has no function. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP_CHECKSUMS +#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS +#else +#define UIP_UDP_CHECKSUMS 0 +#endif + +/** + * The maximum amount of concurrent UDP connections. + * + * \hideinitializer + */ +#ifdef UIP_CONF_UDP_CONNS +#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS +#else /* UIP_CONF_UDP_CONNS */ +#define UIP_UDP_CONNS 10 +#endif /* UIP_CONF_UDP_CONNS */ + +/** + * The name of the function that should be called when UDP datagrams arrive. + * + * \hideinitializer + */ + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name TCP configuration options + * @{ + */ + +/** + * Determines if support for opening connections from uIP should be + * compiled in. + * + * If the applications that are running on top of uIP for this project + * do not need to open outgoing TCP connections, this configration + * option can be turned off to reduce the code size of uIP. + * + * \hideinitializer + */ +#define UIP_ACTIVE_OPEN 1 + +/** + * The maximum number of simultaneously open TCP connections. + * + * Since the TCP connections are statically allocated, turning this + * configuration knob down results in less RAM used. Each TCP + * connection requires approximatly 30 bytes of memory. + * + * \hideinitializer + */ +#ifndef UIP_CONF_MAX_CONNECTIONS +#define UIP_CONNS 10 +#else /* UIP_CONF_MAX_CONNECTIONS */ +#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS +#endif /* UIP_CONF_MAX_CONNECTIONS */ + + +/** + * The maximum number of simultaneously listening TCP ports. + * + * Each listening TCP port requires 2 bytes of memory. + * + * \hideinitializer + */ +#ifndef UIP_CONF_MAX_LISTENPORTS +#define UIP_LISTENPORTS 20 +#else /* UIP_CONF_MAX_LISTENPORTS */ +#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS +#endif /* UIP_CONF_MAX_LISTENPORTS */ + +/** + * Determines if support for TCP urgent data notification should be + * compiled in. + * + * Urgent data (out-of-band data) is a rarely used TCP feature that + * very seldom would be required. + * + * \hideinitializer + */ +#define UIP_URGDATA 0 + +/** + * The initial retransmission timeout counted in timer pulses. + * + * This should not be changed. + */ +#define UIP_RTO 3 + +/** + * The maximum number of times a segment should be retransmitted + * before the connection should be aborted. + * + * This should not be changed. + */ +#define UIP_MAXRTX 8 + +/** + * The maximum number of times a SYN segment should be retransmitted + * before a connection request should be deemed to have been + * unsuccessful. + * + * This should not need to be changed. + */ +#define UIP_MAXSYNRTX 5 + +/** + * The TCP maximum segment size. + * + * This is should not be to set to more than + * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. + */ +#ifndef UIP_CONF_TCP_MSS +#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) +#else +#define UIP_TCP_MSS UIP_CONF_TCP_MSS +#endif + +/** + * The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the uip_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + * + * \hideinitializer + */ +#ifndef UIP_CONF_RECEIVE_WINDOW +#define UIP_RECEIVE_WINDOW UIP_TCP_MSS +#else +#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW +#endif + +/** + * How long a connection should stay in the TIME_WAIT state. + * + * This configiration option has no real implication, and it should be + * left untouched. + */ +#define UIP_TIME_WAIT_TIMEOUT 120 + + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name ARP configuration options + * @{ + */ + +/** + * The size of the ARP table. + * + * This option should be set to a larger value if this uIP node will + * have many connections from the local network. + * + * \hideinitializer + */ +#ifdef UIP_CONF_ARPTAB_SIZE +#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE +#else +#define UIP_ARPTAB_SIZE 8 +#endif + +/** + * The maxium age of ARP table entries measured in 10ths of seconds. + * + * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD + * default). + */ +#define UIP_ARP_MAXAGE 120 + +/** @} */ + +/*------------------------------------------------------------------------------*/ + +/** + * \name General configuration options + * @{ + */ + +/** + * The size of the uIP packet buffer. + * + * The uIP packet buffer should not be smaller than 60 bytes, and does + * not need to be larger than 1500 bytes. Lower size results in lower + * TCP throughput, larger size results in higher TCP throughput. + * + * \hideinitializer + */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_BUFSIZE 400 +#else /* UIP_CONF_BUFFER_SIZE */ +#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE +#endif /* UIP_CONF_BUFFER_SIZE */ + + +/** + * Determines if statistics support should be compiled in. + * + * The statistics is useful for debugging and to show the user. + * + * \hideinitializer + */ +#ifndef UIP_CONF_STATISTICS +#define UIP_STATISTICS 0 +#else /* UIP_CONF_STATISTICS */ +#define UIP_STATISTICS UIP_CONF_STATISTICS +#endif /* UIP_CONF_STATISTICS */ + +/** + * Determines if logging of certain events should be compiled in. + * + * This is useful mostly for debugging. The function uip_log() + * must be implemented to suit the architecture of the project, if + * logging is turned on. + * + * \hideinitializer + */ +#ifndef UIP_CONF_LOGGING +#define UIP_LOGGING 0 +#else /* UIP_CONF_LOGGING */ +#define UIP_LOGGING UIP_CONF_LOGGING +#endif /* UIP_CONF_LOGGING */ + +/** + * Broadcast support. + * + * This flag configures IP broadcast support. This is useful only + * together with UDP. + * + * \hideinitializer + * + */ +#if UIP_UDP && UIP_CONF_BROADCAST +#define UIP_BROADCAST UIP_CONF_BROADCAST +#else /* UIP_CONF_BROADCAST */ +#define UIP_BROADCAST 0 +#endif /* UIP_CONF_BROADCAST */ + +/** + * Print out a uIP log message. + * + * This function must be implemented by the module that uses uIP, and + * is called by uIP whenever a log message is generated. + */ +void uip_log(char *msg); + +/** + * The link level header length. + * + * This is the offset into the uip_buf where the IP header can be + * found. For Ethernet, this should be set to 14. For SLIP, this + * should be set to 0. + * + * \hideinitializer + */ +#ifdef UIP_CONF_LLH_LEN +#define UIP_LLH_LEN UIP_CONF_LLH_LEN +#else /* UIP_CONF_LLH_LEN */ +#define UIP_LLH_LEN 14 +#endif /* UIP_CONF_LLH_LEN */ + +/** @} */ +/*------------------------------------------------------------------------------*/ +/** + * \name CPU architecture configuration + * @{ + * + * The CPU architecture configuration is where the endianess of the + * CPU on which uIP is to be run is specified. Most CPUs today are + * little endian, and the most notable exception are the Motorolas + * which are big endian. The BYTE_ORDER macro should be changed to + * reflect the CPU architecture on which uIP is to be run. + */ + +/** + * The byte order of the CPU architecture on which uIP is to be run. + * + * This option can be either BIG_ENDIAN (Motorola byte order) or + * LITTLE_ENDIAN (Intel byte order). + * + * \hideinitializer + */ +#ifdef UIP_CONF_BYTE_ORDER +#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER +#else /* UIP_CONF_BYTE_ORDER */ +#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN +#endif /* UIP_CONF_BYTE_ORDER */ + +/** @} */ +/*------------------------------------------------------------------------------*/ + +/** + * \name Appication specific configurations + * @{ + * + * An uIP application is implemented using a single application + * function that is called by uIP whenever a TCP/IP event occurs. The + * name of this function must be registered with uIP at compile time + * using the UIP_APPCALL definition. + * + * uIP applications can store the application state within the + * uip_conn structure by specifying the type of the application + * structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t. + * + * The file containing the definitions must be included in the + * uipopt.h file. + * + * The following example illustrates how this can look. + \code + +void httpd_appcall(void); +#define UIP_APPCALL httpd_appcall + +struct httpd_state { + u8_t state; + u16_t count; + char *dataptr; + char *script; +}; +typedef struct httpd_state uip_tcp_appstate_t + \endcode + */ + +/** + * \var #define UIP_APPCALL + * + * The name of the application function that uIP should call in + * response to TCP/IP events. + * + */ + +/** + * \var typedef uip_tcp_appstate_t + * + * The type of the application state that is to be stored in the + * uip_conn structure. This usually is typedef:ed to a struct holding + * application state information. + */ + +/** + * \var typedef uip_udp_appstate_t + * + * The type of the application state that is to be stored in the + * uip_conn structure. This usually is typedef:ed to a struct holding + * application state information. + */ +/** @} */ +/** @} */ + +#endif /* __UIPOPT_H__ */ diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/util.h b/libraries/MySensors/drivers/Ethernet_UIP/utility/util.h new file mode 100644 index 0000000..5042e82 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_UIP/utility/util.h @@ -0,0 +1,13 @@ +#ifndef UTIL_H +#define UTIL_H + +#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) ) +#define ntohs(x) htons(x) + +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Client.h b/libraries/MySensors/drivers/Ethernet_W5100/Client.h new file mode 100644 index 0000000..b8e5d93 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Client.h @@ -0,0 +1,45 @@ +/* + Client.h - Base class that provides Client + Copyright (c) 2011 Adrian McEwen. 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 +*/ + +#ifndef client_h +#define client_h +#include "Print.h" +#include "Stream.h" +#include "IPAddress.h" + +class Client : public Stream { + +public: + virtual int connect(IPAddress ip, uint16_t port) =0; + virtual int connect(const char *host, uint16_t port) =0; + virtual size_t write(uint8_t) =0; + virtual size_t write(const uint8_t *buf, size_t size) =0; + virtual int available() = 0; + virtual int read() = 0; + virtual int read(uint8_t *buf, size_t size) = 0; + virtual int peek() = 0; + virtual void flush() = 0; + virtual void stop() = 0; + virtual uint8_t connected() = 0; + virtual operator bool() = 0; +protected: + uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.cpp b/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.cpp new file mode 100644 index 0000000..040e126 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.cpp @@ -0,0 +1,471 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#include "utility/w5100.h" + +#include +#include +#include "Dhcp.h" +#include "Arduino.h" +#include "utility/util.h" + +int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) +{ + _dhcpLeaseTime=0; + _dhcpT1=0; + _dhcpT2=0; + _timeout = timeout; + _responseTimeout = responseTimeout; + + // zero out _dhcpMacAddr + memset(_dhcpMacAddr, 0, 6); + reset_DHCP_lease(); + + memcpy((void*)_dhcpMacAddr, (void*)mac, 6); + _dhcp_state = STATE_DHCP_START; + return request_DHCP_lease(); +} + +void DhcpClass::reset_DHCP_lease(){ + // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp + memset(_dhcpLocalIp, 0, 20); +} + +//return:0 on error, 1 if request is sent and response is received +int DhcpClass::request_DHCP_lease(){ + + uint8_t messageType = 0; + + + + // Pick an initial transaction ID + _dhcpTransactionId = random(1UL, 2000UL); + _dhcpInitialTransactionId = _dhcpTransactionId; + + _dhcpUdpSocket.stop(); + if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) + { + // Couldn't get a socket + return 0; + } + + presend_DHCP(); + + int result = 0; + + unsigned long startTime = millis(); + + while(_dhcp_state != STATE_DHCP_LEASED) + { + if(_dhcp_state == STATE_DHCP_START) + { + _dhcpTransactionId++; + + send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_DISCOVER; + } + else if(_dhcp_state == STATE_DHCP_REREQUEST){ + _dhcpTransactionId++; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + else if(_dhcp_state == STATE_DHCP_DISCOVER) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_OFFER) + { + // We'll use the transaction ID that the offer came with, + // rather than the one we were up to + _dhcpTransactionId = respId; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + } + else if(_dhcp_state == STATE_DHCP_REQUEST) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_ACK) + { + _dhcp_state = STATE_DHCP_LEASED; + result = 1; + //use default lease time if we didn't get it + if(_dhcpLeaseTime == 0){ + _dhcpLeaseTime = DEFAULT_LEASE; + } + // Calculate T1 & T2 if we didn't get it + if(_dhcpT1 == 0){ + // T1 should be 50% of _dhcpLeaseTime + _dhcpT1 = _dhcpLeaseTime >> 1; + } + if(_dhcpT2 == 0){ + // T2 should be 87.5% (7/8ths) of _dhcpLeaseTime + _dhcpT2 = _dhcpLeaseTime - (_dhcpLeaseTime >> 3); + } + _renewInSec = _dhcpT1; + _rebindInSec = _dhcpT2; + } + else if(messageType == DHCP_NAK) + _dhcp_state = STATE_DHCP_START; + } + + if(messageType == 255) + { + messageType = 0; + _dhcp_state = STATE_DHCP_START; + } + + if(result != 1 && ((millis() - startTime) > _timeout)) + break; + } + + // We're done with the socket now + _dhcpUdpSocket.stop(); + _dhcpTransactionId++; + + _lastCheckLeaseMillis = millis(); + return result; +} + +void DhcpClass::presend_DHCP() +{ +} + +void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) +{ + uint8_t buffer[32]; + memset(buffer, 0, 32); + IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address + + if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) + { + // FIXME Need to return errors + return; + } + + buffer[0] = DHCP_BOOTREQUEST; // op + buffer[1] = DHCP_HTYPE10MB; // htype + buffer[2] = DHCP_HLENETHERNET; // hlen + buffer[3] = DHCP_HOPS; // hops + + // xid + unsigned long xid = htonl(_dhcpTransactionId); + memcpy(buffer + 4, &(xid), 4); + + // 8, 9 - seconds elapsed + buffer[8] = ((secondsElapsed & 0xff00) >> 8); + buffer[9] = (secondsElapsed & 0x00ff); + + // flags + unsigned short flags = htons(DHCP_FLAGSBROADCAST); + memcpy(buffer + 10, &(flags), 2); + + // ciaddr: already zeroed + // yiaddr: already zeroed + // siaddr: already zeroed + // giaddr: already zeroed + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 28); + + memset(buffer, 0, 32); // clear local buffer + + memcpy(buffer, _dhcpMacAddr, 6); // chaddr + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 16); + + memset(buffer, 0, 32); // clear local buffer + + // leave zeroed out for sname && file + // put in W5100 transmit buffer x 6 (192 bytes) + + for(int i = 0; i < 6; i++) { + _dhcpUdpSocket.write(buffer, 32); + } + + // OPT - Magic Cookie + buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); + buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); + buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); + buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); + + // OPT - message type + buffer[4] = dhcpMessageType; + buffer[5] = 0x01; + buffer[6] = messageType; //DHCP_REQUEST; + + // OPT - client identifier + buffer[7] = dhcpClientIdentifier; + buffer[8] = 0x07; + buffer[9] = 0x01; + memcpy(buffer + 10, _dhcpMacAddr, 6); + + // OPT - host name + buffer[16] = hostName; + buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address + strcpy((char*)&(buffer[18]), HOST_NAME); + + printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); + printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); + printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 30); + + if(messageType == DHCP_REQUEST) + { + buffer[0] = dhcpRequestedIPaddr; + buffer[1] = 0x04; + buffer[2] = _dhcpLocalIp[0]; + buffer[3] = _dhcpLocalIp[1]; + buffer[4] = _dhcpLocalIp[2]; + buffer[5] = _dhcpLocalIp[3]; + + buffer[6] = dhcpServerIdentifier; + buffer[7] = 0x04; + buffer[8] = _dhcpDhcpServerIp[0]; + buffer[9] = _dhcpDhcpServerIp[1]; + buffer[10] = _dhcpDhcpServerIp[2]; + buffer[11] = _dhcpDhcpServerIp[3]; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 12); + } + + buffer[0] = dhcpParamRequest; + buffer[1] = 0x06; + buffer[2] = subnetMask; + buffer[3] = routersOnSubnet; + buffer[4] = dns; + buffer[5] = domainName; + buffer[6] = dhcpT1value; + buffer[7] = dhcpT2value; + buffer[8] = endOption; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 9); + + _dhcpUdpSocket.endPacket(); +} + +uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) +{ + uint8_t type = 0; + uint8_t opt_len = 0; + + unsigned long startTime = millis(); + + while(_dhcpUdpSocket.parsePacket() <= 0) + { + if((millis() - startTime) > responseTimeout) + { + return 255; + } + delay(50); + } + // start reading in the packet + RIP_MSG_FIXED fixedMsg; + _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); + + if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) + { + transactionId = ntohl(fixedMsg.xid); + if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) + { + // Need to read the rest of the packet here regardless + _dhcpUdpSocket.flush(); + return 0; + } + + memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); + + // Skip to the option part + // Doing this a byte at a time so we don't have to put a big buffer + // on the stack (as we don't have lots of memory lying around) + for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) + { + _dhcpUdpSocket.read(); // we don't care about the returned byte + } + + while (_dhcpUdpSocket.available() > 0) + { + switch (_dhcpUdpSocket.read()) + { + case endOption : + break; + + case padOption : + break; + + case dhcpMessageType : + opt_len = _dhcpUdpSocket.read(); + type = _dhcpUdpSocket.read(); + break; + + case subnetMask : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpSubnetMask, 4); + break; + + case routersOnSubnet : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpGatewayIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dns : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpDnsServerIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dhcpServerIdentifier : + opt_len = _dhcpUdpSocket.read(); + if ((_dhcpDhcpServerIp[0] == 0 && _dhcpDhcpServerIp[1] == 0 && + _dhcpDhcpServerIp[2] == 0 && _dhcpDhcpServerIp[3] == 0) || + IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP()) + { + _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); + } + else + { + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + } + break; + + case dhcpT1value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); + _dhcpT1 = ntohl(_dhcpT1); + break; + + case dhcpT2value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); + _dhcpT2 = ntohl(_dhcpT2); + break; + + case dhcpIPaddrLeaseTime : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); + _dhcpLeaseTime = ntohl(_dhcpLeaseTime); + _renewInSec = _dhcpLeaseTime; + break; + + default : + opt_len = _dhcpUdpSocket.read(); + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + break; + } + } + } + + // Need to skip to end of the packet regardless here + _dhcpUdpSocket.flush(); + + return type; +} + + +/* + returns: + 0/DHCP_CHECK_NONE: nothing happened + 1/DHCP_CHECK_RENEW_FAIL: renew failed + 2/DHCP_CHECK_RENEW_OK: renew success + 3/DHCP_CHECK_REBIND_FAIL: rebind fail + 4/DHCP_CHECK_REBIND_OK: rebind success +*/ +int DhcpClass::checkLease(){ + int rc = DHCP_CHECK_NONE; + + unsigned long now = millis(); + unsigned long elapsed = now - _lastCheckLeaseMillis; + + // if more then one sec passed, reduce the counters accordingly + if (elapsed >= 1000) { + // set the new timestamps + _lastCheckLeaseMillis = now - (elapsed % 1000); + elapsed = elapsed / 1000; + + // decrease the counters by elapsed seconds + // we assume that the cycle time (elapsed) is fairly constant + // if the remainder is less than cycle time * 2 + // do it early instead of late + if (_renewInSec < elapsed * 2) + _renewInSec = 0; + else + _renewInSec -= elapsed; + + if (_rebindInSec < elapsed * 2) + _rebindInSec = 0; + else + _rebindInSec -= elapsed; + } + + // if we have a lease but should renew, do it + if (_renewInSec == 0 &&_dhcp_state == STATE_DHCP_LEASED) { + _dhcp_state = STATE_DHCP_REREQUEST; + rc = 1 + request_DHCP_lease(); + } + + // if we have a lease or is renewing but should bind, do it + if (_rebindInSec == 0 && (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START)) { + // this should basically restart completely + _dhcp_state = STATE_DHCP_START; + reset_DHCP_lease(); + rc = 3 + request_DHCP_lease(); + } + return rc; +} + +IPAddress DhcpClass::getLocalIp() +{ + return IPAddress(_dhcpLocalIp); +} + +IPAddress DhcpClass::getSubnetMask() +{ + return IPAddress(_dhcpSubnetMask); +} + +IPAddress DhcpClass::getGatewayIp() +{ + return IPAddress(_dhcpGatewayIp); +} + +IPAddress DhcpClass::getDhcpServerIp() +{ + return IPAddress(_dhcpDhcpServerIp); +} + +IPAddress DhcpClass::getDnsServerIp() +{ + return IPAddress(_dhcpDnsServerIp); +} + +void DhcpClass::printByte(char * buf, uint8_t n ) { + char *str = &buf[1]; + buf[0]='0'; + do { + unsigned long m = n; + n /= 16; + char c = m - 16 * n; + *str-- = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); +} diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.h b/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.h new file mode 100644 index 0000000..aeadfbd --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.h @@ -0,0 +1,177 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#ifndef Dhcp_h +#define Dhcp_h + +#include "EthernetUdp.h" + +/* DHCP state machine. */ +#define STATE_DHCP_START 0 +#define STATE_DHCP_DISCOVER 1 +#define STATE_DHCP_REQUEST 2 +#define STATE_DHCP_LEASED 3 +#define STATE_DHCP_REREQUEST 4 +#define STATE_DHCP_RELEASE 5 + +#define DHCP_FLAGSBROADCAST 0x8000 + +/* UDP port numbers for DHCP */ +#define DHCP_SERVER_PORT 67 /* from server to client */ +#define DHCP_CLIENT_PORT 68 /* from client to server */ + +/* DHCP message OP code */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_HTYPE10MB 1 +#define DHCP_HTYPE100MB 2 + +#define DHCP_HLENETHERNET 6 +#define DHCP_HOPS 0 +#define DHCP_SECS 0 + +#define MAGIC_COOKIE 0x63825363 +#define MAX_DHCP_OPT 16 + +#define HOST_NAME "WIZnet" +#define DEFAULT_LEASE (900) //default lease time in seconds + +#define DHCP_CHECK_NONE (0) +#define DHCP_CHECK_RENEW_FAIL (1) +#define DHCP_CHECK_RENEW_OK (2) +#define DHCP_CHECK_REBIND_FAIL (3) +#define DHCP_CHECK_REBIND_OK (4) + +enum +{ + padOption = 0, + subnetMask = 1, + timerOffset = 2, + routersOnSubnet = 3, + /* timeServer = 4, + nameServer = 5,*/ + dns = 6, + /*logServer = 7, + cookieServer = 8, + lprServer = 9, + impressServer = 10, + resourceLocationServer = 11,*/ + hostName = 12, + /*bootFileSize = 13, + meritDumpFile = 14,*/ + domainName = 15, + /*swapServer = 16, + rootPath = 17, + extentionsPath = 18, + IPforwarding = 19, + nonLocalSourceRouting = 20, + policyFilter = 21, + maxDgramReasmSize = 22, + defaultIPTTL = 23, + pathMTUagingTimeout = 24, + pathMTUplateauTable = 25, + ifMTU = 26, + allSubnetsLocal = 27, + broadcastAddr = 28, + performMaskDiscovery = 29, + maskSupplier = 30, + performRouterDiscovery = 31, + routerSolicitationAddr = 32, + staticRoute = 33, + trailerEncapsulation = 34, + arpCacheTimeout = 35, + ethernetEncapsulation = 36, + tcpDefaultTTL = 37, + tcpKeepaliveInterval = 38, + tcpKeepaliveGarbage = 39, + nisDomainName = 40, + nisServers = 41, + ntpServers = 42, + vendorSpecificInfo = 43, + netBIOSnameServer = 44, + netBIOSdgramDistServer = 45, + netBIOSnodeType = 46, + netBIOSscope = 47, + xFontServer = 48, + xDisplayManager = 49,*/ + dhcpRequestedIPaddr = 50, + dhcpIPaddrLeaseTime = 51, + /*dhcpOptionOverload = 52,*/ + dhcpMessageType = 53, + dhcpServerIdentifier = 54, + dhcpParamRequest = 55, + /*dhcpMsg = 56, + dhcpMaxMsgSize = 57,*/ + dhcpT1value = 58, + dhcpT2value = 59, + /*dhcpClassIdentifier = 60,*/ + dhcpClientIdentifier = 61, + endOption = 255 +}; + +typedef struct __attribute__((packed)) _RIP_MSG_FIXED +{ + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint8_t ciaddr[4]; + uint8_t yiaddr[4]; + uint8_t siaddr[4]; + uint8_t giaddr[4]; + uint8_t chaddr[6]; +}RIP_MSG_FIXED; + +class DhcpClass { +private: + uint32_t _dhcpInitialTransactionId; + uint32_t _dhcpTransactionId; + uint8_t _dhcpMacAddr[6]; + uint8_t _dhcpLocalIp[4]; + uint8_t _dhcpSubnetMask[4]; + uint8_t _dhcpGatewayIp[4]; + uint8_t _dhcpDhcpServerIp[4]; + uint8_t _dhcpDnsServerIp[4]; + uint32_t _dhcpLeaseTime; + uint32_t _dhcpT1, _dhcpT2; + unsigned long _renewInSec; + unsigned long _rebindInSec; + unsigned long _timeout; + unsigned long _responseTimeout; + unsigned long _lastCheckLeaseMillis; + uint8_t _dhcp_state; + EthernetUDP _dhcpUdpSocket; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + void presend_DHCP(); + void send_DHCP_MESSAGE(uint8_t, uint16_t); + void printByte(char *, uint8_t); + + uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); +public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dns.cpp b/libraries/MySensors/drivers/Ethernet_W5100/Dns.cpp new file mode 100644 index 0000000..62e36f8 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Dns.cpp @@ -0,0 +1,423 @@ +// Arduino DNS client for WizNet5100-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#include "utility/w5100.h" +#include "EthernetUdp.h" +#include "utility/util.h" + +#include "Dns.h" +#include +//#include +#include "Arduino.h" + + +#define SOCKET_NONE 255 +// Various flags and header field values for a DNS message +#define UDP_HEADER_SIZE 8 +#define DNS_HEADER_SIZE 12 +#define TTL_SIZE 4 +#define QUERY_FLAG (0) +#define RESPONSE_FLAG (1<<15) +#define QUERY_RESPONSE_MASK (1<<15) +#define OPCODE_STANDARD_QUERY (0) +#define OPCODE_INVERSE_QUERY (1<<11) +#define OPCODE_STATUS_REQUEST (2<<11) +#define OPCODE_MASK (15<<11) +#define AUTHORITATIVE_FLAG (1<<10) +#define TRUNCATION_FLAG (1<<9) +#define RECURSION_DESIRED_FLAG (1<<8) +#define RECURSION_AVAILABLE_FLAG (1<<7) +#define RESP_NO_ERROR (0) +#define RESP_FORMAT_ERROR (1) +#define RESP_SERVER_FAILURE (2) +#define RESP_NAME_ERROR (3) +#define RESP_NOT_IMPLEMENTED (4) +#define RESP_REFUSED (5) +#define RESP_MASK (15) +#define TYPE_A (0x0001) +#define CLASS_IN (0x0001) +#define LABEL_COMPRESSION_MASK (0xC0) +// Port number that DNS servers listen on +#define DNS_PORT 53 + +// Possible return codes from ProcessResponse +#define SUCCESS 1 +#define TIMED_OUT -1 +#define INVALID_SERVER -2 +#define TRUNCATED -3 +#define INVALID_RESPONSE -4 + +void DNSClient::begin(const IPAddress& aDNSServer) +{ + iDNSServer = aDNSServer; + iRequestId = 0; +} + + +int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult) +{ + // See if we've been given a valid IP address + const char* p =aIPAddrString; + while (*p && + ( (*p == '.') || (*p >= '0') || (*p <= '9') )) + { + p++; + } + + if (*p == '\0') + { + // It's looking promising, we haven't found any invalid characters + p = aIPAddrString; + int segment =0; + int segmentValue =0; + while (*p && (segment < 4)) + { + if (*p == '.') + { + // We've reached the end of a segment + if (segmentValue > 255) + { + // You can't have IP address segments that don't fit in a byte + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + segment++; + segmentValue = 0; + } + } + else + { + // Next digit + segmentValue = (segmentValue*10)+(*p - '0'); + } + p++; + } + // We've reached the end of address, but there'll still be the last + // segment to deal with + if ((segmentValue > 255) || (segment > 3)) + { + // You can't have IP address segments that don't fit in a byte, + // or more than four segments + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + return 1; + } + } + else + { + return 0; + } +} + +int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) +{ + int ret =0; + + // See if it's a numeric IP address + if (inet_aton(aHostname, aResult)) + { + // It is, our work here is done + return 1; + } + + // Check we've got a valid DNS server to use + if (iDNSServer == INADDR_NONE) + { + return INVALID_SERVER; + } + + // Find a socket to use + if (iUdp.begin(1024+(millis() & 0xF)) == 1) + { + // Try up to three times + int retries = 0; +// while ((retries < 3) && (ret <= 0)) + { + // Send DNS request + ret = iUdp.beginPacket(iDNSServer, DNS_PORT); + if (ret != 0) + { + // Now output the request data + ret = BuildRequest(aHostname); + if (ret != 0) + { + // And finally send the request + ret = iUdp.endPacket(); + if (ret != 0) + { + // Now wait for a response + int wait_retries = 0; + ret = TIMED_OUT; + while ((wait_retries < 3) && (ret == TIMED_OUT)) + { + ret = ProcessResponse(5000, aResult); + wait_retries++; + } + } + } + } + retries++; + } + + // We're done with the socket now + iUdp.stop(); + } + + return ret; +} + +uint16_t DNSClient::BuildRequest(const char* aName) +{ + // Build header + // 1 1 1 1 1 1 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ID | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | QDCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ANCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | NSCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ARCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // As we only support one request at a time at present, we can simplify + // some of this header + iRequestId = millis(); // generate a random ID + uint16_t twoByteBuffer; + + // FIXME We should also check that there's enough space available to write to, rather + // FIXME than assume there's enough space (as the code does at present) + iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId)); + + twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(1); // One question record + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = 0; // Zero answer records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // and zero additional records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + // Build question + const char* start =aName; + const char* end =start; + uint8_t len; + // Run through the name being requested + while (*end) + { + // Find out how long this section of the name is + end = start; + while (*end && (*end != '.') ) + { + end++; + } + + if (end-start > 0) + { + // Write out the size of this section + len = end-start; + iUdp.write(&len, sizeof(len)); + // And then write out the section + iUdp.write((uint8_t*)start, end-start); + } + start = end+1; + } + + // We've got to the end of the question name, so + // terminate it with a zero-length section + len = 0; + iUdp.write(&len, sizeof(len)); + // Finally the type and class of question + twoByteBuffer = htons(TYPE_A); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(CLASS_IN); // Internet class of question + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // Success! Everything buffered okay + return 1; +} + + +uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) +{ + uint32_t startTime = millis(); + + // Wait for a response packet + while(iUdp.parsePacket() <= 0) + { + if((millis() - startTime) > aTimeout) + return TIMED_OUT; + delay(50); + } + + // We've had a reply! + // Read the UDP header + uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header + // Check that it's a response from the right server and the right port + if ( (iDNSServer != iUdp.remoteIP()) || + (iUdp.remotePort() != DNS_PORT) ) + { + // It's not from who we expected + return INVALID_SERVER; + } + + // Read through the rest of the response + if (iUdp.available() < DNS_HEADER_SIZE) + { + return TRUNCATED; + } + iUdp.read(header, DNS_HEADER_SIZE); + + uint16_t header_flags = htons(*((uint16_t*)&header[2])); + // Check that it's a response to this request + if ( ( iRequestId != (*((uint16_t*)&header[0])) ) || + ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) ) + { + // Mark the entire packet as read + iUdp.flush(); + return INVALID_RESPONSE; + } + // Check for any errors in the response (or in our request) + // although we don't do anything to get round these + if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) ) + { + // Mark the entire packet as read + iUdp.flush(); + return -5; //INVALID_RESPONSE; + } + + // And make sure we've got (at least) one answer + uint16_t answerCount = htons(*((uint16_t*)&header[6])); + if (answerCount == 0 ) + { + // Mark the entire packet as read + iUdp.flush(); + return -6; //INVALID_RESPONSE; + } + + // Skip over any questions + for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++) + { + // Skip over the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if (len > 0) + { + // Don't need to actually read the data out for the string, just + // advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } while (len != 0); + + // Now jump over the type and class + for (int i =0; i < 4; i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + + // Now we're up to the bit we're interested in, the answer + // There might be more than one answer (although we'll just use the first + // type A answer) and some authority and additional resource records but + // we're going to ignore all of them. + + for (uint16_t i =0; i < answerCount; i++) + { + // Skip the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if ((len & LABEL_COMPRESSION_MASK) == 0) + { + // It's just a normal label + if (len > 0) + { + // And it's got a length + // Don't need to actually read the data out for the string, + // just advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + else + { + // This is a pointer to a somewhere else in the message for the + // rest of the name. We don't care about the name, and RFC1035 + // says that a name is either a sequence of labels ended with a + // 0 length octet or a pointer or a sequence of labels ending in + // a pointer. Either way, when we get here we're at the end of + // the name + // Skip over the pointer + iUdp.read(); // we don't care about the returned byte + // And set len so that we drop out of the name loop + len = 0; + } + } while (len != 0); + + // Check the type and class + uint16_t answerType; + uint16_t answerClass; + iUdp.read((uint8_t*)&answerType, sizeof(answerType)); + iUdp.read((uint8_t*)&answerClass, sizeof(answerClass)); + + // Ignore the Time-To-Live as we don't do any caching + for (int i =0; i < TTL_SIZE; i++) + { + iUdp.read(); // we don't care about the returned byte + } + + // And read out the length of this answer + // Don't need header_flags anymore, so we can reuse it here + iUdp.read((uint8_t*)&header_flags, sizeof(header_flags)); + + if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) ) + { + if (htons(header_flags) != 4) + { + // It's a weird size + // Mark the entire packet as read + iUdp.flush(); + return -9;//INVALID_RESPONSE; + } + iUdp.read(aAddress.raw_address(), 4); + return SUCCESS; + } + else + { + // This isn't an answer type we're after, move onto the next one + for (uint16_t i =0; i < htons(header_flags); i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + + // Mark the entire packet as read + iUdp.flush(); + + // If we get here then we haven't found an answer + return -10;//INVALID_RESPONSE; +} + diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dns.h b/libraries/MySensors/drivers/Ethernet_W5100/Dns.h new file mode 100644 index 0000000..abe0262 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Dns.h @@ -0,0 +1,41 @@ +// Arduino DNS client for WizNet5100-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#ifndef DNSClient_h +#define DNSClient_h + +#include "EthernetUdp.h" + +class DNSClient +{ +public: + // ctor + void begin(const IPAddress& aDNSServer); + + /** Convert a numeric IP address string into a four-byte IP address. + @param aIPAddrString IP address to convert + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int inet_aton(const char *aIPAddrString, IPAddress& aResult); + + /** Resolve the given hostname to an IP address. + @param aHostname Name to be resolved + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int getHostByName(const char* aHostname, IPAddress& aResult); + +protected: + uint16_t BuildRequest(const char* aName); + uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); + + IPAddress iDNSServer; + uint16_t iRequestId; + EthernetUDP iUdp; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.cpp b/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.cpp new file mode 100644 index 0000000..3eea69a --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.cpp @@ -0,0 +1,136 @@ +#include "utility/w5100.h" +#include "Ethernet.h" +#include "Dhcp.h" + +// XXX: don't make assumptions about the value of MAX_SOCK_NUM. +uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { + 0, 0, 0, 0 }; +uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { + 0, 0, 0, 0 }; + +int EthernetClass::begin(uint8_t *mac_address) +{ + static DhcpClass s_dhcp; + _dhcp = &s_dhcp; + + + // Initialise the basic info + W5100.init(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac_address); + W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); + SPI.endTransaction(); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP(mac_address); + if(ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + } + + return ret; +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip) +{ + // Assume the DNS server will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress dns_server = local_ip; + dns_server[3] = 1; + begin(mac_address, local_ip, dns_server); +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server) +{ + // Assume the gateway will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress gateway = local_ip; + gateway[3] = 1; + begin(mac_address, local_ip, dns_server, gateway); +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway) +{ + IPAddress subnet(255, 255, 255, 0); + begin(mac_address, local_ip, dns_server, gateway, subnet); +} + +void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) +{ + W5100.init(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac); + W5100.setIPAddress(local_ip.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); + SPI.endTransaction(); + _dnsServerAddress = dns_server; +} + +int EthernetClass::maintain(){ + int rc = DHCP_CHECK_NONE; + if(_dhcp != NULL){ + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + switch ( rc ){ + case DHCP_CHECK_NONE: + //nothing done + break; + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + break; + default: + //this is actually a error, it will retry though + break; + } + } + return rc; +} + +IPAddress EthernetClass::localIP() +{ + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getIPAddress(ret.raw_address()); + SPI.endTransaction(); + return ret; +} + +IPAddress EthernetClass::subnetMask() +{ + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getSubnetMask(ret.raw_address()); + SPI.endTransaction(); + return ret; +} + +IPAddress EthernetClass::gatewayIP() +{ + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getGatewayIp(ret.raw_address()); + SPI.endTransaction(); + return ret; +} + +IPAddress EthernetClass::dnsServerIP() +{ + return _dnsServerAddress; +} + +EthernetClass Ethernet; diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.h b/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.h new file mode 100644 index 0000000..2a07ff3 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.h @@ -0,0 +1,41 @@ +#ifndef ethernet_h +#define ethernet_h + +#include +//#include "w5100.h" +#include "IPAddress.h" +#include "EthernetClient.h" +#include "EthernetServer.h" +#include "Dhcp.h" + +#define MAX_SOCK_NUM 4 + +class EthernetClass { +private: + IPAddress _dnsServerAddress; + DhcpClass* _dhcp; +public: + static uint8_t _state[MAX_SOCK_NUM]; + static uint16_t _server_port[MAX_SOCK_NUM]; + // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac_address); + void begin(uint8_t *mac_address, IPAddress local_ip); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + int maintain(); + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + friend class EthernetClient; + friend class EthernetServer; +}; + +extern EthernetClass Ethernet; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.cpp b/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.cpp new file mode 100644 index 0000000..75765e5 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.cpp @@ -0,0 +1,177 @@ +#include "utility/w5100.h" +#include "utility/socket.h" + +extern "C" { + #include "string.h" +} + +#include "Arduino.h" + +#include "Ethernet.h" +#include "EthernetClient.h" +#include "EthernetServer.h" +#include "Dns.h" + +uint16_t EthernetClient::_srcport = 49152; //Use IANA recommended ephemeral port range 49152-65535 + +EthernetClient::EthernetClient() : _sock(MAX_SOCK_NUM) { +} + +EthernetClient::EthernetClient(uint8_t sock) : _sock(sock) { +} + +int EthernetClient::connect(const char* host, uint16_t port) { + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(Ethernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return connect(remote_addr, port); + } else { + return ret; + } +} + +int EthernetClient::connect(IPAddress ip, uint16_t port) { + if (_sock != MAX_SOCK_NUM) + return 0; + + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = socketStatus(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return 0; + + _srcport++; + if (_srcport == 0) _srcport = 49152; //Use IANA recommended ephemeral port range 49152-65535 + socket(_sock, SnMR::TCP, _srcport, 0); + + if (!::connect(_sock, rawIPAddress(ip), port)) { + _sock = MAX_SOCK_NUM; + return 0; + } + + while (status() != SnSR::ESTABLISHED) { + delay(1); + if (status() == SnSR::CLOSED) { + _sock = MAX_SOCK_NUM; + return 0; + } + } + + return 1; +} + +size_t EthernetClient::write(uint8_t b) { + return write(&b, 1); +} + +size_t EthernetClient::write(const uint8_t *buf, size_t size) { + if (_sock == MAX_SOCK_NUM) { + setWriteError(); + return 0; + } + if (!send(_sock, buf, size)) { + setWriteError(); + return 0; + } + return size; +} + +int EthernetClient::available() { + if (_sock != MAX_SOCK_NUM) + return recvAvailable(_sock); + return 0; +} + +int EthernetClient::read() { + uint8_t b; + if ( recv(_sock, &b, 1) > 0 ) + { + // recv worked + return b; + } + else + { + // No data available + return -1; + } +} + +int EthernetClient::read(uint8_t *buf, size_t size) { + return recv(_sock, buf, size); +} + +int EthernetClient::peek() { + uint8_t b; + // Unlike recv, peek doesn't check to see if there's any data available, so we must + if (!available()) + return -1; + ::peek(_sock, &b); + return b; +} + +void EthernetClient::flush() { + ::flush(_sock); +} + +void EthernetClient::stop() { + if (_sock == MAX_SOCK_NUM) + return; + + // attempt to close the connection gracefully (send a FIN to other side) + disconnect(_sock); + unsigned long start = millis(); + + // wait up to a second for the connection to close + uint8_t s; + do { + s = status(); + if (s == SnSR::CLOSED) + break; // exit the loop + delay(1); + } while (millis() - start < 1000); + + // if it hasn't closed, close it forcefully + if (s != SnSR::CLOSED) + close(_sock); + + EthernetClass::_server_port[_sock] = 0; + _sock = MAX_SOCK_NUM; +} + +uint8_t EthernetClient::connected() { + if (_sock == MAX_SOCK_NUM) return 0; + + uint8_t s = status(); + return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT || + (s == SnSR::CLOSE_WAIT && !available())); +} + +uint8_t EthernetClient::status() { + if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED; + return socketStatus(_sock); +} + +// the next function allows us to use the client returned by +// EthernetServer::available() as the condition in an if-statement. + +EthernetClient::operator bool() { + return _sock != MAX_SOCK_NUM; +} + +bool EthernetClient::operator==(const EthernetClient& rhs) { + return _sock == rhs._sock && _sock != MAX_SOCK_NUM && rhs._sock != MAX_SOCK_NUM; +} + +uint8_t EthernetClient::getSocketNumber() { + return _sock; +} diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.h b/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.h new file mode 100644 index 0000000..52a3b8f --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.h @@ -0,0 +1,42 @@ +#ifndef ethernetclient_h +#define ethernetclient_h +#include "Arduino.h" +#include "Print.h" +#include "Client.h" +#include "IPAddress.h" + +class EthernetClient : public Client { + +public: + EthernetClient(); + EthernetClient(uint8_t sock); + + uint8_t status(); + virtual int connect(IPAddress 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(); + virtual bool operator==(const bool value) { return bool() == value; } + virtual bool operator!=(const bool value) { return bool() != value; } + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; + uint8_t getSocketNumber(); + + friend class EthernetServer; + + using Print::write; + +private: + static uint16_t _srcport; + uint8_t _sock; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.cpp b/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.cpp new file mode 100644 index 0000000..cfa813e --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.cpp @@ -0,0 +1,92 @@ +#include "utility/w5100.h" +#include "utility/socket.h" +extern "C" { +#include "string.h" +} + +#include "Ethernet.h" +#include "EthernetClient.h" +#include "EthernetServer.h" + +EthernetServer::EthernetServer(uint16_t port) +{ + _port = port; +} + +void EthernetServer::begin() +{ + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + if (client.status() == SnSR::CLOSED) { + socket(sock, SnMR::TCP, _port, 0); + listen(sock); + EthernetClass::_server_port[sock] = _port; + break; + } + } +} + +void EthernetServer::accept() +{ + int listening = 0; + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + + if (EthernetClass::_server_port[sock] == _port) { + if (client.status() == SnSR::LISTEN) { + listening = 1; + } + else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) { + client.stop(); + } + } + } + + if (!listening) { + begin(); + } +} + +EthernetClient EthernetServer::available() +{ + accept(); + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + if (EthernetClass::_server_port[sock] == _port) { + uint8_t s = client.status(); + if (s == SnSR::ESTABLISHED || s == SnSR::CLOSE_WAIT) { + if (client.available()) { + // XXX: don't always pick the lowest numbered socket. + return client; + } + } + } + } + + return EthernetClient(MAX_SOCK_NUM); +} + +size_t EthernetServer::write(uint8_t b) +{ + return write(&b, 1); +} + +size_t EthernetServer::write(const uint8_t *buffer, size_t size) +{ + size_t n = 0; + + accept(); + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + + if (EthernetClass::_server_port[sock] == _port && + client.status() == SnSR::ESTABLISHED) { + n += client.write(buffer, size); + } + } + + return n; +} diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.h b/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.h new file mode 100644 index 0000000..86ccafe --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.h @@ -0,0 +1,22 @@ +#ifndef ethernetserver_h +#define ethernetserver_h + +#include "Server.h" + +class EthernetClient; + +class EthernetServer : +public Server { +private: + uint16_t _port; + void accept(); +public: + EthernetServer(uint16_t); + EthernetClient available(); + virtual void begin(); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + using Print::write; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.cpp b/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.cpp new file mode 100644 index 0000000..2baee82 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.cpp @@ -0,0 +1,252 @@ +/* + * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.c/socket.h + * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#include "utility/w5100.h" +#include "utility/socket.h" +#include "Ethernet.h" +#include "Udp.h" +#include "Dns.h" + +/* Constructor */ +EthernetUDP::EthernetUDP() : _sock(MAX_SOCK_NUM) {} + +/* Start EthernetUDP socket, listening at local port PORT */ +uint8_t EthernetUDP::begin(uint16_t port) { + if (_sock != MAX_SOCK_NUM) + return 0; + + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = socketStatus(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return 0; + + _port = port; + _remaining = 0; + socket(_sock, SnMR::UDP, _port, 0); + + return 1; +} + +/* return number of bytes available in the current packet, + will return zero if parsePacket hasn't been called yet */ +int EthernetUDP::available() { + return _remaining; +} + +/* Release any resources being used by this EthernetUDP instance */ +void EthernetUDP::stop() +{ + if (_sock == MAX_SOCK_NUM) + return; + + close(_sock); + + EthernetClass::_server_port[_sock] = 0; + _sock = MAX_SOCK_NUM; +} + +int EthernetUDP::beginPacket(const char *host, uint16_t port) +{ + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(Ethernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return beginPacket(remote_addr, port); + } else { + return ret; + } +} + +int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) +{ + _offset = 0; + return startUDP(_sock, rawIPAddress(ip), port); +} + +int EthernetUDP::endPacket() +{ + return sendUDP(_sock); +} + +size_t EthernetUDP::write(uint8_t byte) +{ + return write(&byte, 1); +} + +size_t EthernetUDP::write(const uint8_t *buffer, size_t size) +{ + uint16_t bytes_written = bufferData(_sock, _offset, buffer, size); + _offset += bytes_written; + return bytes_written; +} + +int EthernetUDP::parsePacket() +{ + // discard any remaining bytes in the last packet + flush(); + + if (recvAvailable(_sock) > 0) + { + //HACK - hand-parse the UDP packet using TCP recv method + uint8_t tmpBuf[8]; + int ret =0; + //read 8 header bytes and get IP and port from it + ret = recv(_sock,tmpBuf,8); + if (ret > 0) + { + _remoteIP = tmpBuf; + _remotePort = tmpBuf[4]; + _remotePort = (_remotePort << 8) + tmpBuf[5]; + _remaining = tmpBuf[6]; + _remaining = (_remaining << 8) + tmpBuf[7]; + + // When we get here, any remaining bytes are the data + ret = _remaining; + } + return ret; + } + // There aren't any packets available + return 0; +} + +int EthernetUDP::read() +{ + uint8_t byte; + + if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0)) + { + // We read things without any problems + _remaining--; + return byte; + } + + // If we get here, there's no data available + return -1; +} + +int EthernetUDP::read(unsigned char* buffer, size_t len) +{ + + if (_remaining > 0) + { + + int got; + + if (_remaining <= len) + { + // data should fit in the buffer + got = recv(_sock, buffer, _remaining); + } + else + { + // too much data for the buffer, + // grab as much as will fit + got = recv(_sock, buffer, len); + } + + if (got > 0) + { + _remaining -= got; + return got; + } + + } + + // If we get here, there's no data available or recv failed + return -1; + +} + +int EthernetUDP::peek() +{ + uint8_t b; + // Unlike recv, peek doesn't check to see if there's any data available, so we must. + // If the user hasn't called parsePacket yet then return nothing otherwise they + // may get the UDP header + if (!_remaining) + return -1; + ::peek(_sock, &b); + return b; +} + +void EthernetUDP::flush() +{ + // could this fail (loop endlessly) if _remaining > 0 and recv in read fails? + // should only occur if recv fails after telling us the data is there, lets + // hope the w5100 always behaves :) + + while (_remaining) + { + read(); + } +} + +/* Start EthernetUDP socket, listening at local port PORT */ +uint8_t EthernetUDP::beginMulticast(IPAddress ip, uint16_t port) +{ + if (_sock != MAX_SOCK_NUM) + return 0; + + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = W5100.readSnSR(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return 0; + + // Calculate MAC address from Multicast IP Address + byte mac[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; + + mac[3] = ip[1] & 0x7F; + mac[4] = ip[2]; + mac[5] = ip[3]; + + W5100.writeSnDIPR(_sock, rawIPAddress(ip)); //239.255.0.1 + W5100.writeSnDPORT(_sock, port); + W5100.writeSnDHAR(_sock,mac); + + _remaining = 0; + socket(_sock, SnMR::UDP, port, SnMR::MULTI); + return 1; +} + + diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.h b/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.h new file mode 100644 index 0000000..549e355 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.h @@ -0,0 +1,102 @@ +/* + * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.c/socket.h + * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + * + * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) + * 1) UDP does not guarantee the order in which assembled UDP packets are received. This + * might not happen often in practice, but in larger network topologies, a UDP + * packet can be received out of sequence. + * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being + * aware of it. Again, this may not be a concern in practice on small local networks. + * For more information, see http://www.cafeaulait.org/course/week12/35.html + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#ifndef ethernetudp_h +#define ethernetudp_h + +#include + +#define UDP_TX_PACKET_MAX_SIZE 24 + +class EthernetUDP : public UDP { +private: + uint16_t _port; // local port to listen on + IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed + uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + uint16_t _offset; // offset into the packet being sent + +protected: + uint8_t _sock; // socket ID for Wiz5100 + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed + +public: + EthernetUDP(); // Constructor + virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() { return _remoteIP; }; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() { return _remotePort; }; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.cpp b/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.cpp new file mode 100644 index 0000000..175ba75 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.cpp @@ -0,0 +1,74 @@ +/* + IPAddress.cpp - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. 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 +*/ + +#include +#include "IPAddress.h" + +IPAddress::IPAddress() +{ + _address.dword = 0; +} + +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +{ + _address.bytes[0] = first_octet; + _address.bytes[1] = second_octet; + _address.bytes[2] = third_octet; + _address.bytes[3] = fourth_octet; +} + +IPAddress::IPAddress(uint32_t address) +{ + _address.dword = address; +} + +IPAddress::IPAddress(const uint8_t *address) +{ + memcpy(_address.bytes, address, sizeof(_address.bytes)); +} + +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + memcpy(_address.bytes, address, sizeof(_address.bytes)); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + _address.dword = address; + return *this; +} + +bool IPAddress::operator==(const uint8_t* addr) const +{ + return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; +} + +size_t IPAddress::printTo(Print& p) const +{ + size_t n = 0; + for (int i =0; i < 3; i++) + { + n += p.print(_address.bytes[i], DEC); + n += p.print('.'); + } + n += p.print(_address.bytes[3], DEC); + return n; +} + diff --git a/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.h b/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.h new file mode 100644 index 0000000..94acdc4 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.h @@ -0,0 +1,75 @@ +/* + IPAddress.h - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. 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 +*/ + +#ifndef IPAddress_h +#define IPAddress_h + +#include +#include + +// A class to make it easier to handle and pass around IP addresses + +class IPAddress : public Printable { +private: + union { + uint8_t bytes[4]; // IPv4 address + uint32_t dword; + } _address; + + // Access the raw byte array containing the address. Because this returns a pointer + // to the internal structure rather than a copy of the address this function should only + // be used when you know that the usage of the returned uint8_t* will be transient and not + // stored. + uint8_t* raw_address() { return _address.bytes; }; + +public: + // Constructors + IPAddress(); + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + IPAddress(uint32_t address); + IPAddress(const uint8_t *address); + + // Overloaded cast operator to allow IPAddress objects to be used where a pointer + // to a four-byte uint8_t array is expected + operator uint32_t() const { return _address.dword; }; + bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; }; + bool operator==(const uint8_t* addr) const; + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const { return _address.bytes[index]; }; + uint8_t& operator[](int index) { return _address.bytes[index]; }; + + // Overloaded copy operators to allow initialisation of IPAddress objects from other types + IPAddress& operator=(const uint8_t *address); + IPAddress& operator=(uint32_t address); + + virtual size_t printTo(Print& p) const; + + friend class EthernetClass; + friend class UDP; + friend class Client; + friend class Server; + friend class DhcpClass; + friend class DNSClient; +}; + +const IPAddress INADDR_NONE(0,0,0,0); + + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Server.h b/libraries/MySensors/drivers/Ethernet_W5100/Server.h new file mode 100644 index 0000000..69e3e39 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/Server.h @@ -0,0 +1,30 @@ +/* + Server.h - Base class that provides Server + Copyright (c) 2011 Adrian McEwen. 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 +*/ + +#ifndef server_h +#define server_h + +#include "Print.h" + +class Server : public Print { +public: + virtual void begin() =0; +}; + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.cpp b/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.cpp new file mode 100644 index 0000000..9254b74 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.cpp @@ -0,0 +1,469 @@ +#include "w5100.h" +#include "socket.h" + +static uint16_t local_port; + +/** + * @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it. + * @return 1 for success else 0. + */ +uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) +{ + if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE)) + { + close(s); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnMR(s, protocol | flag); + if (port != 0) { + W5100.writeSnPORT(s, port); + } + else { + local_port++; // if don't set the source port, set local_port number. + W5100.writeSnPORT(s, local_port); + } + + W5100.execCmdSn(s, Sock_OPEN); + SPI.endTransaction(); + return 1; + } + + return 0; +} + + +uint8_t socketStatus(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + uint8_t status = W5100.readSnSR(s); + SPI.endTransaction(); + return status; +} + + +/** + * @brief This function close the socket and parameter is "s" which represent the socket number + */ +void close(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.execCmdSn(s, Sock_CLOSE); + W5100.writeSnIR(s, 0xFF); + SPI.endTransaction(); +} + + +/** + * @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer. + * @return 1 for success else 0. + */ +uint8_t listen(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + if (W5100.readSnSR(s) != SnSR::INIT) { + SPI.endTransaction(); + return 0; + } + W5100.execCmdSn(s, Sock_LISTEN); + SPI.endTransaction(); + return 1; +} + + +/** + * @brief This function established the connection for the channel in Active (client) mode. + * This function waits for the untill the connection is established. + * + * @return 1 for success else 0. + */ +uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port) +{ + if + ( + ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) || + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + (port == 0x00) + ) + return 0; + + // set destination IP + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + W5100.execCmdSn(s, Sock_CONNECT); + SPI.endTransaction(); + + return 1; +} + + + +/** + * @brief This function used for disconnect the socket and parameter is "s" which represent the socket number + * @return 1 for success else 0. + */ +void disconnect(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.execCmdSn(s, Sock_DISCON); + SPI.endTransaction(); +} + + +/** + * @brief This function used to send the data in TCP mode + * @return 1 for success else 0. + */ +uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len) +{ + uint8_t status=0; + uint16_t ret=0; + uint16_t freesize=0; + + if (len > W5100.SSIZE) + ret = W5100.SSIZE; // check size not to exceed MAX size. + else + ret = len; + + // if freebuf is available, start. + do + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + freesize = W5100.getTXFreeSize(s); + status = W5100.readSnSR(s); + SPI.endTransaction(); + if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT)) + { + ret = 0; + break; + } + yield(); + } + while (freesize < ret); + + // copy data + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + /* m2008.01 [bj] : reduce code */ + if ( W5100.readSnSR(s) == SnSR::CLOSED ) + { + SPI.endTransaction(); + close(s); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + return ret; +} + + +/** + * @brief This function is an application I/F function which is used to receive the data in TCP mode. + * It continues to wait for data as much as the application wants to receive. + * + * @return received data size for success else -1. + */ +int16_t recv(SOCKET s, uint8_t *buf, int16_t len) +{ + // Check how much data is available + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + int16_t ret = W5100.getRXReceivedSize(s); + if ( ret == 0 ) + { + // No data available. + uint8_t status = W5100.readSnSR(s); + if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT ) + { + // The remote end has closed its side of the connection, so this is the eof state + ret = 0; + } + else + { + // The connection is still up, but there's no data waiting to be read + ret = -1; + } + } + else if (ret > len) + { + ret = len; + } + + if ( ret > 0 ) + { + W5100.recv_data_processing(s, buf, ret); + W5100.execCmdSn(s, Sock_RECV); + } + SPI.endTransaction(); + return ret; +} + + +int16_t recvAvailable(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + int16_t ret = W5100.getRXReceivedSize(s); + SPI.endTransaction(); + return ret; +} + + +/** + * @brief Returns the first byte in the receive queue (no checking) + * + * @return + */ +uint16_t peek(SOCKET s, uint8_t *buf) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.recv_data_processing(s, buf, 1, 1); + SPI.endTransaction(); + return 1; +} + + +/** + * @brief This function is an application I/F function which is used to send the data for other then TCP mode. + * Unlike TCP transmission, The peer's destination address and the port is needed. + * + * @return This function return send data size for success else -1. + */ +uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port) +{ + uint16_t ret=0; + + if (len > W5100.SSIZE) ret = W5100.SSIZE; // check size not to exceed MAX size. + else ret = len; + + if + ( + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + ((port == 0x00)) ||(ret == 0) + ) + { + /* +2008.01 [bj] : added return value */ + ret = 0; + } + else + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + + // copy data + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* +2008.01 [bj]: clear interrupt */ + W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */ + SPI.endTransaction(); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + } + return ret; +} + + +/** + * @brief This function is an application I/F function which is used to receive the data in other then + * TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well. + * + * @return This function return received data size for success else -1. + */ +uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port) +{ + uint8_t head[8]; + uint16_t data_len=0; + uint16_t ptr=0; + + if ( len > 0 ) + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + ptr = W5100.readSnRX_RD(s); + switch (W5100.readSnMR(s) & 0x07) + { + case SnMR::UDP : + W5100.read_data(s, ptr, head, 0x08); + ptr += 8; + // read peer's IP address, port number. + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + *port = head[4]; + *port = (*port << 8) + head[5]; + data_len = head[6]; + data_len = (data_len << 8) + head[7]; + + W5100.read_data(s, ptr, buf, data_len); // data copy. + ptr += data_len; + + W5100.writeSnRX_RD(s, ptr); + break; + + case SnMR::IPRAW : + W5100.read_data(s, ptr, head, 0x06); + ptr += 6; + + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + data_len = head[4]; + data_len = (data_len << 8) + head[5]; + + W5100.read_data(s, ptr, buf, data_len); // data copy. + ptr += data_len; + + W5100.writeSnRX_RD(s, ptr); + break; + + case SnMR::MACRAW: + W5100.read_data(s, ptr, head, 2); + ptr+=2; + data_len = head[0]; + data_len = (data_len<<8) + head[1] - 2; + + W5100.read_data(s, ptr, buf, data_len); + ptr += data_len; + W5100.writeSnRX_RD(s, ptr); + break; + + default : + break; + } + W5100.execCmdSn(s, Sock_RECV); + SPI.endTransaction(); + } + return data_len; +} + +/** + * @brief Wait for buffered transmission to complete. + */ +void flush(SOCKET s) { + // TODO +} + +uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len) +{ + uint16_t ret=0; + + if (len > W5100.SSIZE) + ret = W5100.SSIZE; // check size not to exceed MAX size. + else + ret = len; + + if (ret == 0) + return 0; + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* in case of igmp, if send fails, then socket closed */ + /* if you want change, remove this code. */ + SPI.endTransaction(); + close(s); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + return ret; +} + +uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len) +{ + uint16_t ret =0; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + if (len > W5100.getTXFreeSize(s)) + { + ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size. + } + else + { + ret = len; + } + W5100.send_data_processing_offset(s, offset, buf, ret); + SPI.endTransaction(); + return ret; +} + +int startUDP(SOCKET s, uint8_t* addr, uint16_t port) +{ + if + ( + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + ((port == 0x00)) + ) + { + return 0; + } + else + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + SPI.endTransaction(); + return 1; + } +} + +int sendUDP(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* +2008.01 [bj]: clear interrupt */ + W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT)); + SPI.endTransaction(); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + + /* Sent ok */ + return 1; +} + diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.h b/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.h new file mode 100644 index 0000000..6a88bce --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.h @@ -0,0 +1,44 @@ +#ifndef _SOCKET_H_ +#define _SOCKET_H_ + +#include "w5100.h" + +extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode) +extern uint8_t socketStatus(SOCKET s); +extern void close(SOCKET s); // Close socket +extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection) +extern void disconnect(SOCKET s); // disconnect the connection +extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection) +extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP) +extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP) +extern int16_t recvAvailable(SOCKET s); +extern uint16_t peek(SOCKET s, uint8_t *buf); +extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW) +extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW) +extern void flush(SOCKET s); // Wait for transmission to complete + +extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len); + +// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a +// number of calls before being sent +/* + @brief This function sets up a UDP datagram, the data for which will be provided by one + or more calls to bufferData and then finally sent with sendUDP. + @return 1 if the datagram was successfully set up, or 0 if there was an error +*/ +extern int startUDP(SOCKET s, uint8_t* addr, uint16_t port); +/* + @brief This function copies up to len bytes of data from buf into a UDP datagram to be + sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. + @return Number of bytes successfully buffered +*/ +uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len); +/* + @brief Send a UDP datagram built up from a sequence of startUDP followed by one or more + calls to bufferData. + @return 1 if the datagram was successfully sent, or 0 if there was an error +*/ +int sendUDP(SOCKET s); + +#endif +/* _SOCKET_H_ */ diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/util.h b/libraries/MySensors/drivers/Ethernet_W5100/utility/util.h new file mode 100644 index 0000000..33d32a9 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/utility/util.h @@ -0,0 +1,14 @@ +#ifndef UTIL_H +#define UTIL_H + +#define htons(x) ( ((x)<< 8 & 0xFF00) | \ + ((x)>> 8 & 0x00FF) ) +#define ntohs(x) htons(x) + +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#endif diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.cpp b/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.cpp new file mode 100644 index 0000000..48409e0 --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2010 by Arduino LLC. All rights reserved. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include +#include + +#include "w5100.h" + +// W5100 controller instance +W5100Class W5100; + +#define TX_RX_MAX_BUF_SIZE 2048 +#define TX_BUF 0x1100 +#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE) + +#define TXBUF_BASE 0x4000 +#define RXBUF_BASE 0x6000 + +void W5100Class::init(void) +{ + delay(300); + +#if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) + SPI.begin(); + initSS(); +#else + SPI.begin(SPI_CS); + // Set clock to 4Mhz (W5100 should support up to about 14Mhz) + SPI.setClockDivider(SPI_CS, 21); + SPI.setDataMode(SPI_CS, SPI_MODE0); +#endif + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + writeMR(1< SSIZE) + { + // Wrap around circular buffer + uint16_t size = SSIZE - offset; + write(dstAddr, data, size); + write(SBASE[s], data + size, len - size); + } + else { + write(dstAddr, data, len); + } + + ptr += len; + writeSnTX_WR(s, ptr); +} + + +void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) +{ + uint16_t ptr; + ptr = readSnRX_RD(s); + read_data(s, ptr, data, len); + if (!peek) + { + ptr += len; + writeSnRX_RD(s, ptr); + } +} + +void W5100Class::read_data(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len) +{ + uint16_t size; + uint16_t src_mask; + uint16_t src_ptr; + + src_mask = src & RMASK; + src_ptr = RBASE[s] + src_mask; + + if( (src_mask + len) > RSIZE ) + { + size = RSIZE - src_mask; + read(src_ptr, (uint8_t *)dst, size); + dst += size; + read(RBASE[s], (uint8_t *) dst, len - size); + } + else + read(src_ptr, (uint8_t *) dst, len); +} + + +uint8_t W5100Class::write(uint16_t _addr, uint8_t _data) +{ +#if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) + setSS(); + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_data); + resetSS(); +#else + SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _data); +#endif + return 1; +} + +uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len) +{ + for (uint16_t i=0; i<_len; i++) + { +#if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) + setSS(); + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + SPI.transfer(_buf[i]); + resetSS(); +#else + SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _buf[i]); + _addr++; +#endif + } + return _len; +} + +uint8_t W5100Class::read(uint16_t _addr) +{ +#if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) + setSS(); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + uint8_t _data = SPI.transfer(0); + resetSS(); +#else + SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + uint8_t _data = SPI.transfer(SPI_CS, 0); +#endif + return _data; +} + +uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len) +{ + for (uint16_t i=0; i<_len; i++) + { +#if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) + setSS(); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + _buf[i] = SPI.transfer(0); + resetSS(); +#else + SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + _buf[i] = SPI.transfer(SPI_CS, 0); + _addr++; +#endif + } + return _len; +} + +void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) { + // Send command to socket + writeSnCR(s, _cmd); + // Wait for command to complete + while (readSnCR(s)) + ; +} diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.h b/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.h new file mode 100644 index 0000000..358e25c --- /dev/null +++ b/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.h @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2010 by Arduino LLC. All rights reserved. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef W5100_H_INCLUDED +#define W5100_H_INCLUDED + +#include "drivers/SPI/SPI.h" + +#define ETHERNET_SHIELD_SPI_CS 10 + +#define MAX_SOCK_NUM 4 + +typedef uint8_t SOCKET; + +#define IDM_OR 0x8000 +#define IDM_AR0 0x8001 +#define IDM_AR1 0x8002 +#define IDM_DR 0x8003 +/* +class MR { +public: + static const uint8_t RST = 0x80; + static const uint8_t PB = 0x10; + static const uint8_t PPPOE = 0x08; + static const uint8_t LB = 0x04; + static const uint8_t AI = 0x02; + static const uint8_t IND = 0x01; +}; +*/ +/* +class IR { +public: + static const uint8_t CONFLICT = 0x80; + static const uint8_t UNREACH = 0x40; + static const uint8_t PPPoE = 0x20; + static const uint8_t SOCK0 = 0x01; + static const uint8_t SOCK1 = 0x02; + static const uint8_t SOCK2 = 0x04; + static const uint8_t SOCK3 = 0x08; + static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); }; +}; +*/ + +class SnMR { +public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x01; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; +}; + +enum SockCMD { + Sock_OPEN = 0x01, + Sock_LISTEN = 0x02, + Sock_CONNECT = 0x04, + Sock_DISCON = 0x08, + Sock_CLOSE = 0x10, + Sock_SEND = 0x20, + Sock_SEND_MAC = 0x21, + Sock_SEND_KEEP = 0x22, + Sock_RECV = 0x40 +}; + +/*class SnCmd { +public: + static const uint8_t OPEN = 0x01; + static const uint8_t LISTEN = 0x02; + static const uint8_t CONNECT = 0x04; + static const uint8_t DISCON = 0x08; + static const uint8_t CLOSE = 0x10; + static const uint8_t SEND = 0x20; + static const uint8_t SEND_MAC = 0x21; + static const uint8_t SEND_KEEP = 0x22; + static const uint8_t RECV = 0x40; +}; +*/ + +class SnIR { +public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; +}; + +class SnSR { +public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; +}; + +class IPPROTO { +public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; +}; + +class W5100Class { + +public: + void init(); + + /** + * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. + * + * It calculate the actual physical address where one has to read + * the data from Receive buffer. Here also take care of the condition while it exceed + * the Rx memory uper-bound of socket. + */ + void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); + + /** + * @brief This function is being called by send() and sendto() function also. + * + * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer + * register. User should read upper byte first and lower byte later to get proper value. + */ + void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); + /** + * @brief A copy of send_data_processing that uses the provided ptr for the + * write offset. Only needed for the "streaming" UDP API, where + * a single UDP packet is built up over a number of calls to + * send_data_processing_ptr, because TX_WR doesn't seem to get updated + * correctly in those scenarios + * @param ptr value to use in place of TX_WR. If 0, then the value is read + * in from TX_WR + * @return New value for ptr, to be used in the next call + */ +// FIXME Update documentation + void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); + + /** + * @brief This function is being called by recv() also. + * + * This function read the Rx read pointer register + * and after copy the data from receive buffer update the Rx write pointer register. + * User should read upper byte first and lower byte later to get proper value. + */ + void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); + + inline void setGatewayIp(uint8_t *_addr); + inline void getGatewayIp(uint8_t *_addr); + + inline void setSubnetMask(uint8_t *_addr); + inline void getSubnetMask(uint8_t *_addr); + + inline void setMACAddress(uint8_t * addr); + inline void getMACAddress(uint8_t * addr); + + inline void setIPAddress(uint8_t * addr); + inline void getIPAddress(uint8_t * addr); + + inline void setRetransmissionTime(uint16_t timeout); + inline void setRetransmissionCount(uint8_t _retry); + + void execCmdSn(SOCKET s, SockCMD _cmd); + + uint16_t getTXFreeSize(SOCKET s); + uint16_t getRXReceivedSize(SOCKET s); + + + // W5100 Registers + // --------------- +private: + static uint8_t write(uint16_t _addr, uint8_t _data); + static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); + static uint8_t read(uint16_t addr); + static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + +#define __GP_REGISTER8(name, address) \ + static inline void write##name(uint8_t _data) { \ + write(address, _data); \ + } \ + static inline uint8_t read##name() { \ + return read(address); \ + } +#define __GP_REGISTER16(name, address) \ + static void write##name(uint16_t _data) { \ + write(address, _data >> 8); \ + write(address+1, _data & 0xFF); \ + } \ + static uint16_t read##name() { \ + uint16_t res = read(address); \ + res = (res << 8) + read(address + 1); \ + return res; \ + } +#define __GP_REGISTER_N(name, address, size) \ + static uint16_t write##name(uint8_t *_buff) { \ + return write(address, _buff, size); \ + } \ + static uint16_t read##name(uint8_t *_buff) { \ + return read(address, _buff, size); \ + } + +public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017); // Timeout address + __GP_REGISTER8 (RCR, 0x0019); // Retry count + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number + __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode + __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode + +#undef __GP_REGISTER8 +#undef __GP_REGISTER16 +#undef __GP_REGISTER_N + + // W5100 Socket registers + // ---------------------- +private: + static inline uint8_t readSn(SOCKET _s, uint16_t _addr); + static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); + static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + + static const uint16_t CH_BASE = 0x0400; + static const uint16_t CH_SIZE = 0x0100; + +#define __SOCKET_REGISTER8(name, address) \ + static inline void write##name(SOCKET _s, uint8_t _data) { \ + writeSn(_s, address, _data); \ + } \ + static inline uint8_t read##name(SOCKET _s) { \ + return readSn(_s, address); \ + } +#define __SOCKET_REGISTER16(name, address) \ + static void write##name(SOCKET _s, uint16_t _data) { \ + writeSn(_s, address, _data >> 8); \ + writeSn(_s, address+1, _data & 0xFF); \ + } \ + static uint16_t read##name(SOCKET _s) { \ + uint16_t res = readSn(_s, address); \ + uint16_t res2 = readSn(_s,address + 1); \ + res = res << 8; \ + res2 = res2 & 0xFF; \ + res = res | res2; \ + return res; \ + } +#define __SOCKET_REGISTER_N(name, address, size) \ + static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ + return writeSn(_s, address, _buff, size); \ + } \ + static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ + return readSn(_s, address, _buff, size); \ + } + +public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + +#undef __SOCKET_REGISTER8 +#undef __SOCKET_REGISTER16 +#undef __SOCKET_REGISTER_N + + +private: + static const uint8_t RST = 7; // Reset BIT + + static const int SOCKETS = 4; + static const uint16_t SMASK = 0x07FF; // Tx buffer MASK + static const uint16_t RMASK = 0x07FF; // Rx buffer MASK +public: + static const uint16_t SSIZE = 2048; // Max Tx buffer size +private: + static const uint16_t RSIZE = 2048; // Max Rx buffer size + uint16_t SBASE[SOCKETS]; // Tx buffer base address + uint16_t RBASE[SOCKETS]; // Rx buffer base address + +private: +#if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) + #define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0) + #if defined(ARDUINO_ARCH_AVR) + #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + inline static void initSS() { DDRB |= _BV(4); }; + inline static void setSS() { PORTB &= ~_BV(4); }; + inline static void resetSS() { PORTB |= _BV(4); }; + #elif defined(__AVR_ATmega32U4__) + inline static void initSS() { DDRB |= _BV(6); }; + inline static void setSS() { PORTB &= ~_BV(6); }; + inline static void resetSS() { PORTB |= _BV(6); }; + #elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) + inline static void initSS() { DDRB |= _BV(0); }; + inline static void setSS() { PORTB &= ~_BV(0); }; + inline static void resetSS() { PORTB |= _BV(0); }; + #else + inline static void initSS() { DDRB |= _BV(2); }; + inline static void setSS() { PORTB &= ~_BV(2); }; + inline static void resetSS() { PORTB |= _BV(2); }; + #endif + #else + inline static void initSS() { + *portModeRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) |= digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); + } + inline static void setSS() { + *portOutputRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) &= ~digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); + } + inline static void resetSS() { + *portOutputRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) |= digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); + } + #endif +#else + #define SPI_ETHERNET_SETTINGS ETHERNET_SHIELD_SPI_CS,SPISettings(4000000, MSBFIRST, SPI_MODE0) + // initSS(), setSS(), resetSS() not needed with EXTENDED_CS_PIN_HANDLING +#endif +}; + +extern W5100Class W5100; + +uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) { + return read(CH_BASE + _s * CH_SIZE + _addr); +} + +uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { + return write(CH_BASE + _s * CH_SIZE + _addr, _data); +} + +uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +void W5100Class::getGatewayIp(uint8_t *_addr) { + readGAR(_addr); +} + +void W5100Class::setGatewayIp(uint8_t *_addr) { + writeGAR(_addr); +} + +void W5100Class::getSubnetMask(uint8_t *_addr) { + readSUBR(_addr); +} + +void W5100Class::setSubnetMask(uint8_t *_addr) { + writeSUBR(_addr); +} + +void W5100Class::getMACAddress(uint8_t *_addr) { + readSHAR(_addr); +} + +void W5100Class::setMACAddress(uint8_t *_addr) { + writeSHAR(_addr); +} + +void W5100Class::getIPAddress(uint8_t *_addr) { + readSIPR(_addr); +} + +void W5100Class::setIPAddress(uint8_t *_addr) { + writeSIPR(_addr); +} + +void W5100Class::setRetransmissionTime(uint16_t _timeout) { + writeRTR(_timeout); +} + +void W5100Class::setRetransmissionCount(uint8_t _retry) { + writeRCR(_retry); +} + +#endif diff --git a/libraries/MySensors/drivers/RF24/RF24.h b/libraries/MySensors/drivers/RF24/RF24.h index 235fb71..a0ae93b 100644 --- a/libraries/MySensors/drivers/RF24/RF24.h +++ b/libraries/MySensors/drivers/RF24/RF24.h @@ -47,8 +47,8 @@ typedef enum { RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16 } rf24_crclength_e class RF24 { private: -#ifdef SOFTSPI - SoftSPI spi; +#ifdef MY_SOFTSPI + SoftSPI spi; #elif defined (SPI_UART) SPIUARTClass uspi; #endif diff --git a/libraries/MySensors/drivers/RF24/RF24_config.h b/libraries/MySensors/drivers/RF24/RF24_config.h index d38ac88..d8c8016 100644 --- a/libraries/MySensors/drivers/RF24/RF24_config.h +++ b/libraries/MySensors/drivers/RF24/RF24_config.h @@ -11,7 +11,7 @@ #ifndef __RF24_CONFIG_H__ #define __RF24_CONFIG_H__ - #include + #include "MyConfig.h" #if ARDUINO < 100 #include @@ -38,17 +38,19 @@ #if defined SPI_UART #include #define _SPI uspi - #elif defined SOFTSPI - // change these pins to your liking - //const uint8_t SOFT_SPI_MISO_PIN = 16; // <-- Moved to MyConfig.h - //const uint8_t SOFT_SPI_MOSI_PIN = 15; // <-- Moved to MyConfig.h - //const uint8_t SOFT_SPI_SCK_PIN = 14; // <-- Moved to MyConfig.h + #elif defined MY_SOFTSPI + #include "drivers/DigitalIO/DigitalIO.h" - const uint8_t SPI_MODE = 0; - #define _SPI spi + // change these pins to your liking + const uint8_t SOFT_SPI_MISO_PIN = MY_SOFT_SPI_MOSI_PIN; + const uint8_t SOFT_SPI_MOSI_PIN = MY_SOFT_SPI_MISO_PIN; + const uint8_t SOFT_SPI_SCK_PIN = MY_SOFT_SPI_SCK_PIN; + + const uint8_t SPI_MODE = 0; + #define _SPI spi #else - #include + #include "drivers/SPI/SPI.h" #define _SPI SPI #endif #endif diff --git a/libraries/MySensors/drivers/RFM69/RFM69.cpp b/libraries/MySensors/drivers/RFM69/RFM69.cpp index 56e47e5..f7e63e7 100644 --- a/libraries/MySensors/drivers/RFM69/RFM69.cpp +++ b/libraries/MySensors/drivers/RFM69/RFM69.cpp @@ -31,7 +31,7 @@ // ********************************************************************************** #include "RFM69.h" #include "RFM69registers.h" -#include +#include "drivers/SPI/SPI.h" volatile byte RFM69::DATA[RF69_MAX_DATA_LEN]; volatile byte RFM69::_mode; // current transceiver state diff --git a/libraries/MySensors/drivers/SPI/SPI.cpp b/libraries/MySensors/drivers/SPI/SPI.cpp new file mode 100644 index 0000000..af14e07 --- /dev/null +++ b/libraries/MySensors/drivers/SPI/SPI.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2010 by Cristian Maglie + * Copyright (c) 2014 by Paul Stoffregen (Transaction API) + * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) + * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) + * SPI Master library for arduino. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include "SPI.h" + +SPIClass SPI; + +uint8_t SPIClass::initialized = 0; +uint8_t SPIClass::interruptMode = 0; +uint8_t SPIClass::interruptMask = 0; +uint8_t SPIClass::interruptSave = 0; +#ifdef SPI_TRANSACTION_MISMATCH_LED +uint8_t SPIClass::inTransactionFlag = 0; +#endif + +void SPIClass::begin() +{ + uint8_t sreg = SREG; + noInterrupts(); // Protect from a scheduler and prevent transactionBegin + if (!initialized) { + // Set SS to high so a connected chip will be "deselected" by default + uint8_t port = digitalPinToPort(SS); + uint8_t bit = digitalPinToBitMask(SS); + volatile uint8_t *reg = portModeRegister(port); + + // if the SS pin is not already configured as an output + // then set it high (to enable the internal pull-up resistor) + if(!(*reg & bit)){ + digitalWrite(SS, HIGH); + } + + // When the SS pin is set as OUTPUT, it can be used as + // a general purpose output port (it doesn't influence + // SPI operations). + pinMode(SS, OUTPUT); + + // Warning: if the SS pin ever becomes a LOW INPUT then SPI + // automatically switches to Slave, so the data direction of + // the SS pin MUST be kept as OUTPUT. + SPCR |= _BV(MSTR); + SPCR |= _BV(SPE); + + // Set direction register for SCK and MOSI pin. + // MISO pin automatically overrides to INPUT. + // By doing this AFTER enabling SPI, we avoid accidentally + // clocking in a single bit since the lines go directly + // from "input" to SPI control. + // http://code.google.com/p/arduino/issues/detail?id=888 + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); + } + initialized++; // reference count + SREG = sreg; +} + +void SPIClass::end() { + uint8_t sreg = SREG; + noInterrupts(); // Protect from a scheduler and prevent transactionBegin + // Decrease the reference counter + if (initialized) + initialized--; + // If there are no more references disable SPI + if (!initialized) { + SPCR &= ~_BV(SPE); + interruptMode = 0; + #ifdef SPI_TRANSACTION_MISMATCH_LED + inTransactionFlag = 0; + #endif + } + SREG = sreg; +} + +// mapping of interrupt numbers to bits within SPI_AVR_EIMSK +#if defined(__AVR_ATmega32U4__) + #define SPI_INT0_MASK (1< + * Copyright (c) 2014 by Paul Stoffregen (Transaction API) + * Copyright (c) 2014 by Matthijs Kooijman (SPISettings AVR) + * Copyright (c) 2014 by Andrew J. Kroll (atomicity fixes) + * SPI Master library for arduino. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef _SPI_H_INCLUDED +#define _SPI_H_INCLUDED + +#include + +// SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(), +// usingInterrupt(), and SPISetting(clock, bitOrder, dataMode) +#define SPI_HAS_TRANSACTION 1 + +// SPI_HAS_NOTUSINGINTERRUPT means that SPI has notUsingInterrupt() method +#define SPI_HAS_NOTUSINGINTERRUPT 1 + +// SPI_ATOMIC_VERSION means that SPI has atomicity fixes and what version. +// This way when there is a bug fix you can check this define to alert users +// of your code if it uses better version of this library. +// This also implies everything that SPI_HAS_TRANSACTION as documented above is +// available too. +#define SPI_ATOMIC_VERSION 1 + +// Uncomment this line to add detection of mismatched begin/end transactions. +// A mismatch occurs if other libraries fail to use SPI.endTransaction() for +// each SPI.beginTransaction(). Connect an LED to this pin. The LED will turn +// on if any mismatch is ever detected. +//#define SPI_TRANSACTION_MISMATCH_LED 5 + +#ifndef LSBFIRST +#define LSBFIRST 0 +#endif +#ifndef MSBFIRST +#define MSBFIRST 1 +#endif + +#define SPI_CLOCK_DIV4 0x00 +#define SPI_CLOCK_DIV16 0x01 +#define SPI_CLOCK_DIV64 0x02 +#define SPI_CLOCK_DIV128 0x03 +#define SPI_CLOCK_DIV2 0x04 +#define SPI_CLOCK_DIV8 0x05 +#define SPI_CLOCK_DIV32 0x06 + +#define SPI_MODE0 0x00 +#define SPI_MODE1 0x04 +#define SPI_MODE2 0x08 +#define SPI_MODE3 0x0C + +#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR +#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR +#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR + +// define SPI_AVR_EIMSK for AVR boards with external interrupt pins +#if defined(EIMSK) + #define SPI_AVR_EIMSK EIMSK +#elif defined(GICR) + #define SPI_AVR_EIMSK GICR +#elif defined(GIMSK) + #define SPI_AVR_EIMSK GIMSK +#endif + +class SPISettings { +public: + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, bitOrder, dataMode); + } else { + init_MightInline(clock, bitOrder, dataMode); + } + } + SPISettings() { + init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); + } +private: + void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { + init_AlwaysInline(clock, bitOrder, dataMode); + } + void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) + __attribute__((__always_inline__)) { + // Clock settings are defined as follows. Note that this shows SPI2X + // inverted, so the bits form increasing numbers. Also note that + // fosc/64 appears twice + // SPR1 SPR0 ~SPI2X Freq + // 0 0 0 fosc/2 + // 0 0 1 fosc/4 + // 0 1 0 fosc/8 + // 0 1 1 fosc/16 + // 1 0 0 fosc/32 + // 1 0 1 fosc/64 + // 1 1 0 fosc/64 + // 1 1 1 fosc/128 + + // We find the fastest clock that is less than or equal to the + // given clock rate. The clock divider that results in clock_setting + // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the + // slowest (128 == 2 ^^ 7, so clock_div = 6). + uint8_t clockDiv; + + // When the clock is known at compiletime, use this if-then-else + // cascade, which the compiler knows how to completely optimize + // away. When clock is not known, use a loop instead, which generates + // shorter code. + if (__builtin_constant_p(clock)) { + if (clock >= F_CPU / 2) { + clockDiv = 0; + } else if (clock >= F_CPU / 4) { + clockDiv = 1; + } else if (clock >= F_CPU / 8) { + clockDiv = 2; + } else if (clock >= F_CPU / 16) { + clockDiv = 3; + } else if (clock >= F_CPU / 32) { + clockDiv = 4; + } else if (clock >= F_CPU / 64) { + clockDiv = 5; + } else { + clockDiv = 6; + } + } else { + uint32_t clockSetting = F_CPU / 2; + clockDiv = 0; + while (clockDiv < 6 && clock < clockSetting) { + clockSetting /= 2; + clockDiv++; + } + } + + // Compensate for the duplicate fosc/64 + if (clockDiv == 6) + clockDiv = 7; + + // Invert the SPI2X bit + clockDiv ^= 0x1; + + // Pack into the SPISettings class + spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) | + (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK); + spsr = clockDiv & SPI_2XCLOCK_MASK; + } + uint8_t spcr; + uint8_t spsr; + friend class SPIClass; +}; + + +class SPIClass { +public: + // Initialize the SPI library + static void begin(); + + // If SPI is used from within an interrupt, this function registers + // that interrupt with the SPI library, so beginTransaction() can + // prevent conflicts. The input interruptNumber is the number used + // with attachInterrupt. If SPI is used from a different interrupt + // (eg, a timer), interruptNumber should be 255. + static void usingInterrupt(uint8_t interruptNumber); + // And this does the opposite. + static void notUsingInterrupt(uint8_t interruptNumber); + // Note: the usingInterrupt and notUsingInterrupt functions should + // not to be called from ISR context or inside a transaction. + // For details see: + // https://github.com/arduino/Arduino/pull/2381 + // https://github.com/arduino/Arduino/pull/2449 + + // Before using SPI.transfer() or asserting chip select pins, + // this function is used to gain exclusive access to the SPI bus + // and configure the correct settings. + inline static void beginTransaction(SPISettings settings) { + if (interruptMode > 0) { + uint8_t sreg = SREG; + noInterrupts(); + + #ifdef SPI_AVR_EIMSK + if (interruptMode == 1) { + interruptSave = SPI_AVR_EIMSK; + SPI_AVR_EIMSK &= ~interruptMask; + SREG = sreg; + } else + #endif + { + interruptSave = sreg; + } + } + + #ifdef SPI_TRANSACTION_MISMATCH_LED + if (inTransactionFlag) { + pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); + digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); + } + inTransactionFlag = 1; + #endif + + SPCR = settings.spcr; + SPSR = settings.spsr; + } + + // Write to the SPI bus (MOSI pin) and also receive (MISO pin) + inline static uint8_t transfer(uint8_t data) { + SPDR = data; + /* + * The following NOP introduces a small delay that can prevent the wait + * loop form iterating when running at the maximum speed. This gives + * about 10% more speed, even if it seems counter-intuitive. At lower + * speeds it is unnoticed. + */ + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; // wait + return SPDR; + } + inline static uint16_t transfer16(uint16_t data) { + union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; + in.val = data; + if (!(SPCR & _BV(DORD))) { + SPDR = in.msb; + asm volatile("nop"); // See transfer(uint8_t) function + while (!(SPSR & _BV(SPIF))) ; + out.msb = SPDR; + SPDR = in.lsb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.lsb = SPDR; + } else { + SPDR = in.lsb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.lsb = SPDR; + SPDR = in.msb; + asm volatile("nop"); + while (!(SPSR & _BV(SPIF))) ; + out.msb = SPDR; + } + return out.val; + } + inline static void transfer(void *buf, size_t count) { + if (count == 0) return; + uint8_t *p = (uint8_t *)buf; + SPDR = *p; + while (--count > 0) { + uint8_t out = *(p + 1); + while (!(SPSR & _BV(SPIF))) ; + uint8_t in = SPDR; + SPDR = out; + *p++ = in; + } + while (!(SPSR & _BV(SPIF))) ; + *p = SPDR; + } + // After performing a group of transfers and releasing the chip select + // signal, this function allows others to access the SPI bus + inline static void endTransaction(void) { + #ifdef SPI_TRANSACTION_MISMATCH_LED + if (!inTransactionFlag) { + pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); + digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH); + } + inTransactionFlag = 0; + #endif + + if (interruptMode > 0) { + #ifdef SPI_AVR_EIMSK + uint8_t sreg = SREG; + #endif + noInterrupts(); + #ifdef SPI_AVR_EIMSK + if (interruptMode == 1) { + SPI_AVR_EIMSK = interruptSave; + SREG = sreg; + } else + #endif + { + SREG = interruptSave; + } + } + } + + // Disable the SPI bus + static void end(); + + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setBitOrder(uint8_t bitOrder) { + if (bitOrder == LSBFIRST) SPCR |= _BV(DORD); + else SPCR &= ~(_BV(DORD)); + } + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setDataMode(uint8_t dataMode) { + SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode; + } + // This function is deprecated. New applications should use + // beginTransaction() to configure SPI settings. + inline static void setClockDivider(uint8_t clockDiv) { + SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK); + SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK); + } + // These undocumented functions should not be used. SPI.transfer() + // polls the hardware flag which is automatically cleared as the + // AVR responds to SPI's interrupt + inline static void attachInterrupt() { SPCR |= _BV(SPIE); } + inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); } + +private: + static uint8_t initialized; + static uint8_t interruptMode; // 0=none, 1=mask, 2=global + static uint8_t interruptMask; // which interrupts to mask + static uint8_t interruptSave; // temp storage, to restore state + #ifdef SPI_TRANSACTION_MISMATCH_LED + static uint8_t inTransactionFlag; + #endif +}; + +extern SPIClass SPI; + +#endif diff --git a/libraries/MySensors/drivers/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/libraries/MySensors/drivers/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino new file mode 100644 index 0000000..df73ade --- /dev/null +++ b/libraries/MySensors/drivers/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino @@ -0,0 +1,143 @@ +/* + SCP1000 Barometric Pressure Sensor Display + + Shows the output of a Barometric Pressure Sensor on a + Uses the SPI library. For details on the sensor, see: + http://www.sparkfun.com/commerce/product_info.php?products_id=8161 + http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ + + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: + http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip + + Circuit: + SCP1000 sensor attached to pins 6, 7, 10 - 13: + DRDY: pin 6 + CSB: pin 7 + MOSI: pin 11 + MISO: pin 12 + SCK: pin 13 + + created 31 July 2010 + modified 14 August 2010 + by Tom Igoe + */ + +// the sensor communicates using SPI, so include the library: +#include + +//Sensor's memory register addresses: +const int PRESSURE = 0x1F; //3 most significant bits of pressure +const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure +const int TEMPERATURE = 0x21; //16 bit temperature reading +const byte READ = 0b11111100; // SCP1000's read command +const byte WRITE = 0b00000010; // SCP1000's write command + +// pins used for the connection with the sensor +// the other you need are controlled by the SPI library): +const int dataReadyPin = 6; +const int chipSelectPin = 7; + +void setup() { + Serial.begin(9600); + + // start the SPI library: + SPI.begin(); + + // initalize the data ready and chip select pins: + pinMode(dataReadyPin, INPUT); + pinMode(chipSelectPin, OUTPUT); + + //Configure SCP1000 for low noise configuration: + writeRegister(0x02, 0x2D); + writeRegister(0x01, 0x03); + writeRegister(0x03, 0x02); + // give the sensor time to set up: + delay(100); +} + +void loop() { + //Select High Resolution Mode + writeRegister(0x03, 0x0A); + + // don't do anything until the data ready pin is high: + if (digitalRead(dataReadyPin) == HIGH) { + //Read the temperature data + int tempData = readRegister(0x21, 2); + + // convert the temperature to celsius and display it: + float realTemp = (float)tempData / 20.0; + Serial.print("Temp[C]="); + Serial.print(realTemp); + + + //Read the pressure data highest 3 bits: + byte pressure_data_high = readRegister(0x1F, 1); + pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 + + //Read the pressure data lower 16 bits: + unsigned int pressure_data_low = readRegister(0x20, 2); + //combine the two parts into one 19-bit number: + long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4; + + // display the temperature: + Serial.println("\tPressure [Pa]=" + String(pressure)); + } +} + +//Read from or write to register from the SCP1000: +unsigned int readRegister(byte thisRegister, int bytesToRead) { + byte inByte = 0; // incoming byte from the SPI + unsigned int result = 0; // result to return + Serial.print(thisRegister, BIN); + Serial.print("\t"); + // SCP1000 expects the register name in the upper 6 bits + // of the byte. So shift the bits left by two bits: + thisRegister = thisRegister << 2; + // now combine the address and the command into one byte + byte dataToSend = thisRegister & READ; + Serial.println(thisRegister, BIN); + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + // send the device the register you want to read: + SPI.transfer(dataToSend); + // send a value of 0 to read the first byte returned: + result = SPI.transfer(0x00); + // decrement the number of bytes left to read: + bytesToRead--; + // if you still have another byte to read: + if (bytesToRead > 0) { + // shift the first byte left, then get the second byte: + result = result << 8; + inByte = SPI.transfer(0x00); + // combine the byte you just got with the previous one: + result = result | inByte; + // decrement the number of bytes left to read: + bytesToRead--; + } + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); + // return the result: + return (result); +} + + +//Sends a write command to SCP1000 + +void writeRegister(byte thisRegister, byte thisValue) { + + // SCP1000 expects the register address in the upper 6 bits + // of the byte. So shift the bits left by two bits: + thisRegister = thisRegister << 2; + // now combine the register address and the command into one byte: + byte dataToSend = thisRegister | WRITE; + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + + SPI.transfer(dataToSend); //Send register location + SPI.transfer(thisValue); //Send value to record into register + + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); +} + diff --git a/libraries/MySensors/drivers/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/libraries/MySensors/drivers/SPI/examples/DigitalPotControl/DigitalPotControl.ino new file mode 100644 index 0000000..c7afcc0 --- /dev/null +++ b/libraries/MySensors/drivers/SPI/examples/DigitalPotControl/DigitalPotControl.ino @@ -0,0 +1,71 @@ +/* + Digital Pot Control + + This example controls an Analog Devices AD5206 digital potentiometer. + The AD5206 has 6 potentiometer channels. Each channel's pins are labeled + A - connect this to voltage + W - this is the pot's wiper, which changes when you set it + B - connect this to ground. + + The AD5206 is SPI-compatible,and to command it, you send two bytes, + one with the channel number (0 - 5) and one with the resistance value for the + channel (0 - 255). + + The circuit: + * All A pins of AD5206 connected to +5V + * All B pins of AD5206 connected to ground + * An LED and a 220-ohm resisor in series connected from each W pin to ground + * CS - to digital pin 10 (SS pin) + * SDI - to digital pin 11 (MOSI pin) + * CLK - to digital pin 13 (SCK pin) + + created 10 Aug 2010 + by Tom Igoe + + Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 + +*/ + + +// inslude the SPI library: +#include + + +// set pin 10 as the slave select for the digital pot: +const int slaveSelectPin = 10; + +void setup() { + // set the slaveSelectPin as an output: + pinMode(slaveSelectPin, OUTPUT); + // initialize SPI: + SPI.begin(); +} + +void loop() { + // go through the six channels of the digital pot: + for (int channel = 0; channel < 6; channel++) { + // change the resistance on this channel from min to max: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, level); + delay(10); + } + // wait a second at the top: + delay(100); + // change the resistance on this channel from max to min: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, 255 - level); + delay(10); + } + } + +} + +void digitalPotWrite(int address, int value) { + // take the SS pin low to select the chip: + digitalWrite(slaveSelectPin, LOW); + // send in the address and value via SPI: + SPI.transfer(address); + SPI.transfer(value); + // take the SS pin high to de-select the chip: + digitalWrite(slaveSelectPin, HIGH); +} diff --git a/libraries/MySensors/drivers/SPI/keywords.txt b/libraries/MySensors/drivers/SPI/keywords.txt new file mode 100644 index 0000000..fa76165 --- /dev/null +++ b/libraries/MySensors/drivers/SPI/keywords.txt @@ -0,0 +1,36 @@ +####################################### +# Syntax Coloring Map SPI +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SPI KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 +transfer KEYWORD2 +setBitOrder KEYWORD2 +setDataMode KEYWORD2 +setClockDivider KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +SPI_CLOCK_DIV4 LITERAL1 +SPI_CLOCK_DIV16 LITERAL1 +SPI_CLOCK_DIV64 LITERAL1 +SPI_CLOCK_DIV128 LITERAL1 +SPI_CLOCK_DIV2 LITERAL1 +SPI_CLOCK_DIV8 LITERAL1 +SPI_CLOCK_DIV32 LITERAL1 +SPI_CLOCK_DIV64 LITERAL1 +SPI_MODE0 LITERAL1 +SPI_MODE1 LITERAL1 +SPI_MODE2 LITERAL1 +SPI_MODE3 LITERAL1 \ No newline at end of file diff --git a/libraries/MySensors/drivers/SPI/library.properties b/libraries/MySensors/drivers/SPI/library.properties new file mode 100644 index 0000000..2964aec --- /dev/null +++ b/libraries/MySensors/drivers/SPI/library.properties @@ -0,0 +1,9 @@ +name=SPI +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. +paragraph= +url=http://www.arduino.cc/en/Reference/SPI +architectures=avr + diff --git a/libraries/MySensors/drivers/SPIFlash/SPIFlash.h b/libraries/MySensors/drivers/SPIFlash/SPIFlash.h index a308760..e6e1d04 100644 --- a/libraries/MySensors/drivers/SPIFlash/SPIFlash.h +++ b/libraries/MySensors/drivers/SPIFlash/SPIFlash.h @@ -42,7 +42,7 @@ #include "pins_arduino.h" #endif -#include +#include "drivers/SPI/SPI.h" /// IMPORTANT: NAND FLASH memory requires erase before write, because /// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s @@ -120,4 +120,4 @@ protected: #endif }; -#endif \ No newline at end of file +#endif diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 7b6adaa..c5e10a4 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -56,37 +56,24 @@ * */ -#include // This include can be removed when using UIPEthernet module -#include - -//#include -//#include -//#include -//#include -//#include -//#include - #define MY_WITH_LEDS_BLINKING #define MY_INCLUSION_MODE_FEATURE #define MY_INCLUSION_BUTTON_FEATURE - #define MY_DEFAULT_LED_BLINK_PERIOD 300 #define MY_INCLUSION_MODE_DURATION 60 // Number of minutes inclusion mode is enabled #define MY_INCLUSION_MODE_BUTTON_PIN 3 // Digital pin used for inclusion mode button #define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin -#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin -#define MY_DEFAULT_TX_LED_PIN 9 // the PCB, on board LED +#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin +#define MY_DEFAULT_TX_LED_PIN 9 // the PCB, on board LED -#define RADIO_CE_PIN 5 // radio chip enable -#define RADIO_SPI_SS_PIN 6 // radio SPI serial select +#define MY_RADIO_CE_PIN 5 // radio chip enable +#define MY_RADIO_SPI_SS_PIN 6 // radio SPI serial select #include -#include -#include #define MY_IP_PORT 5003 // The port you want to open diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino index 0c9179b..a0d734b 100644 --- a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -27,18 +27,20 @@ * */ -#include -#include +//#define MY_DEBUG + +#include "MySensor.h" unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds) #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) #define CHILD_ID 1 // Id of the sensor child -MySensor gw; // Initialize motion message MyMessage msg(CHILD_ID, V_TRIPPED); + + void setup() { gw.begin(); From 6a42e2d5553d5fd98b47eb7d994d5fc95d88a761 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Sat, 12 Sep 2015 00:36:32 +0200 Subject: [PATCH 09/43] Disable RFM69 temporarily --- libraries/MySensors/MySensor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 94f7e45..7071221 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -49,7 +49,7 @@ #include "core/MyHwATMega328.cpp" #include "core/MyTransport.cpp" #include "core/MyTransportNRF24.cpp" -#include "core/MyTransportRFM69.cpp" +//#include "core/MyTransportRFM69.cpp" #include "core/MyGatewayTransport.cpp" #include "core/MyGatewayTransportSerial.cpp" @@ -58,7 +58,7 @@ // Initialize library -MyTransportRFM69 transport; +//MyTransportRFM69 transport; MySensor gw; From f8ee37623074086767715d92bfb8ff2ada8e5079 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Sun, 13 Sep 2015 11:59:09 +0200 Subject: [PATCH 10/43] C:ifying continues.. --- libraries/MySensors/MyConfig.h | 92 +- libraries/MySensors/MySensor.h | 168 +- .../MySensors/core/MyGatewayTransport.cpp | 25 - libraries/MySensors/core/MyGatewayTransport.h | 47 - .../core/MyGatewayTransportEthernet.cpp | 120 +- .../core/MyGatewayTransportEthernet.h | 59 +- .../MySensors/core/MyGatewayTransportSerial.h | 1 - libraries/MySensors/core/MyHw.cpp | 23 - libraries/MySensors/core/MyHw.h | 54 - libraries/MySensors/core/MyHwATMega328.cpp | 94 +- libraries/MySensors/core/MyHwATMega328.h | 51 +- libraries/MySensors/core/MyHwESP8266.cpp | 74 +- libraries/MySensors/core/MyHwESP8266.h | 41 +- libraries/MySensors/core/MySensorCore.cpp | 1891 +++++++++-------- libraries/MySensors/core/MySensorCore.h | 427 ++-- libraries/MySensors/core/MyTransportNRF24.cpp | 9 +- libraries/MySensors/core/MyTransportNRF24.h | 4 +- libraries/MySensors/core/MyTransportRFM69.cpp | 8 +- libraries/MySensors/core/MyTransportRFM69.h | 4 +- .../MySensors/drivers/DigitalIO/DigitalIO.h | 12 +- .../MySensors/drivers/DigitalIO/PinIO.cpp | 4 +- .../drivers/DigitalIO/SoftI2cMaster.cpp | 2 +- .../drivers/DigitalIO/SoftI2cMaster.h | 4 +- .../MySensors/drivers/DigitalIO/SoftSPI.h | 2 +- libraries/MySensors/drivers/RF24/RF24.cpp | 2 +- .../MySensors/drivers/RF24/RF24_config.h | 2 +- .../EthernetGateway/EthernetGateway.ino | 100 +- .../examples/MotionSensor/MotionSensor.ino | 18 +- 28 files changed, 1541 insertions(+), 1797 deletions(-) delete mode 100644 libraries/MySensors/core/MyGatewayTransport.cpp delete mode 100644 libraries/MySensors/core/MyGatewayTransport.h delete mode 100644 libraries/MySensors/core/MyHw.cpp delete mode 100644 libraries/MySensors/core/MyHw.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 71d87c0..c8323be 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -22,33 +22,53 @@ #define MyConfig_h #include -// Enable debug flag for debug prints. This will add a lot to the size of the final sketch but good -// to see what is actually is happening when developing +// Enables this in sketch to show debug prints. This option will add a lot to the size of the +// final sketch but is helpful to see what is actually is happening during development //#define MY_DEBUG -// Enable this line, If you are using TX(1), RX(0) as normal I/O pin -// #define MY_DISABLED_SERIAL +// Enable this in sketch if you want to use TX(1), RX(0) as normal I/O pin +//#define MY_DISABLED_SERIAL + +// Turn off debug if serial pins is used for other stuff +#ifdef MY_DISABLED_SERIAL +#undef MY_DEBUG +#endif // Serial output baud rate (for debug prints and serial gateway) #ifndef MY_BAUD_RATE #define MY_BAUD_RATE 115200 #endif +// Node id defaults to AUTO (tries to fetch id from controller) +#ifndef MY_NODE_ID +#define MY_NODE_ID AUTO +#endif + +// Node parent defaults to AUTO (tries to find a parent automatically) +#ifndef MY_PARENT_NODE_ID +#define MY_PARENT_NODE_ID AUTO +#endif + +// Enables repeater functionality (relays messages from other nodes) +// #define MY_REPEATER_FEATURE + /********************************** * Over the air firmware updates ***********************************/ -// The following define enables the safe over-the-air firmware update feature -// which requires external flash and the DualOptiBoot bootloader. +// Enable MY_OTA_FIRMWARE_FEATURE in sketch to allow safe over-the-air firmware updates. +// This feature requires external flash and the DualOptiBoot bootloader. // Note: You can still have OTA FW updates without external flash but it // requires the MYSBootloader and disabled MY_OTA_FIRMWARE_FEATURE //#define MY_OTA_FIRMWARE_FEATURE + // Slave select pin for external flash -#ifdef MY_OTA_FLASH_SS +#ifndef MY_OTA_FLASH_SS #define MY_OTA_FLASH_SS 8 #endif + // Flash jdecid -#ifdef MY_OTA_FLASH_JDECID +#ifndef MY_OTA_FLASH_JDECID #define MY_OTA_FLASH_JDECID 0x1F65 #endif @@ -112,8 +132,10 @@ /********************************** * Message Signing Settings ***********************************/ -// Disable to completely disable signing functionality in library -//#define MY_SIGNING_FEATURE + +// Enable one of these in sketch to use signing functionality +//#define MY_SIGNING_ATSHA204 +//#define MY_SIGNING_SOFT // Define a suitable timeout for a signature verification session // Consider the turn-around from a nonce being generated to a signed message being received @@ -151,18 +173,30 @@ /********************************** * NRF24L01 Driver Defaults ***********************************/ -#define RF24_CE_PIN 9 -#define RF24_CS_PIN 10 -#define RF24_PA_LEVEL RF24_PA_MAX -#define RF24_PA_LEVEL_GW RF24_PA_LOW -// RF channel for the sensor net, 0-127 -#define RF24_CHANNEL 76 -//RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps -#define RF24_DATARATE RF24_250KBPS -// This is also act as base value for sensor nodeId addresses. Change this (or channel) if you have more than one sensor network. -#define RF24_BASE_RADIO_ID ((uint64_t)0xA8A8E1FC00LL) +#ifndef MY_RF24_CE_PIN +#define MY_RF24_CE_PIN 9 +#endif +#ifndef MY_RF24_CS_PIN +#define MY_RF24_CS_PIN 10 +#endif -// Enable SOFTSPI for NRF24L01 when using the W5100 Ethernet module +#ifndef MY_RF24_PA_LEVEL +#define MY_RF24_PA_LEVEL RF24_PA_MAX +#endif +// RF channel for the sensor net, 0-127 +#ifndef MY_RF24_CHANNEL +#define MY_RF24_CHANNEL 76 +#endif +//RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps +#ifndef MY_RF24_DATARATE +#define MY_RF24_DATARATE RF24_250KBPS +#endif +// This is also act as base value for sensor nodeId addresses. Change this (or channel) if you have more than one sensor network. +#ifndef MY_RF24_BASE_RADIO_ID +#define MY_RF24_BASE_RADIO_ID ((uint64_t)0xA8A8E1FC00LL) +#endif + +// Enable SOFTSPI for NRF24L01, useful for the W5100 Ethernet module //#define MY_SOFTSPI #ifndef MY_SOFT_SPI_SCK_PIN @@ -186,6 +220,11 @@ //#define MY_RFM69_FREQUENCY RF69_915MHZ #endif +// Enable this if you're running the RFM69HW model +#ifndef MY_IS_RFM69HW +#define MY_IS_RFM69HW false +#endif + // Default network id. Use the same for all nodes that will talk to each other #ifndef MY_RFM69_NETWORKID #define MY_RFM69_NETWORKID 100 @@ -210,9 +249,16 @@ * Gateway Transport Ethernet Defaults ***************************************/ // Enable to use DHCP for getting IP address. If not defined, static IP is expected -//#define IP_ADDRESS_DHCP +//#define MY_IP_ADDRESS_VIA_DHCP +#ifndef MY_IP_RENEWAL_INTERVAL +#define MY_IP_RENEWAL_INTERVAL 60000 +#endif + +#ifndef MY_MAC_ADDRESS +#define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +#endif // Enable to use UDP instead of plain Ethernet -#define MY_USE_UDP +//#define MY_USE_UDP #endif diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 7071221..e9d4e75 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -16,50 +16,164 @@ * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ - - #ifndef MySensor_h #define MySensor_h +#define VALUE_TO_STRING(x) #x +#define VALUE(x) VALUE_TO_STRING(x) +#define VAR_NAME_VALUE(var) #var "=" VALUE(var) +// #pragma message(VAR_NAME_VALUE(MY_GATEWAY_FEATURE)) + #include "MyConfig.h" -// Include drivers +#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100_CLIENT) || defined(MY_GATEWAY_W5100_SERVER) + #define MY_GATEWAY_FEATURE + #define MY_NODE_TYPE "gateway" +#elif defined(MY_REPEATER_FEATURE) + #define MY_NODE_TYPE "repeater" +#else + #define MY_NODE_TYPE "sensor" +#endif + +// CORE #include "drivers/SPI/SPI.cpp" -#include "drivers/RF24/RF24.cpp" -#include "drivers/RFM69/RFM69.cpp" +// HARDWARE +#if defined(ARDUINO_ARCH_ESP8266) + #include "core/MyHwESP8266.cpp" +#elif defined(ARDUINO_ARCH_AVR) + #include "core/MyHwATMega328.cpp" +#endif -#include "drivers/ATSHA204/ATSHA204.cpp" -#include "drivers/ATSHA204/sha256.cpp" +// SIGNING +#if defined(MY_SIGNING_ATSHA204) || defined(MY_SIGNING_SOFT) + #include "MySigning.cpp" + #define MY_SIGNING_FEATURE + #if defined(MY_SIGNING_ATSHA204) + #include "MySigningAtsha204.cpp" + #include "drivers/ATSHA204/ATSHA204.cpp" + MySigningAtsha204 signer; + #elif defined(MY_SIGNING_SOFT) + #include "MySigningAtsha204Soft.cpp" + #include "drivers/ATSHA204/sha256.cpp" + MySigningAtsha204Soft signer; + #endif +#endif -#include "drivers/SPIFlash/SPIFlash.cpp" +// RADIO +#if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) + #define MY_RADIO_FEATURE + // SOFTSPI + #ifdef MY_SOFTSPI + #include "drivers/DigitalIO/SoftI2cMaster.cpp" + #include "drivers/DigitalIO/PinIO.cpp" + #endif -#include "drivers/Ethernet_W5100/utility/socket.cpp" -#include "drivers/Ethernet_W5100/utility/w5100.cpp" -#include "drivers/Ethernet_W5100/DNS.cpp" -#include "drivers/Ethernet_W5100/Ethernet.cpp" -#include "drivers/Ethernet_W5100/EthernetUdp.cpp" -#include "drivers/Ethernet_W5100/IPAddress.cpp" + // FLASH + #ifdef MY_OTA_FIRMWARE_FEATURE + SPIFlash flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); + #include "drivers/SPIFlash/SPIFlash.cpp" + #endif + + #include "core/MyTransport.cpp" + #if defined(MY_RADIO_NRF24) + #include "drivers/RF24/RF24.cpp" + #include "core/MyTransportNRF24.cpp" + MyTransportNRF24 transport; + + #elif defined(MY_RADIO_RFM69) + #include "drivers/RFM69/RFM69.cpp" + #include "core/MyTransportRFM69.cpp" + MyTransportRFM69 transport; + #endif +#endif +// GATEWAY - TRANSPORT +#if defined(MY_GATEWAY_FEATURE) + // GATEWAY - PROTOCOL + #include "core/MyProtocol.cpp" + #if defined(MY_GATEWAY_PROTOCOL_DEFAULT) + #include "core/MyProtocolDefault.cpp" + MyProtocolDefault _protocol; + #else + #error No gateway protocol specified! + #endif + #if defined(MY_RADIO_FEATURE) + // We assume that a gateway having a radio also should act as repeater + #define MY_REPEATER_FEATURE + #endif + #if defined(MY_GATEWAY_W5100_CLIENT) || defined(MY_GATEWAY_W5100_SERVER) + #include "drivers/Ethernet_W5100/utility/socket.cpp" + #include "drivers/Ethernet_W5100/utility/w5100.cpp" + #include "drivers/Ethernet_W5100/DNS.cpp" + #include "drivers/Ethernet_W5100/Ethernet.cpp" + #include "drivers/Ethernet_W5100/EthernetUdp.cpp" + #include "drivers/Ethernet_W5100/IPAddress.cpp" + #if !defined(MY_PORT) + #error You must define MY_PORT + #endif + #if !defined(USE_UDP) + #include "drivers/Ethernet_W5100/EthernetServer.cpp" + #endif + #if defined(MY_GATEWAY_W5100_CLIENT) && !defined(MY_CONTROLLER_IP_ADDRESS) + #error You must define MY_CONTROLLER_IP_ADDRESS when acting as client + #endif + + #if defined(MY_GATEWAY_W5100_CLIENT) + #include "drivers/Ethernet_W5100/EthernetClient.cpp" + #include "core/MyGatewayTransportEthernet.cpp" + #endif + #elif defined(MY_GATEWAY_SERIAL) + #include "core/MyGatewayTransportSerial.cpp" + MyGatewayTransportSerial gwTransport(protocol); + #endif +#else + #undef MY_GATEWAY_FEATURE +#endif + +// Make sure to disable child features when parent feature is disabled +#if !defined(MY_RADIO_FEATURE) + #undef MY_OTA_FIRMWARE_FEATURE + #undef MY_REPEATER_FEATURE + #undef MY_SECURE_NODE_WHITELISTING + #undef MY_SIGNING_FEATURE +#endif + +#if !defined(MY_GATEWAY_FEATURE) + #undef MY_INCLUSION_MODE_FEATURE + #undef MY_INCLUSION_BUTTON_FEATURE +#endif + +// Defines used in code for if-statements +#if defined(MY_REPEATER_FEATURE) + #define MY_IS_REPEATER true +#else + #define MY_IS_REPEATER false +#endif + +#if defined(MY_GATEWAY_FEATURE) + #define MY_IS_GATEWAY true +#else + #define MY_IS_GATEWAY false +#endif -// Include core classes -#include "core/MyHw.cpp" -#include "core/MyHwATMega328.cpp" -#include "core/MyTransport.cpp" -#include "core/MyTransportNRF24.cpp" -//#include "core/MyTransportRFM69.cpp" -#include "core/MyGatewayTransport.cpp" -#include "core/MyGatewayTransportSerial.cpp" #include "core/MyMessage.cpp" #include "core/MySensorCore.cpp" +extern void setup(); +extern void loop(); -// Initialize library -//MyTransportRFM69 transport; -MySensor gw; - - +// Initialize library and call sketch functions +int main() { + begin(); + setup(); + while(1) { + // We handle incoming message processing here + process(); + loop(); + } +} #endif diff --git a/libraries/MySensors/core/MyGatewayTransport.cpp b/libraries/MySensors/core/MyGatewayTransport.cpp deleted file mode 100644 index 2306d5f..0000000 --- a/libraries/MySensors/core/MyGatewayTransport.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyGatewayTransport.h" - - -MyGatewayTransport::MyGatewayTransport(MyProtocol &_protocol) : protocol(_protocol) { - -} diff --git a/libraries/MySensors/core/MyGatewayTransport.h b/libraries/MySensors/core/MyGatewayTransport.h deleted file mode 100644 index da03ff5..0000000 --- a/libraries/MySensors/core/MyGatewayTransport.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyGatewayTransport_h -#define MyGatewayTransport_h - -#include "MyMessage.h" -#include "MyProtocol.h" -#include "MyProtocolDefault.h" - -class MyGatewayTransport -{ -public: - // MyProtocol constructor - MyGatewayTransport(MyProtocol &protocol = *new MyProtocolDefault()); - - // initialize the transport driver - virtual bool begin() = 0; - - // Send message to controller - virtual bool send(MyMessage &message) = 0; - - // Check if a new message is available from controller - virtual bool available() = 0; - - // Pick up last message received from controller - virtual MyMessage& receive() = 0; -protected: - MyProtocol& protocol; -}; -#endif diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp index 7b9083d..b2b21ee 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp @@ -19,39 +19,28 @@ #include "MyGatewayTransportEthernet.h" -MyGatewayTransportEthernet::MyGatewayTransportEthernet( - MyProtocol &protocol, - uint8_t *gw_mac -#ifndef IP_ADDRESS_DHCP - , IPAddress gw_ip -#endif /* not IP_ADDRESS_DHCP */ - , uint16_t gw_port -#ifdef IP_ADDRESS_DHCP - , unsigned long ip_renew_interval -#endif /* IP_ADDRESS_DHCP */ - , IPAddress controller_IP - , uint16_t controller_port) : - MyGatewayTransport(protocol), - gatewayMAC(gw_mac), -#ifndef IP_ADDRESS_DHCP - gatewayIP(gw_ip), -#endif /* not IP_ADDRESS_DHCP */ - gatewayPort(gw_port), -#ifdef IP_ADDRESS_DHCP - ip_renewal_period(ip_renew_interval), -#endif /* IP_ADDRESS_DHCP */ - controllerIP(controller_IP), - controllerPort(controller_port) -{ - ; -} +IPAddress _ethernetControllerIP(MY_CONTROLLER_IP_ADDRESS); +IPAddress _ethernetGatewayIP(MY_IP_ADDRESS); +byte _ethernetGatewayMAC[] = { MY_MAC_ADDRESS }; +uint16_t _ethernetGatewayPort = MY_PORT; +char _ethernetInputBuffer[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface +MyMessage _ethernetMsg; -bool MyGatewayTransportEthernet::begin() { -#ifdef IP_ADDRESS_DHCP - // Get IP address from DHCP - Ethernet.begin(gatewayMAC); +#ifdef MY_USE_UDP + EthernetUDP _ethernetServer; #else - Ethernet.begin(gatewayMAC, gatewayIP); + // we have to use pointers due to the constructor of EthernetServer + EthernetServer _ethernetServer(_ethernetGatewayPort); + uint8_t _ethernetInputPos; +#endif /* USE_UDP */ + + +bool gatewayTransportBegin() { +#ifdef MY_IP_ADDRESS + Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); +#else + // Get IP address from DHCP + Ethernet.begin(_ethernetGatewayMAC); #endif /* IP_ADDRESS_DHCP */ // give the Ethernet interface a second to initialize @@ -59,34 +48,32 @@ bool MyGatewayTransportEthernet::begin() { delay(1000); #ifdef MY_USE_UDP - server = new EthernetUDP(); - server->begin(gatewayPort); + _ethernetServer.begin(_ethernetGatewayPort); #else // we have to use pointers due to the constructor of EthernetServer - server = new EthernetServer(gatewayPort); - server->begin(); + _ethernetServer.begin(); #endif /* USE_UDP */ } -bool MyGatewayTransportEthernet::send(MyMessage &message) +bool gatewayTransportSend(MyMessage &message) { - char *msg = NULL; + char *_ethernetMsg = NULL; - if (controllerIP == INADDR_NONE) { + if (_ethernetControllerIP == INADDR_NONE) { // no controller IP address set! return false; } else { - msg = protocol.format(message); + _ethernetMsg = _protocol.format(message); #ifdef MY_USE_UDP - server->beginPacket(controllerIP, controllerPort); - server->write(msg, strlen(msg)); + _ethernetServer.beginPacket(_ethernetControllerIP, MY_CONTROLLER_PORT); + _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); // returns 1 if the packet was sent successfully - return server->endPacket(); + return _ethernetServer.endPacket(); #else EthernetClient client; - if (client.connect(controllerIP, controllerPort)) { - client.write(msg, strlen(msg)); + if (client.connect(_ethernetControllerIP, MY_CONTROLLER_PORT)) { + client.write(_ethernetMsg, strlen(_ethernetMsg)); client.stop(); return true; } @@ -98,71 +85,64 @@ bool MyGatewayTransportEthernet::send(MyMessage &message) } } -bool MyGatewayTransportEthernet::available() +bool gatewayTransportAvailable() { bool available = false; -#ifdef IP_ADDRESS_DHCP +#ifndef MY_IP_ADDRESS // renew IP address using DHCP - renewIP(); + gatewayTransportRenewIP(); #endif #ifdef MY_USE_UDP - int packet_size = server->parsePacket(); + int packet_size = _ethernetServer.parsePacket(); - if (server->available()) { - server->read(inputBuffer, MAX_RECEIVE_LENGTH); + if (_ethernetServer.available()) { + _ethernetServer.read(_ethernetInputBuffer, MAX_RECEIVE_LENGTH); available = true; } #else // if an incoming client connects, there will be // bytes available to read via the client object - EthernetClient client = server->available(); + EthernetClient client = _ethernetServer.available(); if (client) { while (client.available()) { // read the bytes incoming from the client char inChar = client.read(); - if (inputPos < MAX_RECEIVE_LENGTH - 1) { + if (_ethernetInputPos < MAX_RECEIVE_LENGTH - 1) { // if newline then command is complete if (inChar == '\n') { - inputBuffer[inputPos] = 0; + _ethernetInputBuffer[_ethernetInputPos] = 0; available = true; } else { - inputBuffer[inputPos] = inChar; - inputPos++; + _ethernetInputBuffer[_ethernetInputPos] = inChar; + _ethernetInputPos++; } } } } - inputPos = 0; + _ethernetInputPos = 0; #endif if (available) { // Parse message and return parse result - available = protocol.parse(msg, inputBuffer); + available = _protocol.parse(_ethernetMsg, _ethernetInputBuffer); } return available; } -MyMessage& MyGatewayTransportEthernet::receive() +MyMessage& gatewayTransportReceive() { // Return the last parsed message - return msg; + return _ethernetMsg; } -void MyGatewayTransportEthernet::setControllerIPPort(const IPAddress& addr, const uint16_t port) { - controllerIP = addr; - /* set the port if some legal value passed */ - if (port > 0) - controllerPort = port; -} - -#ifdef IP_ADDRESS_DHCP -void MyGatewayTransportEthernet::renewIP() +#ifndef MY_IP_ADDRES +void gatewayTransportRenewIP() { /* renew/rebind IP address 0 - nothing happened @@ -172,7 +152,7 @@ void MyGatewayTransportEthernet::renewIP() 4 - rebind success */ // TODO: Use millis from MyHw ?? - static unsigned long next_time = millis() + ip_renewal_period; + static unsigned long next_time = millis() + MY_IP_RENEWAL_INTERVAL; unsigned long now = millis(); // http://playground.arduino.cc/Code/TimingRollover @@ -184,6 +164,6 @@ void MyGatewayTransportEthernet::renewIP() return; } - next_time = now + ip_renewal_period; + next_time = now + MY_IP_RENEWAL_INTERVAL; } #endif /* IP_ADDRESS_DHCP */ diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.h b/libraries/MySensors/core/MyGatewayTransportEthernet.h index 7256b1a..da1abc1 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.h +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.h @@ -23,7 +23,6 @@ #include "MyConfig.h" #include "MyMessage.h" #include "MyProtocol.h" -#include "MyGatewayTransport.h" #include "MyProtocolDefault.h" #include "drivers/Ethernet_W5100/IPAddress.h" @@ -43,58 +42,20 @@ #define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller -class MyGatewayTransportEthernet : public MyGatewayTransport -{ - public: - MyGatewayTransportEthernet(MyProtocol &protocol, - uint8_t *gw_mac -#ifndef IP_ADDRESS_DHCP - , IPAddress gw_ip -#endif /* not IP_ADDRESS_DHCP */ - , uint16_t gw_port -#ifdef IP_ADDRESS_DHCP - , unsigned long ip_renew_interval -#endif /* IP_ADDRESS_DHCP */ - , IPAddress controller_IP - , uint16_t controller_port - ); +// initialize the driver +bool gatewayTransportBegin(); - // initialize the driver - bool begin(); +// Send message to controller +bool gatewayTransportSend(MyMessage &message); - // Send message to controller - bool send(MyMessage &message); +// Check if a new message is available from controller +bool gatewayTransportAvailable(); - // Check if a new message is available from controller - bool available(); +// Pick up last message received from controller +MyMessage& gatewayTransportReceive(); - // Pick up last message received from controller - MyMessage& receive(); - - // Set the controller IP and Port - void setControllerIPPort(const IPAddress& addr, const uint16_t port); - -protected: - IPAddress controllerIP; - uint16_t controllerPort; - -#ifdef IP_ADDRESS_DHCP - void renewIP(); - unsigned long ip_renewal_period; -#endif /* IP_ADDRESS_DHCP */ - uint8_t *gatewayMAC; - IPAddress gatewayIP; - uint16_t gatewayPort; - -#ifdef MY_USE_UDP - EthernetUDP *server; -#else - EthernetServer *server; - uint8_t inputPos; +#ifndef MY_IP_ADDRESS + void gatewayTransportRenewIP(); #endif - char inputBuffer[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface - MyMessage msg; -}; - #endif /* MyGatewayTransportEthernet_h */ diff --git a/libraries/MySensors/core/MyGatewayTransportSerial.h b/libraries/MySensors/core/MyGatewayTransportSerial.h index 44434cf..302a06c 100644 --- a/libraries/MySensors/core/MyGatewayTransportSerial.h +++ b/libraries/MySensors/core/MyGatewayTransportSerial.h @@ -22,7 +22,6 @@ #include "MyMessage.h" #include "MyProtocol.h" -#include "MyGatewayTransport.h" #include "MyProtocolDefault.h" #define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller diff --git a/libraries/MySensors/core/MyHw.cpp b/libraries/MySensors/core/MyHw.cpp deleted file mode 100644 index 3016a6b..0000000 --- a/libraries/MySensors/core/MyHw.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyHw.h" - -MyHw::MyHw() { -} diff --git a/libraries/MySensors/core/MyHw.h b/libraries/MySensors/core/MyHw.h deleted file mode 100644 index 506648b..0000000 --- a/libraries/MySensors/core/MyHw.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#ifndef MyHw_h -#define MyHw_h - -#include -#include -#include "MyConfig.h" - -/** - * The Hw contains all hardware specific details of the platform - */ - -class MyHw -{ -public: - // MyHw constructor - MyHw(); -/* // The following is defined as macros to save space - virtual void init() = 0; - virtual void watchdogReset() = 0; - virtual void reboot() = 0; - virtual unsigned long millisec() = 0; - virtual uint8_t readConfig(uint8_t pos) = 0; - virtual void writeConfig(uint8_t pos, uint8_t value) = 0; - virtual void readConfigBlock(void* buf, void * pos, size_t length) = 0; - virtual void writeConfigBlock(void* pos, void* buf, uint16_t length) = 0; */ - virtual void sleep(unsigned long ms) = 0; - virtual bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) = 0; - virtual uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) = 0; - #ifdef MY_DEBUG - virtual void debugPrint(bool isGW, const char *fmt, ... ) = 0; - #endif - -}; - -#endif diff --git a/libraries/MySensors/core/MyHwATMega328.cpp b/libraries/MySensors/core/MyHwATMega328.cpp index b20d337..38e16fe 100644 --- a/libraries/MySensors/core/MyHwATMega328.cpp +++ b/libraries/MySensors/core/MyHwATMega328.cpp @@ -19,7 +19,6 @@ #ifdef ARDUINO_ARCH_AVR -#include "MyHw.h" #include "MyHwATMega328.h" int8_t pinIntTrigger = 0; @@ -40,51 +39,10 @@ ISR (WDT_vect) wdt_disable(); } -MyHwATMega328::MyHwATMega328() : MyHw() -{ -} -/* -// The following was redifined as macros to save space - -inline uint8_t MyHwATMega328::readConfig(uint8_t pos) { - return eeprom_read_byte((uint8_t*)pos); -} - -inline void MyHwATMega328::writeConfig(uint8_t pos, uint8_t value) { - eeprom_update_byte((uint8_t*)pos, value); -} - -inline void MyHwATMega328::readConfigBlock(void* buf, void * pos, size_t length) { - eeprom_read_block(buf, (void*)pos, length); -} - -inline void MyHwATMega328::writeConfigBlock(void* pos, void* buf, size_t length) { - eeprom_write_block((void*)pos, (void*)buf, length); -} - - -inline void MyHwATMega328::init() { - Serial.begin(BAUD_RATE); -} - -inline void MyHwATMega328::watchdogReset() { - wdt_reset(); -} - -inline void MyHwATMega328::reboot() { - wdt_enable(WDTO_15MS); for (;;); -} - -inline unsigned long MyHwATMega328::millis() { - return ::millis(); -} -*/ - - -void powerDown(period_t period) { +void hwPowerDown(period_t period) { ADCSRA &= ~(1 << ADEN); @@ -119,35 +77,35 @@ void powerDown(period_t period) { ADCSRA |= (1 << ADEN); } -void MyHwATMega328::internalSleep(unsigned long ms) { +void hwInternalSleep(unsigned long ms) { // Let serial prints finish (debug, log etc) #ifndef MY_DISABLED_SERIAL Serial.flush(); #endif pinIntTrigger = 0; - while (!pinIntTrigger && ms >= 8000) { powerDown(SLEEP_8S); ms -= 8000; } - if (!pinIntTrigger && ms >= 4000) { powerDown(SLEEP_4S); ms -= 4000; } - if (!pinIntTrigger && ms >= 2000) { powerDown(SLEEP_2S); ms -= 2000; } - if (!pinIntTrigger && ms >= 1000) { powerDown(SLEEP_1S); ms -= 1000; } - if (!pinIntTrigger && ms >= 500) { powerDown(SLEEP_500MS); ms -= 500; } - if (!pinIntTrigger && ms >= 250) { powerDown(SLEEP_250MS); ms -= 250; } - if (!pinIntTrigger && ms >= 125) { powerDown(SLEEP_120MS); ms -= 120; } - if (!pinIntTrigger && ms >= 64) { powerDown(SLEEP_60MS); ms -= 60; } - if (!pinIntTrigger && ms >= 32) { powerDown(SLEEP_30MS); ms -= 30; } - if (!pinIntTrigger && ms >= 16) { powerDown(SLEEP_15Ms); ms -= 15; } + while (!pinIntTrigger && ms >= 8000) { hwPowerDown(SLEEP_8S); ms -= 8000; } + if (!pinIntTrigger && ms >= 4000) { hwPowerDown(SLEEP_4S); ms -= 4000; } + if (!pinIntTrigger && ms >= 2000) { hwPowerDown(SLEEP_2S); ms -= 2000; } + if (!pinIntTrigger && ms >= 1000) { hwPowerDown(SLEEP_1S); ms -= 1000; } + if (!pinIntTrigger && ms >= 500) { hwPowerDown(SLEEP_500MS); ms -= 500; } + if (!pinIntTrigger && ms >= 250) { hwPowerDown(SLEEP_250MS); ms -= 250; } + if (!pinIntTrigger && ms >= 125) { hwPowerDown(SLEEP_120MS); ms -= 120; } + if (!pinIntTrigger && ms >= 64) { hwPowerDown(SLEEP_60MS); ms -= 60; } + if (!pinIntTrigger && ms >= 32) { hwPowerDown(SLEEP_30MS); ms -= 30; } + if (!pinIntTrigger && ms >= 16) { hwPowerDown(SLEEP_15Ms); ms -= 15; } } -void MyHwATMega328::sleep(unsigned long ms) { - internalSleep(ms); +void hwSleep(unsigned long ms) { + hwInternalSleep(ms); } -bool MyHwATMega328::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { +bool hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { // Let serial prints finish (debug, log etc) bool pinTriggeredWakeup = true; attachInterrupt(interrupt, wakeUp, mode); if (ms>0) { pinIntTrigger = 0; - internalSleep(ms); + hwInternalSleep(ms); if (0 == pinIntTrigger) { pinTriggeredWakeup = false; } @@ -155,19 +113,19 @@ bool MyHwATMega328::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { #ifndef MY_DISABLED_SERIAL Serial.flush(); #endif - powerDown(SLEEP_FOREVER); + hwPowerDown(SLEEP_FOREVER); } detachInterrupt(interrupt); return pinTriggeredWakeup; } -inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { +uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { int8_t retVal = 1; attachInterrupt(interrupt1, wakeUp, mode1); attachInterrupt(interrupt2, wakeUp2, mode2); if (ms>0) { pinIntTrigger = 0; - internalSleep(ms); + hwInternalSleep(ms); if (0 == pinIntTrigger) { retVal = -1; } @@ -175,7 +133,7 @@ inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t i #ifndef MY_DISABLED_SERIAL Serial.flush(); #endif - powerDown(SLEEP_FOREVER); + hwPowerDown(SLEEP_FOREVER); } detachInterrupt(interrupt1); detachInterrupt(interrupt2); @@ -191,24 +149,24 @@ inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t i #ifdef MY_DEBUG -void MyHwATMega328::debugPrint(bool isGW, const char *fmt, ... ) { +void hwDebugPrint(const char *fmt, ... ) { char fmtBuffer[300]; - if (isGW) { + #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) snprintf_P(fmtBuffer, 299, PSTR("0;0;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); Serial.print(fmtBuffer); - } + #endif va_list args; va_start (args, fmt ); va_end (args); - if (isGW) { + #ifdef MY_GATEWAY_FEATURE // Truncate message if this is gateway node vsnprintf_P(fmtBuffer, 60, fmt, args); fmtBuffer[59] = '\n'; fmtBuffer[60] = '\0'; - } else { + #else vsnprintf_P(fmtBuffer, 299, fmt, args); - } + #endif va_end (args); Serial.print(fmtBuffer); Serial.flush(); diff --git a/libraries/MySensors/core/MyHwATMega328.h b/libraries/MySensors/core/MyHwATMega328.h index 3468db6..90ea09b 100644 --- a/libraries/MySensors/core/MyHwATMega328.h +++ b/libraries/MySensors/core/MyHwATMega328.h @@ -22,7 +22,6 @@ #ifdef ARDUINO_ARCH_AVR -#include "MyHw.h" #include "MyConfig.h" #include "MyMessage.h" #include @@ -42,7 +41,7 @@ #ifndef sleep_bod_disable #define sleep_bod_disable() \ do { \ - unsigned char tempreg; \ + unsigned char tempreg; \ __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \ "ori %[tempreg], %[bods_bodse]" "\n\t" \ "out %[mcucr], %[tempreg]" "\n\t" \ @@ -59,22 +58,22 @@ do { \ // Define these as macros to save valuable space -#define hw_digitalWrite(__pin, __value) (digitalWrite(__pin, __value)) -#define hw_init() Serial.begin(MY_BAUD_RATE) -#define hw_watchdogReset() wdt_reset() -#define hw_reboot() wdt_enable(WDTO_15MS); while (1) -#define hw_millis() millis() -#define hw_readConfig(__pos) (eeprom_read_byte((uint8_t*)(__pos))) +#define hwDigitalWrite(__pin, __value) (digitalWrite(__pin, __value)) +#define hwInit() Serial.begin(MY_BAUD_RATE) +#define hwWatchdogReset() wdt_reset() +#define hwReboot() wdt_enable(WDTO_15MS); while (1) +#define hwMillis() millis() +#define hwReadConfig(__pos) (eeprom_read_byte((uint8_t*)(__pos))) #ifndef eeprom_update_byte - #define hw_writeConfig(loc, val) if((uint8_t)(val) != eeprom_read_byte((uint8_t*)(loc))) { eeprom_write_byte((uint8_t*)(loc), (val)); } + #define hwWriteConfig(loc, val) if((uint8_t)(val) != eeprom_read_byte((uint8_t*)(loc))) { eeprom_write_byte((uint8_t*)(loc), (val)); } #else - #define hw_writeConfig(__pos, __value) (eeprom_update_byte((uint8_t*)(__pos), (__value))) + #define hwWriteConfig(__pos, __value) (eeprom_update_byte((uint8_t*)(__pos), (__value))) #endif // -#define hw_readConfigBlock(__buf, __pos, __length) (eeprom_read_block((__buf), (void*)(__pos), (__length))) -#define hw_writeConfigBlock(__pos, __buf, __length) (eeprom_write_block((void*)(__pos), (void*)__buf, (__length))) +#define hwReadConfigBlock(__buf, __pos, __length) (eeprom_read_block((__buf), (void*)(__pos), (__length))) +#define hwWriteConfigBlock(__pos, __buf, __length) (eeprom_write_block((void*)(__pos), (void*)__buf, (__length))) @@ -93,28 +92,14 @@ enum period_t SLEEP_FOREVER }; -class MyHwATMega328 : public MyHw -{ -public: - MyHwATMega328(); -/* void init(); - void watchdogReset(); - void reboot(); - unsigned long millis(); - uint8_t readConfig(uint8_t pos); - void writeConfig(uint8_t pos, uint8_t value); - void readConfigBlock(void* buf, void * pos, size_t length); - void writeConfigBlock(void* pos, void* buf, size_t length); */ - - void sleep(unsigned long ms); - bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms); - uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); +void hwSleep(unsigned long ms); +bool hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms); +uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); #ifdef MY_DEBUG - void debugPrint(bool isGW, const char *fmt, ... ); -#endif -private: - void internalSleep(unsigned long ms); -}; + void hwDebugPrint(const char *fmt, ... ); #endif +void hwInternalSleep(unsigned long ms); + #endif // #ifdef ARDUINO_ARCH_AVR +#endif diff --git a/libraries/MySensors/core/MyHwESP8266.cpp b/libraries/MySensors/core/MyHwESP8266.cpp index fa36ebf..5a0eb64 100644 --- a/libraries/MySensors/core/MyHwESP8266.cpp +++ b/libraries/MySensors/core/MyHwESP8266.cpp @@ -19,7 +19,6 @@ #ifdef ARDUINO_ARCH_ESP8266 -#include "MyHw.h" #include "MyHwESP8266.h" #include @@ -43,7 +42,7 @@ ISR (WDT_vect) } */ -static void hw_initConfigBlock( size_t length = 1024 /*ATMega328 has 1024 bytes*/ ) +static void hwInitConfigBlock( size_t length = 1024 /*ATMega328 has 1024 bytes*/ ) { static bool initDone = false; if (!initDone) @@ -53,7 +52,7 @@ static void hw_initConfigBlock( size_t length = 1024 /*ATMega328 has 1024 bytes* } } -void hw_readConfigBlock(void* buf, void* adr, size_t length) +void hwReadConfigBlock(void* buf, void* adr, size_t length) { hw_initConfigBlock(); uint8_t* dst = static_cast(buf); @@ -64,7 +63,7 @@ void hw_readConfigBlock(void* buf, void* adr, size_t length) } } -void hw_writeConfigBlock(void* buf, void* adr, size_t length) +void hwWriteConfigBlock(void* buf, void* adr, size_t length) { hw_initConfigBlock(); uint8_t* src = static_cast(buf); @@ -76,14 +75,14 @@ void hw_writeConfigBlock(void* buf, void* adr, size_t length) EEPROM.commit(); } -uint8_t hw_readConfig(int adr) +uint8_t hwReadConfig(int adr) { uint8_t value; hw_readConfigBlock(&value, reinterpret_cast(adr), 1); return value; } -void hw_writeConfig(int adr, uint8_t value) +void hwWriteConfig(int adr, uint8_t value) { uint8_t curr = hw_readConfig(adr); if (curr != value) @@ -94,85 +93,40 @@ void hw_writeConfig(int adr, uint8_t value) -MyHwESP8266::MyHwESP8266() : MyHw() -{ -} - -/* - -// The following was redifined as macros to save space - -inline uint8_t MyHwATMega328::readConfig(uint8_t pos) { - return eeprom_read_byte((uint8_t*)pos); -} - -inline void MyHwATMega328::writeConfig(uint8_t pos, uint8_t value) { - eeprom_update_byte((uint8_t*)pos, value); -} - -inline void MyHwATMega328::readConfigBlock(void* buf, void * pos, size_t length) { - eeprom_read_block(buf, (void*)pos, length); -} - -inline void MyHwATMega328::writeConfigBlock(void* pos, void* buf, size_t length) { - eeprom_write_block((void*)pos, (void*)buf, length); -} - - -inline void MyHwATMega328::init() { - Serial.begin(BAUD_RATE); -} - -inline void MyHwATMega328::watchdogReset() { - wdt_reset(); -} - -inline void MyHwATMega328::reboot() { - wdt_enable(WDTO_15MS); for (;;); -} - -inline unsigned long MyHwATMega328::millis() { - return ::millis(); -} -*/ - - -void MyHwESP8266::sleep(unsigned long ms) { +void hwSleep(unsigned long ms) { // TODO: Not supported! } -bool MyHwESP8266::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { +bool hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { // TODO: Not supported! return false; } -inline uint8_t MyHwESP8266::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { +uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { // TODO: Not supported! return 0; } - - #ifdef MY_DEBUG -void MyHwESP8266::debugPrint(bool isGW, const char *fmt, ... ) { +void hwDebugPrint(bool isGW, const char *fmt, ... ) { char fmtBuffer[300]; - if (isGW) { + #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) snprintf_P(fmtBuffer, 299, PSTR("0;0;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE); Serial.print(fmtBuffer); - } + #endif va_list args; va_start (args, fmt ); va_end (args); - if (isGW) { + #ifdef MY_GATEWAY_FEATURE // Truncate message if this is gateway node vsnprintf_P(fmtBuffer, 60, fmt, args); fmtBuffer[59] = '\n'; fmtBuffer[60] = '\0'; - } else { + #else vsnprintf_P(fmtBuffer, 299, fmt, args); - } + #endif va_end (args); Serial.print(fmtBuffer); Serial.flush(); diff --git a/libraries/MySensors/core/MyHwESP8266.h b/libraries/MySensors/core/MyHwESP8266.h index 03f47c3..6f99201 100644 --- a/libraries/MySensors/core/MyHwESP8266.h +++ b/libraries/MySensors/core/MyHwESP8266.h @@ -22,7 +22,6 @@ #ifndef MyHwESP8266_h #define MyHwESP8266_h -#include "MyHw.h" #include "MyConfig.h" #include "MyMessage.h" @@ -34,16 +33,16 @@ // Define these as macros to save valuable space -#define hw_digitalWrite(__pin, __value) (digitalWrite(__pin, __value)) -#define hw_init() Serial.begin(BAUD_RATE) -#define hw_watchdogReset() wdt_reset() -#define hw_reboot() wdt_enable(WDTO_15MS); while (1) -#define hw_millis() millis() +#define hwDigitalWrite(__pin, __value) (digitalWrite(__pin, __value)) +#define hwInit() Serial.begin(BAUD_RATE) +#define hwWatchdogReset() wdt_reset() +#define hwReboot() wdt_enable(WDTO_15MS); while (1) +#define hwMillis() millis() -void hw_readConfigBlock(void* buf, void* adr, size_t length); -void hw_writeConfigBlock(void* buf, void* adr, size_t length); -void hw_writeConfig(int adr, uint8_t value); -uint8_t hw_readConfig(int adr); +void hwReadConfigBlock(void* buf, void* adr, size_t length); +void hwWriteConfigBlock(void* buf, void* adr, size_t length); +void hwWriteConfig(int adr, uint8_t value); +uint8_t hwReadConfig(int adr); enum period_t { @@ -60,27 +59,13 @@ enum period_t SLEEP_FOREVER }; -class MyHwESP8266 : public MyHw -{ -public: - MyHwESP8266(); -/* void init(); - void watchdogReset(); - void reboot(); - unsigned long millis(); - uint8_t readConfig(uint8_t pos); - void writeConfig(uint8_t pos, uint8_t value); - void readConfigBlock(void* buf, void * pos, size_t length); - void writeConfigBlock(void* pos, void* buf, size_t length); */ - void sleep(unsigned long ms); - bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms); - uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); +void hwSleep(unsigned long ms); +bool hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms); +uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); #ifdef MY_DEBUG - void debugPrint(bool isGW, const char *fmt, ... ); -#endif -}; + void hwDebugPrint(const char *fmt, ... ); #endif #endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/libraries/MySensors/core/MySensorCore.cpp b/libraries/MySensors/core/MySensorCore.cpp index 32b4e8e..05121cf 100644 --- a/libraries/MySensors/core/MySensorCore.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -21,17 +21,58 @@ #include "MySensorCore.h" + +NodeConfig _nc; // Essential settings for node to work +ControllerConfig _cc; // Configuration coming from controller +#ifdef MY_OTA_FIRMWARE_FEATURE +NodeFirmwareConfig _fc; +bool _fwUpdateOngoing; +unsigned long _fwLastRequestTime; +uint16_t _fwBlock; +uint8_t _fwRetry; +#endif + +#ifdef MY_RADIO_FEATURE +bool _autoFindParent; +uint8_t _failedTransmissions; +#endif + +MyMessage _msg; // Buffer for incoming messages. +MyMessage _msgTmp ; // Buffer for temporary messages (acks and nonces among others). + +#ifdef MY_LEDS_BLINKING_FEATURE +// these variables don't need to be volatile, since we are not using interrupts +uint8_t _countRx; +uint8_t _countTx; +uint8_t _countErr; +unsigned long _blink_next_time; +#endif + +#ifdef MY_SIGNING_FEATURE +uint16_t _doSign[16]; // Bitfield indicating which sensors require signed communication +MyMessage _msgSign; // Buffer for message to sign. +#endif + +#ifdef MY_DEBUG + char convBuf[MAX_PAYLOAD*2+1]; +#endif + +uint16_t _heartbeat; +void (*_timeCallback)(unsigned long); // Callback for requested time messages +void (*_msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. + + #define DISTANCE_INVALID (0xFF) #ifdef MY_SIGNING_FEATURE // Macros for manipulating signing requirement table -#define DO_SIGN(node) (node == 0 ? (~doSign[0]&1) : (~doSign[node>>4]&(node%16))) -#define SET_SIGN(node) (node == 0 ? (doSign[0]&=~1) : (doSign[node>>4]&=~(node%16))) -#define CLEAR_SIGN(node) (node == 0 ? (doSign[0]|=1) : (doSign[node>>4]|=(node%16))) +#define DO_SIGN(node) (node == 0 ? (~_doSign[0]&1) : (~_doSign[node>>4]&(node%16))) +#define SET_SIGN(node) (node == 0 ? (_doSign[0]&=~1) : (_doSign[node>>4]&=~(node%16))) +#define CLEAR_SIGN(node) (node == 0 ? (_doSign[0]|=1) : (_doSign[node>>4]|=(node%16))) #endif // Inline function and macros -static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { +static inline MyMessage& build(MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { msg.sender = sender; msg.destination = destination; msg.sensor = sensor; @@ -42,858 +83,6 @@ static inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destinat return msg; } -static inline bool isValidParent( const uint8_t parent ) { - return parent != AUTO; -} -static inline bool isValidDistance( const uint8_t distance ) { - return distance != DISTANCE_INVALID; -} - - -MySensor::MySensor(MyTransport &_radio, MyHw &_hw -#ifdef MY_SIGNING_FEATURE - , MySigning &_signer -#endif - ) - : - radio(_radio), -#ifdef MY_SIGNING_FEATURE - signer(_signer), -#endif -#ifdef MY_OTA_FIRMWARE_FEATURE - flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID), -#endif - hw(_hw) -{ -} - - -#ifdef MY_OTA_FIRMWARE_FEATURE - -// do a crc16 on the whole received firmware -bool MySensor::isValidFirmware() { - // init crc - uint16_t crc = ~0; - for (uint16_t i = 0; i < fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) { - crc ^= flash.readByte(i + FIRMWARE_START_OFFSET); - for (int8_t j = 0; j < 8; ++j) { - if (crc & 1) - crc = (crc >> 1) ^ 0xA001; - else - crc = (crc >> 1); - } - } - return crc == fc.crc; -} - -#endif - -#ifdef MY_LEDS_BLINKING_FEATURE -void MySensor::handleLedsBlinking() { - static unsigned long next_time = hw_millis() + MY_DEFAULT_LED_BLINK_PERIOD; - - // Just return if it is not the time... - // http://playground.arduino.cc/Code/TimingRollover - if ((long)(hw_millis() - blink_next_time) < 0) - return; - else - blink_next_time = hw_millis() + ledBlinkPeriod; - - // do the actual blinking - if(countRx && countRx != 255) { - // switch led on - hw_digitalWrite(MY_DEFAULT_RX_LED_PIN, LED_ON); - } - else if(!countRx) { - // switching off - hw_digitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); - } - if(countRx != 255) - --countRx; - - if(countTx && countTx != 255) { - // switch led on - hw_digitalWrite(MY_DEFAULT_TX_LED_PIN, LED_ON); - } - else if(!countTx) { - // switching off - hw_digitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); - } - if(countTx != 255) - --countTx; - - if(countErr && countErr != 255) { - // switch led on - hw_digitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_ON); - } - else if(!countErr) { - // switching off - hw_digitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); - } - if(countErr != 255) - --countErr; -} - -void MySensor::rxBlink(uint8_t cnt) { - if(countRx == 255) { countRx = cnt; } -} - -void MySensor::txBlink(uint8_t cnt) { - if(countTx == 255) { countTx = cnt; } -} - -void MySensor::errBlink(uint8_t cnt) { - if(countErr == 255) { countErr = cnt; } -} -#endif - -void MySensor::begin(void (*_msgCallback)(const MyMessage &), uint8_t _nodeId, boolean _repeaterMode, uint8_t _parentNodeId) { - #ifndef MY_DISABLED_SERIAL - hw_init(); - #endif - repeaterMode = _repeaterMode; - msgCallback = _msgCallback; - failedTransmissions = 0; - - // Only gateway should use node id 0! - isGateway = _nodeId == GATEWAY_ADDRESS; - - // Setup radio - if (!radio.init()) { - debug(PSTR("radio init fail\n")); - while(1); // Nothing more we can do - } - -#ifdef MY_SIGNING_FEATURE - // Read out the signing requirements from EEPROM - hw_readConfigBlock((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign)); -#endif - -#ifdef MY_LEDS_BLINKING_FEATURE - // Setup led pins - pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); - pinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); - pinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); - - // Set initial state of leds - hw_digitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); - hw_digitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); - hw_digitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); - - // initialize counters - countRx = 0; - countTx = 0; - countErr = 0; -#endif - - if (isGateway) { - // Set configuration for gateway - nc.parentNodeId = GATEWAY_ADDRESS; - nc.distance = 0; - nc.nodeId = GATEWAY_ADDRESS; - } else { - // Read settings from eeprom - hw_readConfigBlock((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig)); - // Read latest received controller configuration from EEPROM - hw_readConfigBlock((void*)&cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); -#ifdef MY_OTA_FIRMWARE_FEATURE - // Read firmware config from EEPROM, i.e. type, version, CRC, blocks - hw_readConfigBlock((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); -#endif - - if (cc.isMetric == 0xff) { - // Eeprom empty, set default to metric - cc.isMetric = 0x01; - } - - autoFindParent = _parentNodeId == AUTO; - if (!autoFindParent) { - nc.parentNodeId = _parentNodeId; - // Save static parent id in eeprom (used by bootloader) - hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, _parentNodeId); - // We don't actually know the distance to gw here. Let's pretend it is 1. - // If the current node is also repeater, be aware of this. - nc.distance = 1; - } else if (!isValidParent(nc.parentNodeId)) { - // Auto find parent, but parent in eeprom is invalid. Try find one. - findParentNode(); - } - - if (_nodeId != AUTO) { - // Set static id - nc.nodeId = _nodeId; - // Save static id in eeprom - hw_writeConfig(EEPROM_NODE_ID_ADDRESS, _nodeId); - } else if (nc.nodeId == AUTO && isValidParent(nc.parentNodeId)) { - // Try to fetch node-id from gateway - requestNodeId(); - } - } - - setupNode(); - debug(PSTR("%s started, id=%d, parent=%d, distance=%d\n"), isGateway?"gateway":(repeaterMode?"repeater":"sensor"), nc.nodeId, nc.parentNodeId, nc.distance); -} - - -uint8_t MySensor::getNodeId() { - return nc.nodeId; -} - -ControllerConfig MySensor::getConfig() { - return cc; -} - -void MySensor::requestNodeId() { - debug(PSTR("req id\n")); - radio.setAddress(nc.nodeId); - build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set(""); - sendWrite(nc.parentNodeId, msg); - wait(2000); -} - -void MySensor::setupNode() { - // Open reading pipe for messages directed to this node (set write pipe to same) - radio.setAddress(nc.nodeId); - - // Present node and request config - if (!isGateway && nc.nodeId != AUTO) { -#ifdef MY_SIGNING_FEATURE - // Notify gateway (and possibly controller) about the signing preferences of this node - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(signer.requestSignatures())); - - // If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages - if (signer.requestSignatures()) { - wait(2000); - } -#endif - - // Send presentation for this radio node (attach - present(NODE_SENSOR_ID, repeaterMode? S_ARDUINO_REPEATER_NODE : S_ARDUINO_NODE); - - // Send a configuration exchange request to controller - // Node sends parent node. Controller answers with latest node configuration - // which is picked up in process() - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG, false).set(nc.parentNodeId)); - - // Wait configuration reply. - wait(2000); - -#ifdef MY_OTA_FIRMWARE_FEATURE - RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)msg.data; - mSetLength(msg, sizeof(RequestFirmwareConfig)); - mSetCommand(msg, C_STREAM); - mSetPayloadType(msg,P_CUSTOM); - // copy node settings to reqFWConfig - memcpy(reqFWConfig,&fc,sizeof(NodeFirmwareConfig)); - // add bootloader information - reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; - fwUpdateOngoing = false; - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); -#endif - - - } -} - -void MySensor::findParentNode() { - static boolean findingParentNode = false; - - if (findingParentNode) - return; - findingParentNode = true; - - failedTransmissions = 0; - - // Set distance to max - nc.distance = 255; - - // Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to) - debug(PSTR("find parent\n")); - - build(msg, nc.nodeId, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT, false).set(""); - // Write msg, but suppress recursive parent search - sendWrite(BROADCAST_ADDRESS, msg); - - // Wait for ping response. - wait(2000); - findingParentNode = false; -} - -boolean MySensor::sendRoute(MyMessage &message) { - uint8_t sender = message.sender; - uint8_t dest = message.destination; - uint8_t last = message.last; - bool ok; - - // If we still don't have any parent id, re-request and skip this message. - if (nc.parentNodeId == AUTO) { - findParentNode(); -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; - } - - // If we still don't have any node id, re-request and skip this message. - if (nc.nodeId == AUTO) { - requestNodeId(); -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; - } - - mSetVersion(message, PROTOCOL_VERSION); - -#ifdef MY_SIGNING_FEATURE - // If destination is known to require signed messages and we are the sender, sign this message unless it is an ACK or a handshake message - if (DO_SIGN(message.destination) && message.sender == nc.nodeId && !mGetAck(message) && mGetLength(message) && - (mGetCommand(message) != C_INTERNAL || - (message.type != I_GET_NONCE && message.type != I_GET_NONCE_RESPONSE && message.type != I_REQUEST_SIGNING && - message.type != I_ID_REQUEST && message.type != I_ID_RESPONSE && - message.type != I_FIND_PARENT && message.type != I_FIND_PARENT_RESPONSE))) { - bool signOk = false; - // Send nonce-request - if (!sendRoute(build(tmpMsg, nc.nodeId, message.destination, message.sensor, C_INTERNAL, I_GET_NONCE, false).set(""))) { - debug(PSTR("nonce tr err\n")); - return false; - } - // We have to wait for the nonce to arrive before we can sign our original message - // Other messages could come in-between. We trust process() takes care of them - unsigned long enter = hw_millis(); - msgSign = message; // Copy the message to sign since message buffer might be touched in process() - while (hw_millis() - enter < MY_VERIFICATION_TIMEOUT_MS) { - if (process()) { - if (mGetCommand(getLastMessage()) == C_INTERNAL && getLastMessage().type == I_GET_NONCE_RESPONSE) { - // Proceed with signing if nonce has been received - if (signer.putNonce(getLastMessage()) && signer.signMsg(msgSign)) { - message = msgSign; // Write the signed message back - signOk = true; - } - break; - } - } - } - if (hw_millis() - enter > MY_VERIFICATION_TIMEOUT_MS) { - debug(PSTR("nonce tmo\n")); -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; - } - if (!signOk) { - debug(PSTR("sign fail\n")); -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; - } - // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed, - // or signature will become invalid and the message rejected by the receiver - } else mSetSigned(message, 0); // Message is not supposed to be signed, make sure it is marked unsigned -#endif - - if (dest == GATEWAY_ADDRESS || !repeaterMode) { - // Store this address in routing table (if repeater) - if (repeaterMode) { - hw_writeConfig(EEPROM_ROUTES_ADDRESS+sender, last); - } - // If destination is the gateway or if we aren't a repeater, let - // our parent take care of the message - ok = sendWrite(nc.parentNodeId, message); - } else { - // Relay the message - uint8_t route = hw_readConfig(EEPROM_ROUTES_ADDRESS+dest); - if (route > GATEWAY_ADDRESS && route < BROADCAST_ADDRESS) { - // This message should be forwarded to a child node. If we send message - // to this nodes pipe then all children will receive it because the are - // all listening to this nodes pipe. - // - // +----B - // -A - // +----C------D - // - // We're node C, Message comes from A and has destination D - // - // Message destination is not gateway and is in routing table for this node. - // Send it downstream - return sendWrite(route, message); - } else if (sender == GATEWAY_ADDRESS && dest == BROADCAST_ADDRESS) { - // Node has not yet received any id. We need to send it - // by doing a broadcast sending, - return sendWrite(BROADCAST_ADDRESS, message); - } else if (isGateway) { - // Destination isn't in our routing table and isn't a broadcast address - // Nothing to do here - return false; - } else { - // A message comes from a child node and we have no - // route for it. - // - // +----B - // -A - // +----C------D <-- Message comes from D - // - // We're node C - // - // Message should be passed to node A (this nodes relay) - - // This message should be routed back towards sensor net gateway - ok = sendWrite(nc.parentNodeId, message); - // Add this child to our "routing table" if it not already exist - hw_writeConfig(EEPROM_ROUTES_ADDRESS+sender, last); - } - } - - if (!ok) { - // Failure when sending to parent node. The parent node might be down and we - // need to find another route to gateway. -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - failedTransmissions++; - if (autoFindParent && failedTransmissions > SEARCH_FAILURES) { - findParentNode(); - } - } else { - failedTransmissions = 0; - } - return ok; -} - -boolean MySensor::sendWrite(uint8_t to, MyMessage &message) { - mSetVersion(message, PROTOCOL_VERSION); - uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message); - message.last = nc.nodeId; -#ifdef MY_LEDS_BLINKING_FEATURE - txBlink(1); -#endif - bool ok = radio.send(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length)); - - debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,st=%s:%s\n"), - message.sender,message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, - mGetPayloadType(message), mGetLength(message), mGetSigned(message), to==BROADCAST_ADDRESS ? "bc" : (ok ? "ok":"fail"), message.getString(convBuf)); - - return ok; -} - -bool MySensor::send(MyMessage &message, bool enableAck) { - message.sender = nc.nodeId; - mSetCommand(message,C_SET); - mSetRequestAck(message,enableAck); - return sendRoute(message); -} - -void MySensor::sendBatteryLevel(uint8_t value, bool enableAck) { - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, enableAck).set(value)); -} - -void MySensor::sendHeartbeat(void) { - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT, false).set(heartbeat++)); - -} - -void MySensor::present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool enableAck) { - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, enableAck).set(childSensorId==NODE_SENSOR_ID?LIBRARY_VERSION:description)); -} - -void MySensor::sendSketchInfo(const char *name, const char *version, bool enableAck) { - if (name != NULL) { - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, enableAck).set(name)); - } - if (version != NULL) { - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, enableAck).set(version)); - } -} - -void MySensor::request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) { - sendRoute(build(msg, nc.nodeId, destination, childSensorId, C_REQ, variableType, false).set("")); -} - -void MySensor::requestTime(void (* _timeCallback)(unsigned long)) { - timeCallback = _timeCallback; - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, false).set("")); -} - -boolean MySensor::process() { - hw_watchdogReset(); - -#ifdef MY_LEDS_BLINKING_FEATURE - handleLedsBlinking(); -#endif - - uint8_t to = 0; - if (!radio.available(&to)) - { -#ifdef MY_OTA_FIRMWARE_FEATURE - unsigned long enter = hw_millis(); - if (fwUpdateOngoing && (enter - fwLastRequestTime > MY_OTA_RETRY_DELAY)) { - if (!fwRetry) { - debug(PSTR("fw upd fail\n")); - // Give up. We have requested MY_OTA_RETRY times without any packet in return. - fwUpdateOngoing = false; -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; - } - fwRetry--; - fwLastRequestTime = enter; - // Time to (re-)request firmware block from controller - RequestFWBlock *firmwareRequest = (RequestFWBlock *)msg.data; - mSetLength(msg, sizeof(RequestFWBlock)); - firmwareRequest->type = fc.type; - firmwareRequest->version = fc.version; - firmwareRequest->block = (fwBlock - 1); - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false)); - } -#endif - return false; - } - -#ifdef MY_SIGNING_FEATURE - (void)signer.checkTimer(); // Manage signing timeout -#endif - - uint8_t len = radio.receive((uint8_t *)&msg); - (void)len; //until somebody makes use of 'len' -#ifdef MY_LEDS_BLINKING_FEATURE - rxBlink(1); -#endif - -#ifdef MY_SIGNING_FEATURE - // Before processing message, reject unsigned messages if signing is required and check signature (if it is signed and addressed to us) - // Note that we do not care at all about any signature found if we do not require signing, nor do we care about ACKs (they are never signed) - if (signer.requestSignatures() && msg.destination == nc.nodeId && mGetLength(msg) && !mGetAck(msg) && - (mGetCommand(msg) != C_INTERNAL || - (msg.type != I_GET_NONCE_RESPONSE && msg.type != I_GET_NONCE && msg.type != I_REQUEST_SIGNING && - msg.type != I_ID_REQUEST && msg.type != I_ID_RESPONSE && - msg.type != I_FIND_PARENT && msg.type != I_FIND_PARENT_RESPONSE))) { - if (!mGetSigned(msg)) { - // Got unsigned message that should have been signed - debug(PSTR("no sign\n")); -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; - } - else if (!signer.verifyMsg(msg)) { - debug(PSTR("verify fail\n")); -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; // This signed message has been tampered with! - } - } -#endif - - // Add string termination, good if we later would want to print it. - msg.data[mGetLength(msg)] = '\0'; - debug(PSTR("read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"), - msg.sender, msg.last, msg.destination, msg.sensor, mGetCommand(msg), msg.type, mGetPayloadType(msg), mGetLength(msg), mGetSigned(msg), msg.getString(convBuf)); - mSetSigned(msg,0); // Clear the sign-flag now as verification (and debug printing) is completed - - if(!(mGetVersion(msg) == PROTOCOL_VERSION)) { - debug(PSTR("ver mismatch\n")); -#ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); -#endif - return false; - } - - uint8_t command = mGetCommand(msg); - uint8_t type = msg.type; - uint8_t sender = msg.sender; - uint8_t last = msg.last; - uint8_t destination = msg.destination; - - if (destination == nc.nodeId) { - // This message is addressed to this node - - if (repeaterMode && last != nc.parentNodeId) { - // Message is from one of the child nodes. Add it to routing table. - hw_writeConfig(EEPROM_ROUTES_ADDRESS+sender, last); - } - - // Check if sender requests an ack back. - if (mGetRequestAck(msg)) { - // Copy message - tmpMsg = msg; - mSetRequestAck(tmpMsg,false); // Reply without ack flag (otherwise we would end up in an eternal loop) - mSetAck(tmpMsg,true); - tmpMsg.sender = nc.nodeId; - tmpMsg.destination = msg.sender; - sendRoute(tmpMsg); - } - - if (command == C_INTERNAL) { - if (type == I_FIND_PARENT_RESPONSE) { - if (autoFindParent) { - // We've received a reply to a FIND_PARENT message. Check if the distance is - // shorter than we already have. - uint8_t distance = msg.getByte(); - if (isValidDistance(distance)) - { - // Distance to gateway is one more for us w.r.t. parent - distance++; - if (isValidDistance(distance) && (distance < nc.distance)) { - // Found a neighbor closer to GW than previously found - nc.distance = distance; - nc.parentNodeId = msg.sender; - hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId); - hw_writeConfig(EEPROM_DISTANCE_ADDRESS, nc.distance); - debug(PSTR("parent=%d, d=%d\n"), nc.parentNodeId, nc.distance); - } - } - } - return false; -#ifdef MY_SIGNING_FEATURE - } else if (type == I_GET_NONCE) { - if (signer.getNonce(msg)) { - sendRoute(build(msg, nc.nodeId, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_GET_NONCE_RESPONSE, false)); - } - return false; // Nonce exchange is an internal MySensor protocol message, no need to inform caller about this - } else if (type == I_REQUEST_SIGNING) { - if (msg.getBool()) { - // We received an indicator that the sender require us to sign all messages we send to it - SET_SIGN(msg.sender); - } else { - // We received an indicator that the sender does not require us to sign all messages we send to it - CLEAR_SIGN(msg.sender); - } - // Save updated table - hw_writeConfigBlock((void*)doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(doSign)); - - // Inform sender about our preference if we are a gateway, but only require signing if the sender required signing - // We do not currently want a gateway to require signing from all nodes in a network just because it wants one node - // to sign it's messages - if (isGateway) { - if (signer.requestSignatures() && DO_SIGN(msg.sender)) - sendRoute(build(msg, nc.nodeId, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(true)); - else - sendRoute(build(msg, nc.nodeId, msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); - } - return false; // Signing request is an internal MySensor protocol message, no need to inform caller about this - } else if (type == I_GET_NONCE_RESPONSE) { - return true; // Just pass along nonce silently (no need to call callback for these) -#endif - } else if (sender == GATEWAY_ADDRESS) { - if (type == I_ID_RESPONSE && nc.nodeId == AUTO) { - nc.nodeId = msg.getByte(); - if (nc.nodeId == AUTO) { - // sensor net gateway will return max id if all sensor id are taken - debug(PSTR("full\n")); - while (1); // Wait here. Nothing else we can do... - } - setupNode(); - // Write id to EEPROM - hw_writeConfig(EEPROM_NODE_ID_ADDRESS, nc.nodeId); - debug(PSTR("id=%d\n"), nc.nodeId); - } else { - processInternalMessages(msg); - } - return false; - } - } -#ifdef MY_OTA_FIRMWARE_FEATURE - else if (command == C_STREAM) { - if (type == ST_FIRMWARE_CONFIG_RESPONSE) { - NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)msg.data; - // compare with current node configuration, if they differ, start fw fetch process - if (memcmp(&fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) { - debug(PSTR("fw update\n")); - // copy new FW config - memcpy(&fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig)); - // Init flash - if (!flash.initialize()) { - debug(PSTR("flash init fail\n")); - fwUpdateOngoing = false; - } else { - // erase lower 32K -> max flash size for ATMEGA328 - flash.blockErase32K(0); - // wait until flash erased - while ( flash.busy() ); - fwBlock = fc.blocks; - fwUpdateOngoing = true; - // reset flags - fwRetry = MY_OTA_RETRY+1; - fwLastRequestTime = 0; - } - return false; - } else debug(PSTR("fw update skipped\n")); - } else if (type == ST_FIRMWARE_RESPONSE) { - if (fwUpdateOngoing) { - // Save block to flash - debug(PSTR("fw block %d\n"), fwBlock); - // extract FW block - ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)msg.data; - // write to flash - flash.writeBytes( ((fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); - // wait until flash written - while ( flash.busy() ); - fwBlock--; - if (!fwBlock) { - // We're finished! Do a checksum and reboot. - fwUpdateOngoing = false; - if (isValidFirmware()) { - debug(PSTR("fw checksum ok\n")); - // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) - uint16_t fwsize = FIRMWARE_BLOCK_SIZE * fc.blocks; - uint8_t OTAbuffer[10] = {'F','L','X','I','M','G',':',(fwsize >> 8),fwsize,':'}; - flash.writeBytes(0, OTAbuffer, 10); - // Write the new firmware config to eeprom - hw_writeConfigBlock((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); - hw_reboot(); - } else { - debug(PSTR("fw checksum fail\n")); - } - } - // reset flags - fwRetry = MY_OTA_RETRY+1; - fwLastRequestTime = 0; - } else { - debug(PSTR("No fw update ongoing\n")); - } - return false; - } - - } -#endif - // Call incoming message callback if available - if (msgCallback != NULL) { - msgCallback(msg); - } - // Return true if message was addressed for this node... - return true; - } else if (repeaterMode && nc.nodeId != AUTO) { - // If this node have an id, relay the message - - if (command == C_INTERNAL && type == I_FIND_PARENT) { - if (sender != nc.parentNodeId) { - if (nc.distance == DISTANCE_INVALID) - findParentNode(); - - if (nc.distance != DISTANCE_INVALID) { - // Relaying nodes should always answer ping messages - // Wait a random delay of 0-2 seconds to minimize collision - // between ping ack messages from other relaying nodes - wait(hw_millis() & 0x3ff); - sendWrite(sender, build(msg, nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false).set(nc.distance)); - } - } - } else if (to == nc.nodeId) { - // We should try to relay this message to another node - sendRoute(msg); - } - } - return false; -} - - -void MySensor::processInternalMessages(MyMessage &msg) { - bool isMetric; - uint8_t type = msg.type; - - if (type == I_REBOOT) { - // Requires MySensors or other bootloader with watchdogs enabled - hw_reboot(); - } else if (type == I_CONFIG) { - // Pick up configuration from controller (currently only metric/imperial) - // and store it in eeprom if changed - isMetric = msg.getString()[0] == 'M' ; - cc.isMetric = isMetric; - hw_writeConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); - } else if (type == I_CHILDREN) { - if (repeaterMode && msg.getString()[0] == 'C') { - // Clears child relay data for this node - debug(PSTR("clear\n")); - uint8_t i = 255; - do { - hw_writeConfig(EEPROM_ROUTES_ADDRESS+i, 0xff); - } while (i--); - // Clear parent node id & distance to gw - hw_writeConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF); - hw_writeConfig(EEPROM_DISTANCE_ADDRESS, 0xFF); - // Find parent node - findParentNode(); - sendRoute(build(msg, nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); - } - } else if (type == I_TIME) { - if (timeCallback != NULL) { - // Deliver time to callback - timeCallback(msg.getULong()); - } - } -} - - -MyMessage& MySensor::getLastMessage() { - return msg; -} - -void MySensor::saveState(uint8_t pos, uint8_t value) { - hw_writeConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); -} -uint8_t MySensor::loadState(uint8_t pos) { - return hw_readConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos); -} - -void MySensor::wait(unsigned long ms) { - unsigned long enter = hw_millis(); - while (hw_millis() - enter < ms) { - process(); - } -} - -void MySensor::sleep(unsigned long ms) { -#ifdef MY_OTA_FIRMWARE_FEATURE - if (fwUpdateOngoing) { - // Do not sleep node while fw update is ongoing - process(); - } else { -#endif - radio.powerDown(); - hw.sleep(ms); -#ifdef MY_OTA_FIRMWARE_FEATURE - } -#endif -} - -bool MySensor::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { -#ifdef MY_OTA_FIRMWARE_FEATURE - if (fwUpdateOngoing) { - // Do not sleep node while fw update is ongoing - process(); - return false; - } else { -#endif - radio.powerDown(); - return hw.sleep(interrupt, mode, ms) ; -#ifdef MY_OTA_FIRMWARE_FEATURE - } -#endif -} - -int8_t MySensor::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { -#ifdef MY_OTA_FIRMWARE_FEATURE - if (fwUpdateOngoing) { - // Do not sleep node while fw update is ongoing - process(); - return -1; - } else { -#endif - radio.powerDown(); - return hw.sleep(interrupt1, mode1, interrupt2, mode2, ms) ; -#ifdef MY_OTA_FIRMWARE_FEATURE - } -#endif -} - - - - - -// Inline function and macros static inline MyMessage& buildGw(MyMessage &msg, uint8_t type) { msg.sender = GATEWAY_ADDRESS; msg.destination = GATEWAY_ADDRESS; @@ -905,120 +94,954 @@ static inline MyMessage& buildGw(MyMessage &msg, uint8_t type) { return msg; } -MyGateway::MyGateway(MyGatewayTransport &_transport, MyTransport &_radio, - MyHw &_hw -#ifdef MY_SIGNING_FEATURE - , MySigning &_signer -#endif - ) : - transport(_transport), MySensor(_radio, _hw -#ifdef MY_SIGNING_FEATURE - , _signer -#endif - ) -{ -#ifdef MY_INCLUSION_MODE_FEATURE - inclusionMode = false; -#endif +static inline bool isValidParent( const uint8_t parent ) { + return parent != AUTO; +} +static inline bool isValidDistance( const uint8_t distance ) { + return distance != DISTANCE_INVALID; +} + + + +#ifdef MY_OTA_FIRMWARE_FEATURE +// do a crc16 on the whole received firmware +bool isValidFirmware() { + // init crc + uint16_t crc = ~0; + for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) { + crc ^= flash.readByte(i + FIRMWARE_START_OFFSET); + for (int8_t j = 0; j < 8; ++j) { + if (crc & 1) + crc = (crc >> 1) ^ 0xA001; + else + crc = (crc >> 1); + } + } + return crc == _fc.crc; } -void MyGateway::begin(void (*_msgCallback)(const MyMessage &)) { - // Setup digital in that triggers inclusion mode -#ifdef MY_INCLUSION_MODE_FEATURE -#ifdef MY_INCLUSION_BUTTON_FEATURE - pinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); - digitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); -#endif #endif - // initialize the transport driver - if (!transport.begin()) { - debug(PSTR("transport driver init fail\n")); - while(1); // Nothing more we can do +#ifdef MY_LEDS_BLINKING_FEATURE +void handleLedsBlinking() { + static unsigned long next_time = hwMillis() + MY_DEFAULT_LED_BLINK_PERIOD; + + // Just return if it is not the time... + // http://playground.arduino.cc/Code/TimingRollover + if ((long)(hwMillis() - _blink_next_time) < 0) + return; + else + _blink_next_time = hwMillis() + ledBlinkPeriod; + + // do the actual blinking + if(_countRx && _countRx != 255) { + // switch led on + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_ON); + } + else if(!_countRx) { + // switching off + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); + } + if(_countRx != 255) + --_countRx; + + if(_countTx && _countTx != 255) { + // switch led on + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_ON); + } + else if(!_countTx) { + // switching off + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); + } + if(_countTx != 255) + --_countTx; + + if(_countErr && _countErr != 255) { + // switch led on + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_ON); + } + else if(!_countErr) { + // switching off + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); + } + if(_countErr != 255) + --_countErr; +} + +void rxBlink(uint8_t cnt) { + if(_countRx == 255) { _countRx = cnt; } +} + +void txBlink(uint8_t cnt) { + if(_countTx == 255) { _countTx = cnt; } +} + +void errBlink(uint8_t cnt) { + if(_countErr == 255) { _countErr = cnt; } +} +#endif + + +void dataCallback(void (*msgCallback)(const MyMessage &)) { + _msgCallback = msgCallback; +} + +void begin() { + + #if defined(MY_INCLUSION_MODE_FEATURE) + inclusionMode = false; + #endif + + #ifndef MY_DISABLED_SERIAL + hwInit(); + #endif + + #ifdef MY_GATEWAY_FEATURE + #if defined(MY_INCLUSION_MODE_FEATURE) && defined(MY_INCLUSION_BUTTON_FEATURE) + // Setup digital in that triggers inclusion mode + pinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); + digitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); + #endif + // initialize the transport driver + if (!gatewayTransportBegin()) { + debug(PSTR("transport driver init fail\n")); + while(1); // Nothing more we can do + } + #endif + + #if defined(MY_GATEWAY_FEATURE) + gatewayTransportSend(buildGw(_msg, I_GATEWAY_READY).set("Gateway startup complete.")); + #endif + + #if defined(MY_RADIO_FEATURE) + _failedTransmissions = 0; + + // Setup radio + if (!transport.init()) { + debug(PSTR("radio init fail\n")); + while(1); // Nothing more we can do + } + #endif + + #ifdef MY_SIGNING_FEATURE + // Read out the signing requirements from EEPROM + hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(_doSign)); + #endif + +#ifdef MY_LEDS_BLINKING_FEATURE + // Setup led pins + pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); + pinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); + pinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); + + // Set initial state of leds + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); + + // initialize counters + _countRx = 0; + _countTx = 0; + _countErr = 0; +#endif + + // Read latest received controller configuration from EEPROM + hwReadConfigBlock((void*)&_cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); + if (_cc.isMetric == 0xff) { + // Eeprom empty, set default to metric + _cc.isMetric = 0x01; } - // Start MySensors in repeater mode - MySensor::begin(_msgCallback, GATEWAY_ADDRESS, true, GATEWAY_ADDRESS); + #if defined(MY_GATEWAY_FEATURE) + // Set configuration for gateway + _nc.parentNodeId = GATEWAY_ADDRESS; + _nc.distance = 0; + _nc.nodeId = GATEWAY_ADDRESS; + #else + // Read settings from eeprom + hwReadConfigBlock((void*)&_nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig)); + // Read latest received controller configuration from EEPROM + hwReadConfigBlock((void*)&_cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); + #ifdef MY_OTA_FIRMWARE_FEATURE + // Read firmware config from EEPROM, i.e. type, version, CRC, blocks + hwReadConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); + #endif - // Startup complete - transport.send(buildGw(msg, I_GATEWAY_READY).set("Gateway startup complete.")); + _autoFindParent = MY_PARENT_NODE_ID == AUTO; + if (!_autoFindParent) { + _nc.parentNodeId = MY_PARENT_NODE_ID; + // Save static parent id in eeprom (used by bootloader) + hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, MY_PARENT_NODE_ID); + // We don't actually know the distance to gw here. Let's pretend it is 1. + // If the current node is also repeater, be aware of this. + _nc.distance = 1; + } else if (!isValidParent(_nc.parentNodeId)) { + // Auto find parent, but parent in eeprom is invalid. Try find one. + findParentNode(); + } + if (MY_NODE_ID != AUTO) { + // Set static id + _nc.nodeId = MY_NODE_ID; + // Save static id in eeprom + hwWriteConfig(EEPROM_NODE_ID_ADDRESS, MY_NODE_ID); + } else if (_nc.nodeId == AUTO && isValidParent(_nc.parentNodeId)) { + // Try to fetch node-id from gateway + requestNodeId(); + } + #endif + + #if defined(MY_RADIO_FEATURE) + setupNode(); + #endif + debug(PSTR("%s started, id=%d, parent=%d, distance=%d\n"), MY_NODE_TYPE, _nc.nodeId, _nc.parentNodeId, _nc.distance); } -boolean MyGateway::sendRoute(MyMessage &message) { - if (message.destination == GATEWAY_ADDRESS) { - // This is a message sent from a sensor attached on the gateway node. - // Pass it directly to the gateway transport layer. - transport.send(message); - } else { - MySensor::sendRoute(message); - } + + + +uint8_t getNodeId() { + return _nc.nodeId; } -boolean MyGateway::process() { -#ifdef MY_INCLUSION_MODE_FEATURE - checkInclusionMode(); +ControllerConfig getConfig() { + return _cc; +} + +#if defined(MY_RADIO_FEATURE) +void requestNodeId() { + debug(PSTR("req id\n")); + transport.setAddress(_nc.nodeId); + build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set(""); + sendWrite(_nc.parentNodeId, _msg); + wait(2000); +} #endif - bool newMessage = false; - if (transport.available()) { - MyMessage &gmsg = transport.receive(); - if (msg.destination == GATEWAY_ADDRESS) { - // Check if sender requests an ack back. - if (mGetRequestAck(gmsg)) { - // Copy message - tmpMsg = gmsg; - mSetRequestAck(tmpMsg, false); // Reply without ack flag (otherwise we would end up in an eternal loop) - mSetAck(tmpMsg, true); - tmpMsg.sender = nc.nodeId; - tmpMsg.destination = msg.sender; - transport.send(tmpMsg); + +#if defined(MY_RADIO_FEATURE) + + +void setupNode() { + // Open reading pipe for messages directed to this node (set write pipe to same) + transport.setAddress(_nc.nodeId); + // Present node and request config + #ifndef MY_GATEWAY_FEATURE + if (_nc.nodeId != AUTO) { + #ifdef MY_SIGNING_FEATURE + // Notify gateway (and possibly controller) about the signing preferences of this node + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(signer.requestSignatures())); + + // If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages + if (signer.requestSignatures()) { + wait(2000); + } + #endif + + // Send presentation for this radio node + #ifdef MY_REPEATER_FEATURE + present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); + #else + present(NODE_SENSOR_ID, S_ARDUINO_NODE); + #endif + // Send a configuration exchange request to controller + // Node sends parent node. Controller answers with latest node configuration + // which is picked up in process() + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG, false).set(_nc.parentNodeId)); + + // Wait configuration reply. + wait(2000); + + #ifdef MY_OTA_FIRMWARE_FEATURE + RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)_msg.data; + mSetLength(_msg, sizeof(RequestFirmwareConfig)); + mSetCommand(_msg, C_STREAM); + mSetPayloadType(_msg,P_CUSTOM); + // copy node settings to reqFWConfig + memcpy(reqFWConfig,&_fc,sizeof(NodeFirmwareConfig)); + // add bootloader information + reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; + _fwUpdateOngoing = false; + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); + #endif + } + #endif +} +#endif + +#if defined(MY_RADIO_FEATURE) +void findParentNode() { + static boolean findingParentNode = false; + + if (findingParentNode) + return; + findingParentNode = true; + + _failedTransmissions = 0; + + // Set distance to max + _nc.distance = 255; + + // Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to) + debug(PSTR("find parent\n")); + + build(_msg, _nc.nodeId, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT, false).set(""); + // Write msg, but suppress recursive parent search + sendWrite(BROADCAST_ADDRESS, _msg); + + // Wait for ping response. + wait(2000); + findingParentNode = false; +} +#endif + + + +boolean sendRoute(MyMessage &message) { + + #if defined(MY_GATEWAY_FEATURE) + if (message.destination == _nc.nodeId) { + // This is a message sent from a sensor attached on the gateway node. + // Pass it directly to the gateway transport layer. + #ifdef MY_LEDS_BLINKING_FEATURE + txBlink(1); + #endif + return gatewayTransportSend(message); + } + #endif + + + #if defined(MY_RADIO_FEATURE) + uint8_t sender = message.sender; + uint8_t dest = message.destination; + uint8_t last = message.last; + bool ok; + + // If we still don't have any parent id, re-request and skip this message. + if (_nc.parentNodeId == AUTO) { + findParentNode(); + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return false; + } + + // If we still don't have any node id, re-request and skip this message. + if (_nc.nodeId == AUTO) { + requestNodeId(); + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return false; + } + + mSetVersion(message, PROTOCOL_VERSION); + + #ifdef MY_SIGNING_FEATURE + // If destination is known to require signed messages and we are the sender, sign this message unless it is an ACK or a handshake message + if (DO_SIGN(message.destination) && message.sender == _nc.nodeId && !mGetAck(message) && mGetLength(message) && + (mGetCommand(message) != C_INTERNAL || + (message.type != I_GET_NONCE && message.type != I_GET_NONCE_RESPONSE && message.type != I_REQUEST_SIGNING && + message.type != I_ID_REQUEST && message.type != I_ID_RESPONSE && + message.type != I_FIND_PARENT && message.type != I_FIND_PARENT_RESPONSE))) { + bool signOk = false; + // Send nonce-request + if (!sendRoute(build(_msgTmp, _nc.nodeId, message.destination, message.sensor, C_INTERNAL, I_GET_NONCE, false).set(""))) { + debug(PSTR("nonce tr err\n")); + return false; } - if (mGetCommand(gmsg) == C_INTERNAL) { - if (msg.type == I_VERSION) { - // Request for version. Create the response - transport.send(buildGw(msg, I_VERSION).set(LIBRARY_VERSION)); -#ifdef MY_INCLUSION_MODE_FEATURE - } else if (msg.type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(msg.data) == 1); + // We have to wait for the nonce to arrive before we can sign our original message + // Other messages could come in-between. We trust process() takes care of them + unsigned long enter = hwMillis(); + _msgSign = message; // Copy the message to sign since message buffer might be touched in process() + while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS) { + if (process()) { + if (mGetCommand(getLastMessage()) == C_INTERNAL && getLastMessage().type == I_GET_NONCE_RESPONSE) { + // Proceed with signing if nonce has been received + if (signer.putNonce(getLastMessage()) && signer.signMsg(_msgSign)) { + message = _msgSign; // Write the signed message back + signOk = true; + } + break; + } + } + } + if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { + debug(PSTR("nonce tmo\n")); + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return false; + } + if (!signOk) { + debug(PSTR("sign fail\n")); + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return false; + } + // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed, + // or signature will become invalid and the message rejected by the receiver + } else mSetSigned(message, 0); // Message is not supposed to be signed, make sure it is marked unsigned + #endif + + if (dest == GATEWAY_ADDRESS || !MY_IS_REPEATER) { + // Store this address in routing table (if repeater) + #if defined (MY_IS_REPEATER) + hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); + #endif + // If destination is the gateway or if we aren't a repeater, let + // our parent take care of the message + ok = sendWrite(_nc.parentNodeId, message); + } else { + // Relay the message + uint8_t route = hwReadConfig(EEPROM_ROUTES_ADDRESS+dest); + if (route > GATEWAY_ADDRESS && route < BROADCAST_ADDRESS) { + // This message should be forwarded to a child node. If we send message + // to this nodes pipe then all children will receive it because the are + // all listening to this nodes pipe. + // + // +----B + // -A + // +----C------D + // + // We're node C, Message comes from A and has destination D + // + // Message destination is not gateway and is in routing table for this node. + // Send it downstream + return sendWrite(route, message); + } else if (sender == GATEWAY_ADDRESS && dest == BROADCAST_ADDRESS) { + // Node has not yet received any id. We need to send it + // by doing a broadcast sending, + return sendWrite(BROADCAST_ADDRESS, message); + } else if (MY_IS_GATEWAY) { + // Destination isn't in our routing table and isn't a broadcast address + // Nothing to do here + return false; + } else { + // A message comes from a child node and we have no + // route for it. + // + // +----B + // -A + // +----C------D <-- Message comes from D + // + // We're node C + // + // Message should be passed to node A (this nodes relay) + + // This message should be routed back towards sensor net gateway + ok = sendWrite(_nc.parentNodeId, message); + // Add this child to our "routing table" if it not already exist + hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); + } + } + + if (!ok) { + // Failure when sending to parent node. The parent node might be down and we + // need to find another route to gateway. + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + _failedTransmissions++; + if (_autoFindParent && _failedTransmissions > SEARCH_FAILURES) { + findParentNode(); + } + } else { + _failedTransmissions = 0; + } + return ok; + #else + return false; + #endif +} + +#ifdef MY_RADIO_FEATURE +boolean sendWrite(uint8_t to, MyMessage &message) { + mSetVersion(message, PROTOCOL_VERSION); + uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message); + message.last = _nc.nodeId; + #ifdef MY_LEDS_BLINKING_FEATURE + txBlink(1); + #endif + bool ok = transport.send(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length)); + + debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,st=%s:%s\n"), + message.sender,message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, + mGetPayloadType(message), mGetLength(message), mGetSigned(message), to==BROADCAST_ADDRESS ? "bc" : (ok ? "ok":"fail"), message.getString(convBuf)); + + return ok; +} #endif + +bool send(MyMessage &message, bool enableAck) { + message.sender = _nc.nodeId; + mSetCommand(message,C_SET); + mSetRequestAck(message,enableAck); + return sendRoute(message); +} + +void sendBatteryLevel(uint8_t value, bool enableAck) { + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, enableAck).set(value)); +} + +void sendHeartbeat(void) { + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT, false).set(_heartbeat++)); + +} + +void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool enableAck) { + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, enableAck).set(childSensorId==NODE_SENSOR_ID?LIBRARY_VERSION:description)); +} + +void sendSketchInfo(const char *name, const char *version, bool enableAck) { + if (name != NULL) { + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, enableAck).set(name)); + } + if (version != NULL) { + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, enableAck).set(version)); + } +} + +void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) { + sendRoute(build(_msg, _nc.nodeId, destination, childSensorId, C_REQ, variableType, false).set("")); +} + +void requestTime(void (* timeCallback)(unsigned long)) { + _timeCallback = timeCallback; + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, false).set("")); +} + +void process() { + hwWatchdogReset(); + + #ifdef MY_LEDS_BLINKING_FEATURE + handleLedsBlinking(); + #endif + + #ifdef MY_INCLUSION_MODE_FEATURE + checkInclusionMode(); + #endif + + #if defined (MY_GATEWAY_FEATURE) + if (gatewayTransportAvailable()) { + MyMessage &_msg = gatewayTransportReceive(); + if (_msg.destination == GATEWAY_ADDRESS) { + // Check if sender requests an ack back. + if (mGetRequestAck(_msg)) { + // Copy message + _msgTmp = _msg; + mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetAck(_msgTmp, true); + _msgTmp.sender = _nc.nodeId; + _msgTmp.destination = _msg.sender; + gatewayTransportSend(_msgTmp); + } + if (mGetCommand(_msg) == C_INTERNAL) { + if (_msg.type == I_VERSION) { + // Request for version. Create the response + gatewayTransportSend(buildGw(_msg, I_VERSION).set(LIBRARY_VERSION)); + #ifdef MY_INCLUSION_MODE_FEATURE + } else if (_msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + setInclusionMode(atoi(_msg.data) == 1); + #endif } else { - processInternalMessages(gmsg); + processInternalMessages(); } } else { // Call incoming message callback if available - if (msgCallback != NULL) { - msgCallback(msg); + if (_msgCallback != NULL) { + _msgCallback(_msg); } - newMessage = true; } } } + #endif - // new message from sensor node - if (MySensor::process()) { - MyMessage &msg = MySensor::getLastMessage(); - newMessage = true; - transport.send(msg); + #if defined(MY_RADIO_FEATURE) + uint8_t to = 0; + if (!transport.available(&to)) + { + #ifdef MY_OTA_FIRMWARE_FEATURE + unsigned long enter = hwMillis(); + if (_fwUpdateOngoing && (enter - _fwLastRequestTime > MY_OTA_RETRY_DELAY)) { + if (!_fwRetry) { + debug(PSTR("fw upd fail\n")); + // Give up. We have requested MY_OTA_RETRY times without any packet in return. + _fwUpdateOngoing = false; + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return; + } + _fwRetry--; + _fwLastRequestTime = enter; + // Time to (re-)request firmware block from controller + RequestFWBlock *firmwareRequest = (RequestFWBlock *)_msg.data; + mSetLength(_msg, sizeof(RequestFWBlock)); + firmwareRequest->type = _fc.type; + firmwareRequest->version = _fc.version; + firmwareRequest->block = (_fwBlock - 1); + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false)); + } + #endif + return; } - return newMessage; + #ifdef MY_SIGNING_FEATURE + (void)signer.checkTimer(); // Manage signing timeout + #endif + + uint8_t len = transport.receive((uint8_t *)&_msg); + (void)len; //until somebody makes use of 'len' + #ifdef MY_LEDS_BLINKING_FEATURE + rxBlink(1); + #endif + + #ifdef MY_SIGNING_FEATURE + // Before processing message, reject unsigned messages if signing is required and check signature (if it is signed and addressed to us) + // Note that we do not care at all about any signature found if we do not require signing, nor do we care about ACKs (they are never signed) + if (signer.requestSignatures() && _msg.destination == _nc.nodeId && mGetLength(_msg) && !mGetAck(_msg) && + (mGetCommand(_msg) != C_INTERNAL || + (_msg.type != I_GET_NONCE_RESPONSE && _msg.type != I_GET_NONCE && _msg.type != I_REQUEST_SIGNING && + _msg.type != I_ID_REQUEST && _msg.type != I_ID_RESPONSE && + _msg.type != I_FIND_PARENT && _msg.type != I_FIND_PARENT_RESPONSE))) { + if (!mGetSigned(_msg)) { + // Got unsigned message that should have been signed + debug(PSTR("no sign\n")); + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return; + } + else if (!signer.verifyMsg(_msg)) { + debug(PSTR("verify fail\n")); + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return; // This signed message has been tampered with! + } + } + #endif + + // Add string termination, good if we later would want to print it. + _msg.data[mGetLength(_msg)] = '\0'; + debug(PSTR("read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"), + _msg.sender, _msg.last, _msg.destination, _msg.sensor, mGetCommand(_msg), _msg.type, mGetPayloadType(_msg), mGetLength(_msg), mGetSigned(_msg), _msg.getString(convBuf)); + mSetSigned(_msg,0); // Clear the sign-flag now as verification (and debug printing) is completed + + if(!(mGetVersion(_msg) == PROTOCOL_VERSION)) { + debug(PSTR("ver mismatch\n")); + #ifdef MY_LEDS_BLINKING_FEATURE + errBlink(1); + #endif + return; + } + + uint8_t command = mGetCommand(_msg); + uint8_t type = _msg.type; + uint8_t sender = _msg.sender; + uint8_t last = _msg.last; + uint8_t destination = _msg.destination; + + if (destination == _nc.nodeId) { + // This message is addressed to this node + + if (MY_IS_REPEATER && last != _nc.parentNodeId) { + // Message is from one of the child nodes. Add it to routing table. + hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); + } + + // Check if sender requests an ack back. + if (mGetRequestAck(_msg)) { + // Copy message + _msgTmp = _msg; + mSetRequestAck(_msgTmp,false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetAck(_msgTmp,true); + _msgTmp.sender = _nc.nodeId; + _msgTmp.destination = _msg.sender; + sendRoute(_msgTmp); + } + + if (command == C_INTERNAL) { + if (type == I_FIND_PARENT_RESPONSE) { + if (_autoFindParent) { + // We've received a reply to a FIND_PARENT message. Check if the distance is + // shorter than we already have. + uint8_t distance = _msg.getByte(); + if (isValidDistance(distance)) + { + // Distance to gateway is one more for us w.r.t. parent + distance++; + if (isValidDistance(distance) && (distance < _nc.distance)) { + // Found a neighbor closer to GW than previously found + _nc.distance = distance; + _nc.parentNodeId = _msg.sender; + hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, _nc.parentNodeId); + hwWriteConfig(EEPROM_DISTANCE_ADDRESS, _nc.distance); + debug(PSTR("parent=%d, d=%d\n"), _nc.parentNodeId, _nc.distance); + } + } + } + return; + #ifdef MY_SIGNING_FEATURE + } else if (type == I_GET_NONCE) { + if (signer.getNonce(_msg)) { + sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_GET_NONCE_RESPONSE, false)); + } + return false; // Nonce exchange is an internal MySensor protocol message, no need to inform caller about this + } else if (type == I_REQUEST_SIGNING) { + if (_msg.getBool()) { + // We received an indicator that the sender require us to sign all messages we send to it + SET_SIGN(_msg.sender); + } else { + // We received an indicator that the sender does not require us to sign all messages we send to it + CLEAR_SIGN(_msg.sender); + } + // Save updated table + hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(_doSign)); + + // Inform sender about our preference if we are a gateway, but only require signing if the sender required signing + // We do not currently want a gateway to require signing from all nodes in a network just because it wants one node + // to sign it's messages + if (MY_GATEWAY_FEATURE) { + if (signer.requestSignatures() && DO_SIGN(_msg.sender)) + sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(true)); + else + sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); + } + return; // Signing request is an internal MySensor protocol message, no need to inform caller about this + } else if (type == I_GET_NONCE_RESPONSE) { + return; // Just pass along nonce silently (no need to call callback for these) + #endif + } else if (sender == GATEWAY_ADDRESS) { + if (type == I_ID_RESPONSE && _nc.nodeId == AUTO) { + _nc.nodeId = _msg.getByte(); + if (_nc.nodeId == AUTO) { + // sensor net gateway will return max id if all sensor id are taken + debug(PSTR("full\n")); + while (1); // Wait here. Nothing else we can do... + } + setupNode(); + // Write id to EEPROM + hwWriteConfig(EEPROM_NODE_ID_ADDRESS, _nc.nodeId); + debug(PSTR("id=%d\n"), _nc.nodeId); + } else { + processInternalMessages(); + } + return; + } + } + #ifdef MY_OTA_FIRMWARE_FEATURE + else if (command == C_STREAM) { + if (type == ST_FIRMWARE_CONFIG_RESPONSE) { + NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)_msg.data; + // compare with current node configuration, if they differ, start fw fetch process + if (memcmp(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) { + debug(PSTR("fw update\n")); + // copy new FW config + memcpy(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig)); + // Init flash + if (!flash.initialize()) { + debug(PSTR("flash init fail\n")); + _fwUpdateOngoing = false; + } else { + // erase lower 32K -> max flash size for ATMEGA328 + flash.blockErase32K(0); + // wait until flash erased + while ( flash.busy() ); + _fwBlock = _fc.blocks; + _fwUpdateOngoing = true; + // reset flags + _fwRetry = MY_OTA_RETRY+1; + _fwLastRequestTime = 0; + } + return ; + } else debug(PSTR("fw update skipped\n")); + } else if (type == ST_FIRMWARE_RESPONSE) { + if (_fwUpdateOngoing) { + // Save block to flash + debug(PSTR("fw block %d\n"), _fwBlock); + // extract FW block + ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)_msg.data; + // write to flash + flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); + // wait until flash written + while ( flash.busy() ); + _fwBlock--; + if (!_fwBlock) { + // We're finished! Do a checksum and reboot. + _fwUpdateOngoing = false; + if (isValidFirmware()) { + debug(PSTR("fw checksum ok\n")); + // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) + uint16_t fwsize = FIRMWARE_BLOCK_SIZE * _fc.blocks; + uint8_t OTAbuffer[10] = {'F','L','X','I','M','G',':',(fwsize >> 8),fwsize,':'}; + flash.writeBytes(0, OTAbuffer, 10); + // Write the new firmware config to eeprom + hwWriteConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); + hwReboot(); + } else { + debug(PSTR("fw checksum fail\n")); + } + } + // reset flags + _fwRetry = MY_OTA_RETRY+1; + _fwLastRequestTime = 0; + } else { + debug(PSTR("No fw update ongoing\n")); + } + return; + } + + } + #endif + // Call incoming message callback if available + if (_msgCallback != NULL) { + _msgCallback(_msg); + } + return; + } else if (MY_IS_REPEATER && _nc.nodeId != AUTO) { + // If this node have an id, relay the message + if (command == C_INTERNAL && type == I_FIND_PARENT) { + if (sender != _nc.parentNodeId) { + if (_nc.distance == DISTANCE_INVALID) + findParentNode(); + + if (_nc.distance != DISTANCE_INVALID) { + // Relaying nodes should always answer ping messages + // Wait a random delay of 0-2 seconds to minimize collision + // between ping ack messages from other relaying nodes + wait(hwMillis() & 0x3ff); + sendWrite(sender, build(_msg, _nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false).set(_nc.distance)); + } + } + } else if (to == _nc.nodeId) { + // We should try to relay this message to another node + sendRoute(_msg); + } + } + #endif } + +void processInternalMessages() { + bool isMetric; + uint8_t type = _msg.type; + + if (type == I_REBOOT) { + // Requires MySensors or other bootloader with watchdogs enabled + hwReboot(); + } else if (type == I_CONFIG) { + // Pick up configuration from controller (currently only metric/imperial) + // and store it in eeprom if changed + isMetric = _msg.getString()[0] == 'M' ; + _cc.isMetric = isMetric; + hwWriteConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); + } else if (type == I_CHILDREN) { + if (MY_IS_REPEATER && _msg.getString()[0] == 'C') { + // Clears child relay data for this node + debug(PSTR("clear\n")); + uint8_t i = 255; + do { + hwWriteConfig(EEPROM_ROUTES_ADDRESS+i, 0xff); + } while (i--); + // Clear parent node id & distance to gw + hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF); + hwWriteConfig(EEPROM_DISTANCE_ADDRESS, 0xFF); + // Find parent node + findParentNode(); + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); + } + } else if (type == I_TIME) { + if (_timeCallback != NULL) { + // Deliver time to callback + _timeCallback(_msg.getULong()); + } + } +} + + +#if defined (MY_REPEATER_FEATURE) +void saveState(uint8_t pos, uint8_t value) { + hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); +} +uint8_t loadState(uint8_t pos) { + return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos); +} +#endif + +void wait(unsigned long ms) { + unsigned long enter = hwMillis(); + while (hwMillis() - enter < ms) { + process(); + } +} + +void sleep(unsigned long ms) { + #if defined(MY_OTA_FIRMWARE_FEATURE) + if (_fwUpdateOngoing) { + // Do not sleep node while fw update is ongoing + process(); + } else { + #endif + #if defined(MY_RADIO_FEATURE) + transport.powerDown(); + #endif + hwSleep(ms); + #if defined(MY_OTA_FIRMWARE_FEATURE) + } + #endif +} + +bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { + #if defined(MY_OTA_FIRMWARE_FEATURE) + if (_fwUpdateOngoing) { + // Do not sleep node while fw update is ongoing + process(); + return false; + } else { + #endif + #if defined(MY_RADIO_FEATURE) + transport.powerDown(); + #endif + return hwSleep(interrupt, mode, ms) ; + #if defined(MY_OTA_FIRMWARE_FEATURE) + } + #endif +} + +int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) { + #if defined(MY_OTA_FIRMWARE_FEATURE) + if (_fwUpdateOngoing) { + // Do not sleep node while fw update is ongoing + process(); + return -1; + } else { + #endif + #if defined(MY_RADIO_FEATURE) + transport.powerDown(); + #endif + return hwSleep(interrupt1, mode1, interrupt2, mode2, ms) ; + #if defined(MY_OTA_FIRMWARE_FEATURE) + } + #endif +} + + #ifdef MY_INCLUSION_MODE_FEATURE -void MyGateway::setInclusionMode(boolean newMode) { +void setInclusionMode(boolean newMode) { if (newMode != inclusionMode) { inclusionMode = newMode; // Send back mode change to controller - transport.send(buildGw(msg, I_INCLUSION_MODE).set(inclusionMode?1:0)); + gatewayTransportSend(buildGw(_msg, I_INCLUSION_MODE).set(inclusionMode?1:0)); if (inclusionMode) { - inclusionStartTime = hw_millis(); + inclusionStartTime = hwMillis(); } } } -void MyGateway::checkInclusionMode() { - +void checkInclusionMode() { #ifdef MY_INCLUSION_BUTTON_FEATURE if (!inclusionMode && digitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == LOW) { // Start inclusion mode @@ -1026,7 +1049,7 @@ void MyGateway::checkInclusionMode() { } #endif - if (inclusionMode && hw_millis()-inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { + if (inclusionMode && hwMillis()-inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode setInclusionMode(false); } diff --git a/libraries/MySensors/core/MySensorCore.h b/libraries/MySensors/core/MySensorCore.h index 5636b29..6deb634 100644 --- a/libraries/MySensors/core/MySensorCore.h +++ b/libraries/MySensors/core/MySensorCore.h @@ -23,9 +23,7 @@ #include "Version.h" // Auto generated by bot #include "MyConfig.h" -#include "MyHw.h" #include "MyTransport.h" -#include "MyTransportNRF24.h" #ifdef MY_SIGNING_FEATURE #include "MySigning.h" #include "MySigningNone.h" @@ -35,25 +33,14 @@ #include "drivers/SPIFlash/SPIFlash.h" #endif -#include "MyGatewayTransport.h" -#include "MyGatewayTransportSerial.h" - #include #include -// Set the hardware driver to use (initialized by MySensor-class) -#if defined(ARDUINO_ARCH_ESP8266) -#include "MyHwESP8266.h" -typedef MyHwESP8266 MyHwDriver; -#elif defined(ARDUINO_ARCH_AVR) -#include "MyHwATMega328.h" -typedef MyHwATMega328 MyHwDriver; -#endif #ifdef MY_DEBUG -#define debug(x,...) hw.debugPrint(isGateway, x, ##__VA_ARGS__) +#define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) #else #define debug(x,...) #endif @@ -146,179 +133,165 @@ typedef struct { } __attribute__((packed)) ReplyFWBlock; -#ifdef __cplusplus -class MySensor -{ - public: - /** - * Constructor - * - * Creates a new instance of Sensor class. - * - */ - MySensor(MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() -#ifdef MY_SIGNING_FEATURE - , MySigning &signer=*new MySigningNone() -#endif - ); - /** - * Begin operation of the MySensors library - * - * Call this in setup(), before calling any other sensor net library methods. - * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. - * @param nodeId The unique id (1-254) for this sensor. Default is AUTO(255) which means sensor tries to fetch an id from controller. - * @param repeaterMode Activate repeater mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false - * @param parentNodeId Use this to force node to always communicate with a certain parent node. Default is AUTO which means node automatically tries to find a parent. - */ - - void begin(void (* msgCallback)(const MyMessage &)=NULL, uint8_t nodeId=AUTO, boolean repeaterMode=false, uint8_t parentNodeId=AUTO); - - /** - * Return the nodes nodeId. - */ - uint8_t getNodeId(); - - /** - * Each node must present all attached sensors before any values can be handled correctly by the controller. - * It is usually good to present all attached sensors after power-up in setup(). - * - * @param sensorId Select a unique sensor id for this sensor. Choose a number between 0-254. - * @param sensorType The sensor type. See sensor typedef in MyMessage.h. - * @param description A textual description of the sensor. - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * @param description A textual description of the sensor. - */ - void present(uint8_t sensorId, uint8_t sensorType, const char *description="", bool ack=false); - - /** - * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. - * @param name String containing a short Sketch name or NULL if not applicable - * @param version String containing a short Sketch version or NULL if not applicable - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * - */ - void sendSketchInfo(const char *name, const char *version, bool ack=false); - - /** - * Sends a message to gateway or one of the other nodes in the radio network - * - * @param msg Message to send - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * @return true Returns true if message reached the first stop on its way to destination. - */ - bool send(MyMessage &msg, bool ack=false); +/** +* Begin operation of the MySensors library +* +* Call this in setup(), before calling any other sensor net library methods. +* @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. +*/ - /** - * Send this nodes battery level to gateway. - * @param level Level between 0-100(%) - * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. - * - */ - void sendBatteryLevel(uint8_t level, bool ack=false); +void dataCallback(void (* msgCallback)(const MyMessage &)=NULL); - /** - * Send a heartbeat message (I'm alive!) to the gateway/controller. - * The payload will be an incremental 16 bit integer value starting at 1 when sensor is powered on. - */ - void sendHeartbeat(void); +/** + * Return the nodes nodeId. + */ +uint8_t getNodeId(); - /** - * Requests a value from gateway or some other sensor in the radio network. - * Make sure to add callback-method in begin-method to handle request responses. - * - * @param childSensorId The unique child id for the different sensors connected to this Arduino. 0-254. - * @param variableType The variableType to fetch - * @param destination The nodeId of other node in radio network. Default is gateway - */ - void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination=GATEWAY_ADDRESS); +/** +* Each node must present all attached sensors before any values can be handled correctly by the controller. +* It is usually good to present all attached sensors after power-up in setup(). +* +* @param sensorId Select a unique sensor id for this sensor. Choose a number between 0-254. +* @param sensorType The sensor type. See sensor typedef in MyMessage.h. +* @param description A textual description of the sensor. +* @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. +* @param description A textual description of the sensor. +*/ +void present(uint8_t sensorId, uint8_t sensorType, const char *description="", bool ack=false); - /** - * Requests time from controller. Answer will be delivered to callback. - * - * @param callback for time request. Incoming argument is seconds since 1970. - */ - void requestTime(void (* timeCallback)(unsigned long)); +/** + * Sends sketch meta information to the gateway. Not mandatory but a nice thing to do. + * @param name String containing a short Sketch name or NULL if not applicable + * @param version String containing a short Sketch version or NULL if not applicable + * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. + * + */ +void sendSketchInfo(const char *name, const char *version, bool ack=false); + +/** +* Sends a message to gateway or one of the other nodes in the radio network +* +* @param msg Message to send +* @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. +* @return true Returns true if message reached the first stop on its way to destination. +*/ +bool send(MyMessage &msg, bool ack=false); - /** - * Processes incoming messages to this node. If this is a relaying node it will - * Returns true if there is a message addressed for this node just was received. - * Use callback to handle incoming messages. - */ - boolean process(); +/** + * Send this nodes battery level to gateway. + * @param level Level between 0-100(%) + * @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack. + * + */ +void sendBatteryLevel(uint8_t level, bool ack=false); - /** - * Returns the most recent node configuration received from controller - */ - ControllerConfig getConfig(); +/** + * Send a heartbeat message (I'm alive!) to the gateway/controller. + * The payload will be an incremental 16 bit integer value starting at 1 when sensor is powered on. + */ +void sendHeartbeat(void); - /** - * Save a state (in local EEPROM). Good for actuators to "remember" state between - * power cycles. - * - * You have 256 bytes to play with. Note that there is a limitation on the number - * of writes the EEPROM can handle (~100 000 cycles on ATMega328). - * - * @param pos The position to store value in (0-255) - * @param Value to store in position - */ - void saveState(uint8_t pos, uint8_t value); +/** +* Requests a value from gateway or some other sensor in the radio network. +* Make sure to add callback-method in begin-method to handle request responses. +* +* @param childSensorId The unique child id for the different sensors connected to this Arduino. 0-254. +* @param variableType The variableType to fetch +* @param destination The nodeId of other node in radio network. Default is gateway +*/ +void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination=GATEWAY_ADDRESS); - /** - * Load a state (from local EEPROM). - * - * @param pos The position to fetch value from (0-255) - * @return Value to store in position - */ - uint8_t loadState(uint8_t pos); - - /** - * Returns the last received message - */ - MyMessage& getLastMessage(void); +/** + * Requests time from controller. Answer will be delivered to callback. + * + * @param callback for time request. Incoming argument is seconds since 1970. + */ +void requestTime(void (* timeCallback)(unsigned long)); - /** - * Wait for a specified amount of time to pass. Keeps process()ing. - * This does not power-down the radio nor the Arduino. - * Because this calls process() in a loop, it is a good way to wait - * in your loop() on a repeater node or sensor that listens to messages. - * @param ms Number of milliseconds to sleep. - */ - void wait(unsigned long ms); +/** + * Returns the most recent node configuration received from controller + */ +ControllerConfig getConfig(); - /** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. - * @param ms Number of milliseconds to sleep. - */ - void sleep(unsigned long ms); +/** + * Save a state (in local EEPROM). Good for actuators to "remember" state between + * power cycles. + * + * You have 256 bytes to play with. Note that there is a limitation on the number + * of writes the EEPROM can handle (~100 000 cycles on ATMega328). + * + * @param pos The position to store value in (0-255) + * @param Value to store in position + */ +void saveState(uint8_t pos, uint8_t value); - /** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change. - * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin - * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 - * @param interrupt Interrupt that should trigger the wakeup - * @param mode RISING, FALLING, CHANGE - * @param ms Number of milliseconds to sleep or 0 to sleep forever - * @return true if wake up was triggered by pin change and false means timer woke it up. - */ - bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); +/** + * Load a state (from local EEPROM). + * + * @param pos The position to fetch value from (0-255) + * @return Value to store in position + */ +uint8_t loadState(uint8_t pos); - /** - * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. - * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin - * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 - * @param interrupt1 First interrupt that should trigger the wakeup - * @param mode1 Mode for first interrupt (RISING, FALLING, CHANGE) - * @param interrupt2 Second interrupt that should trigger the wakeup - * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) - * @param ms Number of milliseconds to sleep or 0 to sleep forever - * @return Interrupt number wake up was triggered by pin change and negative if timer woke it up. - */ - int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); +/** +* Returns the last received message +*/ +MyMessage& getLastMessage(void); + + + +/** + * Wait for a specified amount of time to pass. Keeps process()ing. + * This does not power-down the radio nor the Arduino. + * Because this calls process() in a loop, it is a good way to wait + * in your loop() on a repeater node or sensor that listens to messages. + * @param ms Number of milliseconds to sleep. + */ +void wait(unsigned long ms); + +/** + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer. + * @param ms Number of milliseconds to sleep. + */ +void sleep(unsigned long ms); + +/** + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change. + * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin + * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 + * @param interrupt Interrupt that should trigger the wakeup + * @param mode RISING, FALLING, CHANGE + * @param ms Number of milliseconds to sleep or 0 to sleep forever + * @return true if wake up was triggered by pin change and false means timer woke it up. + */ +bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); + +/** + * Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts. + * See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin + * is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3 + * @param interrupt1 First interrupt that should trigger the wakeup + * @param mode1 Mode for first interrupt (RISING, FALLING, CHANGE) + * @param interrupt2 Second interrupt that should trigger the wakeup + * @param mode2 Mode for second interrupt (RISING, FALLING, CHANGE) + * @param ms Number of milliseconds to sleep or 0 to sleep forever + * @return Interrupt number wake up was triggered by pin change and negative if timer woke it up. + */ +int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); + + + +/****** PRIVATE ********/ +void begin(); + +void process(void); + +void processInternalMessages(); #ifdef MY_LEDS_BLINKING_FEATURE /** @@ -328,121 +301,31 @@ class MySensor void rxBlink(uint8_t cnt); void txBlink(uint8_t cnt); void errBlink(uint8_t cnt); -#endif - - boolean sendRoute(MyMessage &message); - - protected: - NodeConfig nc; // Essential settings for node to work - ControllerConfig cc; // Configuration coming from controller -#ifdef MY_OTA_FIRMWARE_FEATURE - NodeFirmwareConfig fc; - bool fwUpdateOngoing; - unsigned long fwLastRequestTime; - uint16_t fwBlock; - uint8_t fwRetry; - SPIFlash flash; -#endif - - bool repeaterMode; - bool autoFindParent; - bool isGateway; - - MyMessage msg; // Buffer for incoming messages. - MyMessage tmpMsg ; // Buffer for temporary messages (acks and nonces among others). - -#ifdef MY_LEDS_BLINKING_FEATURE - // these variables don't need to be volatile, since we are not using interrupts - uint8_t countRx; - uint8_t countTx; - uint8_t countErr; - void handleLedsBlinking(); // do the actual blinking - unsigned long blink_next_time; #endif - MyTransport& radio; -#ifdef MY_SIGNING_FEATURE - uint16_t doSign[16]; // Bitfield indicating which sensors require signed communication - MyMessage msgSign; // Buffer for message to sign. - MySigning& signer; -#endif - MyHw& hw; - - boolean sendWrite(uint8_t dest, MyMessage &message); - void processInternalMessages(MyMessage &msg); -#ifdef MY_DEBUG - char convBuf[MAX_PAYLOAD*2+1]; -#endif - uint8_t failedTransmissions; - uint16_t heartbeat; - void (*timeCallback)(unsigned long); // Callback for requested time messages - void (*msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. - #ifdef MY_OTA_FIRMWARE_FEATURE -// do a crc16 on the whole received firmware - bool isValidFirmware(); + // do a crc16 on the whole received firmware + bool isValidFirmware(); #endif - private: - - void requestNodeId(); - void setupNode(); - void findParentNode(); - uint8_t crc8Message(MyMessage &message); -}; -#endif - - -class MyGateway : public MySensor -{ -public: - // MyProtocolSerial constructor - MyGateway(MyGatewayTransport &transport=*new MyGatewayTransportSerial(), MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver() -#ifdef MY_SIGNING_FEATURE - , MySigning &signer=*new MySigningNone() -#endif - ); - - - /** - * Begin operation of the MySensors library - * - * Call this in setup(), before calling any other sensor net library methods. - * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. - * @param inclusionModeDuration Number of milliseconds inclusion mode should be enabled - * @param inclusionModeButtonPin Button pin used for enabling inclusion mode - */ - - void begin(void (* msgCallback)(const MyMessage &)=NULL); - - - /** - * See MySensor.h - * - * Overloaded to handle local sensor data sent to controller. - */ - boolean sendRoute(MyMessage &message); - - /** - * Processes incoming messages to this node. - * Returns true if there is a message addressed for this node was received. - * Preferred way of handling incoming messages is to use the callback defined in begin(). - */ - boolean process(); - -private: - - MyGatewayTransport& transport; #ifdef MY_INCLUSION_MODE_FEATURE - void setInclusionMode(bool newMode); void checkInclusionMode(); unsigned long inclusionStartTime; bool inclusionMode; #endif -}; + + +boolean sendRoute(MyMessage &message); +#if defined(MY_RADIO_FEATURE) + boolean sendWrite(uint8_t dest, MyMessage &message); + void requestNodeId(); + void setupNode(); + void findParentNode(); +#endif + #endif diff --git a/libraries/MySensors/core/MyTransportNRF24.cpp b/libraries/MySensors/core/MyTransportNRF24.cpp index d11545d..5affb12 100644 --- a/libraries/MySensors/core/MyTransportNRF24.cpp +++ b/libraries/MySensors/core/MyTransportNRF24.cpp @@ -20,11 +20,10 @@ #include "MyTransport.h" #include "MyTransportNRF24.h" -MyTransportNRF24::MyTransportNRF24(uint8_t ce, uint8_t cs, uint8_t paLevel) +MyTransportNRF24::MyTransportNRF24() : MyTransport(), - rf24(ce, cs), - _paLevel(paLevel) + rf24(MY_RF24_CE_PIN, MY_RF24_CS_PIN) { } @@ -38,9 +37,9 @@ bool MyTransportNRF24::init() { rf24.setAutoAck(1); rf24.setAutoAck(BROADCAST_PIPE,false); // Turn off auto ack for broadcast rf24.enableAckPayload(); - rf24.setChannel(RF24_CHANNEL); + rf24.setChannel(MY_RF24_CHANNEL); rf24.setPALevel(_paLevel); - rf24.setDataRate(RF24_DATARATE); + rf24.setDataRate(MY_RF24_DATARATE); rf24.setRetries(5,15); rf24.setCRCLength(RF24_CRC_16); rf24.enableDynamicPayloads(); diff --git a/libraries/MySensors/core/MyTransportNRF24.h b/libraries/MySensors/core/MyTransportNRF24.h index 535186d..d8a7b81 100644 --- a/libraries/MySensors/core/MyTransportNRF24.h +++ b/libraries/MySensors/core/MyTransportNRF24.h @@ -26,7 +26,7 @@ #include "drivers/RF24/RF24.h" #include "drivers/RF24/RF24_config.h" -#define TO_ADDR(x) (RF24_BASE_RADIO_ID + x) +#define TO_ADDR(x) (MY_RF24_BASE_RADIO_ID + x) #define WRITE_PIPE ((uint8_t)0) #define CURRENT_NODE_PIPE ((uint8_t)1) @@ -35,7 +35,7 @@ class MyTransportNRF24 : public MyTransport { public: - MyTransportNRF24(uint8_t ce=RF24_CE_PIN, uint8_t cs=RF24_CS_PIN, uint8_t paLevel=RF24_PA_LEVEL); + MyTransportNRF24(); bool init(); void setAddress(uint8_t address); uint8_t getAddress(); diff --git a/libraries/MySensors/core/MyTransportRFM69.cpp b/libraries/MySensors/core/MyTransportRFM69.cpp index ca29585..30e923e 100644 --- a/libraries/MySensors/core/MyTransportRFM69.cpp +++ b/libraries/MySensors/core/MyTransportRFM69.cpp @@ -20,18 +20,16 @@ #include "MyTransport.h" #include "MyTransportRFM69.h" -MyTransportRFM69::MyTransportRFM69(uint8_t freqBand, uint8_t networkId, uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, uint8_t interruptNum) +MyTransportRFM69::MyTransportRFM69() : MyTransport(), - radio(slaveSelectPin, interruptPin, isRFM69HW, interruptNum), - _freqBand(freqBand), - _networkId(networkId) + radio(MY_RF69_SPI_CS, MY_RF69_IRQ_PIN, MY_IS_RFM69HW, MY_RF69_IRQ_NUM) { } bool MyTransportRFM69::init() { // Start up the radio library (_address will be set later by the MySensors library) - radio.initialize(_freqBand, _address, _networkId); + radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID); #ifdef MY_RFM69_ENABLE_ENCRYPTION radio.encrypt(RFM69_ENCRYPTKEY); #endif diff --git a/libraries/MySensors/core/MyTransportRFM69.h b/libraries/MySensors/core/MyTransportRFM69.h index affbb25..1336d1e 100644 --- a/libraries/MySensors/core/MyTransportRFM69.h +++ b/libraries/MySensors/core/MyTransportRFM69.h @@ -30,7 +30,7 @@ class MyTransportRFM69 : public MyTransport { public: - MyTransportRFM69(uint8_t freqBand=MY_RFM69_FREQUENCY, uint8_t networkId=MY_RFM69_NETWORKID, uint8_t slaveSelectPin=MY_RF69_SPI_CS, uint8_t interruptPin=MY_RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=MY_RF69_IRQ_NUM); + MyTransportRFM69(); bool init(); void setAddress(uint8_t address); uint8_t getAddress(); @@ -41,8 +41,6 @@ public: private: RFM69 radio; uint8_t _address; - uint8_t _freqBand; - uint8_t _networkId; }; #endif diff --git a/libraries/MySensors/drivers/DigitalIO/DigitalIO.h b/libraries/MySensors/drivers/DigitalIO/DigitalIO.h index 8f47bf1..f984ef8 100644 --- a/libraries/MySensors/drivers/DigitalIO/DigitalIO.h +++ b/libraries/MySensors/drivers/DigitalIO/DigitalIO.h @@ -28,9 +28,9 @@ /** DigitalPin version YYYYMMDD */ #define DIGITAL_IO_VERSION 20140217 //------------------------------------------------------------------------------ -#include -#include -#include -#include -#include -#endif // DigitalIO_h \ No newline at end of file +#include "DigitalPin.h" +#include "I2cConstants.h" +#include "PinIO.h" +#include "SoftI2cMaster.h" +#include "SoftSPI.h" +#endif // DigitalIO_h diff --git a/libraries/MySensors/drivers/DigitalIO/PinIO.cpp b/libraries/MySensors/drivers/DigitalIO/PinIO.cpp index b0367b7..5f1ff52 100644 --- a/libraries/MySensors/drivers/DigitalIO/PinIO.cpp +++ b/libraries/MySensors/drivers/DigitalIO/PinIO.cpp @@ -25,7 +25,7 @@ * @details Two Wire Interface library. * @{ */ -#include +#include "PinIO.h" #include #include //============================================================================== @@ -65,4 +65,4 @@ void PinIO::config(bool mode, bool data) { writeI(data); } } -/** @} */ \ No newline at end of file +/** @} */ diff --git a/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp b/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp index a698636..d02b2bb 100644 --- a/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp +++ b/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp @@ -25,7 +25,7 @@ * @details Software Two Wire Interface library. * @{ */ -#include +#include "SoftI2cMaster.h" //------------------------------------------------------------------------------ /** * Start an I2C transfer with possible continuation. diff --git a/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h b/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h index 7bf3c00..33e11fc 100644 --- a/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h +++ b/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h @@ -33,8 +33,8 @@ #include #endif // ARDUINO #include -#include -#include +#include "DigitalPin.h" +#include "I2cConstants.h" //------------------------------------------------------------------------------ // State codes. diff --git a/libraries/MySensors/drivers/DigitalIO/SoftSPI.h b/libraries/MySensors/drivers/DigitalIO/SoftSPI.h index 036fad6..f51f210 100644 --- a/libraries/MySensors/drivers/DigitalIO/SoftSPI.h +++ b/libraries/MySensors/drivers/DigitalIO/SoftSPI.h @@ -28,7 +28,7 @@ #ifndef SoftSPI_h #define SoftSPI_h -#include +#include "DigitalPin.h" //------------------------------------------------------------------------------ /** Nop for timing. */ #define nop asm volatile ("nop\n\t") diff --git a/libraries/MySensors/drivers/RF24/RF24.cpp b/libraries/MySensors/drivers/RF24/RF24.cpp index 16bff15..d78c875 100644 --- a/libraries/MySensors/drivers/RF24/RF24.cpp +++ b/libraries/MySensors/drivers/RF24/RF24.cpp @@ -19,7 +19,7 @@ void RF24::csn(bool mode) // divider of 4 is the minimum we want. // CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz #ifdef ARDUINO - #if ( !defined(RF24_TINY) && !defined (__arm__) && !defined (SOFTSPI)) || defined (CORE_TEENSY) + #if ( !defined(RF24_TINY) && !defined (__arm__) && !defined (MY_SOFTSPI)) || defined (CORE_TEENSY) _SPI.setBitOrder(MSBFIRST); _SPI.setDataMode(SPI_MODE0); _SPI.setClockDivider(SPI_CLOCK_DIV2); diff --git a/libraries/MySensors/drivers/RF24/RF24_config.h b/libraries/MySensors/drivers/RF24/RF24_config.h index d8c8016..08a23cc 100644 --- a/libraries/MySensors/drivers/RF24/RF24_config.h +++ b/libraries/MySensors/drivers/RF24/RF24_config.h @@ -26,7 +26,7 @@ //#define SERIAL_DEBUG #define MINIMAL //#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART - //#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO + //#define MY_SOFTSPI // Requires library from https://github.com/greiman/DigitalIO /**********************/ // Define _BV for non-Arduino platforms and for Arduino DUE diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index c5e10a4..34ee906 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -56,15 +56,61 @@ * */ +// Enable debug prints to console +#define MY_DEBUG +// This node has a NR24L01+ radio attached +#define MY_RADIO_NRF24 + + +// W5100 Ethernet in client mode (node opens conmection to controller) +#define MY_GATEWAY_W5100_CLIENT +// W5100 Ethernet in client mode (controller opens conmection to node) +//#define MY_GATEWAY_W5100_SERVER + +// Set default gateway protocol (http://www.mysensors.org/download/serial_api_15) +#define MY_GATEWAY_PROTOCOL_DEFAULT + +// Enable Soft SPI for radio (note different radio wiring required) +// Useful for W5100 which sometimes have hard time co-operate with radio on the same spi bus. +//#define MY_SOFTSPI +//#define MY_SOFT_SPI_SCK_PIN 14 +//#define MY_SOFT_SPI_MISO_PIN 16 +//#define MY_SOFT_SPI_MOSI_PIN 15 + + +// Enable to use UDP +#define MY_USE_UDP + +#define MY_IP_ADDRESS 192,168,178,66 // If this is disabled, DHCP is used to retrieve address +// Renewal period if using DHCP +//#define MY_IP_RENEWAL_INTERVAL 60000 +// The port to keep open on node server mode / or port to contact in client mode +#define MY_PORT 5003 + +// Controller ip address (client mode) +#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 +// The port you want to contact on controller (client mode) +#define MY_CONTROLLER_PORT 5003 + +// The MAC address can be anything you want but should be unique on your network. +// Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. +// Note that most of the Ardunio examples use "DEAD BEEF FEED" for the MAC address. +#define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED + +// Flash leds on rx/tx/err #define MY_WITH_LEDS_BLINKING -#define MY_INCLUSION_MODE_FEATURE -#define MY_INCLUSION_BUTTON_FEATURE - +// Set blinking period #define MY_DEFAULT_LED_BLINK_PERIOD 300 -#define MY_INCLUSION_MODE_DURATION 60 // Number of minutes inclusion mode is enabled -#define MY_INCLUSION_MODE_BUTTON_PIN 3 // Digital pin used for inclusion mode button +// Enable inclusion mode +#define MY_INCLUSION_MODE_FEATURE +// Enable Inclusion mode button on gateway +#define MY_INCLUSION_BUTTON_FEATURE +// Set inclusion mode duration (in seconds) +#define MY_INCLUSION_MODE_DURATION 60 +// Digital pin used for inclusion mode button +#define MY_INCLUSION_MODE_BUTTON_PIN 3 #define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin #define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin @@ -76,53 +122,11 @@ #include -#define MY_IP_PORT 5003 // The port you want to open -#ifndef MY_IP_ADDRESS_DHCP -// Gateway IP address if not using DHCP -IPAddress myIp (192, 168, 178, 66); // Configure your static ip-address here COMPILE ERROR HERE? Use Arduino IDE 1.5.7 or later! -#endif /* IP_ADDRESS_DHCP */ - -// NRFRF24L01 radio driver (set low transmit power by default) -MyTransportNRF24 transport(RADIO_CE_PIN, RADIO_SPI_SS_PIN, RF24_PA_LEVEL_GW); -//MyTransportRFM69 transport; - -// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) -//MySigningNone signer; -//MySigningAtsha204Soft signer; -//MySigningAtsha204 signer; - -// Hardware profile -MyHwATMega328 hw; - -// Use default controller protocol -MyProtocolDefault protocol; - -// The MAC address can be anything you want but should be unique on your network. -// Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. -// Note that most of the Ardunio examples use "DEAD BEEF FEED" for the MAC address. -byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // DEAD BEEF FEED - -// Controller IP -IPAddress controllerIP = IPAddress(192, 168, 178, 254); - -// Gateway transport driver -#ifdef IP_ADDRESS_DHCP -MyGatewayTransportEthernet ctrlTransport(protocol, mac, /* gw port */ CONTROLLER_PORT, IP_RENEWAL_INTERVAL, controllerIP, CONTROLLER_PORT); -#else -MyGatewayTransportEthernet ctrlTransport(protocol, mac, myIp, /* gw port */ CONTROLLER_PORT, controllerIP, CONTROLLER_PORT); -#endif - - -// Construct MyGateway library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) -// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h -MyGateway gw(ctrlTransport, transport, hw /*, signer*/); - void setup() { - gw.begin(NULL); + dataCallback(); } void loop() { - gw.process(); } diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino index a0d734b..099226f 100644 --- a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -28,8 +28,14 @@ */ //#define MY_DEBUG +//#define MY_SOFTSPI +//#define MY_OTA_FIRMWARE_FEATURE + +#define MY_RADIO_NRF24 // MY_RADIO_RFM69 + +#include + -#include "MySensor.h" unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds) #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your motion sensor. (Only 2 and 3 generates interrupt!) @@ -43,14 +49,14 @@ MyMessage msg(CHILD_ID, V_TRIPPED); void setup() { - gw.begin(); + dataDallback(); // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Motion Sensor", "1.0"); + sendSketchInfo("Motion Sensor", "1.0"); pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input // Register all sensors to gw (they will be created as child devices) - gw.present(CHILD_ID, S_MOTION); + present(CHILD_ID, S_MOTION); } @@ -60,10 +66,10 @@ void loop() boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; Serial.println(tripped); - gw.send(msg.set(tripped?"1":"0")); // Send tripped value to gw + send(msg.set(tripped?"1":"0")); // Send tripped value to gw // Sleep until interrupt comes in on motion sensor. Send update every two minute. - gw.sleep(INTERRUPT,CHANGE, SLEEP_TIME); + sleep(INTERRUPT,CHANGE, SLEEP_TIME); } From 050782e1e6aa1a09b4e2346237f210154b8f17f9 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Sun, 13 Sep 2015 18:11:49 +0200 Subject: [PATCH 11/43] ESP libraries --- libraries/MySensors/MySensor.h | 36 +- .../{MyTransport.cpp => MyGatewayTransport.h} | 28 +- .../core/MyGatewayTransportEthernet.cpp | 4 +- .../core/MyGatewayTransportEthernet.h | 19 +- .../core/MyGatewayTransportSerial.cpp | 33 +- .../MySensors/core/MyGatewayTransportSerial.h | 24 +- libraries/MySensors/core/MyHw.h | 53 + libraries/MySensors/core/MyHwATMega328.h | 11 +- libraries/MySensors/core/MyHwESP8266.cpp | 18 +- libraries/MySensors/core/MyHwESP8266.h | 31 +- libraries/MySensors/core/MyProtocol.h | 18 +- .../MySensors/core/MyProtocolDefault.cpp | 16 +- libraries/MySensors/core/MyProtocolDefault.h | 14 +- libraries/MySensors/core/MySensorCore.cpp | 32 +- libraries/MySensors/core/MySensorCore.h | 1 - libraries/MySensors/core/MyTransport.h | 32 - libraries/MySensors/core/MyTransportNRF24.cpp | 74 +- libraries/MySensors/core/MyTransportNRF24.h | 23 +- libraries/MySensors/core/MyTransportRFM69.cpp | 47 +- libraries/MySensors/core/MyTransportRFM69.h | 22 +- .../drivers/{ => AVR}/DigitalIO/DigitalIO.h | 0 .../drivers/{ => AVR}/DigitalIO/DigitalPin.h | 0 .../{ => AVR}/DigitalIO/I2cConstants.h | 0 .../drivers/{ => AVR}/DigitalIO/PinIO.cpp | 0 .../drivers/{ => AVR}/DigitalIO/PinIO.h | 0 .../{ => AVR}/DigitalIO/SoftI2cMaster.cpp | 0 .../{ => AVR}/DigitalIO/SoftI2cMaster.h | 0 .../drivers/{ => AVR}/DigitalIO/SoftSPI.h | 0 .../{ => AVR}/DigitalIO/attic/ADS7818.h | 0 .../{ => AVR}/DigitalIO/attic/MCP320X.h | 0 .../{ => AVR}/DigitalIO/attic/MCP355X.h | 0 .../DigitalPinBlink/DigitalPinBlink.ino | 0 .../DigitalPinConfigToggle.ino | 0 .../DigitalPinReadWrite.ino | 0 .../DigitalPinShiftOut/DigitalPinShiftOut.ino | 0 .../examples/PinIOBegin/PinIOBegin.ino | 0 .../PinIOConfigToggle/PinIOConfigToggle.ino | 0 .../PinIOReadWrite/PinIOReadWrite.ino | 0 .../examples/ScanI2cBus/ScanI2cBus.ino | 0 .../SoftDS1307Utility/SoftDS1307Utility.ino | 0 .../examples/testArduino/testArduino.ino | 0 .../testDigitalPin/testDigitalPin.ino | 0 .../testFastDigital/testFastDigital.ino | 0 .../examples/testPinIO/testPinIO.ino | 0 .../examples/testSoftSPI/testSoftSPI.ino | 0 .../drivers/{ => AVR}/Ethernet_UIP/Dhcp.cpp | 0 .../drivers/{ => AVR}/Ethernet_UIP/Dhcp.h | 0 .../drivers/{ => AVR}/Ethernet_UIP/Dns.cpp | 0 .../drivers/{ => AVR}/Ethernet_UIP/Dns.h | 0 .../drivers/{ => AVR}/Ethernet_UIP/README | 0 .../{ => AVR}/Ethernet_UIP/UIPClient.cpp | 0 .../{ => AVR}/Ethernet_UIP/UIPClient.h | 0 .../{ => AVR}/Ethernet_UIP/UIPEthernet.cpp | 0 .../{ => AVR}/Ethernet_UIP/UIPEthernet.h | 0 .../{ => AVR}/Ethernet_UIP/UIPServer.cpp | 0 .../{ => AVR}/Ethernet_UIP/UIPServer.h | 0 .../drivers/{ => AVR}/Ethernet_UIP/UIPUdp.cpp | 0 .../drivers/{ => AVR}/Ethernet_UIP/UIPUdp.h | 0 .../{ => AVR}/Ethernet_UIP/ethernet_comp.h | 0 .../AdvancedChatServer/AdvancedChatServer.ino | 0 .../examples/EchoServer/EchoServer.ino | 0 .../examples/TcpClient/TcpClient.ino | 0 .../examples/TcpServer/TcpServer.ino | 0 .../examples/UdpClient/UdpClient.ino | 0 .../examples/UdpServer/UdpServer.ino | 0 .../{ => AVR}/Ethernet_UIP/keywords.txt | 0 .../{ => AVR}/Ethernet_UIP/library.properties | 0 .../Ethernet_UIP/tests/perl/tcpclient.pl | 0 .../Ethernet_UIP/tests/perl/tcpserver.pl | 0 .../Ethernet_UIP/tests/perl/udpclient.pl | 0 .../Ethernet_UIP/tests/perl/udpserver.pl | 0 .../Ethernet_UIP/utility/Enc28J60Network.cpp | 0 .../Ethernet_UIP/utility/Enc28J60Network.h | 0 .../Ethernet_UIP/utility/clock-arch.c | 0 .../Ethernet_UIP/utility/clock-arch.h | 0 .../{ => AVR}/Ethernet_UIP/utility/enc28j60.h | 0 .../Ethernet_UIP/utility/mempool.cpp | 0 .../{ => AVR}/Ethernet_UIP/utility/mempool.h | 0 .../Ethernet_UIP/utility/mempool_conf.h | 0 .../{ => AVR}/Ethernet_UIP/utility/uip-conf.h | 0 .../{ => AVR}/Ethernet_UIP/utility/uip.c | 0 .../{ => AVR}/Ethernet_UIP/utility/uip.h | 0 .../{ => AVR}/Ethernet_UIP/utility/uip_arch.h | 0 .../{ => AVR}/Ethernet_UIP/utility/uip_arp.c | 0 .../{ => AVR}/Ethernet_UIP/utility/uip_arp.h | 0 .../Ethernet_UIP/utility/uip_clock.h | 0 .../Ethernet_UIP/utility/uip_debug.cpp | 0 .../Ethernet_UIP/utility/uip_debug.h | 0 .../Ethernet_UIP/utility/uip_timer.c | 0 .../Ethernet_UIP/utility/uip_timer.h | 0 .../Ethernet_UIP/utility/uipethernet-conf.h | 0 .../{ => AVR}/Ethernet_UIP/utility/uipopt.h | 0 .../{ => AVR}/Ethernet_UIP/utility/util.h | 0 .../drivers/{ => AVR}/Ethernet_W5100/Client.h | 0 .../drivers/{ => AVR}/Ethernet_W5100/Dhcp.cpp | 0 .../drivers/{ => AVR}/Ethernet_W5100/Dhcp.h | 0 .../drivers/{ => AVR}/Ethernet_W5100/Dns.cpp | 0 .../drivers/{ => AVR}/Ethernet_W5100/Dns.h | 0 .../{ => AVR}/Ethernet_W5100/Ethernet.cpp | 0 .../{ => AVR}/Ethernet_W5100/Ethernet.h | 0 .../Ethernet_W5100/EthernetClient.cpp | 0 .../{ => AVR}/Ethernet_W5100/EthernetClient.h | 0 .../Ethernet_W5100/EthernetServer.cpp | 0 .../{ => AVR}/Ethernet_W5100/EthernetServer.h | 0 .../{ => AVR}/Ethernet_W5100/EthernetUdp.cpp | 0 .../{ => AVR}/Ethernet_W5100/EthernetUdp.h | 0 .../{ => AVR}/Ethernet_W5100/IPAddress.cpp | 0 .../{ => AVR}/Ethernet_W5100/IPAddress.h | 0 .../drivers/{ => AVR}/Ethernet_W5100/Server.h | 0 .../Ethernet_W5100/utility/socket.cpp | 0 .../{ => AVR}/Ethernet_W5100/utility/socket.h | 0 .../{ => AVR}/Ethernet_W5100/utility/util.h | 0 .../Ethernet_W5100/utility/w5100.cpp | 0 .../{ => AVR}/Ethernet_W5100/utility/w5100.h | 2 +- .../MySensors/drivers/{ => AVR}/SPI/SPI.cpp | 0 .../MySensors/drivers/{ => AVR}/SPI/SPI.h | 0 .../BarometricPressureSensor.ino | 0 .../DigitalPotControl/DigitalPotControl.ino | 0 .../drivers/{ => AVR}/SPI/keywords.txt | 0 .../drivers/{ => AVR}/SPI/library.properties | 0 .../drivers/ESP8266/EEPROM/EEPROM.cpp | 118 + .../MySensors/drivers/ESP8266/EEPROM/EEPROM.h | 70 + .../examples/eeprom_clear/eeprom_clear.ino | 26 + .../examples/eeprom_read/eeprom_read.ino | 44 + .../examples/eeprom_write/eeprom_write.ino | 43 + .../drivers/ESP8266/EEPROM/keywords.txt | 18 + .../drivers/ESP8266/EEPROM/library.properties | 8 + .../examples/NTPClient/NTPClient.ino | 153 ++ .../WiFiAccessPoint/WiFiAccessPoint.ino | 68 + .../examples/WiFiClient/WiFiClient.ino | 85 + .../examples/WiFiMulti/WiFiMulti.ino | 33 + .../examples/WiFiScan/WiFiScan.ino | 48 + .../WiFiTelnetToSerial/WiFiTelnetToSerial.ino | 90 + .../examples/WiFiWebServer/WiFiWebServer.ino | 98 + .../drivers/ESP8266/ESP8266WiFi/keywords.txt | 67 + .../ESP8266/ESP8266WiFi/library.properties | 9 + .../ESP8266/ESP8266WiFi/src/ESP8266WiFi.cpp | 700 ++++++ .../ESP8266/ESP8266WiFi/src/ESP8266WiFi.h | 353 +++ .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 207 ++ .../ESP8266WiFi/src/ESP8266WiFiMulti.h | 62 + .../ESP8266/ESP8266WiFi/src/WiFiClient.cpp | 290 +++ .../ESP8266/ESP8266WiFi/src/WiFiClient.h | 127 + .../ESP8266/ESP8266WiFi/src/WiFiServer.cpp | 170 ++ .../ESP8266/ESP8266WiFi/src/WiFiServer.h | 65 + .../ESP8266/ESP8266WiFi/src/WiFiUdp.cpp | 279 +++ .../drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.h | 112 + .../drivers/ESP8266/ESP8266WiFi/src/arch/cc.h | 117 + .../ESP8266/ESP8266WiFi/src/arch/perf.h | 40 + .../ESP8266/ESP8266WiFi/src/arch/sys_arch.h | 0 .../ESP8266WiFi/src/include/ClientContext.h | 319 +++ .../ESP8266WiFi/src/include/UdpContext.h | 389 ++++ .../ESP8266WiFi/src/include/lwipopts.h | 2037 ++++++++++++++++ .../ESP8266/ESP8266WiFi/src/include/slist.h | 38 + .../ESP8266WiFi/src/include/wl_definitions.h | 87 + .../ESP8266/ESP8266WiFi/src/lwip/api.h | 284 +++ .../ESP8266/ESP8266WiFi/src/lwip/api_msg.h | 174 ++ .../ESP8266/ESP8266WiFi/src/lwip/arch.h | 238 ++ .../ESP8266/ESP8266WiFi/src/lwip/autoip.h | 119 + .../ESP8266/ESP8266WiFi/src/lwip/debug.h | 98 + .../ESP8266/ESP8266WiFi/src/lwip/def.h | 127 + .../ESP8266/ESP8266WiFi/src/lwip/dhcp.h | 243 ++ .../ESP8266/ESP8266WiFi/src/lwip/dns.h | 124 + .../ESP8266/ESP8266WiFi/src/lwip/err.h | 86 + .../ESP8266/ESP8266WiFi/src/lwip/icmp.h | 115 + .../ESP8266/ESP8266WiFi/src/lwip/igmp.h | 106 + .../ESP8266/ESP8266WiFi/src/lwip/inet.h | 107 + .../ESP8266WiFi/src/lwip/inet_chksum.h | 90 + .../ESP8266/ESP8266WiFi/src/lwip/init.h | 73 + .../drivers/ESP8266/ESP8266WiFi/src/lwip/ip.h | 215 ++ .../ESP8266/ESP8266WiFi/src/lwip/ip_addr.h | 272 +++ .../ESP8266/ESP8266WiFi/src/lwip/ip_frag.h | 88 + .../ESP8266/ESP8266WiFi/src/lwip/mem.h | 143 ++ .../ESP8266WiFi/src/lwip/mem_manager.h | 81 + .../ESP8266/ESP8266WiFi/src/lwip/memp.h | 116 + .../ESP8266/ESP8266WiFi/src/lwip/memp_std.h | 126 + .../ESP8266/ESP8266WiFi/src/lwip/netbuf.h | 101 + .../ESP8266/ESP8266WiFi/src/lwip/netdb.h | 124 + .../ESP8266/ESP8266WiFi/src/lwip/netif.h | 315 +++ .../ESP8266/ESP8266WiFi/src/lwip/netifapi.h | 108 + .../ESP8266/ESP8266WiFi/src/lwip/opt.h | 2043 +++++++++++++++++ .../ESP8266/ESP8266WiFi/src/lwip/pbuf.h | 160 ++ .../ESP8266/ESP8266WiFi/src/lwip/raw.h | 98 + .../ESP8266/ESP8266WiFi/src/lwip/sio.h | 141 ++ .../ESP8266/ESP8266WiFi/src/lwip/snmp.h | 367 +++ .../ESP8266/ESP8266WiFi/src/lwip/snmp_asn1.h | 101 + .../ESP8266/ESP8266WiFi/src/lwip/snmp_msg.h | 315 +++ .../ESP8266WiFi/src/lwip/snmp_structs.h | 268 +++ .../ESP8266/ESP8266WiFi/src/lwip/sockets.h | 376 +++ .../ESP8266/ESP8266WiFi/src/lwip/stats.h | 292 +++ .../ESP8266/ESP8266WiFi/src/lwip/sys.h | 337 +++ .../ESP8266/ESP8266WiFi/src/lwip/tcp.h | 377 +++ .../ESP8266/ESP8266WiFi/src/lwip/tcp_impl.h | 472 ++++ .../ESP8266/ESP8266WiFi/src/lwip/tcpip.h | 159 ++ .../ESP8266/ESP8266WiFi/src/lwip/timers.h | 98 + .../ESP8266/ESP8266WiFi/src/lwip/udp.h | 171 ++ .../drivers/ESP8266/Ethernet/README.adoc | 24 + .../AdvancedChatServer/AdvancedChatServer.ino | 108 + .../BarometricPressureWebServer.ino | 223 ++ .../examples/ChatServer/ChatServer.ino | 80 + .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 60 + .../DhcpChatServer/DhcpChatServer.ino | 88 + .../examples/TelnetClient/TelnetClient.ino | 94 + .../UDPSendReceiveString.ino | 119 + .../examples/UdpNtpClient/UdpNtpClient.ino | 142 ++ .../Ethernet/examples/WebClient/WebClient.ino | 88 + .../WebClientRepeating/WebClientRepeating.ino | 108 + .../Ethernet/examples/WebServer/WebServer.ino | 101 + .../drivers/ESP8266/Ethernet/keywords.txt | 37 + .../ESP8266/Ethernet/library.properties | 9 + .../drivers/ESP8266/Ethernet/src/Dhcp.cpp | 481 ++++ .../drivers/ESP8266/Ethernet/src/Dhcp.h | 178 ++ .../drivers/ESP8266/Ethernet/src/Dns.cpp | 423 ++++ .../drivers/ESP8266/Ethernet/src/Dns.h | 41 + .../drivers/ESP8266/Ethernet/src/Ethernet.cpp | 136 ++ .../drivers/ESP8266/Ethernet/src/Ethernet.h | 41 + .../ESP8266/Ethernet/src/EthernetClient.cpp | 173 ++ .../ESP8266/Ethernet/src/EthernetClient.h | 41 + .../ESP8266/Ethernet/src/EthernetServer.cpp | 92 + .../ESP8266/Ethernet/src/EthernetServer.h | 22 + .../ESP8266/Ethernet/src/EthernetUdp.cpp | 218 ++ .../ESP8266/Ethernet/src/EthernetUdp.h | 99 + .../ESP8266/Ethernet/src/utility/socket.cpp | 469 ++++ .../ESP8266/Ethernet/src/utility/socket.h | 44 + .../ESP8266/Ethernet/src/utility/util.h | 14 + .../ESP8266/Ethernet/src/utility/w5100.cpp | 225 ++ .../ESP8266/Ethernet/src/utility/w5100.h | 412 ++++ .../MySensors/drivers/ESP8266/SPI/SPI.cpp | 454 ++++ libraries/MySensors/drivers/ESP8266/SPI/SPI.h | 85 + .../drivers/ESP8266/SPI/keywords.txt | 36 + .../drivers/ESP8266/SPI/library.properties | 8 + .../MySensors/drivers/RF24/RF24_config.h | 4 +- .../MySensors/drivers/SPIFlash/SPIFlash.h | 2 +- .../EthernetGateway/EthernetGateway.ino | 2 +- .../examples/MotionSensor/MotionSensor.ino | 6 +- 234 files changed, 21028 insertions(+), 315 deletions(-) rename libraries/MySensors/core/{MyTransport.cpp => MyGatewayTransport.h} (57%) create mode 100644 libraries/MySensors/core/MyHw.h rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/DigitalIO.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/DigitalPin.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/I2cConstants.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/PinIO.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/PinIO.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/SoftI2cMaster.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/SoftI2cMaster.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/SoftSPI.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/attic/ADS7818.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/attic/MCP320X.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/attic/MCP355X.h (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/PinIOBegin/PinIOBegin.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/testArduino/testArduino.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/testDigitalPin/testDigitalPin.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/testFastDigital/testFastDigital.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/testPinIO/testPinIO.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/DigitalIO/examples/testSoftSPI/testSoftSPI.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/Dhcp.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/Dhcp.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/Dns.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/Dns.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/README (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPClient.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPClient.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPEthernet.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPEthernet.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPServer.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPServer.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPUdp.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/UIPUdp.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/ethernet_comp.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/examples/EchoServer/EchoServer.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/examples/TcpClient/TcpClient.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/examples/TcpServer/TcpServer.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/examples/UdpClient/UdpClient.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/examples/UdpServer/UdpServer.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/keywords.txt (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/library.properties (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/tests/perl/tcpclient.pl (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/tests/perl/tcpserver.pl (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/tests/perl/udpclient.pl (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/tests/perl/udpserver.pl (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/Enc28J60Network.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/Enc28J60Network.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/clock-arch.c (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/clock-arch.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/enc28j60.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/mempool.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/mempool.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/mempool_conf.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip-conf.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip.c (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_arch.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_arp.c (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_arp.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_clock.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_debug.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_debug.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_timer.c (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uip_timer.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uipethernet-conf.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/uipopt.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_UIP/utility/util.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Client.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Dhcp.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Dhcp.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Dns.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Dns.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Ethernet.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Ethernet.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/EthernetClient.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/EthernetClient.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/EthernetServer.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/EthernetServer.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/EthernetUdp.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/EthernetUdp.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/IPAddress.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/IPAddress.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/Server.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/utility/socket.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/utility/socket.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/utility/util.h (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/utility/w5100.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/Ethernet_W5100/utility/w5100.h (99%) rename libraries/MySensors/drivers/{ => AVR}/SPI/SPI.cpp (100%) rename libraries/MySensors/drivers/{ => AVR}/SPI/SPI.h (100%) rename libraries/MySensors/drivers/{ => AVR}/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/SPI/examples/DigitalPotControl/DigitalPotControl.ino (100%) rename libraries/MySensors/drivers/{ => AVR}/SPI/keywords.txt (100%) rename libraries/MySensors/drivers/{ => AVR}/SPI/library.properties (100%) create mode 100644 libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.h create mode 100644 libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_clear/eeprom_clear.ino create mode 100644 libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_read/eeprom_read.ino create mode 100644 libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_write/eeprom_write.ino create mode 100644 libraries/MySensors/drivers/ESP8266/EEPROM/keywords.txt create mode 100644 libraries/MySensors/drivers/ESP8266/EEPROM/library.properties create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/NTPClient/NTPClient.ino create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiWebServer/WiFiWebServer.ino create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/keywords.txt create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/library.properties create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/cc.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/perf.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/sys_arch.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/ClientContext.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/UdpContext.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/lwipopts.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/slist.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/wl_definitions.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api_msg.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/arch.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/autoip.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/debug.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/def.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dhcp.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dns.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/err.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/icmp.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/igmp.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet_chksum.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/init.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_addr.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_frag.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem_manager.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp_std.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netbuf.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netdb.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netif.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netifapi.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/opt.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/pbuf.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/raw.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sio.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_asn1.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_msg.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_structs.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sockets.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/stats.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sys.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp_impl.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcpip.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/timers.h create mode 100644 libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/udp.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/README.adoc create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/ChatServer/ChatServer.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/TelnetClient/TelnetClient.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClient/WebClient.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebServer/WebServer.ino create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/keywords.txt create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/library.properties create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/util.h create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.h create mode 100644 libraries/MySensors/drivers/ESP8266/SPI/SPI.cpp create mode 100644 libraries/MySensors/drivers/ESP8266/SPI/SPI.h create mode 100644 libraries/MySensors/drivers/ESP8266/SPI/keywords.txt create mode 100644 libraries/MySensors/drivers/ESP8266/SPI/library.properties diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index e9d4e75..3327516 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -36,13 +36,14 @@ #endif // CORE -#include "drivers/SPI/SPI.cpp" // HARDWARE #if defined(ARDUINO_ARCH_ESP8266) + #include "drivers/ESP8266/SPI/SPI.cpp" #include "core/MyHwESP8266.cpp" #elif defined(ARDUINO_ARCH_AVR) + #include "drivers/AVR/SPI/SPI.cpp" #include "core/MyHwATMega328.cpp" #endif @@ -66,26 +67,25 @@ #define MY_RADIO_FEATURE // SOFTSPI #ifdef MY_SOFTSPI - #include "drivers/DigitalIO/SoftI2cMaster.cpp" - #include "drivers/DigitalIO/PinIO.cpp" + #if defined(ARDUINO_ARCH_ESP8266) + #error Soft SPI is not available on ESP8266 + #endif + #include "drivers/AVR/DigitalIO/SoftI2cMaster.cpp" + #include "drivers/AVR/DigitalIO/PinIO.cpp" #endif // FLASH #ifdef MY_OTA_FIRMWARE_FEATURE - SPIFlash flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); #include "drivers/SPIFlash/SPIFlash.cpp" + SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); #endif - #include "core/MyTransport.cpp" #if defined(MY_RADIO_NRF24) #include "drivers/RF24/RF24.cpp" #include "core/MyTransportNRF24.cpp" - MyTransportNRF24 transport; - #elif defined(MY_RADIO_RFM69) #include "drivers/RFM69/RFM69.cpp" #include "core/MyTransportRFM69.cpp" - MyTransportRFM69 transport; #endif #endif @@ -93,10 +93,8 @@ // GATEWAY - TRANSPORT #if defined(MY_GATEWAY_FEATURE) // GATEWAY - PROTOCOL - #include "core/MyProtocol.cpp" #if defined(MY_GATEWAY_PROTOCOL_DEFAULT) #include "core/MyProtocolDefault.cpp" - MyProtocolDefault _protocol; #else #error No gateway protocol specified! #endif @@ -105,29 +103,29 @@ #define MY_REPEATER_FEATURE #endif #if defined(MY_GATEWAY_W5100_CLIENT) || defined(MY_GATEWAY_W5100_SERVER) - #include "drivers/Ethernet_W5100/utility/socket.cpp" - #include "drivers/Ethernet_W5100/utility/w5100.cpp" - #include "drivers/Ethernet_W5100/DNS.cpp" - #include "drivers/Ethernet_W5100/Ethernet.cpp" - #include "drivers/Ethernet_W5100/EthernetUdp.cpp" - #include "drivers/Ethernet_W5100/IPAddress.cpp" + #include "drivers/AVR/Ethernet_W5100/utility/socket.cpp" + #include "drivers/AVR/Ethernet_W5100/utility/w5100.cpp" + #include "drivers/AVR/Ethernet_W5100/DNS.cpp" + #include "drivers/AVR/Ethernet_W5100/Ethernet.cpp" + #include "drivers/AVR/Ethernet_W5100/EthernetUdp.cpp" + #include "drivers/AVR/Ethernet_W5100/IPAddress.cpp" + #if !defined(MY_PORT) #error You must define MY_PORT #endif #if !defined(USE_UDP) - #include "drivers/Ethernet_W5100/EthernetServer.cpp" + #include "drivers/AVR/Ethernet_W5100/EthernetServer.cpp" #endif #if defined(MY_GATEWAY_W5100_CLIENT) && !defined(MY_CONTROLLER_IP_ADDRESS) #error You must define MY_CONTROLLER_IP_ADDRESS when acting as client #endif #if defined(MY_GATEWAY_W5100_CLIENT) - #include "drivers/Ethernet_W5100/EthernetClient.cpp" + #include "drivers/AVR/Ethernet_W5100/EthernetClient.cpp" #include "core/MyGatewayTransportEthernet.cpp" #endif #elif defined(MY_GATEWAY_SERIAL) #include "core/MyGatewayTransportSerial.cpp" - MyGatewayTransportSerial gwTransport(protocol); #endif #else #undef MY_GATEWAY_FEATURE diff --git a/libraries/MySensors/core/MyTransport.cpp b/libraries/MySensors/core/MyGatewayTransport.h similarity index 57% rename from libraries/MySensors/core/MyTransport.cpp rename to libraries/MySensors/core/MyGatewayTransport.h index 05627de..4df3244 100644 --- a/libraries/MySensors/core/MyTransport.cpp +++ b/libraries/MySensors/core/MyGatewayTransport.h @@ -5,8 +5,8 @@ * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB + * Created by Tomas Hozza + * Copyright (C) 2015 Tomas Hozza * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org @@ -17,7 +17,25 @@ * version 2 as published by the Free Software Foundation. */ -#include "MyTransport.h" +#ifndef MyGatewayTransport_h +#define MyGatewayTransport_h -MyTransport::MyTransport() { -} +#include "MyConfig.h" +#include "MyMessage.h" +#include "MyProtocol.h" + + + +// initialize the driver +bool gatewayTransportBegin(); + +// Send message to controller +bool gatewayTransportSend(MyMessage &message); + +// Check if a new message is available from controller +bool gatewayTransportAvailable(); + +// Pick up last message received from controller +MyMessage& gatewayTransportReceive(); + +#endif /* MyGatewayTransportEthernet_h */ diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp index b2b21ee..83fa9b1 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp @@ -64,7 +64,7 @@ bool gatewayTransportSend(MyMessage &message) return false; } else { - _ethernetMsg = _protocol.format(message); + _ethernetMsg = protocolFormat(message); #ifdef MY_USE_UDP _ethernetServer.beginPacket(_ethernetControllerIP, MY_CONTROLLER_PORT); _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); @@ -128,7 +128,7 @@ bool gatewayTransportAvailable() if (available) { // Parse message and return parse result - available = _protocol.parse(_ethernetMsg, _ethernetInputBuffer); + available = protocolParse(_ethernetMsg, _ethernetInputBuffer); } return available; diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.h b/libraries/MySensors/core/MyGatewayTransportEthernet.h index da1abc1..c7cd7f9 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.h +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.h @@ -24,36 +24,19 @@ #include "MyMessage.h" #include "MyProtocol.h" #include "MyProtocolDefault.h" +#include "MyGatewayTransport.h" -#include "drivers/Ethernet_W5100/IPAddress.h" // Use this if you have attached a Ethernet ENC28J60 shields //#include -// Use this fo WizNET W5100 module and Arduino Ethernet Shield -#include "drivers/Ethernet_W5100/Ethernet.h" -#ifdef MY_USE_UDP -#include "drivers/Ethernet_W5100/EthernetUdp.h" -#endif /* MY_USE_UDP */ #define CONTROLLER_PORT 5003 #define IP_RENEWAL_INTERVAL 60000 // in milliseconds #define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller -// initialize the driver -bool gatewayTransportBegin(); - -// Send message to controller -bool gatewayTransportSend(MyMessage &message); - -// Check if a new message is available from controller -bool gatewayTransportAvailable(); - -// Pick up last message received from controller -MyMessage& gatewayTransportReceive(); - #ifndef MY_IP_ADDRESS void gatewayTransportRenewIP(); #endif diff --git a/libraries/MySensors/core/MyGatewayTransportSerial.cpp b/libraries/MySensors/core/MyGatewayTransportSerial.cpp index f5acbed..313efac 100644 --- a/libraries/MySensors/core/MyGatewayTransportSerial.cpp +++ b/libraries/MySensors/core/MyGatewayTransportSerial.cpp @@ -17,54 +17,55 @@ * version 2 as published by the Free Software Foundation. */ + #include "MyGatewayTransportSerial.h" +char _serialInputString[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface +int _serialInputPos; +MyMessage _serialMsg; -MyGatewayTransportSerial::MyGatewayTransportSerial(MyProtocol &_protocol) : MyGatewayTransport(_protocol),inputPos(0) -{ -} -bool MyGatewayTransportSerial::begin() { +bool gatewayTransportBegin() { return true; } -bool MyGatewayTransportSerial::send(MyMessage &message) { - Serial.print(protocol.format(message)); +bool gatewayTransportSend(MyMessage &message) { + Serial.print(protocolFormat(message)); // Serial print is always successful return true; } -bool MyGatewayTransportSerial::available() { +bool gatewayTransportAvailable() { bool available = false; while (Serial.available()) { // get the new byte: char inChar = (char) Serial.read(); // if the incoming character is a newline, set a flag // so the main loop can do something about it: - if (inputPos < MAX_RECEIVE_LENGTH - 1 && !available) { + if (_serialInputPos < MAX_RECEIVE_LENGTH - 1 && !available) { if (inChar == '\n') { - inputString[inputPos] = 0; + _serialInputString[_serialInputPos] = 0; available = true; } else { // add it to the inputString: - inputString[inputPos] = inChar; - inputPos++; + _serialInputString[_serialInputPos] = inChar; + _serialInputPos++; } } else { // Incoming message too long. Throw away - inputPos = 0; + _serialInputPos = 0; } } if (available) { // Parse message and return parse result - available = protocol.parse(msg, inputString); - inputPos = 0; + available = protocolParse(_serialMsg, _serialInputString); + _serialInputPos = 0; } return available; } -MyMessage & MyGatewayTransportSerial::receive() { +MyMessage & gatewayTransportReceive() { // Return the last parsed message - return msg; + return _serialMsg; } diff --git a/libraries/MySensors/core/MyGatewayTransportSerial.h b/libraries/MySensors/core/MyGatewayTransportSerial.h index 302a06c..7dabf02 100644 --- a/libraries/MySensors/core/MyGatewayTransportSerial.h +++ b/libraries/MySensors/core/MyGatewayTransportSerial.h @@ -21,32 +21,10 @@ #define MyGatewayTransportSerial_h #include "MyMessage.h" +#include "MyGatewayTransport.h" #include "MyProtocol.h" #include "MyProtocolDefault.h" #define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller -class MyGatewayTransportSerial : public MyGatewayTransport -{ -public: - // MyGateway constructor - MyGatewayTransportSerial(MyProtocol &protocol = *new MyProtocolDefault()); - - // initialize the transport driver - bool begin(); - - // Send message to controller - bool send(MyMessage &message); - - // Check if a new message is available from controller - bool available(); - - // Pick up last message received from controller - MyMessage& receive(); -private: - char inputString[MAX_RECEIVE_LENGTH]; // A buffer for incoming commands from serial interface - int inputPos; - MyMessage msg; -}; - #endif diff --git a/libraries/MySensors/core/MyHw.h b/libraries/MySensors/core/MyHw.h new file mode 100644 index 0000000..c4387de --- /dev/null +++ b/libraries/MySensors/core/MyHw.h @@ -0,0 +1,53 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyHw_h +#define MyHw_h + +#include "MyConfig.h" +#include "MyMessage.h" +#include "MyHw.h" + + +#ifdef __cplusplus +#include +#endif + +// Implement these as functions or macros +/* +#define hwDigitalWrite(__pin, __value) +#define hwInit() Serial.begin(BAUD_RATE) +#define hwWatchdogReset() wdt_reset() +#define hwReboot() wdt_enable(WDTO_15MS); while (1) +#define hwMillis() millis() + +void hwReadConfigBlock(void* buf, void* adr, size_t length); +void hwWriteConfigBlock(void* buf, void* adr, size_t length); +void hwWriteConfig(int adr, uint8_t value); +uint8_t hwReadConfig(int adr); +*/ + +void hwSleep(unsigned long ms); +bool hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms); +uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); +#ifdef MY_DEBUG + void hwDebugPrint(const char *fmt, ... ); +#endif + +#endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/libraries/MySensors/core/MyHwATMega328.h b/libraries/MySensors/core/MyHwATMega328.h index 90ea09b..65d0190 100644 --- a/libraries/MySensors/core/MyHwATMega328.h +++ b/libraries/MySensors/core/MyHwATMega328.h @@ -20,8 +20,7 @@ #ifndef MyHwATMega328_h #define MyHwATMega328_h -#ifdef ARDUINO_ARCH_AVR - +#include "MyHw.h" #include "MyConfig.h" #include "MyMessage.h" #include @@ -92,14 +91,6 @@ enum period_t SLEEP_FOREVER }; - -void hwSleep(unsigned long ms); -bool hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms); -uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); -#ifdef MY_DEBUG - void hwDebugPrint(const char *fmt, ... ); -#endif void hwInternalSleep(unsigned long ms); -#endif // #ifdef ARDUINO_ARCH_AVR #endif diff --git a/libraries/MySensors/core/MyHwESP8266.cpp b/libraries/MySensors/core/MyHwESP8266.cpp index 5a0eb64..d638bf2 100644 --- a/libraries/MySensors/core/MyHwESP8266.cpp +++ b/libraries/MySensors/core/MyHwESP8266.cpp @@ -17,10 +17,8 @@ * version 2 as published by the Free Software Foundation. */ -#ifdef ARDUINO_ARCH_ESP8266 - #include "MyHwESP8266.h" -#include +#include "drivers/ESP8266/EEPROM/EEPROM.cpp" /* int8_t pinIntTrigger = 0; @@ -54,7 +52,7 @@ static void hwInitConfigBlock( size_t length = 1024 /*ATMega328 has 1024 bytes*/ void hwReadConfigBlock(void* buf, void* adr, size_t length) { - hw_initConfigBlock(); + hwInitConfigBlock(); uint8_t* dst = static_cast(buf); int offs = reinterpret_cast(adr); while (length-- > 0) @@ -65,7 +63,7 @@ void hwReadConfigBlock(void* buf, void* adr, size_t length) void hwWriteConfigBlock(void* buf, void* adr, size_t length) { - hw_initConfigBlock(); + hwInitConfigBlock(); uint8_t* src = static_cast(buf); int offs = reinterpret_cast(adr); while (length-- > 0) @@ -78,16 +76,16 @@ void hwWriteConfigBlock(void* buf, void* adr, size_t length) uint8_t hwReadConfig(int adr) { uint8_t value; - hw_readConfigBlock(&value, reinterpret_cast(adr), 1); + hwReadConfigBlock(&value, reinterpret_cast(adr), 1); return value; } void hwWriteConfig(int adr, uint8_t value) { - uint8_t curr = hw_readConfig(adr); + uint8_t curr = hwReadConfig(adr); if (curr != value) { - hw_writeConfigBlock(&value, reinterpret_cast(adr), 1); + hwWriteConfigBlock(&value, reinterpret_cast(adr), 1); } } @@ -109,7 +107,7 @@ uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t m } #ifdef MY_DEBUG -void hwDebugPrint(bool isGW, const char *fmt, ... ) { +void hwDebugPrint(const char *fmt, ... ) { char fmtBuffer[300]; #ifdef MY_GATEWAY_FEATURE // prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE) @@ -134,5 +132,3 @@ void hwDebugPrint(bool isGW, const char *fmt, ... ) { //Serial.write(freeRam()); } #endif - -#endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/libraries/MySensors/core/MyHwESP8266.h b/libraries/MySensors/core/MyHwESP8266.h index 6f99201..461ddbb 100644 --- a/libraries/MySensors/core/MyHwESP8266.h +++ b/libraries/MySensors/core/MyHwESP8266.h @@ -16,25 +16,23 @@ * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ - -#ifdef ARDUINO_ARCH_ESP8266 - #ifndef MyHwESP8266_h #define MyHwESP8266_h +#include "MyHw.h" #include "MyConfig.h" #include "MyMessage.h" #ifdef __cplusplus #include -#include +//#include #endif // Define these as macros to save valuable space #define hwDigitalWrite(__pin, __value) (digitalWrite(__pin, __value)) -#define hwInit() Serial.begin(BAUD_RATE) +#define hwInit() Serial.begin(MY_BAUD_RATE) #define hwWatchdogReset() wdt_reset() #define hwReboot() wdt_enable(WDTO_15MS); while (1) #define hwMillis() millis() @@ -44,28 +42,5 @@ void hwWriteConfigBlock(void* buf, void* adr, size_t length); void hwWriteConfig(int adr, uint8_t value); uint8_t hwReadConfig(int adr); -enum period_t -{ - SLEEP_15Ms, - SLEEP_30MS, - SLEEP_60MS, - SLEEP_120MS, - SLEEP_250MS, - SLEEP_500MS, - SLEEP_1S, - SLEEP_2S, - SLEEP_4S, - SLEEP_8S, - SLEEP_FOREVER -}; - - - -void hwSleep(unsigned long ms); -bool hwSleep(uint8_t interrupt, uint8_t mode, unsigned long ms); -uint8_t hwSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms); -#ifdef MY_DEBUG - void hwDebugPrint(const char *fmt, ... ); -#endif #endif // #ifdef ARDUINO_ARCH_ESP8266 diff --git a/libraries/MySensors/core/MyProtocol.h b/libraries/MySensors/core/MyProtocol.h index 5b0298f..c425809 100644 --- a/libraries/MySensors/core/MyProtocol.h +++ b/libraries/MySensors/core/MyProtocol.h @@ -22,18 +22,12 @@ #include "MyMessage.h" -class MyProtocol -{ -public: - // MyProtocol constructor - MyProtocol(); - // parse(message, inputString) - // parse a string into a message element - // returns true if successfully parsed the input string - virtual bool parse(MyMessage &message, char *inputString) = 0; +// parse(message, inputString) +// parse a string into a message element +// returns true if successfully parsed the input string +bool protocolParse(MyMessage &message, char *inputString); - // Format MyMessage to the protocol represenataion - virtual char *format(MyMessage &message) = 0; +// Format MyMessage to the protocol represenataion +char *protocolFormat(MyMessage &message); -}; #endif diff --git a/libraries/MySensors/core/MyProtocolDefault.cpp b/libraries/MySensors/core/MyProtocolDefault.cpp index f410abe..727b337 100644 --- a/libraries/MySensors/core/MyProtocolDefault.cpp +++ b/libraries/MySensors/core/MyProtocolDefault.cpp @@ -21,9 +21,10 @@ #include "MyProtocolDefault.h" #include "MyTransport.h" -MyProtocolDefault::MyProtocolDefault() : MyProtocol() {} +char fmtBuffer[MAX_FORMAT_BUFFER_LENGTH]; +char convBuffer[MAX_PAYLOAD*2+1]; -bool MyProtocolDefault::parse(MyMessage &message, char *inputString) { +bool protocolParse(MyMessage &message, char *inputString) { char *str, *p, *value=NULL; uint8_t bvalue[MAX_PAYLOAD]; uint8_t blen = 0; @@ -58,8 +59,8 @@ bool MyProtocolDefault::parse(MyMessage &message, char *inputString) { blen = 0; uint8_t val; while (*str) { - val = h2i(*str++) << 4; - val += h2i(*str++); + val = protocolH2i(*str++) << 4; + val += protocolH2i(*str++); bvalue[blen] = val; blen++; } @@ -89,13 +90,12 @@ bool MyProtocolDefault::parse(MyMessage &message, char *inputString) { return true; } -char * MyProtocolDefault::format(MyMessage &message) { +char * protocolFormat(MyMessage &message) { snprintf_P(fmtBuffer, MAX_FORMAT_BUFFER_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuffer)); return fmtBuffer; } - -uint8_t MyProtocolDefault::h2i(char c) { +uint8_t protocolH2i(char c) { uint8_t i = 0; if (c <= '9') i += c - '0'; @@ -105,3 +105,5 @@ uint8_t MyProtocolDefault::h2i(char c) { i += c - 'A' + 10; return i; } + + diff --git a/libraries/MySensors/core/MyProtocolDefault.h b/libraries/MySensors/core/MyProtocolDefault.h index 8d35609..4583abd 100644 --- a/libraries/MySensors/core/MyProtocolDefault.h +++ b/libraries/MySensors/core/MyProtocolDefault.h @@ -21,22 +21,10 @@ #define MyProtocolDefault_h #include "MyConfig.h" -#include "MyProtocol.h" #include "MyTransport.h" #define MAX_FORMAT_BUFFER_LENGTH 120 // Max buffersize when formatting messages +uint8_t protocolH2i(char c); -class MyProtocolDefault : public MyProtocol -{ -public: - MyProtocolDefault(); - bool parse(MyMessage &message, char *inputString); - char *format(MyMessage &message); -private: - char fmtBuffer[MAX_FORMAT_BUFFER_LENGTH]; - char convBuffer[MAX_PAYLOAD*2+1]; - - uint8_t h2i(char c); -}; #endif diff --git a/libraries/MySensors/core/MySensorCore.cpp b/libraries/MySensors/core/MySensorCore.cpp index 05121cf..0d8b496 100644 --- a/libraries/MySensors/core/MySensorCore.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -109,7 +109,7 @@ bool isValidFirmware() { // init crc uint16_t crc = ~0; for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) { - crc ^= flash.readByte(i + FIRMWARE_START_OFFSET); + crc ^= _flash.readByte(i + FIRMWARE_START_OFFSET); for (int8_t j = 0; j < 8; ++j) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; @@ -217,7 +217,7 @@ void begin() { _failedTransmissions = 0; // Setup radio - if (!transport.init()) { + if (!transportInit()) { debug(PSTR("radio init fail\n")); while(1); // Nothing more we can do } @@ -311,7 +311,7 @@ ControllerConfig getConfig() { #if defined(MY_RADIO_FEATURE) void requestNodeId() { debug(PSTR("req id\n")); - transport.setAddress(_nc.nodeId); + transportSetAddress(_nc.nodeId); build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set(""); sendWrite(_nc.parentNodeId, _msg); wait(2000); @@ -323,7 +323,7 @@ void requestNodeId() { void setupNode() { // Open reading pipe for messages directed to this node (set write pipe to same) - transport.setAddress(_nc.nodeId); + transportSetAddress(_nc.nodeId); // Present node and request config #ifndef MY_GATEWAY_FEATURE if (_nc.nodeId != AUTO) { @@ -563,7 +563,7 @@ boolean sendWrite(uint8_t to, MyMessage &message) { #ifdef MY_LEDS_BLINKING_FEATURE txBlink(1); #endif - bool ok = transport.send(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length)); + bool ok = transportSend(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length)); debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,st=%s:%s\n"), message.sender,message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, @@ -660,7 +660,7 @@ void process() { #if defined(MY_RADIO_FEATURE) uint8_t to = 0; - if (!transport.available(&to)) + if (!transportAvailable(&to)) { #ifdef MY_OTA_FIRMWARE_FEATURE unsigned long enter = hwMillis(); @@ -692,7 +692,7 @@ void process() { (void)signer.checkTimer(); // Manage signing timeout #endif - uint8_t len = transport.receive((uint8_t *)&_msg); + uint8_t len = transportReceive((uint8_t *)&_msg); (void)len; //until somebody makes use of 'len' #ifdef MY_LEDS_BLINKING_FEATURE rxBlink(1); @@ -842,14 +842,14 @@ void process() { // copy new FW config memcpy(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig)); // Init flash - if (!flash.initialize()) { + if (!_flash.initialize()) { debug(PSTR("flash init fail\n")); _fwUpdateOngoing = false; } else { // erase lower 32K -> max flash size for ATMEGA328 - flash.blockErase32K(0); + _flash.blockErase32K(0); // wait until flash erased - while ( flash.busy() ); + while ( _flash.busy() ); _fwBlock = _fc.blocks; _fwUpdateOngoing = true; // reset flags @@ -865,9 +865,9 @@ void process() { // extract FW block ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)_msg.data; // write to flash - flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); + _flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); // wait until flash written - while ( flash.busy() ); + while ( _flash.busy() ); _fwBlock--; if (!_fwBlock) { // We're finished! Do a checksum and reboot. @@ -877,7 +877,7 @@ void process() { // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) uint16_t fwsize = FIRMWARE_BLOCK_SIZE * _fc.blocks; uint8_t OTAbuffer[10] = {'F','L','X','I','M','G',':',(fwsize >> 8),fwsize,':'}; - flash.writeBytes(0, OTAbuffer, 10); + _flash.writeBytes(0, OTAbuffer, 10); // Write the new firmware config to eeprom hwWriteConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); hwReboot(); @@ -986,7 +986,7 @@ void sleep(unsigned long ms) { } else { #endif #if defined(MY_RADIO_FEATURE) - transport.powerDown(); + transportPowerDown(); #endif hwSleep(ms); #if defined(MY_OTA_FIRMWARE_FEATURE) @@ -1003,7 +1003,7 @@ bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { } else { #endif #if defined(MY_RADIO_FEATURE) - transport.powerDown(); + transportPowerDown(); #endif return hwSleep(interrupt, mode, ms) ; #if defined(MY_OTA_FIRMWARE_FEATURE) @@ -1020,7 +1020,7 @@ int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode } else { #endif #if defined(MY_RADIO_FEATURE) - transport.powerDown(); + transportPowerDown(); #endif return hwSleep(interrupt1, mode1, interrupt2, mode2, ms) ; #if defined(MY_OTA_FIRMWARE_FEATURE) diff --git a/libraries/MySensors/core/MySensorCore.h b/libraries/MySensors/core/MySensorCore.h index 6deb634..24a7874 100644 --- a/libraries/MySensors/core/MySensorCore.h +++ b/libraries/MySensors/core/MySensorCore.h @@ -23,7 +23,6 @@ #include "Version.h" // Auto generated by bot #include "MyConfig.h" -#include "MyTransport.h" #ifdef MY_SIGNING_FEATURE #include "MySigning.h" #include "MySigningNone.h" diff --git a/libraries/MySensors/core/MyTransport.h b/libraries/MySensors/core/MyTransport.h index aab12f3..503f8c1 100644 --- a/libraries/MySensors/core/MyTransport.h +++ b/libraries/MySensors/core/MyTransport.h @@ -29,37 +29,5 @@ #define GATEWAY_ADDRESS ((uint8_t)0) #define BROADCAST_ADDRESS ((uint8_t)0xFF) -class MyTransport -{ -public: - // MyTransport constructor - // different parameters would be needed depending on radio module (e.g. pins connected etc.) - // keeping these parameters as #define's in MyConfig to streamline the driver interface - MyTransport(); - // init() - // different parameters would be needed depending on radio module (e.g. channel, power, crc, etc.) - // keeping these parameters as #define's in MyConfig to streamline the driver interface - virtual bool init() = 0; - // setAddress(address) - // set the node address and start listening to that address (and the broadcast address) - virtual void setAddress(uint8_t address) = 0; - // getAddress() - // returns the current address from the radio driver - virtual uint8_t getAddress() = 0; - // send(to, data, len) - // reliable transmission of the data with given length (in bytes) to the destination address - // returns true if successfully submitted - virtual bool send(uint8_t to, const void* data, uint8_t len) = 0; - // available(to) - // returns true if a new packet arrived in the rx buffer - // populates "to" parameter with the address the packet was sent to (either own address or broadcast) - virtual bool available(uint8_t *to) = 0; - // receive(data) - // returns length of received packet - // populates "data" parameter with received data - virtual uint8_t receive(void* data) = 0; - // powers down the radio - virtual void powerDown() = 0; -}; #endif diff --git a/libraries/MySensors/core/MyTransportNRF24.cpp b/libraries/MySensors/core/MyTransportNRF24.cpp index 5affb12..91e9fc2 100644 --- a/libraries/MySensors/core/MyTransportNRF24.cpp +++ b/libraries/MySensors/core/MyTransportNRF24.cpp @@ -17,76 +17,72 @@ * version 2 as published by the Free Software Foundation. */ -#include "MyTransport.h" #include "MyTransportNRF24.h" -MyTransportNRF24::MyTransportNRF24() - : - MyTransport(), - rf24(MY_RF24_CE_PIN, MY_RF24_CS_PIN) -{ -} +RF24 _rf24(MY_RF24_CE_PIN, MY_RF24_CS_PIN); +uint8_t _address; +uint8_t _paLevel; -bool MyTransportNRF24::init() { +bool transportInit() { // Start up the radio library - rf24.begin(); + _rf24.begin(); - if (!rf24.isPVariant()) { + if (!_rf24.isPVariant()) { return false; } - rf24.setAutoAck(1); - rf24.setAutoAck(BROADCAST_PIPE,false); // Turn off auto ack for broadcast - rf24.enableAckPayload(); - rf24.setChannel(MY_RF24_CHANNEL); - rf24.setPALevel(_paLevel); - rf24.setDataRate(MY_RF24_DATARATE); - rf24.setRetries(5,15); - rf24.setCRCLength(RF24_CRC_16); - rf24.enableDynamicPayloads(); + _rf24.setAutoAck(1); + _rf24.setAutoAck(BROADCAST_PIPE,false); // Turn off auto ack for broadcast + _rf24.enableAckPayload(); + _rf24.setChannel(MY_RF24_CHANNEL); + _rf24.setPALevel(_paLevel); + _rf24.setDataRate(MY_RF24_DATARATE); + _rf24.setRetries(5,15); + _rf24.setCRCLength(RF24_CRC_16); + _rf24.enableDynamicPayloads(); // All nodes listen to broadcast pipe (for FIND_PARENT_RESPONSE messages) - rf24.openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS)); + _rf24.openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS)); return true; } -void MyTransportNRF24::setAddress(uint8_t address) { +void transportSetAddress(uint8_t address) { _address = address; - rf24.openReadingPipe(WRITE_PIPE, TO_ADDR(address)); - rf24.openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(address)); - rf24.startListening(); + _rf24.openReadingPipe(WRITE_PIPE, TO_ADDR(address)); + _rf24.openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(address)); + _rf24.startListening(); } -uint8_t MyTransportNRF24::getAddress() { +uint8_t transportGetAddress() { return _address; } -bool MyTransportNRF24::send(uint8_t to, const void* data, uint8_t len) { +bool transportSend(uint8_t to, const void* data, uint8_t len) { // Make sure radio has powered up - rf24.powerUp(); - rf24.stopListening(); - rf24.openWritingPipe(TO_ADDR(to)); - bool ok = rf24.write(data, len, to == BROADCAST_ADDRESS); - rf24.startListening(); + _rf24.powerUp(); + _rf24.stopListening(); + _rf24.openWritingPipe(TO_ADDR(to)); + bool ok = _rf24.write(data, len, to == BROADCAST_ADDRESS); + _rf24.startListening(); return ok; } -bool MyTransportNRF24::available(uint8_t *to) { +bool transportAvailable(uint8_t *to) { uint8_t pipe = 255; - boolean avail = rf24.available(&pipe); + boolean avail = _rf24.available(&pipe); (void)avail; //until somebody makes use of 'avail' if (pipe == CURRENT_NODE_PIPE) *to = _address; else if (pipe == BROADCAST_PIPE) *to = BROADCAST_ADDRESS; - return (rf24.available() && pipe < 6); + return (_rf24.available() && pipe < 6); } -uint8_t MyTransportNRF24::receive(void* data) { - uint8_t len = rf24.getDynamicPayloadSize(); - rf24.read(data, len); +uint8_t transportReceive(void* data) { + uint8_t len = _rf24.getDynamicPayloadSize(); + _rf24.read(data, len); return len; } -void MyTransportNRF24::powerDown() { - rf24.powerDown(); +void transportPowerDown() { + _rf24.powerDown(); } diff --git a/libraries/MySensors/core/MyTransportNRF24.h b/libraries/MySensors/core/MyTransportNRF24.h index d8a7b81..0d0bcf8 100644 --- a/libraries/MySensors/core/MyTransportNRF24.h +++ b/libraries/MySensors/core/MyTransportNRF24.h @@ -32,21 +32,12 @@ #define CURRENT_NODE_PIPE ((uint8_t)1) #define BROADCAST_PIPE ((uint8_t)2) -class MyTransportNRF24 : public MyTransport -{ -public: - MyTransportNRF24(); - bool init(); - void setAddress(uint8_t address); - uint8_t getAddress(); - bool send(uint8_t to, const void* data, uint8_t len); - bool available(uint8_t *to); - uint8_t receive(void* data); - void powerDown(); -private: - RF24 rf24; - uint8_t _address; - uint8_t _paLevel; -}; +bool transportInit(); +void transportSetAddress(uint8_t address); +uint8_t transportGetAddress(); +bool transportSend(uint8_t to, const void* data, uint8_t len); +bool transportAvailable(uint8_t *to); +uint8_t transportReceive(void* data); +void transportPowerDown(); #endif diff --git a/libraries/MySensors/core/MyTransportRFM69.cpp b/libraries/MySensors/core/MyTransportRFM69.cpp index 30e923e..fc3deb1 100644 --- a/libraries/MySensors/core/MyTransportRFM69.cpp +++ b/libraries/MySensors/core/MyTransportRFM69.cpp @@ -20,52 +20,49 @@ #include "MyTransport.h" #include "MyTransportRFM69.h" -MyTransportRFM69::MyTransportRFM69() - : - MyTransport(), - radio(MY_RF69_SPI_CS, MY_RF69_IRQ_PIN, MY_IS_RFM69HW, MY_RF69_IRQ_NUM) -{ -} +RFM69 _radio(MY_RF69_SPI_CS, MY_RF69_IRQ_PIN, MY_IS_RFM69HW, MY_RF69_IRQ_NUM); +uint8_t _address; -bool MyTransportRFM69::init() { + +bool transportInit() { // Start up the radio library (_address will be set later by the MySensors library) - radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID); + _radio.initialize(MY_RFM69_FREQUENCY, _address, MY_RFM69_NETWORKID); #ifdef MY_RFM69_ENABLE_ENCRYPTION - radio.encrypt(RFM69_ENCRYPTKEY); + _radio.encrypt(RFM69_ENCRYPTKEY); #endif return true; } -void MyTransportRFM69::setAddress(uint8_t address) { +void transportSetAddress(uint8_t address) { _address = address; - radio.setAddress(address); + _radio.setAddress(address); } -uint8_t MyTransportRFM69::getAddress() { +uint8_t transportGetAddress() { return _address; } -bool MyTransportRFM69::send(uint8_t to, const void* data, uint8_t len) { - return radio.sendWithRetry(to,data,len); +bool transportSend(uint8_t to, const void* data, uint8_t len) { + return _radio.sendWithRetry(to,data,len); } -bool MyTransportRFM69::available(uint8_t *to) { - if (radio.TARGETID == BROADCAST_ADDRESS) +bool transportAvailable(uint8_t *to) { + if (_radio.TARGETID == BROADCAST_ADDRESS) *to = BROADCAST_ADDRESS; else *to = _address; - return radio.receiveDone(); + return _radio.receiveDone(); } -uint8_t MyTransportRFM69::receive(void* data) { - memcpy(data,(const void *)radio.DATA, radio.DATALEN); +uint8_t transportReceive(void* data) { + memcpy(data,(const void *)_radio.DATA, _radio.DATALEN); // Send ack back if this message wasn't a broadcast - if (radio.TARGETID != RF69_BROADCAST_ADDR) - radio.ACKRequested(); - radio.sendACK(); - return radio.DATALEN; + if (_radio.TARGETID != RF69_BROADCAST_ADDR) + _radio.ACKRequested(); + _radio.sendACK(); + return _radio.DATALEN; } -void MyTransportRFM69::powerDown() { - radio.sleep(); +void transportPowerDown() { + _radio.sleep(); } diff --git a/libraries/MySensors/core/MyTransportRFM69.h b/libraries/MySensors/core/MyTransportRFM69.h index 1336d1e..36ef1a9 100644 --- a/libraries/MySensors/core/MyTransportRFM69.h +++ b/libraries/MySensors/core/MyTransportRFM69.h @@ -27,20 +27,12 @@ #include "drivers/SPI/SPI.h" -class MyTransportRFM69 : public MyTransport -{ -public: - MyTransportRFM69(); - bool init(); - void setAddress(uint8_t address); - uint8_t getAddress(); - bool send(uint8_t to, const void* data, uint8_t len); - bool available(uint8_t *to); - uint8_t receive(void* data); - void powerDown(); -private: - RFM69 radio; - uint8_t _address; -}; +bool transportInit(); +void transportSetAddress(uint8_t address); +uint8_t transportGetAddress(); +bool transportSend(uint8_t to, const void* data, uint8_t len); +bool transportAvailable(uint8_t *to); +uint8_t transportReceive(void* data); +void transportPowerDown(); #endif diff --git a/libraries/MySensors/drivers/DigitalIO/DigitalIO.h b/libraries/MySensors/drivers/AVR/DigitalIO/DigitalIO.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/DigitalIO.h rename to libraries/MySensors/drivers/AVR/DigitalIO/DigitalIO.h diff --git a/libraries/MySensors/drivers/DigitalIO/DigitalPin.h b/libraries/MySensors/drivers/AVR/DigitalIO/DigitalPin.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/DigitalPin.h rename to libraries/MySensors/drivers/AVR/DigitalIO/DigitalPin.h diff --git a/libraries/MySensors/drivers/DigitalIO/I2cConstants.h b/libraries/MySensors/drivers/AVR/DigitalIO/I2cConstants.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/I2cConstants.h rename to libraries/MySensors/drivers/AVR/DigitalIO/I2cConstants.h diff --git a/libraries/MySensors/drivers/DigitalIO/PinIO.cpp b/libraries/MySensors/drivers/AVR/DigitalIO/PinIO.cpp similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/PinIO.cpp rename to libraries/MySensors/drivers/AVR/DigitalIO/PinIO.cpp diff --git a/libraries/MySensors/drivers/DigitalIO/PinIO.h b/libraries/MySensors/drivers/AVR/DigitalIO/PinIO.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/PinIO.h rename to libraries/MySensors/drivers/AVR/DigitalIO/PinIO.h diff --git a/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp b/libraries/MySensors/drivers/AVR/DigitalIO/SoftI2cMaster.cpp similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.cpp rename to libraries/MySensors/drivers/AVR/DigitalIO/SoftI2cMaster.cpp diff --git a/libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h b/libraries/MySensors/drivers/AVR/DigitalIO/SoftI2cMaster.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/SoftI2cMaster.h rename to libraries/MySensors/drivers/AVR/DigitalIO/SoftI2cMaster.h diff --git a/libraries/MySensors/drivers/DigitalIO/SoftSPI.h b/libraries/MySensors/drivers/AVR/DigitalIO/SoftSPI.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/SoftSPI.h rename to libraries/MySensors/drivers/AVR/DigitalIO/SoftSPI.h diff --git a/libraries/MySensors/drivers/DigitalIO/attic/ADS7818.h b/libraries/MySensors/drivers/AVR/DigitalIO/attic/ADS7818.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/attic/ADS7818.h rename to libraries/MySensors/drivers/AVR/DigitalIO/attic/ADS7818.h diff --git a/libraries/MySensors/drivers/DigitalIO/attic/MCP320X.h b/libraries/MySensors/drivers/AVR/DigitalIO/attic/MCP320X.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/attic/MCP320X.h rename to libraries/MySensors/drivers/AVR/DigitalIO/attic/MCP320X.h diff --git a/libraries/MySensors/drivers/DigitalIO/attic/MCP355X.h b/libraries/MySensors/drivers/AVR/DigitalIO/attic/MCP355X.h similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/attic/MCP355X.h rename to libraries/MySensors/drivers/AVR/DigitalIO/attic/MCP355X.h diff --git a/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinBlink/DigitalPinBlink.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinConfigToggle/DigitalPinConfigToggle.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinReadWrite/DigitalPinReadWrite.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/DigitalPinShiftOut/DigitalPinShiftOut.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/PinIOBegin/PinIOBegin.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/PinIOBegin/PinIOBegin.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/PinIOBegin/PinIOBegin.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/PinIOBegin/PinIOBegin.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/PinIOConfigToggle/PinIOConfigToggle.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/PinIOReadWrite/PinIOReadWrite.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/ScanI2cBus/ScanI2cBus.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/SoftDS1307Utility/SoftDS1307Utility.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/testArduino/testArduino.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/testArduino/testArduino.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/testArduino/testArduino.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/testArduino/testArduino.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/testDigitalPin/testDigitalPin.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/testDigitalPin/testDigitalPin.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/testDigitalPin/testDigitalPin.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/testDigitalPin/testDigitalPin.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/testFastDigital/testFastDigital.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/testFastDigital/testFastDigital.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/testFastDigital/testFastDigital.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/testFastDigital/testFastDigital.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/testPinIO/testPinIO.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/testPinIO/testPinIO.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/testPinIO/testPinIO.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/testPinIO/testPinIO.ino diff --git a/libraries/MySensors/drivers/DigitalIO/examples/testSoftSPI/testSoftSPI.ino b/libraries/MySensors/drivers/AVR/DigitalIO/examples/testSoftSPI/testSoftSPI.ino similarity index 100% rename from libraries/MySensors/drivers/DigitalIO/examples/testSoftSPI/testSoftSPI.ino rename to libraries/MySensors/drivers/AVR/DigitalIO/examples/testSoftSPI/testSoftSPI.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/Dhcp.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dhcp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/Dhcp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dns.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/Dns.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/Dns.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/Dns.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/README b/libraries/MySensors/drivers/AVR/Ethernet_UIP/README similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/README rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/README diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPClient.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPClient.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPClient.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPEthernet.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPServer.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPServer.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPServer.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/UIPUdp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/ethernet_comp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/ethernet_comp.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/ethernet_comp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/ethernet_comp.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/EchoServer/EchoServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/EchoServer/EchoServer.ino similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/examples/EchoServer/EchoServer.ino rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/EchoServer/EchoServer.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpClient/TcpClient.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpClient/TcpClient.ino similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/examples/TcpClient/TcpClient.ino rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpClient/TcpClient.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/TcpServer/TcpServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpServer/TcpServer.ino similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/examples/TcpServer/TcpServer.ino rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpServer/TcpServer.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpClient/UdpClient.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpClient/UdpClient.ino similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/examples/UdpClient/UdpClient.ino rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpClient/UdpClient.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/examples/UdpServer/UdpServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpServer/UdpServer.ino similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/examples/UdpServer/UdpServer.ino rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpServer/UdpServer.ino diff --git a/libraries/MySensors/drivers/Ethernet_UIP/keywords.txt b/libraries/MySensors/drivers/AVR/Ethernet_UIP/keywords.txt similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/keywords.txt rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/keywords.txt diff --git a/libraries/MySensors/drivers/Ethernet_UIP/library.properties b/libraries/MySensors/drivers/AVR/Ethernet_UIP/library.properties similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/library.properties rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/library.properties diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpclient.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpclient.pl similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpclient.pl rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpclient.pl diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpserver.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpserver.pl similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/tests/perl/tcpserver.pl rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpserver.pl diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpclient.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpclient.pl similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpclient.pl rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpclient.pl diff --git a/libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpserver.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpserver.pl similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/tests/perl/udpserver.pl rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpserver.pl diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/Enc28J60Network.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/Enc28J60Network.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/Enc28J60Network.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/Enc28J60Network.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/Enc28J60Network.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/clock-arch.c similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.c rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/clock-arch.c diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/clock-arch.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/clock-arch.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/clock-arch.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/enc28j60.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/enc28j60.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/enc28j60.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/enc28j60.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/mempool.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/mempool.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/mempool.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/mempool.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/mempool.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/mempool_conf.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/mempool_conf.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/mempool_conf.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/mempool_conf.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip-conf.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip-conf.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip-conf.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip-conf.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip.c similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip.c rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip.c diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arch.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arch.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arch.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arch.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.c similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.c rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.c diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_arp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_clock.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_clock.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_clock.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_clock.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.cpp diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_debug.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.c similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.c rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.c diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uip_timer.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uipethernet-conf.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipethernet-conf.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uipethernet-conf.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipethernet-conf.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/uipopt.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipopt.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/uipopt.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipopt.h diff --git a/libraries/MySensors/drivers/Ethernet_UIP/utility/util.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/util.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_UIP/utility/util.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/util.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Client.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Client.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Client.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Client.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Dhcp.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Dhcp.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Dhcp.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dhcp.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Dhcp.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Dhcp.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Dhcp.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dns.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Dns.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Dns.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Dns.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Dns.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Dns.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Dns.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Dns.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Ethernet.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Ethernet.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Ethernet.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Ethernet.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Ethernet.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Ethernet.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Ethernet.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetClient.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetClient.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetClient.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/EthernetClient.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetClient.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetServer.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetServer.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetServer.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/EthernetServer.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetServer.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetUdp.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetUdp.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetUdp.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/EthernetUdp.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/EthernetUdp.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/IPAddress.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/IPAddress.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/IPAddress.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/IPAddress.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/IPAddress.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/IPAddress.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/IPAddress.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/Server.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/Server.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/Server.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/Server.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/socket.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/utility/socket.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/socket.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/socket.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/socket.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/utility/socket.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/socket.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/util.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/util.h similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/utility/util.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/util.h diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.cpp b/libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/w5100.cpp similarity index 100% rename from libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/w5100.cpp diff --git a/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.h b/libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/w5100.h similarity index 99% rename from libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.h rename to libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/w5100.h index 358e25c..0397866 100644 --- a/libraries/MySensors/drivers/Ethernet_W5100/utility/w5100.h +++ b/libraries/MySensors/drivers/AVR/Ethernet_W5100/utility/w5100.h @@ -10,7 +10,7 @@ #ifndef W5100_H_INCLUDED #define W5100_H_INCLUDED -#include "drivers/SPI/SPI.h" +#include "drivers/AVR/SPI/SPI.h" #define ETHERNET_SHIELD_SPI_CS 10 diff --git a/libraries/MySensors/drivers/SPI/SPI.cpp b/libraries/MySensors/drivers/AVR/SPI/SPI.cpp similarity index 100% rename from libraries/MySensors/drivers/SPI/SPI.cpp rename to libraries/MySensors/drivers/AVR/SPI/SPI.cpp diff --git a/libraries/MySensors/drivers/SPI/SPI.h b/libraries/MySensors/drivers/AVR/SPI/SPI.h similarity index 100% rename from libraries/MySensors/drivers/SPI/SPI.h rename to libraries/MySensors/drivers/AVR/SPI/SPI.h diff --git a/libraries/MySensors/drivers/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/libraries/MySensors/drivers/AVR/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino similarity index 100% rename from libraries/MySensors/drivers/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino rename to libraries/MySensors/drivers/AVR/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino diff --git a/libraries/MySensors/drivers/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/libraries/MySensors/drivers/AVR/SPI/examples/DigitalPotControl/DigitalPotControl.ino similarity index 100% rename from libraries/MySensors/drivers/SPI/examples/DigitalPotControl/DigitalPotControl.ino rename to libraries/MySensors/drivers/AVR/SPI/examples/DigitalPotControl/DigitalPotControl.ino diff --git a/libraries/MySensors/drivers/SPI/keywords.txt b/libraries/MySensors/drivers/AVR/SPI/keywords.txt similarity index 100% rename from libraries/MySensors/drivers/SPI/keywords.txt rename to libraries/MySensors/drivers/AVR/SPI/keywords.txt diff --git a/libraries/MySensors/drivers/SPI/library.properties b/libraries/MySensors/drivers/AVR/SPI/library.properties similarity index 100% rename from libraries/MySensors/drivers/SPI/library.properties rename to libraries/MySensors/drivers/AVR/SPI/library.properties diff --git a/libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.cpp b/libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.cpp new file mode 100644 index 0000000..dfd968a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.cpp @@ -0,0 +1,118 @@ +/* + EEPROM.cpp - esp8266 EEPROM emulation + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ + +#include "Arduino.h" +#include "EEPROM.h" + + extern "C" { +#include "c_types.h" +#include "ets_sys.h" +#include "os_type.h" +#include "osapi.h" +#include "spi_flash.h" +} + +EEPROMClass::EEPROMClass(uint32_t sector) +: _sector(sector) +, _data(0) +, _size(0) +, _dirty(false) +{ +} + +void EEPROMClass::begin(size_t size) { + if (size <= 0) + return; + if (size > SPI_FLASH_SEC_SIZE) + size = SPI_FLASH_SEC_SIZE; + + if (_data) { + delete[] _data; + } + + _data = new uint8_t[size]; + _size = size; + + noInterrupts(); + spi_flash_read(_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast(_data), _size); + interrupts(); +} + +void EEPROMClass::end() { + if (!_size) + return; + + commit(); + if(_data) { + delete[] _data; + } + _data = 0; + _size = 0; +} + + +uint8_t EEPROMClass::read(int address) { + if (address < 0 || (size_t)address >= _size) + return 0; + if(!_data) + return 0; + + return _data[address]; +} + +void EEPROMClass::write(int address, uint8_t value) { + if (address < 0 || (size_t)address >= _size) + return; + if(!_data) + return; + + _data[address] = value; + _dirty = true; +} + +bool EEPROMClass::commit() { + bool ret = false; + if (!_size) + return false; + if(!_dirty) + return true; + if(!_data) + return false; + + noInterrupts(); + if(spi_flash_erase_sector(_sector) == SPI_FLASH_RESULT_OK) { + if(spi_flash_write(_sector * SPI_FLASH_SEC_SIZE, reinterpret_cast(_data), _size) == SPI_FLASH_RESULT_OK) { + _dirty = false; + ret = true; + } + } + interrupts(); + + return ret; +} + +uint8_t * EEPROMClass::getDataPtr() { + _dirty = true; + return &_data[0]; +} + +extern "C" uint32_t _SPIFFS_end; +EEPROMClass EEPROM((((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE)); diff --git a/libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.h b/libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.h new file mode 100644 index 0000000..ef7ac45 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/EEPROM/EEPROM.h @@ -0,0 +1,70 @@ +/* + EEPROM.cpp - esp8266 EEPROM emulation + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ + +#ifndef EEPROM_h +#define EEPROM_h + +#include +#include +#include + +class EEPROMClass { +public: + EEPROMClass(uint32_t sector); + + void begin(size_t size); + uint8_t read(int address); + void write(int address, uint8_t val); + bool commit(); + void end(); + + uint8_t * getDataPtr(); + + template + T &get(int address, T &t) { + if (address < 0 || address + sizeof(T) > _size) + return t; + + memcpy((uint8_t*) &t, _data + address, sizeof(T)); + return t; + } + + template + const T &put(int address, const T &t) { + if (address < 0 || address + sizeof(T) > _size) + return t; + + memcpy(_data + address, (const uint8_t*) &t, sizeof(T)); + _dirty = true; + return t; + } + +protected: + uint32_t _sector; + uint8_t* _data; + size_t _size; + bool _dirty; +}; + +extern EEPROMClass EEPROM; + +#endif + diff --git a/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_clear/eeprom_clear.ino b/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_clear/eeprom_clear.ino new file mode 100644 index 0000000..98b7ad7 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_clear/eeprom_clear.ino @@ -0,0 +1,26 @@ +/* + * EEPROM Clear + * + * Sets all of the bytes of the EEPROM to 0. + * This example code is in the public domain. + + */ + +#include + +void setup() +{ + EEPROM.begin(512); + // write a 0 to all 512 bytes of the EEPROM + for (int i = 0; i < 512; i++) + EEPROM.write(i, 0); + + // turn the LED on when we're done + pinMode(13, OUTPUT); + digitalWrite(13, HIGH); + EEPROM.end(); +} + +void loop() +{ +} diff --git a/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_read/eeprom_read.ino b/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_read/eeprom_read.ino new file mode 100644 index 0000000..d1395b3 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_read/eeprom_read.ino @@ -0,0 +1,44 @@ +/* + * EEPROM Read + * + * Reads the value of each byte of the EEPROM and prints it + * to the computer. + * This example code is in the public domain. + */ + +#include + +// start reading from the first byte (address 0) of the EEPROM +int address = 0; +byte value; + +void setup() +{ + // initialize serial and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + EEPROM.begin(512); +} + +void loop() +{ + // read a byte from the current address of the EEPROM + value = EEPROM.read(address); + + Serial.print(address); + Serial.print("\t"); + Serial.print(value, DEC); + Serial.println(); + + // advance to the next address of the EEPROM + address = address + 1; + + // there are only 512 bytes of EEPROM, from 0 to 511, so if we're + // on address 512, wrap around to address 0 + if (address == 512) + address = 0; + + delay(500); +} diff --git a/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_write/eeprom_write.ino b/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_write/eeprom_write.ino new file mode 100644 index 0000000..b41a5ca --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/EEPROM/examples/eeprom_write/eeprom_write.ino @@ -0,0 +1,43 @@ +/* + * EEPROM Write + * + * Stores values read from analog input 0 into the EEPROM. + * These values will stay in the EEPROM when the board is + * turned off and may be retrieved later by another sketch. + */ + +#include + +// the current address in the EEPROM (i.e. which byte +// we're going to write to next) +int addr = 0; + +void setup() +{ + EEPROM.begin(512); +} + +void loop() +{ + // need to divide by 4 because analog inputs range from + // 0 to 1023 and each byte of the EEPROM can only hold a + // value from 0 to 255. + int val = analogRead(A0) / 4; + + // write the value to the appropriate byte of the EEPROM. + // these values will remain there when the board is + // turned off. + EEPROM.write(addr, val); + + // advance to the next address. there are 512 bytes in + // the EEPROM, so go back to 0 when we hit 512. + // save all changes to the flash. + addr = addr + 1; + if (addr == 512) + { + addr = 0; + EEPROM.commit(); + } + + delay(100); +} diff --git a/libraries/MySensors/drivers/ESP8266/EEPROM/keywords.txt b/libraries/MySensors/drivers/ESP8266/EEPROM/keywords.txt new file mode 100644 index 0000000..d3218fe --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/EEPROM/keywords.txt @@ -0,0 +1,18 @@ +####################################### +# Syntax Coloring Map For Ultrasound +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +EEPROM KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/MySensors/drivers/ESP8266/EEPROM/library.properties b/libraries/MySensors/drivers/ESP8266/EEPROM/library.properties new file mode 100644 index 0000000..fbd9908 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/EEPROM/library.properties @@ -0,0 +1,8 @@ +name=EEPROM +version=1.0 +author=Ivan Grokhotkov +maintainer=Ivan Grokhotkov +sentence=Enables reading and writing data to the permanent FLASH storage, up to 4kb. +paragraph= +url=http://arduino.cc/en/Reference/EEPROM +architectures=esp8266 diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/NTPClient/NTPClient.ino b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/NTPClient/NTPClient.ino new file mode 100644 index 0000000..4176c51 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/NTPClient/NTPClient.ino @@ -0,0 +1,153 @@ +/* + + Udp NTP Client + + Get the time from a Network Time Protocol (NTP) time server + Demonstrates use of UDP sendPacket and ReceivePacket + For more on NTP time servers and the messages needed to communicate with them, + see http://en.wikipedia.org/wiki/Network_Time_Protocol + + created 4 Sep 2010 + by Michael Margolis + modified 9 Apr 2012 + by Tom Igoe + updated for the ESP8266 12 Apr 2015 + by Ivan Grokhotkov + + This code is in the public domain. + + */ + +#include +#include + +char ssid[] = "*************"; // your network SSID (name) +char pass[] = "********"; // your network password + + +unsigned int localPort = 2390; // local port to listen for UDP packets + +/* Don't hardwire the IP address or we won't get the benefits of the pool. + * Lookup the IP address for the host name instead */ +//IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server +IPAddress timeServerIP; // time.nist.gov NTP server address +const char* ntpServerName = "time.nist.gov"; + +const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message + +byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets + +// A UDP instance to let us send and receive packets over UDP +WiFiUDP udp; + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println(); + + // We start by connecting to a WiFi network + Serial.print("Connecting to "); + Serial.println(ssid); + WiFi.begin(ssid, pass); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + + Serial.println("Starting UDP"); + udp.begin(localPort); + Serial.print("Local port: "); + Serial.println(udp.localPort()); +} + +void loop() +{ + //get a random server from the pool + WiFi.hostByName(ntpServerName, timeServerIP); + + sendNTPpacket(timeServerIP); // send an NTP packet to a time server + // wait to see if a reply is available + delay(1000); + + int cb = udp.parsePacket(); + if (!cb) { + Serial.println("no packet yet"); + } + else { + Serial.print("packet received, length="); + Serial.println(cb); + // We've received a packet, read the data from it + udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer + + //the timestamp starts at byte 40 of the received packet and is four bytes, + // or two words, long. First, esxtract the two words: + + unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); + unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); + // combine the four bytes (two words) into a long integer + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = highWord << 16 | lowWord; + Serial.print("Seconds since Jan 1 1900 = " ); + Serial.println(secsSince1900); + + // now convert NTP time into everyday time: + Serial.print("Unix time = "); + // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: + const unsigned long seventyYears = 2208988800UL; + // subtract seventy years: + unsigned long epoch = secsSince1900 - seventyYears; + // print Unix time: + Serial.println(epoch); + + + // print the hour, minute and second: + Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) + Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) + Serial.print(':'); + if ( ((epoch % 3600) / 60) < 10 ) { + // In the first 10 minutes of each hour, we'll want a leading '0' + Serial.print('0'); + } + Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) + Serial.print(':'); + if ( (epoch % 60) < 10 ) { + // In the first 10 seconds of each minute, we'll want a leading '0' + Serial.print('0'); + } + Serial.println(epoch % 60); // print the second + } + // wait ten seconds before asking for the time again + delay(10000); +} + +// send an NTP request to the time server at the given address +unsigned long sendNTPpacket(IPAddress& address) +{ + Serial.println("sending NTP packet..."); + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + udp.beginPacket(address, 123); //NTP requests are to port 123 + udp.write(packetBuffer, NTP_PACKET_SIZE); + udp.endPacket(); +} diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino new file mode 100644 index 0000000..1a11307 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, Majenko Technologies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * * Neither the name of Majenko Technologies nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Create a WiFi access point and provide a web server on it. */ + +#include +#include +#include + +/* Set these to your desired credentials. */ +const char *ssid = "ESPap"; +const char *password = "thereisnospoon"; + +ESP8266WebServer server(80); + +/* Just a little test message. Go to http://192.168.4.1 in a web browser + * connected to this access point to see it. + */ +void handleRoot() { + server.send(200, "text/html", "

You are connected

"); +} + +void setup() { + delay(1000); + Serial.begin(115200); + Serial.println(); + Serial.print("Configuring access point..."); + /* You can remove the password parameter if you want the AP to be open. */ + WiFi.softAP(ssid, password); + + IPAddress myIP = WiFi.softAPIP(); + Serial.print("AP IP address: "); + Serial.println(myIP); + server.on("/", handleRoot); + server.begin(); + Serial.println("HTTP server started"); +} + +void loop() { + server.handleClient(); +} diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino new file mode 100644 index 0000000..7ffc78a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino @@ -0,0 +1,85 @@ +/* + * This sketch sends data via HTTP GET requests to data.sparkfun.com service. + * + * You need to get streamId and privateKey at data.sparkfun.com and paste them + * below. Or just customize this script to talk to other HTTP servers. + * + */ + +#include + +const char* ssid = "your-ssid"; +const char* password = "your-password"; + +const char* host = "data.sparkfun.com"; +const char* streamId = "...................."; +const char* privateKey = "...................."; + +void setup() { + Serial.begin(115200); + delay(10); + + // We start by connecting to a WiFi network + + Serial.println(); + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +int value = 0; + +void loop() { + delay(5000); + ++value; + + Serial.print("connecting to "); + Serial.println(host); + + // Use WiFiClient class to create TCP connections + WiFiClient client; + const int httpPort = 80; + if (!client.connect(host, httpPort)) { + Serial.println("connection failed"); + return; + } + + // We now create a URI for the request + String url = "/input/"; + url += streamId; + url += "?private_key="; + url += privateKey; + url += "&value="; + url += value; + + Serial.print("Requesting URL: "); + Serial.println(url); + + // This will send the request to the server + client.print(String("GET ") + url + " HTTP/1.1\r\n" + + "Host: " + host + "\r\n" + + "Connection: close\r\n\r\n"); + delay(10); + + // Read all the lines of the reply from server and print them to Serial + while(client.available()){ + String line = client.readStringUntil('\r'); + Serial.print(line); + } + + Serial.println(); + Serial.println("closing connection"); +} + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino new file mode 100644 index 0000000..7080325 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiMulti/WiFiMulti.ino @@ -0,0 +1,33 @@ +/* + * This sketch trys to Connect to the best AP based on a given list + * + */ + +#include +#include + +ESP8266WiFiMulti wifiMulti; + +void setup() { + Serial.begin(115200); + delay(10); + + wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); + wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); + wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); + + Serial.println("Connecting Wifi..."); + if(wifiMulti.run() == WL_CONNECTED) { + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + } +} + +void loop() { + if(wifiMulti.run() != WL_CONNECTED) { + Serial.println("WiFi not connected!"); + delay(1000); + } +} \ No newline at end of file diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino new file mode 100644 index 0000000..3e6ff73 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino @@ -0,0 +1,48 @@ +/* + * This sketch demonstrates how to scan WiFi networks. + * The API is almost the same as with the WiFi Shield library, + * the most obvious difference being the different file you need to include: + */ +#include "ESP8266WiFi.h" + +void setup() { + Serial.begin(115200); + + // Set WiFi to station mode and disconnect from an AP if it was previously connected + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + delay(100); + + Serial.println("Setup done"); +} + +void loop() { + Serial.println("scan start"); + + // WiFi.scanNetworks will return the number of networks found + int n = WiFi.scanNetworks(); + Serial.println("scan done"); + if (n == 0) + Serial.println("no networks found"); + else + { + Serial.print(n); + Serial.println(" networks found"); + for (int i = 0; i < n; ++i) + { + // Print SSID and RSSI for each network found + Serial.print(i + 1); + Serial.print(": "); + Serial.print(WiFi.SSID(i)); + Serial.print(" ("); + Serial.print(WiFi.RSSI(i)); + Serial.print(")"); + Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*"); + delay(10); + } + } + Serial.println(""); + + // Wait a bit before scanning again + delay(5000); +} diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino new file mode 100644 index 0000000..43a9d82 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiTelnetToSerial/WiFiTelnetToSerial.ino @@ -0,0 +1,90 @@ +/* + WiFiTelnetToSerial - Example Transparent UART to Telnet Server for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the ESP8266WiFi library for Arduino environment. + + 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 +*/ +#include + +//how many clients should be able to telnet to this ESP8266 +#define MAX_SRV_CLIENTS 1 +const char* ssid = "**********"; +const char* password = "**********"; + +WiFiServer server(21); +WiFiClient serverClients[MAX_SRV_CLIENTS]; + +void setup() { + Serial1.begin(115200); + WiFi.begin(ssid, password); + Serial1.print("\nConnecting to "); Serial1.println(ssid); + uint8_t i = 0; + while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500); + if(i == 21){ + Serial1.print("Could not connect to"); Serial1.println(ssid); + while(1) delay(500); + } + //start UART and the server + Serial.begin(115200); + server.begin(); + server.setNoDelay(true); + + Serial1.print("Ready! Use 'telnet "); + Serial1.print(WiFi.localIP()); + Serial1.println(" 21' to connect"); +} + +void loop() { + uint8_t i; + //check if there are any new clients + if (server.hasClient()){ + for(i = 0; i < MAX_SRV_CLIENTS; i++){ + //find free/disconnected spot + if (!serverClients[i] || !serverClients[i].connected()){ + if(serverClients[i]) serverClients[i].stop(); + serverClients[i] = server.available(); + Serial1.print("New client: "); Serial1.print(i); + continue; + } + } + //no free/disconnected spot so reject + WiFiClient serverClient = server.available(); + serverClient.stop(); + } + //check clients for data + for(i = 0; i < MAX_SRV_CLIENTS; i++){ + if (serverClients[i] && serverClients[i].connected()){ + if(serverClients[i].available()){ + //get data from the telnet client and push it to the UART + while(serverClients[i].available()) Serial.write(serverClients[i].read()); + } + } + } + //check UART for data + if(Serial.available()){ + size_t len = Serial.available(); + uint8_t sbuf[len]; + Serial.readBytes(sbuf, len); + //push UART data to all connected telnet clients + for(i = 0; i < MAX_SRV_CLIENTS; i++){ + if (serverClients[i] && serverClients[i].connected()){ + serverClients[i].write(sbuf, len); + delay(1); + } + } + } +} diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiWebServer/WiFiWebServer.ino b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiWebServer/WiFiWebServer.ino new file mode 100644 index 0000000..fa40678 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/examples/WiFiWebServer/WiFiWebServer.ino @@ -0,0 +1,98 @@ +/* + * This sketch demonstrates how to set up a simple HTTP-like server. + * The server will set a GPIO pin depending on the request + * http://server_ip/gpio/0 will set the GPIO2 low, + * http://server_ip/gpio/1 will set the GPIO2 high + * server_ip is the IP address of the ESP8266 module, will be + * printed to Serial when the module is connected. + */ + +#include + +const char* ssid = "your-ssid"; +const char* password = "your-password"; + +// Create an instance of the server +// specify the port to listen on as an argument +WiFiServer server(80); + +void setup() { + Serial.begin(115200); + delay(10); + + // prepare GPIO2 + pinMode(2, OUTPUT); + digitalWrite(2, 0); + + // Connect to WiFi network + Serial.println(); + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.println("WiFi connected"); + + // Start the server + server.begin(); + Serial.println("Server started"); + + // Print the IP address + Serial.println(WiFi.localIP()); +} + +void loop() { + // Check if a client has connected + WiFiClient client = server.available(); + if (!client) { + return; + } + + // Wait until the client sends some data + Serial.println("new client"); + while(!client.available()){ + delay(1); + } + + // Read the first line of the request + String req = client.readStringUntil('\r'); + Serial.println(req); + client.flush(); + + // Match the request + int val; + if (req.indexOf("/gpio/0") != -1) + val = 0; + else if (req.indexOf("/gpio/1") != -1) + val = 1; + else { + Serial.println("invalid request"); + client.stop(); + return; + } + + // Set GPIO2 according to the request + digitalWrite(2, val); + + client.flush(); + + // Prepare the response + String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n\r\n\r\nGPIO is now "; + s += (val)?"high":"low"; + s += "\n"; + + // Send the response to the client + client.print(s); + delay(1); + Serial.println("Client disonnected"); + + // The client will actually be disconnected + // when the function returns and 'client' object is detroyed +} + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/keywords.txt b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/keywords.txt new file mode 100644 index 0000000..e693ea4 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/keywords.txt @@ -0,0 +1,67 @@ +####################################### +# Syntax Coloring Map For ESP8266WiFi +####################################### + +####################################### +# Library (KEYWORD3) +####################################### + +ESP8266WiFi KEYWORD3 + +####################################### +# Datatypes (KEYWORD1) +####################################### + +WiFi KEYWORD1 +WiFiClient KEYWORD1 +WiFiServer KEYWORD1 +WiFiUDP KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +status KEYWORD2 +mode KEYWORD2 +connect KEYWORD2 +write KEYWORD2 +available KEYWORD2 +config KEYWORD2 +setDNS KEYWORD2 +read KEYWORD2 +flush KEYWORD2 +stop KEYWORD2 +connected KEYWORD2 +begin KEYWORD2 +beginMulticast KEYWORD2 +disconnect KEYWORD2 +macAddress KEYWORD2 +localIP KEYWORD2 +subnetMask KEYWORD2 +gatewayIP KEYWORD2 +SSID KEYWORD2 +BSSID KEYWORD2 +RSSI KEYWORD2 +encryptionType KEYWORD2 +beginPacket KEYWORD2 +beginPacketMulticast KEYWORD2 +endPacket KEYWORD2 +parsePacket KEYWORD2 +destinationIP KEYWORD2 +remoteIP KEYWORD2 +remotePort KEYWORD2 +softAP KEYWORD2 +softAPIP KEYWORD2 +softAPmacAddress KEYWORD2 +softAPConfig KEYWORD2 +printDiag KEYWORD2 +hostByName KEYWORD2 +scanNetworks KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +WIFI_AP LITERAL1 +WIFI_STA LITERAL1 +WIFI_AP_STA LITERAL1 + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/library.properties b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/library.properties new file mode 100644 index 0000000..3db731e --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/library.properties @@ -0,0 +1,9 @@ +name=ESP8266WiFi +version=1.0 +author=Ivan Grokhotkov +maintainer=Ivan Grokhtkov +sentence=Enables network connection (local and Internet) using the ESP8266 built-in WiFi. +paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through WiFi. The shield can connect either to open or encrypted networks (WEP, WPA). The IP address can be assigned statically or through a DHCP. The library can also manage DNS. +category=Communication +url= +architectures=esp8266 diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.cpp b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.cpp new file mode 100644 index 0000000..f65907f --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.cpp @@ -0,0 +1,700 @@ +/* + ESP8266WiFi.cpp - WiFi library for esp8266 + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ + +#include "ESP8266WiFi.h" +extern "C" { +#include "c_types.h" +#include "ets_sys.h" +#include "os_type.h" +#include "osapi.h" +#include "mem.h" +#include "user_interface.h" +#include "smartconfig.h" +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/dns.h" +} + +#include "WiFiClient.h" +#include "WiFiUdp.h" + +extern "C" void esp_schedule(); +extern "C" void esp_yield(); + +ESP8266WiFiClass::ESP8266WiFiClass() +: _smartConfigStarted(false) +, _smartConfigDone(false) +, _useApMode(false) +, _useClientMode(false) +, _useStaticIp(false) +{ + wifi_set_event_handler_cb((wifi_event_handler_cb_t)&ESP8266WiFiClass::_eventCallback); +} + +void ESP8266WiFiClass::mode(WiFiMode m) +{ + if(wifi_get_opmode() == (uint8)m) { + return; + } + ETS_UART_INTR_DISABLE(); + wifi_set_opmode(m); + ETS_UART_INTR_ENABLE(); +} + +int ESP8266WiFiClass::begin(char* ssid, char *passphrase, int32_t channel, uint8_t bssid[6]){ + return begin((const char*) ssid, (const char*) passphrase, channel, bssid); +} + +int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase, int32_t channel, uint8_t bssid[6]){ + _useClientMode = true; + + if(_useApMode) { + // turn on AP+STA mode + mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_STA); + } + + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { + // fail SSID to long or missing! + return WL_CONNECT_FAILED; + } + + if(passphrase && strlen(passphrase) > 63) { + // fail passphrase to long! + return WL_CONNECT_FAILED; + } + + struct station_config conf; + strcpy(reinterpret_cast(conf.ssid), ssid); + + if (passphrase) { + strcpy(reinterpret_cast(conf.password), passphrase); + } else { + *conf.password = 0; + } + + if (bssid) { + conf.bssid_set = 1; + memcpy((void *) &conf.bssid[0], (void *) bssid, 6); + } else { + conf.bssid_set = 0; + } + + ETS_UART_INTR_DISABLE(); + wifi_station_set_config(&conf); + wifi_station_connect(); + ETS_UART_INTR_ENABLE(); + + if(channel > 0 && channel <= 13) { + wifi_set_channel(channel); + } + + if(!_useStaticIp) + wifi_station_dhcpc_start(); + return status(); +} + +uint8_t ESP8266WiFiClass::waitForConnectResult(){ + if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled + return WL_DISCONNECTED; + while (status() == WL_DISCONNECTED) + delay(100); + return status(); +} + + +// You will have to set the DNS-Server manually later since this will not enable DHCP2 +void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet) +{ + struct ip_info info; + info.ip.addr = static_cast(local_ip); + info.gw.addr = static_cast(gateway); + info.netmask.addr = static_cast(subnet); + + wifi_station_dhcpc_stop(); + wifi_set_ip_info(STATION_IF, &info); + + _useStaticIp = true; +} + +void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns) +{ + struct ip_info info; + info.ip.addr = static_cast(local_ip); + info.gw.addr = static_cast(gateway); + info.netmask.addr = static_cast(subnet); + + wifi_station_dhcpc_stop(); + wifi_set_ip_info(STATION_IF, &info); + + // Set DNS-Server + ip_addr_t d; + d.addr = static_cast(dns); + dns_setserver(0,&d); + + _useStaticIp = true; +} + +int ESP8266WiFiClass::disconnect() +{ + struct station_config conf; + *conf.ssid = 0; + *conf.password = 0; + ETS_UART_INTR_DISABLE(); + wifi_station_set_config(&conf); + wifi_station_disconnect(); + ETS_UART_INTR_ENABLE(); + return 0; +} + +void ESP8266WiFiClass::softAP(const char* ssid) +{ + softAP(ssid, 0); +} + + +void ESP8266WiFiClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden) +{ + _useApMode = true; + if(_useClientMode) { + // turn on AP+STA mode + mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_AP); + } + + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { + // fail SSID to long or missing! + return; + } + + if(passphrase && strlen(passphrase) > 63) { + // fail passphrase to long! + return; + } + + struct softap_config conf; + wifi_softap_get_config(&conf); + strcpy(reinterpret_cast(conf.ssid), ssid); + conf.channel = channel; + conf.ssid_len = strlen(ssid); + conf.ssid_hidden = ssid_hidden; + conf.max_connection = 4; + conf.beacon_interval = 100; + + if (!passphrase || strlen(passphrase) == 0) + { + conf.authmode = AUTH_OPEN; + *conf.password = 0; + } + else + { + conf.authmode = AUTH_WPA2_PSK; + strcpy(reinterpret_cast(conf.password), passphrase); + } + + ETS_UART_INTR_DISABLE(); + wifi_softap_set_config(&conf); + ETS_UART_INTR_ENABLE(); +} + +void ESP8266WiFiClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) +{ + struct ip_info info; + info.ip.addr = static_cast(local_ip); + info.gw.addr = static_cast(gateway); + info.netmask.addr = static_cast(subnet); + wifi_softap_dhcps_stop(); + wifi_set_ip_info(SOFTAP_IF, &info); + wifi_softap_dhcps_start(); +} + +uint8_t* ESP8266WiFiClass::macAddress(uint8_t* mac) +{ + wifi_get_macaddr(STATION_IF, mac); + return mac; +} + +String ESP8266WiFiClass::macAddress(void) +{ + uint8_t mac[6]; + char macStr[18] = {0}; + wifi_get_macaddr(STATION_IF, mac); + + sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return String(macStr); +} + +uint8_t* ESP8266WiFiClass::softAPmacAddress(uint8_t* mac) +{ + wifi_get_macaddr(SOFTAP_IF, mac); + return mac; +} + +String ESP8266WiFiClass::softAPmacAddress(void) +{ + uint8_t mac[6]; + char macStr[18] = {0}; + wifi_get_macaddr(SOFTAP_IF, mac); + + sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return String(macStr); +} + +IPAddress ESP8266WiFiClass::localIP() +{ + struct ip_info ip; + wifi_get_ip_info(STATION_IF, &ip); + return IPAddress(ip.ip.addr); +} + +IPAddress ESP8266WiFiClass::softAPIP() +{ + struct ip_info ip; + wifi_get_ip_info(SOFTAP_IF, &ip); + return IPAddress(ip.ip.addr); +} + +IPAddress ESP8266WiFiClass::subnetMask() +{ + struct ip_info ip; + wifi_get_ip_info(STATION_IF, &ip); + return IPAddress(ip.netmask.addr); +} + +IPAddress ESP8266WiFiClass::gatewayIP() +{ + struct ip_info ip; + wifi_get_ip_info(STATION_IF, &ip); + return IPAddress(ip.gw.addr); +} + +char* ESP8266WiFiClass::SSID() +{ + static struct station_config conf; + wifi_station_get_config(&conf); + return reinterpret_cast(conf.ssid); +} + +uint8_t* ESP8266WiFiClass::BSSID(void) +{ + static struct station_config conf; + wifi_station_get_config(&conf); + return reinterpret_cast(conf.bssid); +} + +String ESP8266WiFiClass::BSSIDstr(void) +{ + static struct station_config conf; + char mac[18] = {0}; + wifi_station_get_config(&conf); + sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X", conf.bssid[0], conf.bssid[1], conf.bssid[2], conf.bssid[3], conf.bssid[4], conf.bssid[5]); + return String(mac); +} + + +int32_t ESP8266WiFiClass::channel(void) { + return wifi_get_channel(); +} + + +int32_t ESP8266WiFiClass::RSSI(void) { + return wifi_station_get_rssi(); +} + +extern "C" +{ + typedef STAILQ_HEAD(, bss_info) bss_info_head_t; +} + +void ESP8266WiFiClass::_scanDone(void* result, int status) +{ + if (status != OK) + { + ESP8266WiFiClass::_scanCount = 0; + ESP8266WiFiClass::_scanResult = 0; + } + else + { + + int i = 0; + bss_info_head_t* head = reinterpret_cast(result); + + for (bss_info* it = STAILQ_FIRST(head); it; it = STAILQ_NEXT(it, next), ++i); + ESP8266WiFiClass::_scanCount = i; + if (i == 0) + { + ESP8266WiFiClass::_scanResult = 0; + } + else + { + bss_info* copied_info = new bss_info[i]; + i = 0; + for (bss_info* it = STAILQ_FIRST(head); it; it = STAILQ_NEXT(it, next), ++i) + { + memcpy(copied_info + i, it, sizeof(bss_info)); + } + + ESP8266WiFiClass::_scanResult = copied_info; + } + + } + + ESP8266WiFiClass::_scanStarted = false; + ESP8266WiFiClass::_scanComplete = true; + + if(!ESP8266WiFiClass::_scanAsync) { + esp_schedule(); + } +} + +int8_t ESP8266WiFiClass::scanComplete() { + + if(_scanStarted) { + return WIFI_SCAN_RUNNING; + } + + if(_scanComplete) { + return ESP8266WiFiClass::_scanCount; + } + + return WIFI_SCAN_FAILD; +} + +void ESP8266WiFiClass::scanDelete() +{ + if (ESP8266WiFiClass::_scanResult) + { + delete[] reinterpret_cast(ESP8266WiFiClass::_scanResult); + ESP8266WiFiClass::_scanResult = 0; + ESP8266WiFiClass::_scanCount = 0; + } + _scanComplete = false; +} + +int8_t ESP8266WiFiClass::scanNetworks(bool async) +{ + if(ESP8266WiFiClass::_scanStarted) { + return WIFI_SCAN_RUNNING; + } + + ESP8266WiFiClass::_scanAsync = async; + + if(_useApMode) { + // turn on AP+STA mode + mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_STA); + } + + int status = wifi_station_get_connect_status(); + if (status != STATION_GOT_IP && status != STATION_IDLE) + { + disconnect(); + } + + scanDelete(); + + struct scan_config config; + config.ssid = 0; + config.bssid = 0; + config.channel = 0; + config.show_hidden = 0; + if(wifi_station_scan(&config, reinterpret_cast(&ESP8266WiFiClass::_scanDone))) { + ESP8266WiFiClass::_scanComplete = false; + ESP8266WiFiClass::_scanStarted = true; + + if(ESP8266WiFiClass::_scanAsync) { + delay(0); // time for the OS to trigger the scan + return WIFI_SCAN_RUNNING; + } + + esp_yield(); + return ESP8266WiFiClass::_scanCount; + } else { + return WIFI_SCAN_FAILD; + } + +} + +void * ESP8266WiFiClass::_getScanInfoByIndex(int i) +{ + if (!ESP8266WiFiClass::_scanResult || (size_t)i > ESP8266WiFiClass::_scanCount) + { + return 0; + } + + return reinterpret_cast(ESP8266WiFiClass::_scanResult) + i; +} + +const char* ESP8266WiFiClass::SSID(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return 0; + + return reinterpret_cast(it->ssid); +} + +uint8_t * ESP8266WiFiClass::BSSID(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return 0; + + return it->bssid; +} + +String ESP8266WiFiClass::BSSIDstr(uint8_t i) +{ + char mac[18] = {0}; + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return String(""); + + sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X", it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]); + return String(mac); +} + +int32_t ESP8266WiFiClass::channel(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return 0; + + return it->channel; +} + +bool ESP8266WiFiClass::isHidden(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return false; + + return (it->is_hidden != 0); +} + +bool ESP8266WiFiClass::getNetworkInfo(uint8_t i, String &ssid, uint8_t &encType, int32_t &rssi, uint8_t* &bssid, int32_t &channel, bool &isHidden) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return false; + + ssid = (const char*)it->ssid; + encType = encryptionType(i); + rssi = it->rssi; + bssid = it->bssid; // move ptr + channel = it->channel; + isHidden = (it->is_hidden != 0); + + return true; +} + +int32_t ESP8266WiFiClass::RSSI(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return 0; + + return it->rssi; +} + +uint8_t ESP8266WiFiClass::encryptionType(uint8_t i) +{ + struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i)); + if (!it) + return -1; + + int authmode = it->authmode; + if (authmode == AUTH_OPEN) + return ENC_TYPE_NONE; + if (authmode == AUTH_WEP) + return ENC_TYPE_WEP; + if (authmode == AUTH_WPA_PSK) + return ENC_TYPE_TKIP; + if (authmode == AUTH_WPA2_PSK) + return ENC_TYPE_CCMP; + if (authmode == AUTH_WPA_WPA2_PSK) + return ENC_TYPE_AUTO; + return -1; +} + +wl_status_t ESP8266WiFiClass::status() +{ + int status = wifi_station_get_connect_status(); + + if (status == STATION_GOT_IP) + return WL_CONNECTED; + else if (status == STATION_NO_AP_FOUND) + return WL_NO_SSID_AVAIL; + else if (status == STATION_CONNECT_FAIL || status == STATION_WRONG_PASSWORD) + return WL_CONNECT_FAILED; + else if (status == STATION_IDLE) + return WL_IDLE_STATUS; + else + return WL_DISCONNECTED; +} + +void wifi_dns_found_callback(const char *name, ip_addr_t *ipaddr, void *callback_arg) +{ + if (ipaddr) + (*reinterpret_cast(callback_arg)) = ipaddr->addr; + esp_schedule(); // resume the hostByName function +} + +int ESP8266WiFiClass::hostByName(const char* aHostname, IPAddress& aResult) +{ + ip_addr_t addr; + aResult = static_cast(0); + err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult); + if (err == ERR_OK) + { + aResult = addr.addr; + } + else if (err == ERR_INPROGRESS) + { + esp_yield(); + // will return here when dns_found_callback fires + } + + return (aResult != 0) ? 1 : 0; +} + +void ESP8266WiFiClass::beginSmartConfig() +{ + if (_smartConfigStarted) + return; + + if(_useApMode) { + // turn on AP+STA mode + mode(WIFI_AP_STA); + } else { + // turn on STA mode + mode(WIFI_STA); + } + + _smartConfigStarted = true; + _smartConfigDone = false; + + //SC_TYPE_ESPTOUCH use ESPTOUCH for smartconfig, or use SC_TYPE_AIRKISS for AIRKISS + smartconfig_start(SC_TYPE_ESPTOUCH, reinterpret_cast(&ESP8266WiFiClass::_smartConfigCallback), 1); +} + +void ESP8266WiFiClass::stopSmartConfig() +{ + if (!_smartConfigStarted) + return; + + smartconfig_stop(); + _smartConfigStarted = false; +} + +bool ESP8266WiFiClass::smartConfigDone() +{ + if (!_smartConfigStarted) + return false; + + return _smartConfigDone; +} + +void ESP8266WiFiClass::_smartConfigCallback(uint32_t st, void* result) +{ + sc_status status = (sc_status) st; + if (status == SC_STATUS_LINK) { + station_config* sta_conf = reinterpret_cast(result); + + wifi_station_set_config(sta_conf); + wifi_station_disconnect(); + wifi_station_connect(); + + WiFi._smartConfigDone = true; + } + else if (status == SC_STATUS_LINK_OVER) { + WiFi.stopSmartConfig(); + } +} + +void ESP8266WiFiClass::_eventCallback(void* arg) +{ + System_Event_t* event = reinterpret_cast(arg); + DEBUGV("wifi evt: %d\r\n", event->event); + + if (event->event == EVENT_STAMODE_DISCONNECTED) { + WiFiClient::stopAll(); + WiFiUDP::stopAll(); + } +} + +void ESP8266WiFiClass::printDiag(Print& p) +{ + const char* modes[] = {"NULL", "STA", "AP", "STA+AP"}; + p.print("Mode: "); + p.println(modes[wifi_get_opmode()]); + + const char* phymodes[] = {"", "B", "G", "N"}; + p.print("PHY mode: "); + p.println(phymodes[(int) wifi_get_phy_mode()]); + + p.print("Channel: "); + p.println(wifi_get_channel()); + + p.print("AP id: "); + p.println(wifi_station_get_current_ap_id()); + + p.print("Status: "); + p.println(wifi_station_get_connect_status()); + + p.print("Auto connect: "); + p.println(wifi_station_get_auto_connect()); + + static struct station_config conf; + wifi_station_get_config(&conf); + + const char* ssid = reinterpret_cast(conf.ssid); + p.print("SSID ("); + p.print(strlen(ssid)); + p.print("): "); + p.println(ssid); + + const char* passphrase = reinterpret_cast(conf.password); + p.print("Passphrase ("); + p.print(strlen(passphrase)); + p.print("): "); + p.println(passphrase); + + p.print("BSSID set: "); + p.println(conf.bssid_set); + +} + +bool ESP8266WiFiClass::_scanAsync = false; +bool ESP8266WiFiClass::_scanStarted = false; +bool ESP8266WiFiClass::_scanComplete = false; + +size_t ESP8266WiFiClass::_scanCount = 0; +void* ESP8266WiFiClass::_scanResult = 0; + + +ESP8266WiFiClass WiFi; diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.h new file mode 100644 index 0000000..bd4502b --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFi.h @@ -0,0 +1,353 @@ +/* + ESP8266WiFi.h - esp8266 Wifi support. + Based on WiFi.h from Ardiono WiFi shield library. + Copyright (c) 2011-2014 Arduino. All right reserved. + Modified by Ivan Grokhotkov, December 2014 + + 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 +*/ + +#ifndef WiFi_h +#define WiFi_h + +#include + +extern "C" { + #include "include/wl_definitions.h" +} + +#include "IPAddress.h" +#include "WiFiClient.h" +#include "WiFiServer.h" + +#define WIFI_SCAN_RUNNING (-1) +#define WIFI_SCAN_FAILD (-2) + +enum WiFiMode { WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3 }; + +class ESP8266WiFiClass +{ +public: + + ESP8266WiFiClass(); + + void mode(WiFiMode); + + /** + * Start Wifi connection + * if passphrase is set the most secure supported mode will be automatically selected + * @param ssid const char* Pointer to the SSID string. + * @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal). + * @param bssid uint8_t[6] Optional. BSSID / MAC of AP + * @param channel Optional. Channel of AP + * @return + */ + int begin(const char* ssid, const char *passphrase = NULL, int32_t channel = 0, uint8_t bssid[6] = NULL); + int begin(char* ssid, char *passphrase = NULL, int32_t channel = 0, uint8_t bssid[6] = NULL); + + + /* Wait for Wifi connection to reach a result + * returns the status reached or disconnect if STA is off + */ + uint8_t waitForConnectResult(); + + /* Set up an open access point + * + * param ssid: Pointer to the SSID string. + */ + void softAP(const char* ssid); + + + /* Set up a WPA2-secured access point + * + * param ssid: Pointer to the SSID string. + * param passphrase: Pointer to passphrase, 8 characters min. + * param channel: WiFi channel number, 1 - 13. + * param ssid_hidden: Network cloaking? 0 = broadcast SSID, 1 = hide SSID + */ + void softAP(const char* ssid, const char* passphrase, int channel = 1, int ssid_hidden = 0); + + /* Change Ip configuration settings disabling the dhcp client + * + * param local_ip: Static ip configuration + * param gateway: Static gateway configuration + * param subnet: Static Subnet mask + */ + void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet); + + /* Change Ip configuration settings disabling the dhcp client + * + * param local_ip: Static ip configuration + * param gateway: Static gateway configuration + * param subnet: Static Subnet mask + * param dns: Defined DNS + */ + void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns); + + /* Configure access point + * + * param local_ip: access point IP + * param gateway: gateway IP + * param subnet: subnet mask + */ + void softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet); + + /* + * Disconnect from the network + * + * return: one value of wl_status_t enum + */ + int disconnect(void); + + /* + * Get the station interface MAC address. + * + * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH + * return: String + */ + uint8_t* macAddress(uint8_t* mac); + String macAddress(void); + + /* + * Get the softAP interface MAC address. + * + * return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH + * return: String + */ + uint8_t* softAPmacAddress(uint8_t* mac); + String softAPmacAddress(void); + + /* + * Get the station interface IP address. + * + * return: Ip address value + */ + IPAddress localIP(); + + /* + * Get the softAP interface IP address. + * + * return: Ip address value + */ + IPAddress softAPIP(); + + /* + * Get the interface subnet mask address. + * + * return: subnet mask address value + */ + IPAddress subnetMask(); + + /* + * Get the gateway ip address. + * + * return: gateway ip address value + */ + IPAddress gatewayIP(); + + /* + * Return the current SSID associated with the network + * + * return: ssid string + */ + char* SSID(); + + /* + * Return the current bssid / mac associated with the network if configured + * + * return: bssid uint8_t * + */ + uint8_t * BSSID(void); + + /* + * Return the current bssid / mac associated with the network if configured + * + * return: bssid string + */ + String BSSIDstr(void); + + /* + * Return the current channel associated with the network + * + * return: channel + */ + int32_t channel(void); + + /* + * Return the current network RSSI. + * + * return: RSSI value + */ + + int32_t RSSI(); + + + /* + * called to get the scan state in Async mode + * + * return -1 if scan not fin + * return -2 if scan not triggered + */ + int8_t scanComplete(); + + /* + * delete last scan result from RAM + */ + void scanDelete(); + + /* + * Start scan WiFi networks available + * + * return: Number of discovered networks + */ + int8_t scanNetworks(bool async = false); + + /* + * Return the SSID discovered during the network scan. + * + * param networkItem: specify from which network item want to get the information + * + * return: ssid string of the specified item on the networks scanned list + */ + const char* SSID(uint8_t networkItem); + + /* + * Return the encryption type of the networks discovered during the scanNetworks + * + * param networkItem: specify from which network item want to get the information + * + * return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list + */ + uint8_t encryptionType(uint8_t networkItem); + + /* + * Return the RSSI of the networks discovered during the scanNetworks + * + * param networkItem: specify from which network item want to get the information + * + * return: signed value of RSSI of the specified item on the networks scanned list + */ + int32_t RSSI(uint8_t networkItem); + + + /** + * return MAC / BSSID of scanned wifi + * @param networkItem specify from which network item want to get the information + * @return uint8_t * MAC / BSSID of scanned wifi + */ + uint8_t * BSSID(uint8_t networkItem); + + /** + * return MAC / BSSID of scanned wifi + * @param networkItem specify from which network item want to get the information + * @return String MAC / BSSID of scanned wifi + */ + String BSSIDstr(uint8_t networkItem); + + /** + * return channel of scanned wifi + * @param networkItem specify from which network item want to get the information + * @return uint32_t channel of scanned wifi + */ + int32_t channel(uint8_t networkItem); + + /** + * return if the scanned wifi is Hidden (no SSID) + * @param networkItem specify from which network item want to get the information + * @return bool (true == hidden) + */ + bool isHidden(uint8_t networkItem); + + /** + * loads all infos from a scanned wifi in to the ptr parameters + * @param networkItem uint8_t + * @param ssid const char** + * @param encryptionType uint8_t * + * @param RSSI int32_t * + * @param BSSID uint8_t ** + * @param channel int32_t * + * @param isHidden bool * + * @return (true if ok) + */ + bool getNetworkInfo(uint8_t networkItem, String &ssid, uint8_t &encryptionType, int32_t &RSSI, uint8_t* &BSSID, int32_t &channel, bool &isHidden); + + + /* + * Return Connection status. + * + * return: one of the value defined in wl_status_t + */ + wl_status_t status(); + + /* + * Resolve the given hostname to an IP address. + * param aHostname: Name to be resolved + * param aResult: IPAddress structure to store the returned IP address + * result: 1 if aIPAddrString was successfully converted to an IP address, + * else error code + */ + int hostByName(const char* aHostname, IPAddress& aResult); + + /* + * Output WiFi settings to an object derived from Print interface (like Serial). + * + */ + void printDiag(Print& dest); + + /* + * Start SmartConfig + * + */ + void beginSmartConfig(); + + /* + * Query SmartConfig status, to decide when stop config + * + */ + bool smartConfigDone(); + + /* + * Stop SmartConfig + * + */ + void stopSmartConfig(); + + friend class WiFiClient; + friend class WiFiServer; + +protected: + static void _scanDone(void* result, int status); + void * _getScanInfoByIndex(int i); + static void _smartConfigCallback(uint32_t status, void* result); + static void _eventCallback(void *event); + bool _smartConfigStarted; + bool _smartConfigDone; + + bool _useApMode; + bool _useClientMode; + bool _useStaticIp; + + static bool _scanAsync; + static bool _scanStarted; + static bool _scanComplete; + + static size_t _scanCount; + static void* _scanResult; + +}; + +extern ESP8266WiFiClass WiFi; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.cpp new file mode 100644 index 0000000..edf2c21 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -0,0 +1,207 @@ +/** + * + * @file ESP8266WiFiMulti.cpp + * @date 16.05.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * + * 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 + * + */ + +#include "ESP8266WiFiMulti.h" +#include +#include + +ESP8266WiFiMulti::ESP8266WiFiMulti() { +} + +ESP8266WiFiMulti::~ESP8266WiFiMulti() { + APlistClean(); +} + +bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) { + return APlistAdd(ssid, passphrase); +} + +wl_status_t ESP8266WiFiMulti::run(void) { + + int8_t scanResult; + wl_status_t status = WiFi.status(); + if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) { + + scanResult = WiFi.scanComplete(); + if(scanResult == WIFI_SCAN_RUNNING) { + // scan is running + return WL_NO_SSID_AVAIL; + } else if(scanResult > 0) { + // scan done analyze + WifiAPlist_t bestNetwork { NULL, NULL }; + int bestNetworkDb = INT_MIN; + uint8 bestBSSID[6]; + int32_t bestChannel; + + DEBUG_WIFI_MULTI("[WIFI] scan done\n"); + delay(0); + + if(scanResult <= 0) { + DEBUG_WIFI_MULTI("[WIFI] no networks found\n"); + } else { + DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", scanResult); + for(int8_t i = 0; i < scanResult; ++i) { + + String ssid_scan; + int32_t rssi_scan; + uint8_t sec_scan; + uint8_t* BSSID_scan; + int32_t chan_scan; + bool hidden_scan; + + WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan); + + bool known = false; + for(uint32_t x = 0; x < APlist.size(); x++) { + WifiAPlist_t entry = APlist[x]; + + if(ssid_scan == entry.ssid) { // SSID match + known = true; + if(rssi_scan > bestNetworkDb) { // best network + if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan + bestNetworkDb = rssi_scan; + bestChannel = chan_scan; + memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork)); + memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID)); + } + } + break; + } + } + + if(known) { + DEBUG_WIFI_MULTI(" ---> "); + } else { + DEBUG_WIFI_MULTI(" "); + } + + DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*'); + delay(0); + } + } + + // clean up ram + WiFi.scanDelete(); + + DEBUG_WIFI_MULTI("\n\n"); + delay(0); + + if(bestNetwork.ssid) { + DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)\n", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb); + + WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID); + status = WiFi.status(); + + // wait for connection or fail + while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) { + delay(10); + status = WiFi.status(); + } + + IPAddress ip; + uint8_t * mac; + switch(status) { + case WL_CONNECTED: + ip = WiFi.localIP(); + mac = WiFi.BSSID(); + DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n"); + DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID()); + DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n", WiFi.channel()); + break; + case WL_NO_SSID_AVAIL: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild AP not found.\n"); + break; + case WL_CONNECT_FAILED: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild.\n"); + break; + default: + DEBUG_WIFI_MULTI("[WIFI] Connecting Faild (%d).\n", status); + break; + } + } else { + DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n"); + } + } else { + // start scan + DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n"); + WiFi.disconnect(); + + DEBUG_WIFI_MULTI("[WIFI] start scan\n"); + // scan wifi async mode + WiFi.scanNetworks(true); + } + } + return status; +} + +// ################################################################################## + +bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) { + + WifiAPlist_t newAP; + + if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) { + // fail SSID to long or missing! + return false; + } + + if(passphrase && strlen(passphrase) > 63) { + // fail passphrase to long! + return false; + } + + newAP.ssid = strdup(ssid); + + if(!newAP.ssid) { + return false; + } + + if(passphrase && *passphrase != 0x00) { + newAP.passphrase = strdup(passphrase); + if(!newAP.passphrase) { + free(newAP.ssid); + return false; + } + } + + APlist.push_back(newAP); + return true; +} + +void ESP8266WiFiMulti::APlistClean(void) { + for(uint32_t i = 0; i < APlist.size(); i++) { + WifiAPlist_t entry = APlist[i]; + if(entry.ssid) { + free(entry.ssid); + } + if(entry.passphrase) { + free(entry.passphrase); + } + } + APlist.clear(); +} + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.h new file mode 100644 index 0000000..dbfbbb7 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/ESP8266WiFiMulti.h @@ -0,0 +1,62 @@ +/** + * + * @file ESP8266WiFiMulti.h + * @date 16.05.2015 + * @author Markus Sattler + * + * Copyright (c) 2015 Markus Sattler. All rights reserved. + * This file is part of the esp8266 core for Arduino environment. + * + * 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 + * + */ + + +#ifndef WIFICLIENTMULTI_H_ +#define WIFICLIENTMULTI_H_ + +#include "ESP8266WiFi.h" +#undef min +#undef max +#include + +//#define DEBUG_WIFI_MULTI(...) Serial1.printf( __VA_ARGS__ ) + +#ifndef DEBUG_WIFI_MULTI +#define DEBUG_WIFI_MULTI(...) +#endif + +typedef struct { + char * ssid; + char * passphrase; +} WifiAPlist_t; + +class ESP8266WiFiMulti { + public: + ESP8266WiFiMulti(); + ~ESP8266WiFiMulti(); + + bool addAP(const char* ssid, const char *passphrase = NULL); + + wl_status_t run(void); + + private: + std::vector APlist; + bool APlistAdd(const char* ssid, const char *passphrase = NULL); + void APlistClean(void); + +}; + +#endif /* WIFICLIENTMULTI_H_ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.cpp b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.cpp new file mode 100644 index 0000000..9117a41 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.cpp @@ -0,0 +1,290 @@ +/* + WiFiClient.cpp - TCP/IP client for esp8266, mostly compatible + with Arduino WiFi shield library + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ + +#define LWIP_INTERNAL + +extern "C" +{ + #include "include/wl_definitions.h" + #include "osapi.h" + #include "ets_sys.h" +} + +#include "debug.h" +#include "ESP8266WiFi.h" +#include "WiFiClient.h" +#include "WiFiServer.h" +#include "lwip/opt.h" +#include "lwip/ip.h" +#include "lwip/tcp.h" +#include "lwip/inet.h" +#include "lwip/netif.h" +#include "cbuf.h" +#include "include/ClientContext.h" +#include "c_types.h" + +uint16_t WiFiClient::_localPort = 0; + +template<> +WiFiClient* SList::_s_first = 0; + + +WiFiClient::WiFiClient() +: _client(0) +{ + WiFiClient::_add(this); +} + +WiFiClient::WiFiClient(ClientContext* client) : _client(client) +{ + _client->ref(); + WiFiClient::_add(this); +} + +WiFiClient::~WiFiClient() +{ + WiFiClient::_remove(this); + if (_client) + _client->unref(); +} + +WiFiClient::WiFiClient(const WiFiClient& other) +{ + _client = other._client; + if (_client) + _client->ref(); + WiFiClient::_add(this); +} + +WiFiClient& WiFiClient::operator=(const WiFiClient& other) +{ + if (_client) + _client->unref(); + _client = other._client; + if (_client) + _client->ref(); + return *this; +} + + +int WiFiClient::connect(const char* host, uint16_t port) +{ + IPAddress remote_addr; + if (WiFi.hostByName(host, remote_addr)) + { + return connect(remote_addr, port); + } + return 0; +} + +int WiFiClient::connect(IPAddress ip, uint16_t port) +{ + ip_addr_t addr; + addr.addr = ip; + + if (_client) + stop(); + + // if the default interface is down, tcp_connect exits early without + // ever calling tcp_err + // http://lists.gnu.org/archive/html/lwip-devel/2010-05/msg00001.html + netif* interface = ip_route(&addr); + if (!interface) { + DEBUGV("no route to host\r\n"); + return 1; + } + + tcp_pcb* pcb = tcp_new(); + if (!pcb) + return 0; + + if (_localPort > 0) { + pcb->local_port = _localPort++; + } + + tcp_arg(pcb, this); + tcp_err(pcb, &WiFiClient::_s_err); + tcp_connect(pcb, &addr, port, reinterpret_cast(&WiFiClient::_s_connected)); + + esp_yield(); + if (_client) + return 1; + + // if tcp_error was called, pcb has already been destroyed. + // tcp_abort(pcb); + return 0; +} + +int8_t WiFiClient::_connected(void* pcb, int8_t err) +{ + tcp_pcb* tpcb = reinterpret_cast(pcb); + _client = new ClientContext(tpcb, 0, 0); + _client->ref(); + esp_schedule(); + return ERR_OK; +} + +void WiFiClient::_err(int8_t err) +{ + DEBUGV(":err %d\r\n", err); + esp_schedule(); +} + + +void WiFiClient::setNoDelay(bool nodelay) { + if (!_client) + return; + _client->setNoDelay(nodelay); +} + +bool WiFiClient::getNoDelay() { + if (!_client) + return false; + return _client->getNoDelay(); +} + +size_t WiFiClient::write(uint8_t b) +{ + return write(&b, 1); +} + +size_t WiFiClient::write(const uint8_t *buf, size_t size) +{ + if (!_client || !size) + { + return 0; + } + + return _client->write(reinterpret_cast(buf), size); +} + +extern "C" uint32_t esp_micros_at_task_start(); + +int WiFiClient::available() +{ + static uint32_t lastPollTime = 0; + if (!_client) + return 0; + + if (lastPollTime > esp_micros_at_task_start()) + yield(); + + lastPollTime = micros(); + + int result = _client->getSize(); + return result; +} + +int WiFiClient::read() +{ + if (!available()) + return -1; + + return _client->read(); +} + + +int WiFiClient::read(uint8_t* buf, size_t size) +{ + return (int) _client->read(reinterpret_cast(buf), size); +} + +int WiFiClient::peek() +{ + if (!available()) + return -1; + + return _client->peek(); +} + +void WiFiClient::flush() +{ + if (_client) + _client->flush(); +} + +void WiFiClient::stop() +{ + if (!_client) + return; + + _client->unref(); + _client = 0; +} + +uint8_t WiFiClient::connected() +{ + if (!_client) + return 0; + + return _client->state() == ESTABLISHED || available(); +} + +uint8_t WiFiClient::status() +{ + if (!_client) + return CLOSED; + return _client->state(); +} + + WiFiClient::operator bool() +{ + return _client != 0; +} + +IPAddress WiFiClient::remoteIP() +{ + if (!_client) + return IPAddress(0U); + + return IPAddress(_client->getRemoteAddress()); +} + +uint16_t WiFiClient::remotePort() +{ + if (!_client) + return 0; + + return _client->getRemotePort(); +} + +int8_t WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err) +{ + return reinterpret_cast(arg)->_connected(tpcb, err); +} + +void WiFiClient::_s_err(void* arg, int8_t err) +{ + reinterpret_cast(arg)->_err(err); +} + +void WiFiClient::stopAll() +{ + for (WiFiClient* it = _s_first; it; it = it->_next) { + ClientContext* c = it->_client; + if (c) { + c->abort(); + c->unref(); + it->_client = 0; + } + } +} diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.h new file mode 100644 index 0000000..161ca0b --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiClient.h @@ -0,0 +1,127 @@ +/* + WiFiClient.h - Library for Arduino Wifi shield. + Copyright (c) 2011-2014 Arduino. 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 + + Modified by Ivan Grokhotkov, December 2014 - esp8266 support +*/ + +#ifndef wificlient_h +#define wificlient_h +#include "Arduino.h" +#include "Print.h" +#include "Client.h" +#include "IPAddress.h" +#include +#include "include/slist.h" + +class ClientContext; +class WiFiServer; + +class WiFiClient : public Client, public SList { +protected: + WiFiClient(ClientContext* client); + +public: + WiFiClient(); + virtual ~WiFiClient(); + WiFiClient(const WiFiClient&); + WiFiClient& operator=(const WiFiClient&); + + uint8_t status(); + virtual int connect(IPAddress 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); + template + size_t write(T& source, size_t unitSize); + + 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(); + + IPAddress remoteIP(); + uint16_t remotePort(); + bool getNoDelay(); + void setNoDelay(bool nodelay); + static void setLocalPortStart(uint16_t port) { _localPort = port; } + + template size_t write(T &src){ + uint8_t obuf[1460]; + size_t doneLen = 0; + size_t sentLen; + int i; + + while (src.available() > 1460){ + src.read(obuf, 1460); + sentLen = write(obuf, 1460); + doneLen = doneLen + sentLen; + if(sentLen != 1460){ + return doneLen; + } + } + + uint16_t leftLen = src.available(); + src.read(obuf, leftLen); + sentLen = write(obuf, leftLen); + doneLen = doneLen + sentLen; + return doneLen; + } + + friend class WiFiServer; + + using Print::write; + + static void stopAll(); + +private: + + static int8_t _s_connected(void* arg, void* tpcb, int8_t err); + static void _s_err(void* arg, int8_t err); + + int8_t _connected(void* tpcb, int8_t err); + void _err(int8_t err); + + ClientContext* _client; + static uint16_t _localPort; +}; + + +template +inline size_t WiFiClient::write(T& source, size_t unitSize) { + std::unique_ptr buffer(new uint8_t[unitSize]); + size_t size_sent = 0; + while(true) { + size_t left = source.available(); + if (!left) + break; + size_t will_send = (left < unitSize) ? left : unitSize; + source.read(buffer.get(), will_send); + size_t cb = write(buffer.get(), will_send); + size_sent += cb; + if (cb != will_send) { + break; + } + } + return size_sent; +} + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.cpp b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.cpp new file mode 100644 index 0000000..69ad4ff --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.cpp @@ -0,0 +1,170 @@ +/* + WiFiServer.cpp - TCP/IP server for esp8266, mostly compatible + with Arduino WiFi shield library + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ + + +#define LWIP_INTERNAL + +extern "C" { + #include "osapi.h" + #include "ets_sys.h" +} + +#include "debug.h" +#include "ESP8266WiFi.h" +#include "WiFiClient.h" +#include "WiFiServer.h" +#include "lwip/opt.h" +#include "lwip/tcp.h" +#include "lwip/inet.h" +#include "cbuf.h" +#include "include/ClientContext.h" + +WiFiServer::WiFiServer(uint16_t port) +{ + _port = port; + _pcb = 0; + _unclaimed = 0; + _discarded = 0; +} + +void WiFiServer::begin() +{ + err_t err; + + tcp_pcb* pcb = tcp_new(); + if (!pcb) + return; + + err = tcp_bind(pcb, INADDR_ANY, _port); + + if (err != ERR_OK) + { + tcp_close(pcb); + return; + } + + tcp_pcb* listen_pcb = tcp_listen(pcb); + if (!listen_pcb) + { + tcp_close(pcb); + return; + } + _pcb = listen_pcb; + tcp_accept(listen_pcb, &WiFiServer::_s_accept); + tcp_arg(listen_pcb, (void*) this); +} + +void WiFiServer::setNoDelay(bool nodelay){ + if(!_pcb) return; + if(nodelay) tcp_nagle_disable(_pcb); + else tcp_nagle_enable(_pcb); +} + +bool WiFiServer::getNoDelay(){ + if(!_pcb) return false; + return tcp_nagle_disabled(_pcb); +} + +extern "C" uint32_t esp_micros_at_task_start(); + +bool WiFiServer::hasClient(){ + if (_unclaimed) return true; + return false; +} + +WiFiClient WiFiServer::available(byte* status) +{ + static uint32_t lastPollTime = 0; + + if (_unclaimed) + { + WiFiClient result(_unclaimed); + _unclaimed = _unclaimed->next(); + DEBUGV("WS:av\r\n"); + return result; + } + + if (lastPollTime > esp_micros_at_task_start()) + yield(); + lastPollTime = micros(); + + return WiFiClient(); +} + +uint8_t WiFiServer::status() { + if (!_pcb) + return CLOSED; + return _pcb->state; +} + + +size_t WiFiServer::write(uint8_t b) +{ + return write(&b, 1); +} + +size_t WiFiServer::write(const uint8_t *buffer, size_t size) +{ + // write to all clients + // not implemented + return 0; +} + +template +T* slist_append_tail(T* head, T* item) +{ + if (!head) + return item; + T* last = head; + while(last->next()) + last = last->next(); + last->next(item); + return head; +} + +int8_t WiFiServer::_accept(tcp_pcb* apcb, int8_t err) +{ + DEBUGV("WS:ac\r\n"); + ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this); + _unclaimed = slist_append_tail(_unclaimed, client); + tcp_accepted(_pcb); + // printf("WiFiServer::_accept\r\n"); + return ERR_OK; +} + +void WiFiServer::_discard(ClientContext* client) +{ + // _discarded = slist_append_tail(_discarded, client); + DEBUGV("WS:dis\r\n"); + // printf("WiFiServer::_discard\r\n"); +} + +int8_t WiFiServer::_s_accept(void *arg, tcp_pcb* newpcb, int8_t err) +{ + return reinterpret_cast(arg)->_accept(newpcb, err); +} + +void WiFiServer::_s_discard(void* server, ClientContext* ctx) +{ + reinterpret_cast(server)->_discard(ctx); +} + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.h new file mode 100644 index 0000000..ef64276 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiServer.h @@ -0,0 +1,65 @@ +/* + WiFiServer.h - Library for Arduino Wifi shield. + Copyright (c) 2011-2014 Arduino LLC. 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 + + Modified by Ivan Grokhotkov, December 2014 - esp8266 support +*/ + +#ifndef wifiserver_h +#define wifiserver_h + +extern "C" { + #include "include/wl_definitions.h" + + struct tcp_pcb; +} + +#include "Server.h" + +class ClientContext; +class WiFiClient; + +class WiFiServer : public Server { +private: + uint16_t _port; + tcp_pcb* _pcb; + + ClientContext* _unclaimed; + ClientContext* _discarded; + +public: + WiFiServer(uint16_t port); + WiFiClient available(uint8_t* status = NULL); + bool hasClient(); + void begin(); + void setNoDelay(bool nodelay); + bool getNoDelay(); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + uint8_t status(); + + using Print::write; + +protected: + int8_t _accept(tcp_pcb* newpcb, int8_t err); + void _discard(ClientContext* client); + + static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err); + static void _s_discard(void* server, ClientContext* ctx); +}; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.cpp b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.cpp new file mode 100644 index 0000000..80b0055 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.cpp @@ -0,0 +1,279 @@ +/* + WiFiUdp.cpp - UDP client/server for esp8266, mostly compatible + with Arduino WiFi shield library + + Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ + +#define LWIP_INTERNAL +#include + +extern "C" +{ + #include "include/wl_definitions.h" + #include "osapi.h" + #include "ets_sys.h" +} + +#include "debug.h" +#include "ESP8266WiFi.h" +#include "WiFiUdp.h" +#include "lwip/opt.h" +#include "lwip/udp.h" +#include "lwip/inet.h" +#include "lwip/igmp.h" +#include "lwip/mem.h" +#include "include/UdpContext.h" + + +template<> +WiFiUDP* SList::_s_first = 0; + +/* Constructor */ +WiFiUDP::WiFiUDP() : _ctx(0) +{ + WiFiUDP::_add(this); +} + +WiFiUDP::WiFiUDP(const WiFiUDP& other) +{ + _ctx = other._ctx; + if (_ctx) + _ctx->ref(); + WiFiUDP::_add(this); +} + +WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs) +{ + _ctx = rhs._ctx; + if (_ctx) + _ctx->ref(); + return *this; +} + +WiFiUDP::~WiFiUDP() +{ + WiFiUDP::_remove(this); + if (_ctx) + _ctx->unref(); +} + +/* Start WiFiUDP socket, listening at local port */ +uint8_t WiFiUDP::begin(uint16_t port) +{ + if (_ctx) { + _ctx->unref(); + _ctx = 0; + } + + _ctx = new UdpContext; + _ctx->ref(); + ip_addr_t addr; + addr.addr = INADDR_ANY; + return (_ctx->listen(addr, port)) ? 1 : 0; +} + +uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port) +{ + if (_ctx) { + _ctx->unref(); + _ctx = 0; + } + + ip_addr_t ifaddr; + ifaddr.addr = (uint32_t) interfaceAddr; + ip_addr_t multicast_addr; + multicast_addr.addr = (uint32_t) multicast; + + if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) { + return 0; + } + + _ctx = new UdpContext; + _ctx->ref(); + if (!_ctx->listen(*IP_ADDR_ANY, port)) { + return 0; + } + + return 1; +} + +/* return number of bytes available in the current packet, + will return zero if parsePacket hasn't been called yet */ +int WiFiUDP::available() { + if (!_ctx) + return 0; + return static_cast(_ctx->getSize()); +} + +/* Release any resources being used by this WiFiUDP instance */ +void WiFiUDP::stop() +{ + if (_ctx) { + _ctx->disconnect(); + _ctx->unref(); + } + _ctx = 0; +} + +int WiFiUDP::beginPacket(const char *host, uint16_t port) +{ + IPAddress remote_addr; + if (WiFi.hostByName(host, remote_addr)) + { + return beginPacket(remote_addr, port); + } + return 0; +} + +int WiFiUDP::beginPacket(IPAddress ip, uint16_t port) +{ + ip_addr_t addr; + addr.addr = ip; + + if (!_ctx) { + _ctx = new UdpContext; + _ctx->ref(); + } + return (_ctx->connect(addr, port)) ? 1 : 0; +} + +int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port, + IPAddress interfaceAddress, int ttl) +{ + ip_addr_t mcastAddr; + mcastAddr.addr = multicastAddress; + ip_addr_t ifaceAddr; + ifaceAddr.addr = interfaceAddress; + + if (!_ctx) { + _ctx = new UdpContext; + _ctx->ref(); + } + if (!_ctx->connect(mcastAddr, port)) { + return 0; + } + _ctx->setMulticastInterface(ifaceAddr); + _ctx->setMulticastTTL(ttl); + return 1; +} + +int WiFiUDP::endPacket() +{ + if (!_ctx) + return 0; + + _ctx->send(); + return 1; +} + +size_t WiFiUDP::write(uint8_t byte) +{ + return write(&byte, 1); +} + +size_t WiFiUDP::write(const uint8_t *buffer, size_t size) +{ + if (!_ctx) + return 0; + + return _ctx->append(reinterpret_cast(buffer), size); +} + +int WiFiUDP::parsePacket() +{ + if (!_ctx) + return 0; + if (!_ctx->next()) + return 0; + return _ctx->getSize(); +} + +int WiFiUDP::read() +{ + if (!_ctx) + return -1; + + return _ctx->read(); +} + +int WiFiUDP::read(unsigned char* buffer, size_t len) +{ + if (!_ctx) + return 0; + + return _ctx->read(reinterpret_cast(buffer), len); +} + +int WiFiUDP::peek() +{ + if (!_ctx) + return 0; + + return _ctx->peek(); +} + +void WiFiUDP::flush() +{ + if (_ctx) + _ctx->flush(); +} + +IPAddress WiFiUDP::remoteIP() +{ + if (!_ctx) + return IPAddress(0U); + + return IPAddress(_ctx->getRemoteAddress()); +} + +uint16_t WiFiUDP::remotePort() +{ + if (!_ctx) + return 0; + + return _ctx->getRemotePort(); +} + +IPAddress WiFiUDP::destinationIP() +{ + IPAddress addr; + + if (!_ctx) + return addr; + + addr = _ctx->getDestAddress(); + return addr; +} + +uint16_t WiFiUDP::localPort() +{ + if (!_ctx) + return 0; + + return _ctx->getLocalPort(); +} + +void WiFiUDP::stopAll() +{ + for (WiFiUDP* it = _s_first; it; it = it->_next) { + DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first); + it->stop(); + } +} + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.h new file mode 100644 index 0000000..16aa0a3 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/WiFiUdp.h @@ -0,0 +1,112 @@ +/* + WiFiUdp.h - Library for Arduino Wifi shield. + Copyright (c) 2011-2014 Arduino LLC. 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 + + Modified by Ivan Grokhotkov, January 2015 - esp8266 support +*/ + +#ifndef WIFIUDP_H +#define WIFIUDP_H + +#include +#include + +#define UDP_TX_PACKET_MAX_SIZE 8192 + +class UdpContext; + +class WiFiUDP : public UDP, public SList { +private: + UdpContext* _ctx; + +public: + WiFiUDP(); // Constructor + WiFiUDP(const WiFiUDP& other); + WiFiUDP& operator=(const WiFiUDP& rhs); + ~WiFiUDP(); + + operator bool() const { return _ctx != 0; } + + // initialize, start listening on specified port. + // Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t begin(uint16_t port); + // Finish with the UDP connetion + virtual void stop(); + // join a multicast group and listen on the given port + uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port); + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Start building up a packet to send to the multicast address + // multicastAddress - muticast address to send to + // interfaceAddress - the local IP address of the interface that should be used + // use WiFi.localIP() or WiFi.softAPIP() depending on the interface you need + // ttl - multicast packet TTL (default is 1) + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacketMulticast(IPAddress multicastAddress, + uint16_t port, + IPAddress interfaceAddress, + int ttl = 1); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP(); + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort(); + // Return the destination address for incoming packets, + // useful to distinguish multicast and ordinary packets + IPAddress destinationIP(); + // Return the local port for outgoing packets + uint16_t localPort(); + + static void stopAll(); + +}; + +#endif //WIFIUDP_H + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/cc.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/cc.h new file mode 100644 index 0000000..ff03b30 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/cc.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +//#include +#include "c_types.h" +#include "ets_sys.h" +#include "osapi.h" +#define EFAULT 14 + +//#define LWIP_PROVIDE_ERRNO + +#if (1) +#define BYTE_ORDER LITTLE_ENDIAN +#else +#define BYTE_ORDER BIG_ENDIAN +#endif + + +typedef unsigned char u8_t; +typedef signed char s8_t; +typedef unsigned short u16_t; +typedef signed short s16_t; +typedef unsigned long u32_t; +typedef signed long s32_t; +typedef unsigned long mem_ptr_t; + +#define S16_F "d" +#define U16_F "d" +#define X16_F "x" + +#define S32_F "d" +#define U32_F "d" +#define X32_F "x" + + + +//#define PACK_STRUCT_FIELD(x) x __attribute__((packed)) +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END + +//#define LWIP_DEBUG + +#ifdef LWIP_DEBUG +#define LWIP_PLATFORM_DIAG(x) os_printf x +#define LWIP_PLATFORM_ASSERT(x) ETS_ASSERT(x) +#else +#define LWIP_PLATFORM_DIAG(x) +#define LWIP_PLATFORM_ASSERT(x) +#endif + +#define SYS_ARCH_DECL_PROTECT(x) +#define SYS_ARCH_PROTECT(x) +#define SYS_ARCH_UNPROTECT(x) + +#define LWIP_PLATFORM_BYTESWAP 1 +#define LWIP_PLATFORM_HTONS(_n) ((u16_t)((((_n) & 0xff) << 8) | (((_n) >> 8) & 0xff))) +#define LWIP_PLATFORM_HTONL(_n) ((u32_t)( (((_n) & 0xff) << 24) | (((_n) & 0xff00) << 8) | (((_n) >> 8) & 0xff00) | (((_n) >> 24) & 0xff) )) + +#if LWIP_RAW +extern u8_t memp_memory_RAW_PCB_base[]; +#endif /* LWIP_RAW */ + +#if LWIP_UDP +extern u8_t memp_memory_UDP_PCB_base[]; +#endif /* LWIP_UDP */ + +#if LWIP_TCP +extern u8_t memp_memory_TCP_PCB_base[]; +extern u8_t memp_memory_TCP_PCB_LISTEN_base[]; +extern u8_t memp_memory_TCP_SEG_base[] SHMEM_ATTR; +#endif /* LWIP_TCP */ + +#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ +extern u8_t memp_memory_SYS_TIMEOUT_base[]; +#endif /* LWIP_TIMERS */ + +extern u8_t memp_memory_PBUF_base[]; +extern u8_t memp_memory_PBUF_POOL_base[]; + + + +#endif /* __ARCH_CC_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/perf.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/perf.h new file mode 100644 index 0000000..089faca --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/perf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __PERF_H__ +#define __PERF_H__ + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +#endif /* __PERF_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/sys_arch.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/arch/sys_arch.h new file mode 100644 index 0000000..e69de29 diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/ClientContext.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/ClientContext.h new file mode 100644 index 0000000..6193568 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/ClientContext.h @@ -0,0 +1,319 @@ +/* + ClientContext.h - TCP connection handling on top of lwIP + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 + */ +#ifndef CLIENTCONTEXT_H +#define CLIENTCONTEXT_H + +class ClientContext; +class WiFiClient; + +typedef void (*discard_cb_t)(void*, ClientContext*); + +extern "C" void esp_yield(); +extern "C" void esp_schedule(); + +class ClientContext { + public: + ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg) : + _pcb(pcb), _rx_buf(0), _rx_buf_offset(0), _discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0), _send_waiting(false) { + tcp_setprio(pcb, TCP_PRIO_MIN); + tcp_arg(pcb, this); + tcp_recv(pcb, &_s_recv); + tcp_sent(pcb, &_s_sent); + tcp_err(pcb, &_s_error); + } + + err_t abort(){ + if(_pcb) { + DEBUGV(":abort\r\n"); + tcp_arg(_pcb, NULL); + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + tcp_abort(_pcb); + _pcb = 0; + } + return ERR_ABRT; + } + + err_t close(){ + err_t err = ERR_OK; + if(_pcb) { + DEBUGV(":close\r\n"); + tcp_arg(_pcb, NULL); + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + err = tcp_close(_pcb); + if(err != ERR_OK) { + DEBUGV(":tc err %d\r\n", err); + tcp_abort(_pcb); + err = ERR_ABRT; + } + _pcb = 0; + } + return err; + } + + ~ClientContext() { + } + + ClientContext* next() const { + return _next; + } + + ClientContext* next(ClientContext* new_next) { + _next = new_next; + return _next; + } + + void ref() { + ++_refcnt; + DEBUGV(":ref %d\r\n", _refcnt); + } + + void unref() { + if(this != 0) { + DEBUGV(":ur %d\r\n", _refcnt); + if(--_refcnt == 0) { + flush(); + close(); + if(_discard_cb) + _discard_cb(_discard_cb_arg, this); + delete this; + } + } + } + + void setNoDelay(bool nodelay){ + if(!_pcb) return; + if(nodelay) tcp_nagle_disable(_pcb); + else tcp_nagle_enable(_pcb); + } + + bool getNoDelay(){ + if(!_pcb) return false; + return tcp_nagle_disabled(_pcb); + } + + uint32_t getRemoteAddress() { + if(!_pcb) return 0; + + return _pcb->remote_ip.addr; + } + + uint16_t getRemotePort() { + if(!_pcb) return 0; + + return _pcb->remote_port; + } + + size_t getSize() const { + if(!_rx_buf) return 0; + + return _rx_buf->tot_len - _rx_buf_offset; + } + + char read() { + if(!_rx_buf) return 0; + + char c = reinterpret_cast(_rx_buf->payload)[_rx_buf_offset]; + _consume(1); + return c; + } + + size_t read(char* dst, size_t size) { + if(!_rx_buf) return 0; + + size_t max_size = _rx_buf->tot_len - _rx_buf_offset; + size = (size < max_size) ? size : max_size; + + DEBUGV(":rd %d, %d, %d\r\n", size, _rx_buf->tot_len, _rx_buf_offset); + size_t size_read = 0; + while(size) { + size_t buf_size = _rx_buf->len - _rx_buf_offset; + size_t copy_size = (size < buf_size) ? size : buf_size; + DEBUGV(":rdi %d, %d\r\n", buf_size, copy_size); + os_memcpy(dst, reinterpret_cast(_rx_buf->payload) + _rx_buf_offset, copy_size); + dst += copy_size; + _consume(copy_size); + size -= copy_size; + size_read += copy_size; + } + return size_read; + } + + char peek() { + if(!_rx_buf) return 0; + + return reinterpret_cast(_rx_buf->payload)[_rx_buf_offset]; + } + + void flush() { + if(!_rx_buf) { + return; + } + if(_pcb) { + tcp_recved(_pcb, (size_t) _rx_buf->tot_len); + } + pbuf_free(_rx_buf); + _rx_buf = 0; + _rx_buf_offset = 0; + } + + uint8_t state() const { + if(!_pcb) return CLOSED; + + return _pcb->state; + } + + size_t write(const char* data, size_t size) { + if(!_pcb) { + DEBUGV(":wr !_pcb\r\n"); + return 0; + } + + if(size == 0) { + return 0; + } + + size_t room = tcp_sndbuf(_pcb); + size_t will_send = (room < size) ? room : size; + err_t err = tcp_write(_pcb, data, will_send, 0); + if(err != ERR_OK) { + DEBUGV(":wr !ERR_OK\r\n"); + return 0; + } + + _size_sent = will_send; + DEBUGV(":wr\r\n"); + tcp_output( _pcb ); + _send_waiting = true; + delay(5000); // max send timeout + _send_waiting = false; + DEBUGV(":ww\r\n"); + return will_send - _size_sent; + } + + private: + + err_t _sent(tcp_pcb* pcb, uint16_t len) { + DEBUGV(":sent %d\r\n", len); + _size_sent -= len; + if(_size_sent == 0 && _send_waiting) esp_schedule(); + return ERR_OK; + } + + void _consume(size_t size) { + ptrdiff_t left = _rx_buf->len - _rx_buf_offset - size; + if(left > 0) { + _rx_buf_offset += size; + } else if(!_rx_buf->next) { + DEBUGV(":c0 %d, %d\r\n", size, _rx_buf->tot_len); + if(_pcb) tcp_recved(_pcb, _rx_buf->len); + pbuf_free(_rx_buf); + _rx_buf = 0; + _rx_buf_offset = 0; + } else { + DEBUGV(":c %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf->tot_len); + auto head = _rx_buf; + _rx_buf = _rx_buf->next; + _rx_buf_offset = 0; + pbuf_ref(_rx_buf); + if(_pcb) tcp_recved(_pcb, head->len); + pbuf_free(head); + } + } + + err_t _recv(tcp_pcb* pcb, pbuf* pb, err_t err) { + + if(pb == 0) // connection closed + { + DEBUGV(":rcla\r\n"); + return abort(); + } + + if(_rx_buf) { + // there is some unread data + // chain the new pbuf to the existing one + DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len); + pbuf_cat(_rx_buf, pb); + } else { + DEBUGV(":rn %d\r\n", pb->tot_len); + _rx_buf = pb; + _rx_buf_offset = 0; + } + return ERR_OK; + } + + void _error(err_t err) { + DEBUGV(":er %d %d %d\r\n", err, _size_sent, _send_waiting); + if (err != ERR_ABRT) { + abort(); + } + else { + tcp_arg(_pcb, NULL); + tcp_sent(_pcb, NULL); + tcp_recv(_pcb, NULL); + tcp_err(_pcb, NULL); + _pcb = NULL; + } + if(_size_sent && _send_waiting) { + esp_schedule(); + } + } + + err_t _poll(tcp_pcb* pcb) { + return ERR_OK; + } + + static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err) { + return reinterpret_cast(arg)->_recv(tpcb, pb, err); + } + + static void _s_error(void *arg, err_t err) { + reinterpret_cast(arg)->_error(err); + } + + static err_t _s_poll(void *arg, struct tcp_pcb *tpcb) { + return reinterpret_cast(arg)->_poll(tpcb); + } + + static err_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len) { + return reinterpret_cast(arg)->_sent(tpcb, len); + } + + private: + ClientContext* _next; + int _refcnt; + + tcp_pcb* _pcb; + + pbuf* _rx_buf; + size_t _rx_buf_offset; + + discard_cb_t _discard_cb; + void* _discard_cb_arg; + + size_t _size_sent; + bool _send_waiting; +}; + +#endif//CLIENTCONTEXT_H diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/UdpContext.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/UdpContext.h new file mode 100644 index 0000000..f7cebc8 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/UdpContext.h @@ -0,0 +1,389 @@ +/* + UdpContext.h - UDP connection handling on top of lwIP + + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ +#ifndef UDPCONTEXT_H +#define UDPCONTEXT_H + +class UdpContext; + +extern "C" void esp_yield(); +extern "C" void esp_schedule(); + +#define GET_IP_HDR(pb) reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN); +#define GET_UDP_HDR(pb) reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN); + +class UdpContext +{ +public: + + typedef std::function rxhandler_t; + + UdpContext() + : _pcb(0) + , _rx_buf(0) + , _first_buf_taken(false) + , _rx_buf_offset(0) + , _refcnt(0) + , _tx_buf_head(0) + , _tx_buf_cur(0) + , _tx_buf_offset(0) + , _multicast_ttl(1) + , _dest_port(0) + { + _pcb = udp_new(); + _dest_addr.addr = 0; + } + + ~UdpContext() + { + udp_remove(_pcb); + _pcb = 0; + if (_tx_buf_head) + { + pbuf_free(_tx_buf_head); + _tx_buf_head = 0; + _tx_buf_cur = 0; + _tx_buf_offset = 0; + } + if (_rx_buf) + { + pbuf_free(_rx_buf); + _rx_buf = 0; + _rx_buf_offset = 0; + } + } + + void ref() + { + ++_refcnt; + } + + void unref() + { + if(this != 0) { + DEBUGV(":ur %d\r\n", _refcnt); + if(--_refcnt == 0) { + delete this; + } + } + } + + bool connect(ip_addr_t addr, uint16_t port) + { + _dest_addr = addr; + _dest_port = port; + return true; + } + + bool listen(ip_addr_t addr, uint16_t port) + { + udp_recv(_pcb, &_s_recv, (void *) this); + err_t err = udp_bind(_pcb, &addr, port); + return err == ERR_OK; + } + + void disconnect() + { + udp_disconnect(_pcb); + } + + void setMulticastInterface(ip_addr_t addr) + { + // newer versions of lwip have a macro to set the multicast ip + // udp_set_multicast_netif_addr(_pcb, addr); + _pcb->multicast_ip = addr; + } + + void setMulticastTTL(int ttl) + { + // newer versions of lwip have an additional field (mcast_ttl) for this purpose + // and a macro to set it instead of direct field access + // udp_set_multicast_ttl(_pcb, ttl); + _multicast_ttl = ttl; + } + + // warning: handler is called from tcp stack context + // esp_yield and non-reentrant functions which depend on it will fail + void onRx(rxhandler_t handler) { + _on_rx = handler; + } + + size_t getSize() const + { + if (!_rx_buf) + return 0; + + return _rx_buf->len - _rx_buf_offset; + } + + uint32_t getRemoteAddress() + { + if (!_rx_buf) + return 0; + + ip_hdr* iphdr = GET_IP_HDR(_rx_buf); + return iphdr->src.addr; + } + + uint16_t getRemotePort() + { + if (!_rx_buf) + return 0; + + udp_hdr* udphdr = GET_UDP_HDR(_rx_buf); + return ntohs(udphdr->src); + } + + uint32_t getDestAddress() + { + ip_hdr* iphdr = GET_IP_HDR(_rx_buf); + return iphdr->dest.addr; + } + + uint16_t getLocalPort() + { + if (!_pcb) + return 0; + + return _pcb->local_port; + } + + bool next() + { + if (!_rx_buf) + return false; + + if (!_first_buf_taken) + { + _first_buf_taken = true; + return true; + } + + auto head = _rx_buf; + _rx_buf = _rx_buf->next; + _rx_buf_offset = 0; + + if (_rx_buf) + { + pbuf_ref(_rx_buf); + } + pbuf_free(head); + return _rx_buf != 0; + } + + int read() + { + if (!_rx_buf || _rx_buf->len == _rx_buf_offset) + return -1; + + char c = reinterpret_cast(_rx_buf->payload)[_rx_buf_offset]; + _consume(1); + return c; + } + + size_t read(char* dst, size_t size) + { + if (!_rx_buf) + return 0; + + size_t max_size = _rx_buf->len - _rx_buf_offset; + size = (size < max_size) ? size : max_size; + DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset); + + os_memcpy(dst, reinterpret_cast(_rx_buf->payload) + _rx_buf_offset, size); + _consume(size); + + return size; + } + + char peek() + { + if (!_rx_buf) + return 0; + + return reinterpret_cast(_rx_buf->payload)[_rx_buf_offset]; + } + + void flush() + { + if (!_rx_buf) + return; + + _consume(_rx_buf->len - _rx_buf_offset); + } + + + size_t append(const char* data, size_t size) + { + if (!_tx_buf_head || _tx_buf_head->tot_len < _tx_buf_offset + size) + { + _reserve(_tx_buf_offset + size); + } + + size_t left_to_copy = size; + while(left_to_copy) + { + // size already used in current pbuf + size_t used_cur = _tx_buf_offset - (_tx_buf_head->tot_len - _tx_buf_cur->tot_len); + size_t free_cur = _tx_buf_cur->len - used_cur; + if (free_cur == 0) + { + _tx_buf_cur = _tx_buf_cur->next; + continue; + } + size_t will_copy = (left_to_copy < free_cur) ? left_to_copy : free_cur; + os_memcpy(reinterpret_cast(_tx_buf_cur->payload) + used_cur, data, will_copy); + _tx_buf_offset += will_copy; + left_to_copy -= will_copy; + data += will_copy; + } + return size; + } + + void send(ip_addr_t* addr = 0, uint16_t port = 0) + { + size_t orig_size = _tx_buf_head->tot_len; + + size_t data_size = _tx_buf_offset; + size_t size_adjustment = orig_size - data_size; + for (pbuf* p = _tx_buf_head; p; p = p->next) + { + p->tot_len -= size_adjustment; + if (!p->next) + { + p->len = p->tot_len; + } + } + + if (!addr) { + addr = &_dest_addr; + port = _dest_port; + } + + uint16_t old_ttl = _pcb->ttl; + if (ip_addr_ismulticast(addr)) { + _pcb->ttl = _multicast_ttl; + } + + udp_sendto(_pcb, _tx_buf_head, addr, port); + + _pcb->ttl = old_ttl; + + for (pbuf* p = _tx_buf_head; p; p = p->next) + { + p->tot_len += size_adjustment; + if (!p->next) + { + p->len = p->tot_len; + } + } + + pbuf_free(_tx_buf_head); + _tx_buf_head = 0; + _tx_buf_cur = 0; + _tx_buf_offset = 0; + } + +private: + + void _reserve(size_t size) + { + const size_t pbuf_unit_size = 512; + if (!_tx_buf_head) + { + _tx_buf_head = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM); + _tx_buf_cur = _tx_buf_head; + _tx_buf_offset = 0; + } + + size_t cur_size = _tx_buf_head->tot_len; + if (size < cur_size) + return; + + size_t grow_size = size - cur_size; + + while(grow_size) + { + pbuf* pb = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM); + pbuf_cat(_tx_buf_head, pb); + if (grow_size < pbuf_unit_size) + return; + grow_size -= pbuf_unit_size; + } + } + + void _consume(size_t size) + { + _rx_buf_offset += size; + } + + void _recv(udp_pcb *upcb, pbuf *pb, + ip_addr_t *addr, u16_t port) + { + if (_rx_buf) + { + // there is some unread data + // chain the new pbuf to the existing one + DEBUGV(":urch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len); + pbuf_cat(_rx_buf, pb); + } + else + { + DEBUGV(":urn %d\r\n", pb->tot_len); + _first_buf_taken = false; + _rx_buf = pb; + _rx_buf_offset = 0; + } + if (_on_rx) { + _on_rx(); + } + } + + + static void _s_recv(void *arg, + udp_pcb *upcb, pbuf *p, + ip_addr_t *addr, u16_t port) + { + reinterpret_cast(arg)->_recv(upcb, p, addr, port); + } + +private: + int _refcnt; + udp_pcb* _pcb; + + ip_addr_t _dest_addr; + uint16_t _dest_port; + + uint16_t _multicast_ttl; + + bool _first_buf_taken; + pbuf* _rx_buf; + size_t _rx_buf_offset; + + pbuf* _tx_buf_head; + pbuf* _tx_buf_cur; + size_t _tx_buf_offset; + + rxhandler_t _on_rx; +}; + + + +#endif//CLIENTCONTEXT_H diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/lwipopts.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/lwipopts.h new file mode 100644 index 0000000..1678a40 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/lwipopts.h @@ -0,0 +1,2037 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + + +#define EBUF_LWIP 1 +#define LWIP_ESP 1 +#define EP_OFFSET 36 +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 1 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 0 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) os_memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) os_memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 1 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 1 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 4 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 16000 +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 1 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 1 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 10 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB (*((volatile uint32*)0x600011FC)) +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 2 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 0 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 0 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 10 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT 6 +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 0 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 0 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 4 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 0 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 0 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 0 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 0 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 0 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 0 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 0 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 10 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 1 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 1 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 0 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 0 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 0 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 0 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 1 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 0 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 1 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 0 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 0 +#endif + +/** + * SNMP_PRIVATE_MIB: + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 0 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 1 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 1 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 5 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 5 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ 0 +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 1460 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF 2 * TCP_MSS +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT ((TCP_SND_BUF)/2) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be grater + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. + */ +#ifndef LWIP_EVENT_API +#define LWIP_EVENT_API 0 +#define LWIP_CALLBACK_API 1 +#else +#define LWIP_EVENT_API 1 +#define LWIP_CALLBACK_API 0 +#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 0 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 0 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 0 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 0 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 0 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 1 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 0 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else +#define ETHARP_STATS 0 +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_OFF +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +#endif /* __LWIP_OPT_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/slist.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/slist.h new file mode 100644 index 0000000..0606f72 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/slist.h @@ -0,0 +1,38 @@ +#ifndef SLIST_H +#define SLIST_H + +template +class SList { +public: + SList() : _next(0) { } + +protected: + + static void _add(T* self) { + T* tmp = _s_first; + _s_first = self; + self->_next = tmp; + } + + static void _remove(T* self) { + if (_s_first == self) { + _s_first = self->_next; + self->_next = 0; + return; + } + + for (T* prev = _s_first; prev->_next; prev = prev->_next) { + if (prev->_next == self) { + prev->_next = self->_next; + self->_next = 0; + return; + } + } + } + + static T* _s_first; + T* _next; +}; + + +#endif //SLIST_H diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/wl_definitions.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/wl_definitions.h new file mode 100644 index 0000000..45bee67 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/include/wl_definitions.h @@ -0,0 +1,87 @@ +/* + wl_definitions.h - Library for Arduino Wifi shield. + Copyright (c) 2011-2014 Arduino. 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 +*/ +/* + * wl_definitions.h + * + * Created on: Mar 6, 2011 + * Author: dlafauci + */ + +#ifndef WL_DEFINITIONS_H_ +#define WL_DEFINITIONS_H_ + +// Maximum size of a SSID +#define WL_SSID_MAX_LENGTH 32 +// Length of passphrase. Valid lengths are 8-63. +#define WL_WPA_KEY_MAX_LENGTH 63 +// Length of key in bytes. Valid values are 5 and 13. +#define WL_WEP_KEY_MAX_LENGTH 13 +// Size of a MAC-address or BSSID +#define WL_MAC_ADDR_LENGTH 6 +// Size of a MAC-address or BSSID +#define WL_IPV4_LENGTH 4 +// Maximum size of a SSID list +#define WL_NETWORKS_LIST_MAXNUM 10 +// Maxmium number of socket +#define MAX_SOCK_NUM 4 +// Socket not available constant +#define SOCK_NOT_AVAIL 255 +// Default state value for Wifi state field +#define NA_STATE -1 +//Maximum number of attempts to establish wifi connection +#define WL_MAX_ATTEMPT_CONNECTION 10 + +typedef enum { + WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library + WL_IDLE_STATUS = 0, + WL_NO_SSID_AVAIL = 1, + WL_SCAN_COMPLETED = 2, + WL_CONNECTED = 3, + WL_CONNECT_FAILED = 4, + WL_CONNECTION_LOST = 5, + WL_DISCONNECTED = 6 +} wl_status_t; + +/* Encryption modes */ +enum wl_enc_type { /* Values map to 802.11 encryption suites... */ + ENC_TYPE_WEP = 5, + ENC_TYPE_TKIP = 2, + ENC_TYPE_CCMP = 4, + /* ... except these two, 7 and 8 are reserved in 802.11-2007 */ + ENC_TYPE_NONE = 7, + ENC_TYPE_AUTO = 8 +}; + +#if !defined(LWIP_INTERNAL) +enum wl_tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; +#endif + +#endif /* WL_DEFINITIONS_H_ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api.h new file mode 100644 index 0000000..91b9e5d --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api.h @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_H__ +#define __LWIP_API_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/netbuf.h" +#include "lwip/sys.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ + +/* Flags for netconn_write (u8_t) */ +#define NETCONN_NOFLAG 0x00 +#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */ +#define NETCONN_COPY 0x01 +#define NETCONN_MORE 0x02 +#define NETCONN_DONTBLOCK 0x04 + +/* Flags for struct netconn.flags (u8_t) */ +/** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores whether to wake up the original application task + if data couldn't be sent in the first try. */ +#define NETCONN_FLAG_WRITE_DELAYED 0x01 +/** Should this netconn avoid blocking? */ +#define NETCONN_FLAG_NON_BLOCKING 0x02 +/** Was the last connect action a non-blocking one? */ +#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04 +/** If this is set, a TCP netconn must call netconn_recved() to update + the TCP receive window (done automatically if not set). */ +#define NETCONN_FLAG_NO_AUTO_RECVED 0x08 +/** If a nonblocking write has been rejected before, poll_tcp needs to + check if the netconn is writable again */ +#define NETCONN_FLAG_CHECK_WRITESPACE 0x10 + + +/* Helpers to process several netconn_types by the same code */ +#define NETCONNTYPE_GROUP(t) (t&0xF0) +#define NETCONNTYPE_DATAGRAM(t) (t&0xE0) + +/** Protocol family and type of the netconn */ +enum netconn_type { + NETCONN_INVALID = 0, + /* NETCONN_TCP Group */ + NETCONN_TCP = 0x10, + /* NETCONN_UDP Group */ + NETCONN_UDP = 0x20, + NETCONN_UDPLITE = 0x21, + NETCONN_UDPNOCHKSUM= 0x22, + /* NETCONN_RAW Group */ + NETCONN_RAW = 0x40 +}; + +/** Current state of the netconn. Non-TCP netconns are always + * in state NETCONN_NONE! */ +enum netconn_state { + NETCONN_NONE, + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, + NETCONN_CLOSE +}; + +/** Use to inform the callback function about changes */ +enum netconn_evt { + NETCONN_EVT_RCVPLUS, + NETCONN_EVT_RCVMINUS, + NETCONN_EVT_SENDPLUS, + NETCONN_EVT_SENDMINUS, + NETCONN_EVT_ERROR +}; + +#if LWIP_IGMP +/** Used for netconn_join_leave_group() */ +enum netconn_igmp { + NETCONN_JOIN, + NETCONN_LEAVE +}; +#endif /* LWIP_IGMP */ + +/* forward-declare some structs to avoid to include their headers */ +struct ip_pcb; +struct tcp_pcb; +struct udp_pcb; +struct raw_pcb; +struct netconn; +struct api_msg_msg; + +/** A callback prototype to inform about events for a netconn */ +typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len); + +/** A netconn descriptor */ +struct netconn { + /** type of the netconn (TCP, UDP or RAW) */ + enum netconn_type type; + /** current state of the netconn */ + enum netconn_state state; + /** the lwIP internal protocol control block */ + union { + struct ip_pcb *ip; + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; + } pcb; + /** the last error this netconn had */ + err_t last_err; + /** sem that is used to synchroneously execute functions in the core context */ + sys_sem_t op_completed; + /** mbox where received packets are stored until they are fetched + by the netconn application thread (can grow quite big) */ + sys_mbox_t recvmbox; +#if LWIP_TCP + /** mbox where new connections are stored until processed + by the application thread */ + sys_mbox_t acceptmbox; +#endif /* LWIP_TCP */ + /** only used for socket layer */ +#if LWIP_SOCKET + int socket; +#endif /* LWIP_SOCKET */ +#if LWIP_SO_RCVTIMEO + /** timeout to wait for new data to be received + (or connections to arrive for listening netconns) */ + int recv_timeout; +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF + /** maximum amount of bytes queued in recvmbox + not used for TCP: adjust TCP_WND instead! */ + int recv_bufsize; + /** number of bytes currently in recvmbox to be received, + tested against recv_bufsize to limit bytes on recvmbox + for UDP and RAW, used for FIONREAD */ + s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ + /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ + u8_t flags; +#if LWIP_TCP + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores how much is already sent. */ + size_t write_offset; + /** TCP: when data passed to netconn_write doesn't fit into the send buffer, + this temporarily stores the message. + Also used during connect and close. */ + struct api_msg_msg *current_msg; +#endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; +}; + +/** Register an Network connection event */ +#define API_EVENT(c,e,l) if (c->callback) { \ + (*c->callback)(c, e, l); \ + } + +/** Set conn->last_err to err but don't overwrite fatal errors */ +#define NETCONN_SET_SAFE_ERR(conn, err) do { \ + SYS_ARCH_DECL_PROTECT(lev); \ + SYS_ARCH_PROTECT(lev); \ + if (!ERR_IS_FATAL((conn)->last_err)) { \ + (conn)->last_err = err; \ + } \ + SYS_ARCH_UNPROTECT(lev); \ +} while(0); + +/* Network connection functions: */ +#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) +#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) +struct +netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, + netconn_callback callback); +err_t netconn_delete(struct netconn *conn); +/** Get the type of a netconn (as enum netconn_type). */ +#define netconn_type(conn) (conn->type) + +err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); +#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) +#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + +err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port); +err_t netconn_disconnect (struct netconn *conn); +err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog); +#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG) +err_t netconn_accept(struct netconn *conn, struct netconn **new_conn); +err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf); +err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf); +void netconn_recved(struct netconn *conn, u32_t length); +err_t netconn_sendto(struct netconn *conn, struct netbuf *buf, + ip_addr_t *addr, u16_t port); +err_t netconn_send(struct netconn *conn, struct netbuf *buf); +err_t netconn_write(struct netconn *conn, const void *dataptr, size_t size, + u8_t apiflags); +err_t netconn_close(struct netconn *conn); +err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx); + +#if LWIP_IGMP +err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr, + ip_addr_t *netif_addr, enum netconn_igmp join_or_leave); +#endif /* LWIP_IGMP */ +#if LWIP_DNS +err_t netconn_gethostbyname(const char *name, ip_addr_t *addr); +#endif /* LWIP_DNS */ + +#define netconn_err(conn) ((conn)->last_err) +#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize) + +/** Set the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_set_nonblocking(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0) +/** Get the blocking status of netconn calls (@todo: write/send is missing) */ +#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0) + +/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_set_noautorecved(conn, val) do { if(val) { \ + (conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \ +} else { \ + (conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0) +/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */ +#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0) + +#if LWIP_SO_RCVTIMEO +/** Set the receive timeout in milliseconds */ +#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout)) +/** Get the receive timeout in milliseconds */ +#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout) +#endif /* LWIP_SO_RCVTIMEO */ +#if LWIP_SO_RCVBUF +/** Set the receive buffer in bytes */ +#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize)) +/** Get the receive buffer in bytes */ +#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize) +#endif /* LWIP_SO_RCVBUF*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api_msg.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api_msg.h new file mode 100644 index 0000000..f99d8c3 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/api_msg.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_API_MSG_H__ +#define __LWIP_API_MSG_H__ + +#include "lwip/opt.h" + +#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/sys.h" +#include "lwip/igmp.h" +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* For the netconn API, these values are use as a bitmask! */ +#define NETCONN_SHUT_RD 1 +#define NETCONN_SHUT_WR 2 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + +/* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +/** This struct includes everything that is necessary to execute a function + for a netconn in another thread context (mainly used to process netconns + in the tcpip_thread context to be thread safe). */ +struct api_msg_msg { + /** The netconn which to process - always needed: it includes the semaphore + which is used to block the application thread until the function finished. */ + struct netconn *conn; + /** The return value of the function executed in tcpip_thread. */ + err_t err; + /** Depending on the executed function, one of these union members is used */ + union { + /** used for do_send */ + struct netbuf *b; + /** used for do_newconn */ + struct { + u8_t proto; + } n; + /** used for do_bind and do_connect */ + struct { + ip_addr_t *ipaddr; + u16_t port; + } bc; + /** used for do_getaddr */ + struct { + ip_addr_t *ipaddr; + u16_t *port; + u8_t local; + } ad; + /** used for do_write */ + struct { + const void *dataptr; + size_t len; + u8_t apiflags; + } w; + /** used for do_recv */ + struct { + u32_t len; + } r; + /** used for do_close (/shutdown) */ + struct { + u8_t shut; + } sd; +#if LWIP_IGMP + /** used for do_join_leave_group */ + struct { + ip_addr_t *multiaddr; + ip_addr_t *netif_addr; + enum netconn_igmp join_or_leave; + } jl; +#endif /* LWIP_IGMP */ +#if TCP_LISTEN_BACKLOG + struct { + u8_t backlog; + } lb; +#endif /* TCP_LISTEN_BACKLOG */ + } msg; +}; + +/** This struct contains a function to execute in another thread context and + a struct api_msg_msg that serves as an argument for this function. + This is passed to tcpip_apimsg to execute functions in tcpip_thread context. */ +struct api_msg { + /** function to execute in tcpip_thread context */ + void (* function)(struct api_msg_msg *msg); + /** arguments for this function */ + struct api_msg_msg msg; +}; + +#if LWIP_DNS +/** As do_gethostbyname requires more arguments but doesn't require a netconn, + it has its own struct (to avoid struct api_msg getting bigger than necessary). + do_gethostbyname must be called using tcpip_callback instead of tcpip_apimsg + (see netconn_gethostbyname). */ +struct dns_api_msg { + /** Hostname to query or dotted IP address string */ + const char *name; + /** Rhe resolved address is stored here */ + ip_addr_t *addr; + /** This semaphore is posted when the name is resolved, the application thread + should wait on it. */ + sys_sem_t *sem; + /** Errors are given back here */ + err_t *err; +}; +#endif /* LWIP_DNS */ + +void do_newconn ( struct api_msg_msg *msg); +void do_delconn ( struct api_msg_msg *msg); +void do_bind ( struct api_msg_msg *msg); +void do_connect ( struct api_msg_msg *msg); +void do_disconnect ( struct api_msg_msg *msg); +void do_listen ( struct api_msg_msg *msg); +void do_send ( struct api_msg_msg *msg); +void do_recv ( struct api_msg_msg *msg); +void do_write ( struct api_msg_msg *msg); +void do_getaddr ( struct api_msg_msg *msg); +void do_close ( struct api_msg_msg *msg); +void do_shutdown ( struct api_msg_msg *msg); +#if LWIP_IGMP +void do_join_leave_group( struct api_msg_msg *msg); +#endif /* LWIP_IGMP */ + +#if LWIP_DNS +void do_gethostbyname(void *arg); +#endif /* LWIP_DNS */ + +struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +void netconn_free(struct netconn *conn); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETCONN */ + +#endif /* __LWIP_API_MSG_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/arch.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/arch.h new file mode 100644 index 0000000..524af6b --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/arch.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ARCH_H__ +#define __LWIP_ARCH_H__ + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#endif + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#endif + +#include "arch/cc.h" + +/** Temporary: define format string for size_t if not defined in cc.h */ +#ifndef SZT_F +#define SZT_F U32_F +#endif /* SZT_F */ +/** Temporary upgrade helper: define format string for u8_t as hex if not + defined in cc.h */ +#ifndef X8_F +#define X8_F "02x" +#endif /* X8_F */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef PACK_STRUCT_BEGIN +#define PACK_STRUCT_BEGIN +#endif /* PACK_STRUCT_BEGIN */ + +#ifndef PACK_STRUCT_END +#define PACK_STRUCT_END +#endif /* PACK_STRUCT_END */ + +#ifndef PACK_STRUCT_FIELD +#define PACK_STRUCT_FIELD(x) x +#endif /* PACK_STRUCT_FIELD */ + + +#ifndef LWIP_UNUSED_ARG +#define LWIP_UNUSED_ARG(x) (void)x +#endif /* LWIP_UNUSED_ARG */ + + +#ifdef LWIP_PROVIDE_ERRNO + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + + +#define ENSROK 0 /* DNS server returned answer with no data */ +#define ENSRNODATA 160 /* DNS server returned answer with no data */ +#define ENSRFORMERR 161 /* DNS server claims query was misformatted */ +#define ENSRSERVFAIL 162 /* DNS server returned general failure */ +#define ENSRNOTFOUND 163 /* Domain name not found */ +#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */ +#define ENSRREFUSED 165 /* DNS server refused query */ +#define ENSRBADQUERY 166 /* Misformatted DNS query */ +#define ENSRBADNAME 167 /* Misformatted domain name */ +#define ENSRBADFAMILY 168 /* Unsupported address family */ +#define ENSRBADRESP 169 /* Misformatted DNS reply */ +#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */ +#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */ +#define ENSROF 172 /* End of file */ +#define ENSRFILE 173 /* Error reading file */ +#define ENSRNOMEM 174 /* Out of memory */ +#define ENSRDESTRUCTION 175 /* Application terminated lookup */ +#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */ +#define ENSRCNAMELOOP 177 /* Domain name is too long */ + +#ifndef errno +extern int errno; +#endif + +#endif /* LWIP_PROVIDE_ERRNO */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ARCH_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/autoip.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/autoip.h new file mode 100644 index 0000000..23c264a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/autoip.h @@ -0,0 +1,119 @@ +/** + * @file + * + * AutoIP Automatic LinkLocal IP Configuration + */ + +/* + * + * Copyright (c) 2007 Dominik Spies + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Dominik Spies + * + * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform + * with RFC 3927. + * + * + * Please coordinate changes and requests with Dominik Spies + * + */ + +#ifndef __LWIP_AUTOIP_H__ +#define __LWIP_AUTOIP_H__ + +#include "lwip/opt.h" + +#if LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" +#include "netif/etharp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* AutoIP Timing */ +#define AUTOIP_TMR_INTERVAL 100 +#define AUTOIP_TICKS_PER_SECOND (1000 / AUTOIP_TMR_INTERVAL) + +/* RFC 3927 Constants */ +#define PROBE_WAIT 1 /* second (initial random delay) */ +#define PROBE_MIN 1 /* second (minimum delay till repeated probe) */ +#define PROBE_MAX 2 /* seconds (maximum delay till repeated probe) */ +#define PROBE_NUM 3 /* (number of probe packets) */ +#define ANNOUNCE_NUM 2 /* (number of announcement packets) */ +#define ANNOUNCE_INTERVAL 2 /* seconds (time between announcement packets) */ +#define ANNOUNCE_WAIT 2 /* seconds (delay before announcing) */ +#define MAX_CONFLICTS 10 /* (max conflicts before rate limiting) */ +#define RATE_LIMIT_INTERVAL 60 /* seconds (delay between successive attempts) */ +#define DEFEND_INTERVAL 10 /* seconds (min. wait between defensive ARPs) */ + +/* AutoIP client states */ +#define AUTOIP_STATE_OFF 0 +#define AUTOIP_STATE_PROBING 1 +#define AUTOIP_STATE_ANNOUNCING 2 +#define AUTOIP_STATE_BOUND 3 + +struct autoip +{ + ip_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */ + u8_t state; /* current AutoIP state machine state */ + u8_t sent_num; /* sent number of probes or announces, dependent on state */ + u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */ + u8_t lastconflict; /* ticks until a conflict can be solved by defending */ + u8_t tried_llipaddr; /* total number of probed/used Link Local IP-Addresses */ +}; + + +/** Init srand, has to be called before entering mainloop */ +void autoip_init(void); + +/** Set a struct autoip allocated by the application to work with */ +void autoip_set_struct(struct netif *netif, struct autoip *autoip); + +/** Start AutoIP client */ +err_t autoip_start(struct netif *netif); + +/** Stop AutoIP client */ +err_t autoip_stop(struct netif *netif); + +/** Handles every incoming ARP Packet, called by etharp_arp_input */ +void autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr); + +/** Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds */ +void autoip_tmr(void); + +/** Handle a possible change in the network configuration */ +void autoip_network_changed(struct netif *netif); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_AUTOIP */ + +#endif /* __LWIP_AUTOIP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/debug.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/debug.h new file mode 100644 index 0000000..d8359ea --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/debug.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEBUG_H__ +#define __LWIP_DEBUG_H__ + +#include "lwip/arch.h" + +/** lower two bits indicate debug level + * - 0 all + * - 1 warning + * - 2 serious + * - 3 severe + */ +#define LWIP_DBG_LEVEL_ALL 0x00 +#define LWIP_DBG_LEVEL_OFF LWIP_DBG_LEVEL_ALL /* compatibility define only */ +#define LWIP_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */ +#define LWIP_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */ +#define LWIP_DBG_LEVEL_SEVERE 0x03 +#define LWIP_DBG_MASK_LEVEL 0x03 + +/** flag for LWIP_DEBUGF to enable that debug message */ +#define LWIP_DBG_ON 0x80U +/** flag for LWIP_DEBUGF to disable that debug message */ +#define LWIP_DBG_OFF 0x00U + +/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */ +#define LWIP_DBG_TRACE 0x40U +/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */ +#define LWIP_DBG_STATE 0x20U +/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */ +#define LWIP_DBG_FRESH 0x10U +/** flag for LWIP_DEBUGF to halt after printing this debug message */ +#define LWIP_DBG_HALT 0x08U + +#ifndef LWIP_NOASSERT +#define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \ + LWIP_PLATFORM_ASSERT(message); } while(0) +#else /* LWIP_NOASSERT */ +#define LWIP_ASSERT(message, assertion) +#endif /* LWIP_NOASSERT */ + +/** if "expression" isn't true, then print "message" and execute "handler" expression */ +#ifndef LWIP_ERROR +#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \ + LWIP_PLATFORM_ASSERT(message); handler;}} while(0) +#endif /* LWIP_ERROR */ + +#ifdef LWIP_DEBUG +/** print debug message only if debug message type is enabled... + * AND is of correct type AND is at least LWIP_DBG_LEVEL + */ +#define LWIP_DEBUGF(debug, message) do { \ + if ( \ + ((debug) & LWIP_DBG_ON) && \ + ((debug) & LWIP_DBG_TYPES_ON) && \ + ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + LWIP_PLATFORM_DIAG(message); \ + if ((debug) & LWIP_DBG_HALT) { \ + while(1); \ + } \ + } \ + } while(0) + +#else /* LWIP_DEBUG */ +#define LWIP_DEBUGF(debug, message) +#endif /* LWIP_DEBUG */ + +#endif /* __LWIP_DEBUG_H__ */ + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/def.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/def.h new file mode 100644 index 0000000..9b6de6a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/def.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_DEF_H__ +#define __LWIP_DEF_H__ + +/* arch.h might define NULL already */ +#include "lwip/arch.h" +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y)) +#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y)) + +#ifndef NULL +#define NULL ((void *)0) +#endif + +/** Get the absolute difference between 2 u32_t values (correcting overflows) + * 'a' is expected to be 'higher' (without overflow) than 'b'. */ +#define LWIP_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1))) + +/* Endianess-optimized shifting of two u8_t to create one u16_t */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define LWIP_MAKE_U16(a, b) ((a << 8) | b) +#else +#define LWIP_MAKE_U16(a, b) ((b << 8) | a) +#endif + +#ifndef LWIP_PLATFORM_BYTESWAP +#define LWIP_PLATFORM_BYTESWAP 0 +#endif + +#ifndef LWIP_PREFIX_BYTEORDER_FUNCS +/* workaround for naming collisions on some platforms */ + +#ifdef htons +#undef htons +#endif /* htons */ +#ifdef htonl +#undef htonl +#endif /* htonl */ +#ifdef ntohs +#undef ntohs +#endif /* ntohs */ +#ifdef ntohl +#undef ntohl +#endif /* ntohl */ + +#define htons(x) lwip_htons(x) +#define ntohs(x) lwip_ntohs(x) +#define htonl(x) lwip_htonl(x) +#define ntohl(x) lwip_ntohl(x) +#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */ + +#if BYTE_ORDER == BIG_ENDIAN +#define lwip_htons(x) (x) +#define lwip_ntohs(x) (x) +#define lwip_htonl(x) (x) +#define lwip_ntohl(x) (x) +#define PP_HTONS(x) (x) +#define PP_NTOHS(x) (x) +#define PP_HTONL(x) (x) +#define PP_NTOHL(x) (x) +#else /* BYTE_ORDER != BIG_ENDIAN */ +#if LWIP_PLATFORM_BYTESWAP +#define lwip_htons(x) LWIP_PLATFORM_HTONS(x) +#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x) +#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x) +#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x) +#else /* LWIP_PLATFORM_BYTESWAP */ +u16_t lwip_htons(u16_t x); +u16_t lwip_ntohs(u16_t x); +u32_t lwip_htonl(u32_t x); +u32_t lwip_ntohl(u32_t x); +#endif /* LWIP_PLATFORM_BYTESWAP */ + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) + +#endif /* BYTE_ORDER == BIG_ENDIAN */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_DEF_H__ */ + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dhcp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dhcp.h new file mode 100644 index 0000000..ba21068 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dhcp.h @@ -0,0 +1,243 @@ +/** @file + */ + +#ifndef __LWIP_DHCP_H__ +#define __LWIP_DHCP_H__ + +#include "lwip/opt.h" + +#if LWIP_DHCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/netif.h" +#include "lwip/udp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** period (in seconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_SECS 60 +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +#define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL) +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +#define DHCP_FINE_TIMER_MSECS 500 + +#define DHCP_CHADDR_LEN 16U +#define DHCP_SNAME_LEN 64U +#define DHCP_FILE_LEN 128U + +struct dhcp +{ + /** transaction identifier of last sent request */ + u32_t xid; + /** our connection to the DHCP server */ + struct udp_pcb *pcb; + /** incoming msg */ + struct dhcp_msg *msg_in; + /** current DHCP state machine state */ + u8_t state; + /** retries of current request */ + u8_t tries; +#if LWIP_DHCP_AUTOIP_COOP + u8_t autoip_coop_state; +#endif + u8_t subnet_mask_given; + + struct pbuf *p_out; /* pbuf of outcoming msg */ + struct dhcp_msg *msg_out; /* outgoing msg */ + u16_t options_out_len; /* outgoing msg options length */ + u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */ + ip_addr_t offered_ip_addr; + ip_addr_t offered_sn_mask; + ip_addr_t offered_gw_addr; + + u32_t offered_t0_lease; /* lease period (in seconds) */ + u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */ + /* @todo: LWIP_DHCP_BOOTP_FILE configuration option? + integrate with possible TFTP-client for booting? */ +#define LWIP_DHCP_BOOTP_FILE 0 +#if LWIP_DHCP_BOOTP_FILE + ip_addr_t offered_si_addr; + char boot_file_name[DHCP_FILE_LEN]; +#endif /* LWIP_DHCP_BOOTPFILE */ +}; + +/* MUST be compiled with "pack structs" or equivalent! */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +/** minimum set of fields of any DHCP message */ +struct dhcp_msg +{ + PACK_STRUCT_FIELD(u8_t op); + PACK_STRUCT_FIELD(u8_t htype); + PACK_STRUCT_FIELD(u8_t hlen); + PACK_STRUCT_FIELD(u8_t hops); + PACK_STRUCT_FIELD(u32_t xid); + PACK_STRUCT_FIELD(u16_t secs); + PACK_STRUCT_FIELD(u16_t flags); + PACK_STRUCT_FIELD(ip_addr_p_t ciaddr); + PACK_STRUCT_FIELD(ip_addr_p_t yiaddr); + PACK_STRUCT_FIELD(ip_addr_p_t siaddr); + PACK_STRUCT_FIELD(ip_addr_p_t giaddr); + PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]); + PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]); + PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]); + PACK_STRUCT_FIELD(u32_t cookie); +#define DHCP_MIN_OPTIONS_LEN 68U +/** make sure user does not configure this too small */ +#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN)) +# undef DHCP_OPTIONS_LEN +#endif +/** allow this to be configured in lwipopts.h, but not too small */ +#if (!defined(DHCP_OPTIONS_LEN)) +/** set this to be sufficient for your options in outgoing DHCP msgs */ +# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN +#endif + PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) +void dhcp_cleanup(struct netif *netif); +/** start DHCP configuration */ +err_t dhcp_start(struct netif *netif); +/** enforce early lease renewal (not needed normally)*/ +err_t dhcp_renew(struct netif *netif); +/** release the DHCP lease, usually called before dhcp_stop()*/ +err_t dhcp_release(struct netif *netif); +/** stop DHCP configuration */ +void dhcp_stop(struct netif *netif); +/** inform server of our manual IP address */ +void dhcp_inform(struct netif *netif); +/** Handle a possible change in the network configuration */ +void dhcp_network_changed(struct netif *netif); + +/** if enabled, check whether the offered IP address is not in use, using ARP */ +#if DHCP_DOES_ARP_CHECK +void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr); +#endif + +/** to be called every minute */ +void dhcp_coarse_tmr(void); +/** to be called every half second */ +void dhcp_fine_tmr(void); + +/** DHCP message item offsets and length */ +#define DHCP_OP_OFS 0 +#define DHCP_HTYPE_OFS 1 +#define DHCP_HLEN_OFS 2 +#define DHCP_HOPS_OFS 3 +#define DHCP_XID_OFS 4 +#define DHCP_SECS_OFS 8 +#define DHCP_FLAGS_OFS 10 +#define DHCP_CIADDR_OFS 12 +#define DHCP_YIADDR_OFS 16 +#define DHCP_SIADDR_OFS 20 +#define DHCP_GIADDR_OFS 24 +#define DHCP_CHADDR_OFS 28 +#define DHCP_SNAME_OFS 44 +#define DHCP_FILE_OFS 108 +#define DHCP_MSG_LEN 236 + +#define DHCP_COOKIE_OFS DHCP_MSG_LEN +#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4) + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 + +/** DHCP client states */ +#define DHCP_OFF 0 +#define DHCP_REQUESTING 1 +#define DHCP_INIT 2 +#define DHCP_REBOOTING 3 +#define DHCP_REBINDING 4 +#define DHCP_RENEWING 5 +#define DHCP_SELECTING 6 +#define DHCP_INFORMING 7 +#define DHCP_CHECKING 8 +#define DHCP_PERMANENT 9 +#define DHCP_BOUND 10 +/** not yet implemented #define DHCP_RELEASING 11 */ +#define DHCP_BACKING_OFF 12 + +/** AUTOIP cooperatation flags */ +#define DHCP_AUTOIP_COOP_STATE_OFF 0 +#define DHCP_AUTOIP_COOP_STATE_ON 1 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/** DHCP message types */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +/** DHCP hardware type, currently only ethernet is supported */ +#define DHCP_HTYPE_ETH 1 + +#define DHCP_MAGIC_COOKIE 0x63825363UL + +/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */ + +/** BootP options */ +#define DHCP_OPTION_PAD 0 +#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */ +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_HOSTNAME 12 +#define DHCP_OPTION_IP_TTL 23 +#define DHCP_OPTION_MTU 26 +#define DHCP_OPTION_BROADCAST 28 +#define DHCP_OPTION_TCP_TTL 37 +#define DHCP_OPTION_END 255 + +/** DHCP options */ +#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ +#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ +#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */ + +#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */ +#define DHCP_OPTION_MESSAGE_TYPE_LEN 1 + +#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */ +#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */ + +#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */ +#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2 + +#define DHCP_OPTION_T1 58 /* T1 renewal time */ +#define DHCP_OPTION_T2 59 /* T2 rebinding time */ +#define DHCP_OPTION_US 60 +#define DHCP_OPTION_CLIENT_ID 61 +#define DHCP_OPTION_TFTP_SERVERNAME 66 +#define DHCP_OPTION_BOOTFILE 67 + +/** possible combinations of overloading the file and sname fields with options */ +#define DHCP_OVERLOAD_NONE 0 +#define DHCP_OVERLOAD_FILE 1 +#define DHCP_OVERLOAD_SNAME 2 +#define DHCP_OVERLOAD_SNAME_FILE 3 + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DHCP */ + +#endif /*__LWIP_DHCP_H__*/ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dns.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dns.h new file mode 100644 index 0000000..6c7d9b0 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/dns.h @@ -0,0 +1,124 @@ +/** + * lwip DNS resolver header file. + + * Author: Jim Pettinato + * April 2007 + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LWIP_DNS_H__ +#define __LWIP_DNS_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ + +/** DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ + +/* The size used for the next line is rather a hack, but it prevents including socket.h in all files + that include memp.h, and that would possibly break portability (since socket.h defines some types + and constants possibly already define by the OS). + Calculation rule: + sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */ +#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1) + +#if DNS_LOCAL_HOSTLIST +/** struct used for local host-list */ +struct local_hostlist_entry { + /** static hostname */ + const char *name; + /** static host address in network byteorder */ + ip_addr_t addr; + struct local_hostlist_entry *next; +}; +#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN +#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH +#endif +#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1)) +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#endif /* DNS_LOCAL_HOSTLIST */ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg); + +void dns_init(void); +void dns_tmr(void); +void dns_setserver(u8_t numdns, ip_addr_t *dnsserver); +ip_addr_t dns_getserver(u8_t numdns); +err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr, + dns_found_callback found, void *callback_arg); + +#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +int dns_local_removehost(const char *hostname, const ip_addr_t *addr); +err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); +#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS */ + +#endif /* __LWIP_DNS_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/err.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/err.h new file mode 100644 index 0000000..cb69a9f --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/err.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ERR_H__ +#define __LWIP_ERR_H__ + +#include "lwip/opt.h" +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ +#ifdef LWIP_ERR_T +typedef LWIP_ERR_T err_t; +#else /* LWIP_ERR_T */ +typedef s8_t err_t; +#endif /* LWIP_ERR_T*/ + +/* Definitions for error constants. */ + +#define ERR_OK 0 /* No error, everything OK. */ +#define ERR_MEM -1 /* Out of memory error. */ +#define ERR_BUF -2 /* Buffer error. */ +#define ERR_TIMEOUT -3 /* Timeout. */ +#define ERR_RTE -4 /* Routing problem. */ +#define ERR_INPROGRESS -5 /* Operation in progress */ +#define ERR_VAL -6 /* Illegal value. */ +#define ERR_WOULDBLOCK -7 /* Operation would block. */ + +#define ERR_IS_FATAL(e) ((e) < ERR_WOULDBLOCK) + +#define ERR_ABRT -8 /* Connection aborted. */ +#define ERR_RST -9 /* Connection reset. */ +#define ERR_CLSD -10 /* Connection closed. */ +#define ERR_CONN -11 /* Not connected. */ + +#define ERR_ARG -12 /* Illegal argument. */ + +#define ERR_USE -13 /* Address in use. */ + +#define ERR_IF -14 /* Low-level netif error */ +#define ERR_ISCONN -15 /* Already connected. */ + + +#ifdef LWIP_DEBUG +extern const char *lwip_strerr(err_t err)ICACHE_FLASH_ATTR; +#else +#define lwip_strerr(x) "" +#endif /* LWIP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ERR_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/icmp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/icmp.h new file mode 100644 index 0000000..9bcb7bc --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/icmp.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_ICMP_H__ +#define __LWIP_ICMP_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ +#define ICMP_ECHO 8 /* echo */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ +#define ICMP_TSR 14 /* timestamp reply */ +#define ICMP_IRQ 15 /* information request */ +#define ICMP_IR 16 /* information reply */ + +enum icmp_dur_type { + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_PROTO = 2, /* protocol unreachable */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ +}; + +enum icmp_te_type { + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ +}; + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +/** This is the standard ICMP header only that the u32_t data + * is splitted to two u16_t like ICMP echo needs it. + * This header is also used for other ICMP types that do not + * use the data part. + * ¶¨ÒåICMP»ØËÍÇëÇó±¨ÎÄÊײ¿½á¹¹£¬ + * ÓÉÓÚËùÓÐICMP±¨ÎÄÊײ¿ÓкܴóÏàËÆÐÔ£¬ + * ¸Ã½á¹¹Í¬ÑùÊÊÓÃÓÚÆäËüICMP±¨ÎÄ¡£ + */ +PACK_STRUCT_BEGIN +struct icmp_echo_hdr { + PACK_STRUCT_FIELD(u8_t type); + PACK_STRUCT_FIELD(u8_t code); + PACK_STRUCT_FIELD(u16_t chksum); + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u16_t seqno); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +//¶ÁÈ¡ICMPÊײ¿ÖÐ×Ö¶Î +#define ICMPH_TYPE(hdr) ((hdr)->type) +#define ICMPH_CODE(hdr) ((hdr)->code) + +/** Combines type and code to an u16_t ÏòICMP±¨ÎÄÊײ¿×Ö¶ÎÖÐдÈëÏàÓ¦Öµ*/ +#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t)) +#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c)) + + +#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */ + +void icmp_input(struct pbuf *p, struct netif *inp)ICACHE_FLASH_ATTR; +void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)ICACHE_FLASH_ATTR; +void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)ICACHE_FLASH_ATTR; + +#endif /* LWIP_ICMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_ICMP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/igmp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/igmp.h new file mode 100644 index 0000000..8cf9a48 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/igmp.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2002 CITEL Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is a contribution to the lwIP TCP/IP stack. + * The Swedish Institute of Computer Science and Adam Dunkels + * are specifically granted permission to redistribute this + * source code. +*/ + +#ifndef __LWIP_IGMP_H__ +#define __LWIP_IGMP_H__ + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" + +#if LWIP_IGMP /* don't build if not configured for use in lwipopts.h */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* IGMP timer */ +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL) +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + +/* MAC Filter Actions, these are passed to a netif's + * igmp_mac_filter callback function. */ +#define IGMP_DEL_MAC_FILTER 0 +#define IGMP_ADD_MAC_FILTER 1 + + +/** + * igmp group structure - there is + * a list of groups for each interface + * these should really be linked from the interface, but + * if we keep them separate we will not affect the lwip original code + * too much + * + * There will be a group for the all systems group address but this + * will not run the state machine as it is used to kick off reports + * from all the other groups + */ +struct igmp_group { + /** next link */ + struct igmp_group *next; + /** interface on which the group is active */ + struct netif *netif; + /** multicast address */ + ip_addr_t group_address; + /** signifies we were the last person to report */ + u8_t last_reporter_flag; + /** current state of the group */ + u8_t group_state; + /** timer for reporting, negative is OFF */ + u16_t timer; + /** counter of simultaneous uses */ + u8_t use; +}; + +/* Prototypes */ +void igmp_init(void)ICACHE_FLASH_ATTR; +err_t igmp_start(struct netif *netif)ICACHE_FLASH_ATTR; +err_t igmp_stop(struct netif *netif)ICACHE_FLASH_ATTR; +void igmp_report_groups(struct netif *netif)ICACHE_FLASH_ATTR; +struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr)ICACHE_FLASH_ATTR; +void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)ICACHE_FLASH_ATTR; +err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)ICACHE_FLASH_ATTR; +err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)ICACHE_FLASH_ATTR; +void igmp_tmr(void)ICACHE_FLASH_ATTR; +#define LWIP_RAND() rand() +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_IGMP */ + +#endif /* __LWIP_IGMP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet.h new file mode 100644 index 0000000..7bff49b --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_H__ +#define __LWIP_INET_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** For compatibility with BSD code */ +struct in_addr { + u32_t s_addr; +}; + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IN_CLASSA(a) IP_CLASSA(a) +#define IN_CLASSA_NET IP_CLASSA_NET +#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT +#define IN_CLASSA_HOST IP_CLASSA_HOST +#define IN_CLASSA_MAX IP_CLASSA_MAX + +#define IN_CLASSB(b) IP_CLASSB(b) +#define IN_CLASSB_NET IP_CLASSB_NET +#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT +#define IN_CLASSB_HOST IP_CLASSB_HOST +#define IN_CLASSB_MAX IP_CLASSB_MAX + +#define IN_CLASSC(c) IP_CLASSC(c) +#define IN_CLASSC_NET IP_CLASSC_NET +#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT +#define IN_CLASSC_HOST IP_CLASSC_HOST +#define IN_CLASSC_MAX IP_CLASSC_MAX + +#define IN_CLASSD(d) IP_CLASSD(d) +#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ +#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ +#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ +#define IN_CLASSD_MAX IP_CLASSD_MAX + +#define IN_MULTICAST(a) IP_MULTICAST(a) + +#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) +#define IN_BADCLASS(a) IP_BADCLASS(a) + +#define IN_LOOPBACKNET IP_LOOPBACKNET + +#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) +#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) +/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */ +#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr)) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) ipaddr_addr(cp) +#define inet_aton(cp, addr) ipaddr_aton(cp, (ip_addr_t*)addr) +#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) ipaddr_ntoa_r((ip_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet_chksum.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet_chksum.h new file mode 100644 index 0000000..41be641 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/inet_chksum.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INET_CHKSUM_H__ +#define __LWIP_INET_CHKSUM_H__ + +#include "lwip/opt.h" + +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +/** Swap the bytes in an u16_t: much like htons() for little-endian */ +#ifndef SWAP_BYTES_IN_WORD +#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) +/* little endian and PLATFORM_BYTESWAP defined */ +#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w) +#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */ +/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */ +#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8) +#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/ +#endif /* SWAP_BYTES_IN_WORD */ + +/** Split an u32_t in two u16_ts and add them up */ +#ifndef FOLD_U32T +#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL)) +#endif + +#if LWIP_CHECKSUM_ON_COPY +/** Function-like macro: same as MEMCPY but returns the checksum of copied data + as u16_t */ +#ifndef LWIP_CHKSUM_COPY +#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len) +#ifndef LWIP_CHKSUM_COPY_ALGORITHM +#define LWIP_CHKSUM_COPY_ALGORITHM 1 +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ +#endif /* LWIP_CHKSUM_COPY */ +#else /* LWIP_CHECKSUM_ON_COPY */ +#define LWIP_CHKSUM_COPY_ALGORITHM 0 +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +extern "C" { +#endif + +u16_t inet_chksum(void *dataptr, u16_t len)ICACHE_FLASH_ATTR; +u16_t inet_chksum_pbuf(struct pbuf *p)ICACHE_FLASH_ATTR; +u16_t inet_chksum_pseudo(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len)ICACHE_FLASH_ATTR; +u16_t inet_chksum_pseudo_partial(struct pbuf *p, + ip_addr_t *src, ip_addr_t *dest, + u8_t proto, u16_t proto_len, u16_t chksum_len)ICACHE_FLASH_ATTR; +#if LWIP_CHKSUM_COPY_ALGORITHM +u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len)ICACHE_FLASH_ATTR; +#endif /* LWIP_CHKSUM_COPY_ALGORITHM */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INET_H__ */ + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/init.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/init.h new file mode 100644 index 0000000..7a58aec --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/init.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_INIT_H__ +#define __LWIP_INIT_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** X.x.x: Major version of the stack */ +#define LWIP_VERSION_MAJOR 1U +/** x.X.x: Minor version of the stack */ +#define LWIP_VERSION_MINOR 4U +/** x.x.X: Revision of the stack */ +#define LWIP_VERSION_REVISION 0U +/** For release candidates, this is set to 1..254 + * For official releases, this is set to 255 (LWIP_RC_RELEASE) + * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ +#define LWIP_VERSION_RC 2U + +/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ +#define LWIP_RC_RELEASE 255U +/** LWIP_VERSION_RC is set to LWIP_RC_DEVELOPMENT for CVS versions */ +#define LWIP_RC_DEVELOPMENT 0U + +#define LWIP_VERSION_IS_RELEASE (LWIP_VERSION_RC == LWIP_RC_RELEASE) +#define LWIP_VERSION_IS_DEVELOPMENT (LWIP_VERSION_RC == LWIP_RC_DEVELOPMENT) +#define LWIP_VERSION_IS_RC ((LWIP_VERSION_RC != LWIP_RC_RELEASE) && (LWIP_VERSION_RC != LWIP_RC_DEVELOPMENT)) + +/** Provides the version of the stack */ +#define LWIP_VERSION (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 | \ + LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC) + +/* Modules initialization */ +void lwip_init(void) ICACHE_FLASH_ATTR; +//void lwip_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_INIT_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip.h new file mode 100644 index 0000000..1f361fa --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_H__ +#define __LWIP_IP_H__ + +#include "lwip/opt.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the function ip_output_if_opt() is only used with IGMP */ +#define IP_OPTIONS_SEND LWIP_IGMP + +#define IP_HLEN 20 + +#define IP_PROTO_ICMP 1 +#define IP_PROTO_IGMP 2 +#define IP_PROTO_UDP 17 +#define IP_PROTO_UDPLITE 136 +#define IP_PROTO_TCP 6 + +/* This is passed as the destination address to ip_output_if (not + to ip_output), meaning that an IP header already is constructed + in the pbuf. This is used when TCP retransmits. */ +#ifdef IP_HDRINCL +#undef IP_HDRINCL +#endif /* IP_HDRINCL */ +#define IP_HDRINCL NULL + +#if LWIP_NETIF_HWADDRHINT +#define IP_PCB_ADDRHINT ;u8_t addr_hint +#else +#define IP_PCB_ADDRHINT +#endif /* LWIP_NETIF_HWADDRHINT */ + +/* This is the common part of all PCB types. It needs to be at the + beginning of a PCB type definition. It is located here so that + changes to this common part are made in one location instead of + having to change all PCB structs. */ +#define IP_PCB \ + /* ip addresses in network byte order */ \ + ip_addr_t local_ip; \ + ip_addr_t remote_ip; \ + /* Socket options */ \ + u8_t so_options; \ + /* Type Of Service */ \ + u8_t tos; \ + /* Time To Live */ \ + u8_t ttl \ + /* link layer address resolution hint */ \ + IP_PCB_ADDRHINT + +struct ip_pcb { +/* Common members of all PCB types */ + IP_PCB; +}; + +/* + * Option flags per-socket. These are the same like SO_XXX. + */ +/*#define SOF_DEBUG (u8_t)0x01U Unimplemented: turn on debugging info recording */ +#define SOF_ACCEPTCONN (u8_t)0x02U /* socket has had listen() */ +#define SOF_REUSEADDR (u8_t)0x04U /* allow local address reuse */ +#define SOF_KEEPALIVE (u8_t)0x08U /* keep connections alive */ +/*#define SOF_DONTROUTE (u8_t)0x10U Unimplemented: just use interface addresses */ +#define SOF_BROADCAST (u8_t)0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +/*#define SOF_USELOOPBACK (u8_t)0x40U Unimplemented: bypass hardware when possible */ +#define SOF_LINGER (u8_t)0x80U /* linger on close if data present */ +/*#define SOF_OOBINLINE (u16_t)0x0100U Unimplemented: leave received OOB data in line */ +/*#define SOF_REUSEPORT (u16_t)0x0200U Unimplemented: allow local address & port reuse */ + +/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ +#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/) + + +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_hdr { + /* version / header length / type of service */ + PACK_STRUCT_FIELD(u16_t _v_hl_tos); + /* total length */ + PACK_STRUCT_FIELD(u16_t _len); + /* identification */ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + /* time to live */ + PACK_STRUCT_FIELD(u8_t _ttl); + /* protocol*/ + PACK_STRUCT_FIELD(u8_t _proto); + /* checksum */ + PACK_STRUCT_FIELD(u16_t _chksum); + /* source and destination IP addresses */ + PACK_STRUCT_FIELD(ip_addr_p_t src); + PACK_STRUCT_FIELD(ip_addr_p_t dest); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12) +#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f) +#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff) +#define IPH_LEN(hdr) ((hdr)->_len) +#define IPH_ID(hdr) ((hdr)->_id) +#define IPH_OFFSET(hdr) ((hdr)->_offset) +#define IPH_TTL(hdr) ((hdr)->_ttl) +#define IPH_PROTO(hdr) ((hdr)->_proto) +#define IPH_CHKSUM(hdr) ((hdr)->_chksum) + +#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos))) +#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) +#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) +#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) +#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) +#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) +#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) + +/** The interface that provided the packet for the current callback invocation. */ +extern struct netif *current_netif; +/** Header of the input packet currently being processed. */ +extern const struct ip_hdr *current_header; +/** Source IP address of current_header */ +extern ip_addr_t current_iphdr_src; +/** Destination IP address of current_header */ +extern ip_addr_t current_iphdr_dest; + +#define ip_init() /* Compatibility define, not init needed. */ +struct netif *ip_route(ip_addr_t *dest)ICACHE_FLASH_ATTR; +struct netif *ip_router(ip_addr_t *dest, ip_addr_t *source); + +err_t ip_input(struct pbuf *p, struct netif *inp)ICACHE_FLASH_ATTR; +err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto)ICACHE_FLASH_ATTR; +err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, + struct netif *netif)ICACHE_FLASH_ATTR; +#if LWIP_NETIF_HWADDRHINT +err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)ICACHE_FLASH_ATTR; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if IP_OPTIONS_SEND +err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, + u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options, + u16_t optlen)ICACHE_FLASH_ATTR; +#endif /* IP_OPTIONS_SEND */ +/** Get the interface that received the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_netif() (current_netif) +/** Get the IP header of the current packet. + * This function must only be called from a receive callback (udp_recv, + * raw_recv, tcp_accept). It will return NULL otherwise. */ +#define ip_current_header() (current_header) +/** Source IP address of current_header */ +#define ip_current_src_addr() (¤t_iphdr_src) +/** Destination IP address of current_header */ +#define ip_current_dest_addr() (¤t_iphdr_dest) + +#if IP_DEBUG +void ip_debug_print(struct pbuf *p)ICACHE_FLASH_ATTR; +#else +#define ip_debug_print(p) +#endif /* IP_DEBUG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_H__ */ + + diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_addr.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_addr.h new file mode 100644 index 0000000..2787d12 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_addr.h @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_IP_ADDR_H__ +#define __LWIP_IP_ADDR_H__ + +#include "lwip/opt.h" +#include "lwip/def.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is the aligned version of ip_addr_t, + used as local variable, on the stack, etc. */ +#if !defined(IP2STR) +struct ip_addr { + u32_t addr; +}; +#endif + +/* This is the packed version of ip_addr_t, + used in network headers that are itself packed */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr_packed { + PACK_STRUCT_FIELD(u32_t addr); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/** ip_addr_t uses a struct for convenience only, so that the same defines can + * operate both on ip_addr_t as well as on ip_addr_p_t. */ +#if !defined(IP2STR) +typedef struct ip_addr ip_addr_t; +#endif +typedef struct ip_addr_packed ip_addr_p_t; + +/* + * struct ipaddr2 is used in the definition of the ARP packet format in + * order to support compilers that don't have structure packing. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct ip_addr2 { + PACK_STRUCT_FIELD(u16_t addrw[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* Forward declaration to not include netif.h */ +struct netif; + +extern const ip_addr_t ip_addr_any; +extern const ip_addr_t ip_addr_broadcast; + +/** IP_ADDR_ can be used as a fixed IP address + * for the wildcard and the broadcast address + */ +#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) +#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) + +/** 255.255.255.255 */ +#if !defined(IPADDR_NONE) +#define IPADDR_NONE ((u32_t)0xffffffffUL) +#endif +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#if !defined(IPADDR_ANY) +#define IPADDR_ANY ((u32_t)0x00000000UL) +#endif +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ +#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0) +#define IP_CLASSA_NET 0xff000000 +#define IP_CLASSA_NSHIFT 24 +#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET) +#define IP_CLASSA_MAX 128 + +#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL) +#define IP_CLASSB_NET 0xffff0000 +#define IP_CLASSB_NSHIFT 16 +#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET) +#define IP_CLASSB_MAX 65536 + +#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL) +#define IP_CLASSC_NET 0xffffff00 +#define IP_CLASSC_NSHIFT 8 +#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET) + +#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL) +#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */ +#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */ +#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */ +#define IP_MULTICAST(a) IP_CLASSD(a) + +#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) +#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL) + +#define IP_LOOPBACKNET 127 /* official! */ + + +#if !defined(IP4_ADDR) +#if BYTE_ORDER == BIG_ENDIAN +/** Set an IP address given by the four byte-parts */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \ + ((u32_t)((b) & 0xff) << 16) | \ + ((u32_t)((c) & 0xff) << 8) | \ + (u32_t)((d) & 0xff) +#else +/** Set an IP address given by the four byte-parts. + Little-endian version that prevents the use of htonl. */ +#define IP4_ADDR(ipaddr, a,b,c,d) \ + (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \ + ((u32_t)((c) & 0xff) << 16) | \ + ((u32_t)((b) & 0xff) << 8) | \ + (u32_t)((a) & 0xff) +#endif +#endif + +/** MEMCPY-like copying of IP addresses where addresses are known to be + * 16-bit-aligned if the port is correctly configured (so a port could define + * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */ +#ifndef IPADDR2_COPY +#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t)) +#endif + +/** Copy IP address - faster than ip_addr_set: no NULL check */ +#define ip_addr_copy(dest, src) ((dest).addr = (src).addr) +/** Safely copy one IP address to another (src may be NULL) */ +#define ip_addr_set(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0 : \ + (src)->addr)) +/** Set complete address to zero */ +#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0) +/** Set address to IPADDR_ANY (no need for htonl()) */ +#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY) +/** Set address to loopback address */ +#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK)) +/** Safely copy one IP address to another and change byte order + * from host- to network-order. */ +#define ip_addr_set_hton(dest, src) ((dest)->addr = \ + ((src) == NULL ? 0:\ + htonl((src)->addr))) +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** Get the network address by combining host address with netmask */ +#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr)) + +/** + * Determine if two address are on the same network. + * + * @arg addr1 IP address 1 + * @arg addr2 IP address 2 + * @arg mask network identifier mask + * @return !0 if the network identifiers of both address match + */ +#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \ + (mask)->addr) == \ + ((addr2)->addr & \ + (mask)->addr)) +#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr) + +#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY) + +#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif)) +u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif)ICACHE_FLASH_ATTR; + +#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr) +u8_t ip4_addr_netmask_valid(u32_t netmask)ICACHE_FLASH_ATTR; + +#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL)) + +#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL)) + +#define ip_addr_debug_print(debug, ipaddr) \ + LWIP_DEBUGF(debug, ("%" U16_F ".%" U16_F ".%" U16_F ".%" U16_F, \ + ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \ + ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0)) + +/* Get one byte from the 4-byte address */ +#if !defined(IP2STR) +#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0]) +#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1]) +#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2]) +#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3]) +/* These are cast to u16_t, with the intent that they are often arguments + * to printf using the U16_F format from cc.h. */ +#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr)) +#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr)) +#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr)) +#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr)) +#endif + +/** For backwards compatibility */ +#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) + +#if !defined(IP2STR) +u32_t ipaddr_addr(const char *cp)ICACHE_FLASH_ATTR; +#endif +int ipaddr_aton(const char *cp, ip_addr_t *addr)ICACHE_FLASH_ATTR; +/** returns ptr to static buffer; not reentrant! */ +char *ipaddr_ntoa(const ip_addr_t *addr)ICACHE_FLASH_ATTR; +char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)ICACHE_FLASH_ATTR; + +#if !defined(IP2STR) +#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \ + ip4_addr2_16(ipaddr), \ + ip4_addr3_16(ipaddr), \ + ip4_addr4_16(ipaddr) + +#define IPSTR "%d.%d.%d.%d" + +struct ip_info { + struct ip_addr ip; + struct ip_addr netmask; + struct ip_addr gw; +}; +#endif +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_ADDR_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_frag.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_frag.h new file mode 100644 index 0000000..df6db5f --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/ip_frag.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Jani Monoses + * + */ + +#ifndef __LWIP_IP_FRAG_H__ +#define __LWIP_IP_FRAG_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if IP_REASSEMBLY +/* The IP reassembly timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + +/* IP reassembly helper struct. + * This is exported because memp needs to know the size. + */ +struct ip_reassdata { + struct ip_reassdata *next; + struct pbuf *p; + struct ip_hdr iphdr; + u16_t datagram_len; + u8_t flags; + u8_t timer; +}; + +void ip_reass_init(void)ICACHE_FLASH_ATTR; +void ip_reass_tmr(void)ICACHE_FLASH_ATTR; +struct pbuf * ip_reass(struct pbuf *p)ICACHE_FLASH_ATTR; +#endif /* IP_REASSEMBLY */ + +#if IP_FRAG +#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +/** A custom pbuf that holds a reference to another pbuf, which is freed + * when this custom pbuf is freed. This is used to create a custom PBUF_REF + * that points into the original pbuf. */ +struct pbuf_custom_ref { + /** 'base class' */ + struct pbuf_custom pc; + /** pointer to the original pbuf that is referenced */ + struct pbuf *original; +}; +#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest)ICACHE_FLASH_ATTR; +#endif /* IP_FRAG */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_IP_FRAG_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem.h new file mode 100644 index 0000000..7a4febc --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_MEM_H__ +#define __LWIP_MEM_H__ + +#include "lwip/opt.h" +#include "mem_manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if MEM_LIBC_MALLOC + +#include /* for size_t */ + +typedef size_t mem_size_t; + +/* aliases for C library malloc() */ +#define mem_init() +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef mem_free +#define mem_free vPortFree +#endif +#ifndef mem_malloc +#define mem_malloc pvPortMalloc +#endif +#ifndef mem_calloc +#define mem_calloc pvPortCalloc +#endif +#ifndef mem_realloc +#define mem_realloc pvPortRealloc +#endif +#ifndef mem_zalloc +#define mem_zalloc pvPortZalloc +#endif + +#ifndef os_malloc +#define os_malloc(s) mem_malloc((s)) +#endif +#ifndef os_realloc +#define os_realloc(p, s) mem_realloc((p), (s)) +#endif +#ifndef os_zalloc +#define os_zalloc(s) mem_zalloc((s)) +#endif +#ifndef os_free +#define os_free(p) mem_free((p)) +#endif + +/* Since there is no C library allocation function to shrink memory without + moving it, define this to nothing. */ +#ifndef mem_trim +#define mem_trim(mem, size) (mem) +#endif +#else /* MEM_LIBC_MALLOC */ + +/* MEM_SIZE would have to be aligned, but using 64000 here instead of + * 65535 leaves some room for alignment... + */ +#if MEM_SIZE > 64000l +typedef u32_t mem_size_t; +#define MEM_SIZE_F U32_F +#else +typedef u16_t mem_size_t; +#define MEM_SIZE_F U16_F +#endif /* MEM_SIZE > 64000 */ + +#if MEM_USE_POOLS +/** mem_init is not used when using pools instead of a heap */ +#define mem_init() +/** mem_trim is not used when using pools instead of a heap: + we can't free part of a pool element and don't want to copy the rest */ +#define mem_trim(mem, size) (mem) +#else /* MEM_USE_POOLS */ +/* lwIP alternative malloc */ +void mem_init(void)ICACHE_FLASH_ATTR; +void *mem_trim(void *mem, mem_size_t size)ICACHE_FLASH_ATTR; +#endif /* MEM_USE_POOLS */ +void *mem_malloc(mem_size_t size)ICACHE_FLASH_ATTR; +void *mem_calloc(mem_size_t count, mem_size_t size)ICACHE_FLASH_ATTR; +void mem_free(void *mem)ICACHE_FLASH_ATTR; +#endif /* MEM_LIBC_MALLOC */ + +/** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and + * LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4). + */ +#ifndef LWIP_MEM_ALIGN_SIZE +#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1)) +#endif + +/** Calculate safe memory size for an aligned buffer when using an unaligned + * type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the + * start (e.g. if buffer is u8_t[] and actual data will be u32_t*) + */ +#ifndef LWIP_MEM_ALIGN_BUFFER +#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1)) +#endif + +/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT + * so that ADDR % MEM_ALIGNMENT == 0 + */ +#ifndef LWIP_MEM_ALIGN +#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1))) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEM_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem_manager.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem_manager.h new file mode 100644 index 0000000..0355968 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/mem_manager.h @@ -0,0 +1,81 @@ +#ifndef __MEM_MANAGER_H__ +#define __MEM_MANAGER_H__ + +#include "c_types.h" + +/*------------------------±äÁ¿¶¨Òå------------------------*/ + +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#ifndef IOT_SIP_MODE +//#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x3fffc000 - (uint32)&_heap_start ) )//fix 16000 to 24000 on 14.2.26 +#else +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8000 ) ) +#endif +#define portBYTE_ALIGNMENT 8 +#define pdFALSE 0 +#define pdTRUE 1 + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#if portBYTE_ALIGNMENT == 8 + #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#define configUSE_MALLOC_FAILED_HOOK 1 +#define portPOINTER_SIZE_TYPE unsigned int + +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) + +//#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +//static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; +//static unsigned char *ucHeap; + +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; //The next free block in the list. + size_t xBlockSize; //The size of the free block. +} xBlockLink; + +static const unsigned short heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) ); + +//static const size_t xTotalHeapSize = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); + +//static xBlockLink xStart, *pxEnd = NULL; + +//static size_t xFreeBytesRemaining = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); + + +/*------------------------º¯ÊýÉùÃ÷-----------------------------------*/ + +//static void prvInsertBlockIntoFreeList( xBlockLink *pxBlockToInsert ) ;//ICACHE_FLASH_ATTR; + +//static void prvHeapInit( void ) ;//ICACHE_FLASH_ATTR; + +void vApplicationMallocFailedHook( void ) ;//ICACHE_FLASH_ATTR; + +void *pvPortMalloc( size_t xWantedSize ) ;//ICACHE_FLASH_ATTR; + +void vPortFree( void *pv ) ;//ICACHE_FLASH_ATTR; + +size_t xPortGetFreeHeapSize( void ) ;//ICACHE_FLASH_ATTR; + +void vPortInitialiseBlocks( void ) ;//ICACHE_FLASH_ATTR; +/*-----------------------------------------------------------*/ + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp.h new file mode 100644 index 0000000..764dedb --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_MEMP_H__ +#define __LWIP_MEMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create the list of all memory pools managed by memp. MEMP_MAX represents a NULL pool at the end */ +typedef enum { +#define LWIP_MEMPOOL(name,num,size,desc, attr) MEMP_##name, +#include "lwip/memp_std.h" + MEMP_MAX +} memp_t; + +#if MEM_USE_POOLS +/* Use a helper type to get the start and end of the user "memory pools" for mem_malloc */ +typedef enum { + /* Get the first (via: + MEMP_POOL_HELPER_START = ((u8_t) 1*MEMP_POOL_A + 0*MEMP_POOL_B + 0*MEMP_POOL_C + 0)*/ + MEMP_POOL_HELPER_FIRST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START 1 +#define LWIP_MALLOC_MEMPOOL(num, size) * MEMP_POOL_##size + 0 +#define LWIP_MALLOC_MEMPOOL_END +#include "lwip/memp_std.h" + ) , + /* Get the last (via: + MEMP_POOL_HELPER_END = ((u8_t) 0 + MEMP_POOL_A*0 + MEMP_POOL_B*0 + MEMP_POOL_C*1) */ + MEMP_POOL_HELPER_LAST = ((u8_t) +#define LWIP_MEMPOOL(name,num,size,desc) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL(num, size) 0 + MEMP_POOL_##size * +#define LWIP_MALLOC_MEMPOOL_END 1 +#include "lwip/memp_std.h" + ) +} memp_pool_helper_t; + +/* The actual start and stop values are here (cast them over) + We use this helper type and these defines so we can avoid using const memp_t values */ +#define MEMP_POOL_FIRST ((memp_t) MEMP_POOL_HELPER_FIRST) +#define MEMP_POOL_LAST ((memp_t) MEMP_POOL_HELPER_LAST) +#endif /* MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC || MEM_USE_POOLS +extern const u16_t memp_sizes[MEMP_MAX]; +#endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ + +#if MEMP_MEM_MALLOC + +#include "mem.h" + +#define memp_init() +#define memp_malloc(type) mem_malloc(memp_sizes[type]) +#define memp_free(type, mem) mem_free(mem) + +#else /* MEMP_MEM_MALLOC */ + +#if MEM_USE_POOLS +/** This structure is used to save the pool one element came from. */ +struct memp_malloc_helper +{ + memp_t poolnr; +}; +#endif /* MEM_USE_POOLS */ + +void memp_init(void)ICACHE_FLASH_ATTR; + +#if MEMP_OVERFLOW_CHECK +void *memp_malloc_fn(memp_t type, const char* file, const int line)ICACHE_FLASH_ATTR; +#define memp_malloc(t) memp_malloc_fn((t), __FILE__, __LINE__) +#else +void *memp_malloc(memp_t type)ICACHE_FLASH_ATTR; +#endif +void memp_free(memp_t type, void *mem)ICACHE_FLASH_ATTR; + +#endif /* MEMP_MEM_MALLOC */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_MEMP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp_std.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp_std.h new file mode 100644 index 0000000..b20a240 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/memp_std.h @@ -0,0 +1,126 @@ +/* + * SETUP: Make sure we define everything we will need. + * + * We have create three types of pools: + * 1) MEMPOOL - standard pools + * 2) MALLOC_MEMPOOL - to be used by mem_malloc in mem.c + * 3) PBUF_MEMPOOL - a mempool of pbuf's, so include space for the pbuf struct + * + * If the include'r doesn't require any special treatment of each of the types + * above, then will declare #2 & #3 to be just standard mempools. + */ +#ifndef LWIP_MALLOC_MEMPOOL +/* This treats "malloc pools" just like any other pool. + The pools are a little bigger to provide 'size' as the amount of user data. */ +#define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size, attr) +#define LWIP_MALLOC_MEMPOOL_START +#define LWIP_MALLOC_MEMPOOL_END +#endif /* LWIP_MALLOC_MEMPOOL */ + +#ifndef LWIP_PBUF_MEMPOOL +/* This treats "pbuf pools" just like any other pool. + * Allocates buffers for a pbuf struct AND a payload size */ +#define LWIP_PBUF_MEMPOOL(name, num, payload, desc, attr) LWIP_MEMPOOL(name, num, (MEMP_ALIGN_SIZE(sizeof(struct pbuf)) + MEMP_ALIGN_SIZE(payload)), desc, attr) +#endif /* LWIP_PBUF_MEMPOOL */ + + +/* + * A list of internal pools used by LWIP. + * + * LWIP_MEMPOOL(pool_name, number_elements, element_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + */ +#if LWIP_RAW +LWIP_MEMPOOL(RAW_PCB, MEMP_NUM_RAW_PCB, sizeof(struct raw_pcb), "RAW_PCB", DMEM_ATTR) +#endif /* LWIP_RAW */ + +#if LWIP_UDP +LWIP_MEMPOOL(UDP_PCB, MEMP_NUM_UDP_PCB, sizeof(struct udp_pcb), "UDP_PCB", DMEM_ATTR) +#endif /* LWIP_UDP */ + +#if LWIP_TCP +LWIP_MEMPOOL(TCP_PCB, MEMP_NUM_TCP_PCB, sizeof(struct tcp_pcb), "TCP_PCB", DMEM_ATTR) +LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN, sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN", DMEM_ATTR) +LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg), "TCP_SEG", DMEM_ATTR) +#endif /* LWIP_TCP */ + +#if IP_REASSEMBLY +LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA", DMEM_ATTR) +#endif /* IP_REASSEMBLY */ +#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF +LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF", DMEM_ATTR) +#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */ + +#if LWIP_NETCONN +LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF") +LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn), "NETCONN") +#endif /* LWIP_NETCONN */ + +#if NO_SYS==0 +LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API") +#if !LWIP_TCPIP_CORE_LOCKING_INPUT +LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT") +#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ +#endif /* NO_SYS==0 */ + +#if ARP_QUEUEING +LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE", DMEM_ATTR) +#endif /* ARP_QUEUEING */ + +#if LWIP_IGMP +LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP", DMEM_ATTR) +#endif /* LWIP_IGMP */ + +#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */ +LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT", DMEM_ATTR) +#endif /* LWIP_TIMERS */ + +#if LWIP_SNMP +LWIP_MEMPOOL(SNMP_ROOTNODE, MEMP_NUM_SNMP_ROOTNODE, sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE") +LWIP_MEMPOOL(SNMP_NODE, MEMP_NUM_SNMP_NODE, sizeof(struct mib_list_node), "SNMP_NODE") +LWIP_MEMPOOL(SNMP_VARBIND, MEMP_NUM_SNMP_VARBIND, sizeof(struct snmp_varbind), "SNMP_VARBIND") +LWIP_MEMPOOL(SNMP_VALUE, MEMP_NUM_SNMP_VALUE, SNMP_MAX_VALUE_SIZE, "SNMP_VALUE") +#endif /* LWIP_SNMP */ +#if LWIP_DNS && LWIP_SOCKET +LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB") +#endif /* LWIP_DNS && LWIP_SOCKET */ +#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC +LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST") +#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#if PPP_SUPPORT && PPPOE_SUPPORT +LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF") +#endif /* PPP_SUPPORT && PPPOE_SUPPORT */ + +/* + * A list of pools of pbuf's used by LWIP. + * + * LWIP_PBUF_MEMPOOL(pool_name, number_elements, pbuf_payload_size, pool_description) + * creates a pool name MEMP_pool_name. description is used in stats.c + * This allocates enough space for the pbuf struct and a payload. + * (Example: pbuf_payload_size=0 allocates only size for the struct) + */ +LWIP_PBUF_MEMPOOL(PBUF, MEMP_NUM_PBUF, 0, "PBUF_REF/ROM", DMEM_ATTR) + +/* XXX: need to align to 4 byte as memp strcut is 4-byte long. otherwise will crash */ +#define LWIP_MEM_ALIGN4_SIZE(size) (((size) + 4 - 1) & ~(4-1)) + +LWIP_PBUF_MEMPOOL(PBUF_POOL, PBUF_POOL_SIZE, LWIP_MEM_ALIGN4_SIZE(PBUF_POOL_BUFSIZE), "PBUF_POOL", DMEM_ATTR) + + +/* + * Allow for user-defined pools; this must be explicitly set in lwipopts.h + * since the default is to NOT look for lwippools.h + */ +#if MEMP_USE_CUSTOM_POOLS +#include "lwippools.h" +#endif /* MEMP_USE_CUSTOM_POOLS */ + +/* + * REQUIRED CLEANUP: Clear up so we don't get "multiply defined" error later + * (#undef is ignored for something that is not defined) + */ +#undef LWIP_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL +#undef LWIP_MALLOC_MEMPOOL_START +#undef LWIP_MALLOC_MEMPOOL_END +#undef LWIP_PBUF_MEMPOOL diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netbuf.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netbuf.h new file mode 100644 index 0000000..b554a57 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netbuf.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETBUF_H__ +#define __LWIP_NETBUF_H__ + +#include "lwip/opt.h" +#include "lwip/pbuf.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** This netbuf has dest-addr/port set */ +#define NETBUF_FLAG_DESTADDR 0x01 +/** This netbuf includes a checksum */ +#define NETBUF_FLAG_CHKSUM 0x02 + +struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY +#if LWIP_CHECKSUM_ON_COPY + u8_t flags; +#endif /* LWIP_CHECKSUM_ON_COPY */ + u16_t toport_chksum; +#if LWIP_NETBUF_RECVINFO + ip_addr_t toaddr; +#endif /* LWIP_NETBUF_RECVINFO */ +#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */ +}; + +/* Network buffer functions: */ +struct netbuf * netbuf_new (void)ICACHE_FLASH_ATTR; +void netbuf_delete (struct netbuf *buf)ICACHE_FLASH_ATTR; +void * netbuf_alloc (struct netbuf *buf, u16_t size)ICACHE_FLASH_ATTR; +void netbuf_free (struct netbuf *buf)ICACHE_FLASH_ATTR; +err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size)ICACHE_FLASH_ATTR; +void netbuf_chain (struct netbuf *head, + struct netbuf *tail)ICACHE_FLASH_ATTR; + +err_t netbuf_data (struct netbuf *buf, + void **dataptr, u16_t *len)ICACHE_FLASH_ATTR; +s8_t netbuf_next (struct netbuf *buf)ICACHE_FLASH_ATTR; +void netbuf_first (struct netbuf *buf)ICACHE_FLASH_ATTR; + + +#define netbuf_copy_partial(buf, dataptr, len, offset) \ + pbuf_copy_partial((buf)->p, (dataptr), (len), (offset)) +#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0) +#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len) +#define netbuf_len(buf) ((buf)->p->tot_len) +#define netbuf_fromaddr(buf) (&((buf)->addr)) +#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr) +#define netbuf_fromport(buf) ((buf)->port) +#if LWIP_NETBUF_RECVINFO +#define netbuf_destaddr(buf) (&((buf)->toaddr)) +#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr) +#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0) +#endif /* LWIP_NETBUF_RECVINFO */ +#if LWIP_CHECKSUM_ON_COPY +#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \ + (buf)->toport_chksum = chksum; } while(0) +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETBUF_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netdb.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netdb.h new file mode 100644 index 0000000..7587e2f --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netdb.h @@ -0,0 +1,124 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt + * + */ +#ifndef __LWIP_NETDB_H__ +#define __LWIP_NETDB_H__ + +#include "lwip/opt.h" + +#if LWIP_DNS && LWIP_SOCKET + +#include /* for size_t */ + +#include "lwip/inet.h" +#include "lwip/sockets.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* some rarely used options */ +#ifndef LWIP_DNS_API_DECLARE_H_ERRNO +#define LWIP_DNS_API_DECLARE_H_ERRNO 1 +#endif + +#ifndef LWIP_DNS_API_DEFINE_ERRORS +#define LWIP_DNS_API_DEFINE_ERRORS 1 +#endif + +#ifndef LWIP_DNS_API_DECLARE_STRUCTS +#define LWIP_DNS_API_DECLARE_STRUCTS 1 +#endif + +#if LWIP_DNS_API_DEFINE_ERRORS +/** Errors used by the DNS API functions, h_errno can be one of them */ +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 +#endif /* LWIP_DNS_API_DEFINE_ERRORS */ + +#if LWIP_DNS_API_DECLARE_STRUCTS +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; +#endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +#if LWIP_DNS_API_DECLARE_H_ERRNO +/* application accessable error code set by the DNS API functions */ +extern int h_errno; +#endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ + +struct hostent *lwip_gethostbyname(const char *name); +int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); +void lwip_freeaddrinfo(struct addrinfo *ai); +int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#if LWIP_COMPAT_SOCKETS +#define gethostbyname(name) lwip_gethostbyname(name) +#define gethostbyname_r(name, ret, buf, buflen, result, h_errnop) \ + lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop) +#define freeaddrinfo(addrinfo) lwip_freeaddrinfo(addrinfo) +#define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_DNS && LWIP_SOCKET */ + +#endif /* __LWIP_NETDB_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netif.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netif.h new file mode 100644 index 0000000..8bf1375 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netif.h @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_NETIF_H__ +#define __LWIP_NETIF_H__ + +#include "lwip/opt.h" + +#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) + +#include "lwip/err.h" + +#include "lwip/ip_addr.h" + +#include "lwip/def.h" +#include "lwip/pbuf.h" +#if LWIP_DHCP +struct dhcp; +#endif +#if LWIP_AUTOIP +struct autoip; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Throughout this file, IP addresses are expected to be in + * the same byte order as in IP_PCB. */ + +/** must be the maximum of all used hardware address lengths + across all types of interfaces in use */ +#define NETIF_MAX_HWADDR_LEN 6U + +/** Whether the network interface is 'up'. This is + * a software flag used to control whether this network + * interface is enabled and processes traffic. + * It is set by the startup code (for static IP configuration) or + * by dhcp/autoip when an address has been assigned. + */ +#define NETIF_FLAG_UP 0x01U +/** If set, the netif has broadcast capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_BROADCAST 0x02U +/** If set, the netif is one end of a point-to-point connection. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_POINTTOPOINT 0x04U +/** If set, the interface is configured using DHCP. + * Set by the DHCP code when starting or stopping DHCP. */ +#define NETIF_FLAG_DHCP 0x08U +/** If set, the interface has an active link + * (set by the network interface driver). + * Either set by the netif driver in its init function (if the link + * is up at that time) or at a later point once the link comes up + * (if link detection is supported by the hardware). */ +#define NETIF_FLAG_LINK_UP 0x10U +/** If set, the netif is an ethernet device using ARP. + * Set by the netif driver in its init function. + * Used to check input packet types and use of DHCP. */ +#define NETIF_FLAG_ETHARP 0x20U +/** If set, the netif is an ethernet device. It might not use + * ARP or TCP/IP if it is used for PPPoE only. + */ +#define NETIF_FLAG_ETHERNET 0x40U +/** If set, the netif has IGMP capability. + * Set by the netif driver in its init function. */ +#define NETIF_FLAG_IGMP 0x80U + +/** Function prototype for netif init functions. Set up flags and output/linkoutput + * callback functions in this function. + * + * @param netif The netif to initialize + */ +typedef err_t (*netif_init_fn)(struct netif *netif); +/** Function prototype for netif->input functions. This function is saved as 'input' + * callback function in the netif struct. Call it when a packet has been received. + * + * @param p The received packet, copied into a pbuf + * @param inp The netif which received the packet + */ +typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp); +/** Function prototype for netif->output functions. Called by lwIP when a packet + * shall be sent. For ethernet netif, set this to 'etharp_output' and set + * 'linkoutput'. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (p->payload points to IP header) + * @param ipaddr The IP address to which the packet shall be sent + */ +typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p, + ip_addr_t *ipaddr); +/** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * + * @param netif The netif which shall send a packet + * @param p The packet to send (raw ethernet packet) + */ +typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p); +/** Function prototype for netif status- or link-callback functions. */ +typedef void (*netif_status_callback_fn)(struct netif *netif); +/** Function prototype for netif igmp_mac_filter functions */ +typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif, + ip_addr_t *group, u8_t action); + +/** Generic data structure used for all lwIP network interfaces. + * The following fields should be filled in by the initialization + * function for the device driver: hwaddr_len, hwaddr[], mtu, flags */ +struct netif { + /** pointer to next in linked list */ + struct netif *next; + + /** IP address configuration in network byte order */ + ip_addr_t ip_addr; + ip_addr_t netmask; + ip_addr_t gw; + + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. ÏòIP²ãÊäÈëÊý¾Ý°ü*/ + netif_input_fn input; + /** This function is called by the IP module when it wants + * to send a packet on the interface. This function typically + * first resolves the hardware address, then sends the packet. ·¢ËÍIPÊý¾Ý°ü*/ + netif_output_fn output; + /** This function is called by the ARP module when it wants + * to send a packet on the interface. This function outputs + * the pbuf as-is on the link medium. µ×²ãÊý¾Ý°ü·¢ËÍ*/ + netif_linkoutput_fn linkoutput; +#if LWIP_NETIF_STATUS_CALLBACK + /** This function is called when the netif state is set to up or down + */ + netif_status_callback_fn status_callback; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK + /** This function is called when the netif link is set to up or down + */ + netif_status_callback_fn link_callback; +#endif /* LWIP_NETIF_LINK_CALLBACK */ + /** This field can be set by the device driver and could point + * to state information for the device. ×ÔÓÉÉèÖÃ×ֶΣ¬±ÈÈçÖ¸Ïòµ×²ãÉ豸Ïà¹ØÐÅÏ¢*/ + void *state; +#if LWIP_DHCP + /** the DHCP client state information for this netif */ + struct dhcp *dhcp; +#endif /* LWIP_DHCP */ +#if LWIP_AUTOIP + /** the AutoIP client state information for this netif */ + struct autoip *autoip; +#endif +#if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ + char* hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + /** maximum transfer unit (in bytes) ¸Ã½Ó¿ÚÔÊÐíµÄ×î´óÊý¾Ý°ü³¤¶È£¬¶àÊÇ1500*/ + u16_t mtu; + /** number of bytes used in hwaddr¸Ã½Ó¿ÚÎïÀíµØÖ·³¤¶È */ + u8_t hwaddr_len; + /** link level hardware address of this interface ¸Ã½Ó¿ÚÎïÀíµØÖ·*/ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** flags (see NETIF_FLAG_ above) ¸Ã½Ó¿Ú״̬¡¢ÊôÐÔ×Ö¶Î*/ + u8_t flags; + /** descriptive abbreviation ¸Ã½Ó¿ÚµÄÃû×Ö*/ + char name[2]; + /** number of this interface ¸Ã½Ó¿ÚµÄ±àºÅ*/ + u8_t num; +#if LWIP_SNMP + /** link type (from "snmp_ifType" enum from snmp.h) */ + u8_t link_type; + /** (estimate) link speed */ + u32_t link_speed; + /** timestamp at last change made (up/down) */ + u32_t ts; + /** counters */ + u32_t ifinoctets; + u32_t ifinucastpkts; + u32_t ifinnucastpkts; + u32_t ifindiscards; + u32_t ifoutoctets; + u32_t ifoutucastpkts; + u32_t ifoutnucastpkts; + u32_t ifoutdiscards; +#endif /* LWIP_SNMP */ +#if LWIP_IGMP + /** This function could be called to add or delete a entry in the multicast + filter table of the ethernet MAC.*/ + netif_igmp_mac_filter_fn igmp_mac_filter; +#endif /* LWIP_IGMP */ +#if LWIP_NETIF_HWADDRHINT + u8_t *addr_hint; +#endif /* LWIP_NETIF_HWADDRHINT */ +#if ENABLE_LOOPBACK + /* List of packets to be queued for ourselves. Ö¸Ïò·¢Ë͸ø×Ô¼ºµÄÊý¾Ý°üµÄpbuf*/ + struct pbuf *loop_first;//µÚÒ»¸ö + struct pbuf *loop_last;//×îºóÒ»¸ö +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ +}; + +#if LWIP_SNMP +#define NETIF_INIT_SNMP(netif, type, speed) \ + /* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \ + (netif)->link_type = (type); \ + /* your link speed here (units: bits per second) */ \ + (netif)->link_speed = (speed); \ + (netif)->ts = 0; \ + (netif)->ifinoctets = 0; \ + (netif)->ifinucastpkts = 0; \ + (netif)->ifinnucastpkts = 0; \ + (netif)->ifindiscards = 0; \ + (netif)->ifoutoctets = 0; \ + (netif)->ifoutucastpkts = 0; \ + (netif)->ifoutnucastpkts = 0; \ + (netif)->ifoutdiscards = 0 +#else /* LWIP_SNMP */ +#define NETIF_INIT_SNMP(netif, type, speed) +#endif /* LWIP_SNMP */ + + +/** The list of network interfaces. */ +extern struct netif *netif_list; +/** The default network interface. */ +extern struct netif *netif_default; + +void netif_init(void)ICACHE_FLASH_ATTR; + +struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)ICACHE_FLASH_ATTR; + +void +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw)ICACHE_FLASH_ATTR; +void netif_remove(struct netif * netif)ICACHE_FLASH_ATTR; + +/* Returns a network interface given its name. The name is of the form + "et0", where the first two letters are the "name" field in the + netif structure, and the digit is in the num field in the same + structure. */ +struct netif *netif_find(char *name)ICACHE_FLASH_ATTR; + +void netif_set_default(struct netif *netif)ICACHE_FLASH_ATTR; + +void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)ICACHE_FLASH_ATTR; +void netif_set_netmask(struct netif *netif, ip_addr_t *netmask)ICACHE_FLASH_ATTR; +void netif_set_gw(struct netif *netif, ip_addr_t *gw)ICACHE_FLASH_ATTR; + +void netif_set_up(struct netif *netif)ICACHE_FLASH_ATTR; +void netif_set_down(struct netif *netif)ICACHE_FLASH_ATTR; +/** Ask if an interface is up */ +#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_STATUS_CALLBACK +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)ICACHE_FLASH_ATTR; +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +void netif_set_link_up(struct netif *netif)ICACHE_FLASH_ATTR; +void netif_set_link_down(struct netif *netif)ICACHE_FLASH_ATTR; +/** Ask if a link is up */ +#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0) + +#if LWIP_NETIF_LINK_CALLBACK +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)ICACHE_FLASH_ATTR; +#endif /* LWIP_NETIF_LINK_CALLBACK */ + +#if LWIP_NETIF_HOSTNAME +#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0) +#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL) +#endif /* LWIP_NETIF_HOSTNAME */ + +#if LWIP_IGMP +#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0) +#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL) +#endif /* LWIP_IGMP */ + +#if ENABLE_LOOPBACK +err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip)ICACHE_FLASH_ATTR; +void netif_poll(struct netif *netif)ICACHE_FLASH_ATTR; +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +void netif_poll_all(void)ICACHE_FLASH_ATTR; +#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_NETIF_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netifapi.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netifapi.h new file mode 100644 index 0000000..33318ef --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/netifapi.h @@ -0,0 +1,108 @@ +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ + +#ifndef __LWIP_NETIFAPI_H__ +#define __LWIP_NETIFAPI_H__ + +#include "lwip/opt.h" + +#if LWIP_NETIF_API /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*netifapi_void_fn)(struct netif *netif); +typedef err_t (*netifapi_errt_fn)(struct netif *netif); + +struct netifapi_msg_msg { +#if !LWIP_TCPIP_CORE_LOCKING + sys_sem_t sem; +#endif /* !LWIP_TCPIP_CORE_LOCKING */ + err_t err; + struct netif *netif; + union { + struct { + ip_addr_t *ipaddr; + ip_addr_t *netmask; + ip_addr_t *gw; + void *state; + netif_init_fn init; + netif_input_fn input; + } add; + struct { + netifapi_void_fn voidfunc; + netifapi_errt_fn errtfunc; + } common; + } msg; +}; + +struct netifapi_msg { + void (* function)(struct netifapi_msg_msg *msg); + struct netifapi_msg_msg msg; +}; + + +/* API for application */ +err_t netifapi_netif_add ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw, + void *state, + netif_init_fn init, + netif_input_fn input); + +err_t netifapi_netif_set_addr ( struct netif *netif, + ip_addr_t *ipaddr, + ip_addr_t *netmask, + ip_addr_t *gw ); + +err_t netifapi_netif_common ( struct netif *netif, + netifapi_void_fn voidfunc, + netifapi_errt_fn errtfunc); + +#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL) +#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL) +#define netifapi_netif_set_down(n) netifapi_netif_common(n, netif_set_down, NULL) +#define netifapi_netif_set_default(n) netifapi_netif_common(n, netif_set_default, NULL) +#define netifapi_dhcp_start(n) netifapi_netif_common(n, NULL, dhcp_start) +#define netifapi_dhcp_stop(n) netifapi_netif_common(n, dhcp_stop, NULL) +#define netifapi_autoip_start(n) netifapi_netif_common(n, NULL, autoip_start) +#define netifapi_autoip_stop(n) netifapi_netif_common(n, NULL, autoip_stop) + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_NETIF_API */ + +#endif /* __LWIP_NETIFAPI_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/opt.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/opt.h new file mode 100644 index 0000000..1a681c9 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/opt.h @@ -0,0 +1,2043 @@ +/** + * @file + * + * lwIP Options Configuration + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_OPT_H__ +#define __LWIP_OPT_H__ + +/* + * Include user defined options first. Anything not defined in these files + * will be set to standard values. Override anything you dont like! + */ +#include "include/lwipopts.h" +#include "lwip/debug.h" + +/* + ----------------------------------------------- + ---------- Platform specific locking ---------- + ----------------------------------------------- +*/ + +/** + * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain + * critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#ifndef SYS_LIGHTWEIGHT_PROT +#define SYS_LIGHTWEIGHT_PROT 0 +#endif + +/** + * NO_SYS==1: Provides VERY minimal functionality. Otherwise, + * use lwIP facilities. + */ +#ifndef NO_SYS +#define NO_SYS 1 +#endif + +/** + * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 + * Mainly for compatibility to old versions. + */ +#ifndef NO_SYS_NO_TIMERS +#define NO_SYS_NO_TIMERS 1 +#endif + +/** + * MEMCPY: override this if you have a faster implementation at hand than the + * one included in your C library + */ +#ifndef MEMCPY +#define MEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/** + * SMEMCPY: override this with care! Some compilers (e.g. gcc) can inline a + * call to memcpy() if the length is known at compile time and is small. + */ +#ifndef SMEMCPY +#define SMEMCPY(dst,src,len) memcpy(dst,src,len) +#endif + +/* + ------------------------------------ + ---------- Memory options ---------- + ------------------------------------ +*/ +/** + * MEM_LIBC_MALLOC==1: Use malloc/free/realloc provided by your C-library + * instead of the lwip internal allocator. Can save code size if you + * already use it. + */ +#ifndef MEM_LIBC_MALLOC +#define MEM_LIBC_MALLOC 0 +#endif + +/** +* MEMP_MEM_MALLOC==1: Use mem_malloc/mem_free instead of the lwip pool allocator. +* Especially useful with MEM_LIBC_MALLOC but handle with care regarding execution +* speed and usage from interrupts! +*/ +#ifndef MEMP_MEM_MALLOC +#define MEMP_MEM_MALLOC 0 +#endif + +/** + * MEM_ALIGNMENT: should be set to the alignment of the CPU + * 4 byte alignment -> #define MEM_ALIGNMENT 4 + * 2 byte alignment -> #define MEM_ALIGNMENT 2 + */ +#ifndef MEM_ALIGNMENT +#define MEM_ALIGNMENT 1 +#endif + +/** + * MEM_SIZE: the size of the heap memory. If the application will send + * a lot of data that needs to be copied, this should be set high. + */ +#ifndef MEM_SIZE +#define MEM_SIZE 1600 +#endif + +/** + * MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array. + * This can be used to individually change the location of each pool. + * Default is one big array for all pools + */ +#ifndef MEMP_SEPARATE_POOLS +#define MEMP_SEPARATE_POOLS 0 +#endif + +/** + * MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable + * amount of bytes before and after each memp element in every pool and fills + * it with a prominent default value. + * MEMP_OVERFLOW_CHECK == 0 no checking + * MEMP_OVERFLOW_CHECK == 1 checks each element when it is freed + * MEMP_OVERFLOW_CHECK >= 2 checks each element in every pool every time + * memp_malloc() or memp_free() is called (useful but slow!) + */ +#ifndef MEMP_OVERFLOW_CHECK +#define MEMP_OVERFLOW_CHECK 0 +#endif + +/** + * MEMP_SANITY_CHECK==1: run a sanity check after each memp_free() to make + * sure that there are no cycles in the linked lists. + */ +#ifndef MEMP_SANITY_CHECK +#define MEMP_SANITY_CHECK 0 +#endif + +/** + * MEM_USE_POOLS==1: Use an alternative to malloc() by allocating from a set + * of memory pools of various sizes. When mem_malloc is called, an element of + * the smallest pool that can provide the length needed is returned. + * To use this, MEMP_USE_CUSTOM_POOLS also has to be enabled. + */ +#ifndef MEM_USE_POOLS +#define MEM_USE_POOLS 0 +#endif + +/** + * MEM_USE_POOLS_TRY_BIGGER_POOL==1: if one malloc-pool is empty, try the next + * bigger pool - WARNING: THIS MIGHT WASTE MEMORY but it can make a system more + * reliable. */ +#ifndef MEM_USE_POOLS_TRY_BIGGER_POOL +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +#endif + +/** + * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h + * that defines additional pools beyond the "standard" ones required + * by lwIP. If you set this to 1, you must have lwippools.h in your + * inlude path somewhere. + */ +#ifndef MEMP_USE_CUSTOM_POOLS +#define MEMP_USE_CUSTOM_POOLS 0 +#endif + +/** + * Set this to 1 if you want to free PBUF_RAM pbufs (or call mem_free()) from + * interrupt context (or another context that doesn't allow waiting for a + * semaphore). + * If set to 1, mem_malloc will be protected by a semaphore and SYS_ARCH_PROTECT, + * while mem_free will only use SYS_ARCH_PROTECT. mem_malloc SYS_ARCH_UNPROTECTs + * with each loop so that mem_free can run. + * + * ATTENTION: As you can see from the above description, this leads to dis-/ + * enabling interrupts often, which can be slow! Also, on low memory, mem_malloc + * can need longer. + * + * If you don't want that, at least for NO_SYS=0, you can still use the following + * functions to enqueue a deallocation call which then runs in the tcpip_thread + * context: + * - pbuf_free_callback(p); + * - mem_free_callback(m); + */ +#ifndef LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 0 +#endif + +/* + ------------------------------------------------ + ---------- Internal Memory Pool Sizes ---------- + ------------------------------------------------ +*/ +/** + * MEMP_NUM_PBUF: the number of memp struct pbufs (used for PBUF_ROM and PBUF_REF). + * If the application sends a lot of data out of ROM (or other static memory), + * this should be set high. + */ +#ifndef MEMP_NUM_PBUF +#define MEMP_NUM_PBUF 16 +#endif + +/** + * MEMP_NUM_RAW_PCB: Number of raw connection PCBs + * (requires the LWIP_RAW option) + */ +#ifndef MEMP_NUM_RAW_PCB +#define MEMP_NUM_RAW_PCB 4 +#endif + +/** + * MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One + * per active UDP "connection". + * (requires the LWIP_UDP option) + */ +#ifndef MEMP_NUM_UDP_PCB +#define MEMP_NUM_UDP_PCB 4 +#endif + +/** + * MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB +#define MEMP_NUM_TCP_PCB 5 +#endif + +/** + * MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_PCB_LISTEN +#define MEMP_NUM_TCP_PCB_LISTEN 8 +#endif + +/** + * MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. + * (requires the LWIP_TCP option) + */ +#ifndef MEMP_NUM_TCP_SEG +#define MEMP_NUM_TCP_SEG 16 +#endif + +/** + * MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for + * reassembly (whole packets, not fragments!) + */ +#ifndef MEMP_NUM_REASSDATA +#define MEMP_NUM_REASSDATA 5 +#endif + +/** + * MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent + * (fragments, not whole packets!). + * This is only used with IP_FRAG_USES_STATIC_BUF==0 and + * LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs + * where the packet is not yet sent when netif->output returns. + */ +#ifndef MEMP_NUM_FRAG_PBUF +#define MEMP_NUM_FRAG_PBUF 15 +#endif + +/** + * MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing + * packets (pbufs) that are waiting for an ARP request (to resolve + * their destination address) to finish. + * (requires the ARP_QUEUEING option) + */ +#ifndef MEMP_NUM_ARP_QUEUE +#define MEMP_NUM_ARP_QUEUE 30 +#endif + +/** + * MEMP_NUM_IGMP_GROUP: The number of multicast groups whose network interfaces + * can be members et the same time (one per netif - allsystems group -, plus one + * per netif membership). + * (requires the LWIP_IGMP option) + */ +#ifndef MEMP_NUM_IGMP_GROUP +#define MEMP_NUM_IGMP_GROUP 8 +#endif + +/** + * MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. + * (requires NO_SYS==0) + */ +#ifndef MEMP_NUM_SYS_TIMEOUT +#define MEMP_NUM_SYS_TIMEOUT 3 +#endif + +/** + * MEMP_NUM_NETBUF: the number of struct netbufs. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF 2 +#endif + +/** + * MEMP_NUM_NETCONN: the number of struct netconns. + * (only needed if you use the sequential API, like api_lib.c) + */ +#ifndef MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN 4 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used + * for callback/timeout API communication. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_API +#define MEMP_NUM_TCPIP_MSG_API 8 +#endif + +/** + * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used + * for incoming packets. + * (only needed if you use tcpip.c) + */ +#ifndef MEMP_NUM_TCPIP_MSG_INPKT +#define MEMP_NUM_TCPIP_MSG_INPKT 8 +#endif + +/** + * MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree. + */ +#ifndef MEMP_NUM_SNMP_NODE +#define MEMP_NUM_SNMP_NODE 50 +#endif + +/** + * MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree. + * Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least! + */ +#ifndef MEMP_NUM_SNMP_ROOTNODE +#define MEMP_NUM_SNMP_ROOTNODE 30 +#endif + +/** + * MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to + * be changed normally) - 2 of these are used per request (1 for input, + * 1 for output) + */ +#ifndef MEMP_NUM_SNMP_VARBIND +#define MEMP_NUM_SNMP_VARBIND 2 +#endif + +/** + * MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used + * (does not have to be changed normally) - 3 of these are used per request + * (1 for the value read and 2 for OIDs - input and output) + */ +#ifndef MEMP_NUM_SNMP_VALUE +#define MEMP_NUM_SNMP_VALUE 3 +#endif + +/** + * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls + * (before freeing the corresponding memory using lwip_freeaddrinfo()). + */ +#ifndef MEMP_NUM_NETDB +#define MEMP_NUM_NETDB 1 +#endif + +/** + * MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list + * if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1. + */ +#ifndef MEMP_NUM_LOCALHOSTLIST +#define MEMP_NUM_LOCALHOSTLIST 1 +#endif + +/** + * MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE + * interfaces (only used with PPPOE_SUPPORT==1) + */ +#ifndef MEMP_NUM_PPPOE_INTERFACES +#define MEMP_NUM_PPPOE_INTERFACES 1 +#endif + +/** + * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. + */ +#ifndef PBUF_POOL_SIZE +#define PBUF_POOL_SIZE 16 +#endif + +/* + --------------------------------- + ---------- ARP options ---------- + --------------------------------- +*/ +/** + * LWIP_ARP==1: Enable ARP functionality. + */ +#ifndef LWIP_ARP +#define LWIP_ARP 1 +#endif + +/** + * ARP_TABLE_SIZE: Number of active MAC-IP address pairs cached. + */ +#ifndef ARP_TABLE_SIZE +#define ARP_TABLE_SIZE 10 +#endif + +/** + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. + */ +#ifndef ARP_QUEUEING +#define ARP_QUEUEING 0 +#endif + +/** + * ETHARP_TRUST_IP_MAC==1: Incoming IP packets cause the ARP table to be + * updated with the source MAC and IP addresses supplied in the packet. + * You may want to disable this if you do not trust LAN peers to have the + * correct addresses, or as a limited approach to attempt to handle + * spoofing. If disabled, lwIP will need to make a new ARP request if + * the peer is not already in the ARP table, adding a little latency. + * The peer *is* in the ARP table if it requested our address before. + * Also notice that this slows down input processing of every IP packet! + */ +#ifndef ETHARP_TRUST_IP_MAC +#define ETHARP_TRUST_IP_MAC 0 +#endif + +/** + * ETHARP_SUPPORT_VLAN==1: support receiving ethernet packets with VLAN header. + * Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check. + * If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted. + * If ETHARP_VLAN_CHECK is not defined, all traffic is accepted. + */ +#ifndef ETHARP_SUPPORT_VLAN +#define ETHARP_SUPPORT_VLAN 0 +#endif + +/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP + * might be disabled + */ +#ifndef LWIP_ETHERNET +#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT) +#endif + +/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure + * alignment of payload after that header. Since the header is 14 bytes long, + * without this padding e.g. addresses in the IP header will not be aligned + * on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms. + */ +#ifndef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 +#endif + +/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table + * entries (using etharp_add_static_entry/etharp_remove_static_entry). + */ +#ifndef ETHARP_SUPPORT_STATIC_ENTRIES +#define ETHARP_SUPPORT_STATIC_ENTRIES 0 +#endif + + +/* + -------------------------------- + ---------- IP options ---------- + -------------------------------- +*/ +/** + * IP_FORWARD==1: Enables the ability to forward IP packets across network + * interfaces. If you are going to run lwIP on a device with only one network + * interface, define this to 0. + */ +#ifndef IP_FORWARD +#define IP_FORWARD 0 +#endif + +/** + * IP_OPTIONS_ALLOWED: Defines the behavior for IP options. + * IP_OPTIONS_ALLOWED==0: All packets with IP options are dropped. + * IP_OPTIONS_ALLOWED==1: IP options are allowed (but not parsed). + */ +#ifndef IP_OPTIONS_ALLOWED +#define IP_OPTIONS_ALLOWED 1 +#endif + +/** + * IP_REASSEMBLY==1: Reassemble incoming fragmented IP packets. Note that + * this option does not affect outgoing packet sizes, which can be controlled + * via IP_FRAG. + */ +#ifndef IP_REASSEMBLY +#define IP_REASSEMBLY 0 +#endif + +/** + * IP_FRAG==1: Fragment outgoing IP packets if their size exceeds MTU. Note + * that this option does not affect incoming packet sizes, which can be + * controlled via IP_REASSEMBLY. + */ +#ifndef IP_FRAG +#define IP_FRAG 1 +#endif + +/** + * IP_REASS_MAXAGE: Maximum time (in multiples of IP_TMR_INTERVAL - so seconds, normally) + * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived + * in this time, the whole packet is discarded. + */ +#ifndef IP_REASS_MAXAGE +#define IP_REASS_MAXAGE 3 +#endif + +/** + * IP_REASS_MAX_PBUFS: Total maximum amount of pbufs waiting to be reassembled. + * Since the received pbufs are enqueued, be sure to configure + * PBUF_POOL_SIZE > IP_REASS_MAX_PBUFS so that the stack is still able to receive + * packets even if the maximum amount of fragments is enqueued for reassembly! + */ +#ifndef IP_REASS_MAX_PBUFS +#define IP_REASS_MAX_PBUFS 10 +#endif + +/** + * IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP + * fragmentation. Otherwise pbufs are allocated and reference the original + * packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1, + * new PBUF_RAM pbufs are used for fragments). + * ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs! + */ +#ifndef IP_FRAG_USES_STATIC_BUF +#define IP_FRAG_USES_STATIC_BUF 0 +#endif + +/** + * IP_FRAG_MAX_MTU: Assumed max MTU on any interface for IP frag buffer + * (requires IP_FRAG_USES_STATIC_BUF==1) + */ +#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU) +#define IP_FRAG_MAX_MTU 1500 +#endif + +/** + * IP_DEFAULT_TTL: Default value for Time-To-Live used by transport layers. + */ +#ifndef IP_DEFAULT_TTL +#define IP_DEFAULT_TTL 255 +#endif + +/** + * IP_SOF_BROADCAST=1: Use the SOF_BROADCAST field to enable broadcast + * filter per pcb on udp and raw send operations. To enable broadcast filter + * on recv operations, you also have to set IP_SOF_BROADCAST_RECV=1. + */ +#ifndef IP_SOF_BROADCAST +#define IP_SOF_BROADCAST 0 +#endif + +/** + * IP_SOF_BROADCAST_RECV (requires IP_SOF_BROADCAST=1) enable the broadcast + * filter on recv operations. + */ +#ifndef IP_SOF_BROADCAST_RECV +#define IP_SOF_BROADCAST_RECV 0 +#endif + +/* + ---------------------------------- + ---------- ICMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_ICMP==1: Enable ICMP module inside the IP stack. + * Be careful, disable that make your product non-compliant to RFC1122 + */ +#ifndef LWIP_ICMP +#define LWIP_ICMP 1 +#endif + +/** + * ICMP_TTL: Default value for Time-To-Live used by ICMP packets. + */ +#ifndef ICMP_TTL +#define ICMP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_BROADCAST_PING==1: respond to broadcast pings (default is unicast only) + */ +#ifndef LWIP_BROADCAST_PING +#define LWIP_BROADCAST_PING 0 +#endif + +/** + * LWIP_MULTICAST_PING==1: respond to multicast pings (default is unicast only) + */ +#ifndef LWIP_MULTICAST_PING +#define LWIP_MULTICAST_PING 0 +#endif + +/* + --------------------------------- + ---------- RAW options ---------- + --------------------------------- +*/ +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef LWIP_RAW +#define LWIP_RAW 1 +#endif + +/** + * LWIP_RAW==1: Enable application layer to hook into the IP layer itself. + */ +#ifndef RAW_TTL +#define RAW_TTL (IP_DEFAULT_TTL) +#endif + +/* + ---------------------------------- + ---------- DHCP options ---------- + ---------------------------------- +*/ +/** + * LWIP_DHCP==1: Enable DHCP module. + */ +#ifndef LWIP_DHCP +#define LWIP_DHCP 0 +#endif + +/** + * DHCP_DOES_ARP_CHECK==1: Do an ARP check on the offered address. + */ +#ifndef DHCP_DOES_ARP_CHECK +#define DHCP_DOES_ARP_CHECK ((LWIP_DHCP) && (LWIP_ARP)) +#endif + +/* + ------------------------------------ + ---------- AUTOIP options ---------- + ------------------------------------ +*/ +/** + * LWIP_AUTOIP==1: Enable AUTOIP module. + */ +#ifndef LWIP_AUTOIP +#define LWIP_AUTOIP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP==1: Allow DHCP and AUTOIP to be both enabled on + * the same interface at the same time. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP +#define LWIP_DHCP_AUTOIP_COOP 0 +#endif + +/** + * LWIP_DHCP_AUTOIP_COOP_TRIES: Set to the number of DHCP DISCOVER probes + * that should be sent before falling back on AUTOIP. This can be set + * as low as 1 to get an AutoIP address very quickly, but you should + * be prepared to handle a changing IP address when DHCP overrides + * AutoIP. + */ +#ifndef LWIP_DHCP_AUTOIP_COOP_TRIES +#define LWIP_DHCP_AUTOIP_COOP_TRIES 9 +#endif + +/* + ---------------------------------- + ---------- SNMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_SNMP==1: Turn on SNMP module. UDP must be available for SNMP + * transport. + */ +#ifndef LWIP_SNMP +#define LWIP_SNMP 0 +#endif + +/** + * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will + * allow. At least one request buffer is required. + * Does not have to be changed unless external MIBs answer request asynchronously + */ +#ifndef SNMP_CONCURRENT_REQUESTS +#define SNMP_CONCURRENT_REQUESTS 1 +#endif + +/** + * SNMP_TRAP_DESTINATIONS: Number of trap destinations. At least one trap + * destination is required + */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif + +/** + * SNMP_PRIVATE_MIB: + * When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. + */ +#ifndef SNMP_PRIVATE_MIB +#define SNMP_PRIVATE_MIB 0 +#endif + +/** + * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). + * Unsafe requests are disabled by default! + */ +#ifndef SNMP_SAFE_REQUESTS +#define SNMP_SAFE_REQUESTS 1 +#endif + +/** + * The maximum length of strings used. This affects the size of + * MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_OCTET_STRING_LEN +#define SNMP_MAX_OCTET_STRING_LEN 127 +#endif + +/** + * The maximum depth of the SNMP tree. + * With private MIBs enabled, this depends on your MIB! + * This affects the size of MEMP_SNMP_VALUE elements. + */ +#ifndef SNMP_MAX_TREE_DEPTH +#define SNMP_MAX_TREE_DEPTH 15 +#endif + +/** + * The size of the MEMP_SNMP_VALUE elements, normally calculated from + * SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH. + */ +#ifndef SNMP_MAX_VALUE_SIZE +#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) +#endif + +/* + ---------------------------------- + ---------- IGMP options ---------- + ---------------------------------- +*/ +/** + * LWIP_IGMP==1: Turn on IGMP module. + */ +#ifndef LWIP_IGMP +#define LWIP_IGMP 0 +#endif + +/* + ---------------------------------- + ---------- DNS options ----------- + ---------------------------------- +*/ +/** + * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS + * transport. + */ +#ifndef LWIP_DNS +#define LWIP_DNS 0 +#endif + +/** DNS maximum number of entries to maintain locally. */ +#ifndef DNS_TABLE_SIZE +#define DNS_TABLE_SIZE 4 +#endif + +/** DNS maximum host name length supported in the name table. */ +#ifndef DNS_MAX_NAME_LENGTH +#define DNS_MAX_NAME_LENGTH 256 +#endif + +/** The maximum of DNS servers */ +#ifndef DNS_MAX_SERVERS +#define DNS_MAX_SERVERS 2 +#endif + +/** DNS do a name checking between the query and the response. */ +#ifndef DNS_DOES_NAME_CHECK +#define DNS_DOES_NAME_CHECK 1 +#endif + +/** DNS message max. size. Default value is RFC compliant. */ +#ifndef DNS_MSG_SIZE +#define DNS_MSG_SIZE 512 +#endif + +/** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, + * you have to define + * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} + * (an array of structs name/address, where address is an u32_t in network + * byte order). + * + * Instead, you can also use an external function: + * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) + * that returns the IP address or INADDR_NONE if not found. + */ +#ifndef DNS_LOCAL_HOSTLIST +#define DNS_LOCAL_HOSTLIST 0 +#endif /* DNS_LOCAL_HOSTLIST */ + +/** If this is turned on, the local host-list can be dynamically changed + * at runtime. */ +#ifndef DNS_LOCAL_HOSTLIST_IS_DYNAMIC +#define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 +#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ + +/* + --------------------------------- + ---------- UDP options ---------- + --------------------------------- +*/ +/** + * LWIP_UDP==1: Turn on UDP. + */ +#ifndef LWIP_UDP +#define LWIP_UDP 1 +#endif + +/** + * LWIP_UDPLITE==1: Turn on UDP-Lite. (Requires LWIP_UDP) + */ +#ifndef LWIP_UDPLITE +#define LWIP_UDPLITE 0 +#endif + +/** + * UDP_TTL: Default Time-To-Live value. + */ +#ifndef UDP_TTL +#define UDP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * LWIP_NETBUF_RECVINFO==1: append destination addr and port to every netbuf. + */ +#ifndef LWIP_NETBUF_RECVINFO +#define LWIP_NETBUF_RECVINFO 0 +#endif + +/* + --------------------------------- + ---------- TCP options ---------- + --------------------------------- +*/ +/** + * LWIP_TCP==1: Turn on TCP. + */ +#ifndef LWIP_TCP +#define LWIP_TCP 1 +#endif + +/** + * TCP_TTL: Default Time-To-Live value. + */ +#ifndef TCP_TTL +#define TCP_TTL (IP_DEFAULT_TTL) +#endif + +/** + * TCP_WND: The size of a TCP window. This must be at least + * (2 * TCP_MSS) for things to work well + */ +#ifndef TCP_WND +#define TCP_WND (4 * TCP_MSS) +#endif + +/** + * TCP_MAXRTX: Maximum number of retransmissions of data segments. + */ +#ifndef TCP_MAXRTX +#define TCP_MAXRTX 12 +#endif + +/** + * TCP_SYNMAXRTX: Maximum number of retransmissions of SYN segments. + */ +#ifndef TCP_SYNMAXRTX +#define TCP_SYNMAXRTX 6 +#endif + +/** + * TCP_QUEUE_OOSEQ==1: TCP will queue segments that arrive out of order. + * Define to 0 if your device is low on memory. + */ +#ifndef TCP_QUEUE_OOSEQ +#define TCP_QUEUE_OOSEQ (LWIP_TCP) +#endif + +/** + * TCP_MSS: TCP Maximum segment size. (default is 536, a conservative default, + * you might want to increase this.) + * For the receive side, this MSS is advertised to the remote side + * when opening a connection. For the transmit size, this MSS sets + * an upper limit on the MSS advertised by the remote host. + */ +#ifndef TCP_MSS +#define TCP_MSS 536 +#endif + +/** + * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really + * sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which + * reflects the available reassembly buffer size at the remote host) and the + * largest size permitted by the IP layer" (RFC 1122) + * Setting this to 1 enables code that checks TCP_MSS against the MTU of the + * netif used for a connection and limits the MSS if it would be too big otherwise. + */ +#ifndef TCP_CALCULATE_EFF_SEND_MSS +#define TCP_CALCULATE_EFF_SEND_MSS 1 +#endif + + +/** + * TCP_SND_BUF: TCP sender buffer space (bytes). + */ +#ifndef TCP_SND_BUF +#define TCP_SND_BUF 256 +#endif + +/** + * TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least + * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. + */ +#ifndef TCP_SND_QUEUELEN +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) +#endif + +/** + * TCP_SNDLOWAT: TCP writable space (bytes). This must be less than + * TCP_SND_BUF. It is the amount of space which must be available in the + * TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT). + */ +#ifndef TCP_SNDLOWAT +#define TCP_SNDLOWAT ((TCP_SND_BUF)/2) +#endif + +/** + * TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be grater + * than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below + * this number, select returns writable (combined with TCP_SNDLOWAT). + */ +#ifndef TCP_SNDQUEUELOWAT +#define TCP_SNDQUEUELOWAT ((TCP_SND_QUEUELEN)/2) +#endif + +/** + * TCP_LISTEN_BACKLOG: Enable the backlog option for tcp listen pcb. + */ +#ifndef TCP_LISTEN_BACKLOG +#define TCP_LISTEN_BACKLOG 0 +#endif + +/** + * The maximum allowed backlog for TCP listen netconns. + * This backlog is used unless another is explicitly specified. + * 0xff is the maximum (u8_t). + */ +#ifndef TCP_DEFAULT_LISTEN_BACKLOG +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +#endif + +/** + * TCP_OVERSIZE: The maximum number of bytes that tcp_write may + * allocate ahead of time in an attempt to create shorter pbuf chains + * for transmission. The meaningful range is 0 to TCP_MSS. Some + * suggested values are: + * + * 0: Disable oversized allocation. Each tcp_write() allocates a new + pbuf (old behaviour). + * 1: Allocate size-aligned pbufs with minimal excess. Use this if your + * scatter-gather DMA requires aligned fragments. + * 128: Limit the pbuf/memory overhead to 20%. + * TCP_MSS: Try to create unfragmented TCP packets. + * TCP_MSS/4: Try to create 4 fragments or less per TCP packet. + */ +#ifndef TCP_OVERSIZE +#define TCP_OVERSIZE TCP_MSS +#endif + +/** + * LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option. + */ +#ifndef LWIP_TCP_TIMESTAMPS +#define LWIP_TCP_TIMESTAMPS 0 +#endif + +/** + * TCP_WND_UPDATE_THRESHOLD: difference in window to trigger an + * explicit window update + */ +#ifndef TCP_WND_UPDATE_THRESHOLD +#define TCP_WND_UPDATE_THRESHOLD (TCP_WND / 4) +#endif + +/** + * LWIP_EVENT_API and LWIP_CALLBACK_API: Only one of these should be set to 1. + * LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all + * events (accept, sent, etc) that happen in the system. + * LWIP_CALLBACK_API==1: The PCB callback function is called directly + * for the event. + */ +//#ifndef LWIP_EVENT_API +//#define LWIP_EVENT_API 0 +//#define LWIP_CALLBACK_API 1 +//#else +//#define LWIP_EVENT_API 1 +//#define LWIP_CALLBACK_API 0 +//#endif + + +/* + ---------------------------------- + ---------- Pbuf options ---------- + ---------------------------------- +*/ +/** + * PBUF_LINK_HLEN: the number of bytes that should be allocated for a + * link level header. The default is 14, the standard value for + * Ethernet. + */ +#ifndef PBUF_LINK_HLEN +#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE) +#endif + +/** + * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is + * designed to accomodate single full size TCP frame in one pbuf, including + * TCP_MSS, IP header, and link header. + */ +#ifndef PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) +#endif + +/* + ------------------------------------------------ + ---------- Network Interfaces options ---------- + ------------------------------------------------ +*/ +/** + * LWIP_NETIF_HOSTNAME==1: use DHCP_OPTION_HOSTNAME with netif's hostname + * field. + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 0 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 0 +#endif + +/** + * LWIP_NETIF_STATUS_CALLBACK==1: Support a callback function whenever an interface + * changes its up/down status (i.e., due to DHCP IP acquistion) + */ +#ifndef LWIP_NETIF_STATUS_CALLBACK +#define LWIP_NETIF_STATUS_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface + * whenever the link changes (i.e., link down) + */ +#ifndef LWIP_NETIF_LINK_CALLBACK +#define LWIP_NETIF_LINK_CALLBACK 0 +#endif + +/** + * LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table + * indices) in struct netif. TCP and UDP can make use of this to prevent + * scanning the ARP table for every sent packet. While this is faster for big + * ARP tables or many concurrent connections, it might be counterproductive + * if you have a tiny ARP table or if there never are concurrent connections. + */ +#ifndef LWIP_NETIF_HWADDRHINT +#define LWIP_NETIF_HWADDRHINT 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP + * address equal to the netif IP address, looping them back up the stack. + */ +#ifndef LWIP_NETIF_LOOPBACK +#define LWIP_NETIF_LOOPBACK 1 +#endif + +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + +/** + * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in + * the system, as netifs must change how they behave depending on this setting + * for the LWIP_NETIF_LOOPBACK option to work. + * Setting this is needed to avoid reentering non-reentrant functions like + * tcp_input(). + * LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a + * multithreaded environment like tcpip.c. In this case, netif->input() + * is called directly. + * LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup. + * The packets are put on a list and netif_poll() must be called in + * the main application loop. + */ +#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING +#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS) +#endif + +/** + * LWIP_NETIF_TX_SINGLE_PBUF: if this is set to 1, lwIP tries to put all data + * to be sent into one single pbuf. This is for compatibility with DMA-enabled + * MACs that do not support scatter-gather. + * Beware that this might involve CPU-memcpy before transmitting that would not + * be needed without this flag! Use this only if you need to! + * + * @todo: TCP and IP-frag do not work with this, yet: + */ +#ifndef LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 0 +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ + +/* + ------------------------------------ + ---------- LOOPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_LOOPIF==1: Support loop interface (127.0.0.1) and loopif.c + */ +#ifndef LWIP_HAVE_LOOPIF +#define LWIP_HAVE_LOOPIF 1 +#endif + +/* + ------------------------------------ + ---------- SLIPIF options ---------- + ------------------------------------ +*/ +/** + * LWIP_HAVE_SLIPIF==1: Support slip interface and slipif.c + */ +#ifndef LWIP_HAVE_SLIPIF +#define LWIP_HAVE_SLIPIF 0 +#endif + +/* + ------------------------------------ + ---------- Thread options ---------- + ------------------------------------ +*/ +/** + * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread. + */ +#ifndef TCPIP_THREAD_NAME +#define TCPIP_THREAD_NAME "tcpip_thread" +#endif + +/** + * TCPIP_THREAD_STACKSIZE: The stack size used by the main tcpip thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_STACKSIZE +#define TCPIP_THREAD_STACKSIZE 0 +#endif + +/** + * TCPIP_THREAD_PRIO: The priority assigned to the main tcpip thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef TCPIP_THREAD_PRIO +#define TCPIP_THREAD_PRIO 1 +#endif + +/** + * TCPIP_MBOX_SIZE: The mailbox size for the tcpip thread messages + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when tcpip_init is called. + */ +#ifndef TCPIP_MBOX_SIZE +#define TCPIP_MBOX_SIZE 0 +#endif + +/** + * SLIPIF_THREAD_NAME: The name assigned to the slipif_loop thread. + */ +#ifndef SLIPIF_THREAD_NAME +#define SLIPIF_THREAD_NAME "slipif_loop" +#endif + +/** + * SLIP_THREAD_STACKSIZE: The stack size used by the slipif_loop thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_STACKSIZE +#define SLIPIF_THREAD_STACKSIZE 0 +#endif + +/** + * SLIPIF_THREAD_PRIO: The priority assigned to the slipif_loop thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef SLIPIF_THREAD_PRIO +#define SLIPIF_THREAD_PRIO 1 +#endif + +/** + * PPP_THREAD_NAME: The name assigned to the pppInputThread. + */ +#ifndef PPP_THREAD_NAME +#define PPP_THREAD_NAME "pppInputThread" +#endif + +/** + * PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_STACKSIZE +#define PPP_THREAD_STACKSIZE 0 +#endif + +/** + * PPP_THREAD_PRIO: The priority assigned to the pppInputThread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef PPP_THREAD_PRIO +#define PPP_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_THREAD_NAME: The name assigned to any other lwIP thread. + */ +#ifndef DEFAULT_THREAD_NAME +#define DEFAULT_THREAD_NAME "lwIP" +#endif + +/** + * DEFAULT_THREAD_STACKSIZE: The stack size used by any other lwIP thread. + * The stack size value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_STACKSIZE +#define DEFAULT_THREAD_STACKSIZE 0 +#endif + +/** + * DEFAULT_THREAD_PRIO: The priority assigned to any other lwIP thread. + * The priority value itself is platform-dependent, but is passed to + * sys_thread_new() when the thread is created. + */ +#ifndef DEFAULT_THREAD_PRIO +#define DEFAULT_THREAD_PRIO 1 +#endif + +/** + * DEFAULT_RAW_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_RAW. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_RAW_RECVMBOX_SIZE +#define DEFAULT_RAW_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_UDP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_UDP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_TCP_RECVMBOX_SIZE: The mailbox size for the incoming packets on a + * NETCONN_TCP. The queue size value itself is platform-dependent, but is passed + * to sys_mbox_new() when the recvmbox is created. + */ +#ifndef DEFAULT_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE 0 +#endif + +/** + * DEFAULT_ACCEPTMBOX_SIZE: The mailbox size for the incoming connections. + * The queue size value itself is platform-dependent, but is passed to + * sys_mbox_new() when the acceptmbox is created. + */ +#ifndef DEFAULT_ACCEPTMBOX_SIZE +#define DEFAULT_ACCEPTMBOX_SIZE 0 +#endif + +/* + ---------------------------------------------- + ---------- Sequential layer options ---------- + ---------------------------------------------- +*/ +/** + * LWIP_TCPIP_CORE_LOCKING: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING +#define LWIP_TCPIP_CORE_LOCKING 0 +#endif + +/** + * LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!) + * Don't use it if you're not an active lwIP project member + */ +#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT +#define LWIP_TCPIP_CORE_LOCKING_INPUT 0 +#endif + +/** + * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) + */ +#ifndef LWIP_NETCONN +#define LWIP_NETCONN 0 +#endif + +/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create + * timers running in tcpip_thread from another thread. + */ +#ifndef LWIP_TCPIP_TIMEOUT +#define LWIP_TCPIP_TIMEOUT 1 +#endif + +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/** + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 0 +#endif + +/** + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 1 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 0 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 0 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 0 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT INT_MAX +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/** + * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets + * to all local matches if SO_REUSEADDR is turned on. + * WARNING: Adds a memcpy for every packet if passing to more than one pcb! + */ +#ifndef SO_REUSE_RXTOALL +#define SO_REUSE_RXTOALL 0 +#endif + +/* + ---------------------------------------- + ---------- Statistics options ---------- + ---------------------------------------- +*/ +/** + * LWIP_STATS==1: Enable statistics collection in lwip_stats. + */ +#ifndef LWIP_STATS +#define LWIP_STATS 1 +#endif + +#if LWIP_STATS + +/** + * LWIP_STATS_DISPLAY==1: Compile in the statistics output functions. + */ +#ifndef LWIP_STATS_DISPLAY +#define LWIP_STATS_DISPLAY 0 +#endif + +/** + * LINK_STATS==1: Enable link stats. + */ +#ifndef LINK_STATS +#define LINK_STATS 1 +#endif + +/** + * ETHARP_STATS==1: Enable etharp stats. + */ +#ifndef ETHARP_STATS +#define ETHARP_STATS (LWIP_ARP) +#endif + +/** + * IP_STATS==1: Enable IP stats. + */ +#ifndef IP_STATS +#define IP_STATS 1 +#endif + +/** + * IPFRAG_STATS==1: Enable IP fragmentation stats. Default is + * on if using either frag or reass. + */ +#ifndef IPFRAG_STATS +#define IPFRAG_STATS (IP_REASSEMBLY || IP_FRAG) +#endif + +/** + * ICMP_STATS==1: Enable ICMP stats. + */ +#ifndef ICMP_STATS +#define ICMP_STATS 1 +#endif + +/** + * IGMP_STATS==1: Enable IGMP stats. + */ +#ifndef IGMP_STATS +#define IGMP_STATS (LWIP_IGMP) +#endif + +/** + * UDP_STATS==1: Enable UDP stats. Default is on if + * UDP enabled, otherwise off. + */ +#ifndef UDP_STATS +#define UDP_STATS (LWIP_UDP) +#endif + +/** + * TCP_STATS==1: Enable TCP stats. Default is on if TCP + * enabled, otherwise off. + */ +#ifndef TCP_STATS +#define TCP_STATS (LWIP_TCP) +#endif + +/** + * MEM_STATS==1: Enable mem.c stats. + */ +#ifndef MEM_STATS +#define MEM_STATS ((MEM_LIBC_MALLOC == 0) && (MEM_USE_POOLS == 0)) +#endif + +/** + * MEMP_STATS==1: Enable memp.c pool stats. + */ +#ifndef MEMP_STATS +#define MEMP_STATS (MEMP_MEM_MALLOC == 0) +#endif + +/** + * SYS_STATS==1: Enable system stats (sem and mbox counts, etc). + */ +#ifndef SYS_STATS +#define SYS_STATS (NO_SYS == 0) +#endif + +#else + +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define IGMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define SYS_STATS 0 +#define LWIP_STATS_DISPLAY 0 + +#endif /* LWIP_STATS */ + +/* + --------------------------------- + ---------- PPP options ---------- + --------------------------------- +*/ +/** + * PPP_SUPPORT==1: Enable PPP. + */ +#ifndef PPP_SUPPORT +#define PPP_SUPPORT 0 +#endif + +/** + * PPPOE_SUPPORT==1: Enable PPP Over Ethernet + */ +#ifndef PPPOE_SUPPORT +#define PPPOE_SUPPORT 0 +#endif + +/** + * PPPOS_SUPPORT==1: Enable PPP Over Serial + */ +#ifndef PPPOS_SUPPORT +#define PPPOS_SUPPORT PPP_SUPPORT +#endif + +#if PPP_SUPPORT + +/** + * NUM_PPP: Max PPP sessions. + */ +#ifndef NUM_PPP +#define NUM_PPP 1 +#endif + +/** + * PAP_SUPPORT==1: Support PAP. + */ +#ifndef PAP_SUPPORT +#define PAP_SUPPORT 0 +#endif + +/** + * CHAP_SUPPORT==1: Support CHAP. + */ +#ifndef CHAP_SUPPORT +#define CHAP_SUPPORT 0 +#endif + +/** + * MSCHAP_SUPPORT==1: Support MSCHAP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef MSCHAP_SUPPORT +#define MSCHAP_SUPPORT 0 +#endif + +/** + * CBCP_SUPPORT==1: Support CBCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CBCP_SUPPORT +#define CBCP_SUPPORT 0 +#endif + +/** + * CCP_SUPPORT==1: Support CCP. CURRENTLY NOT SUPPORTED! DO NOT SET! + */ +#ifndef CCP_SUPPORT +#define CCP_SUPPORT 0 +#endif + +/** + * VJ_SUPPORT==1: Support VJ header compression. + */ +#ifndef VJ_SUPPORT +#define VJ_SUPPORT 0 +#endif + +/** + * MD5_SUPPORT==1: Support MD5 (see also CHAP). + */ +#ifndef MD5_SUPPORT +#define MD5_SUPPORT 0 +#endif + +/* + * Timeouts + */ +#ifndef FSM_DEFTIMEOUT +#define FSM_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef FSM_DEFMAXTERMREQS +#define FSM_DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXCONFREQS +#define FSM_DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ +#endif + +#ifndef FSM_DEFMAXNAKLOOPS +#define FSM_DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ +#endif + +#ifndef UPAP_DEFTIMEOUT +#define UPAP_DEFTIMEOUT 6 /* Timeout (seconds) for retransmitting req */ +#endif + +#ifndef UPAP_DEFREQTIME +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ +#endif + +#ifndef CHAP_DEFTIMEOUT +#define CHAP_DEFTIMEOUT 6 /* Timeout time in seconds */ +#endif + +#ifndef CHAP_DEFTRANSMITS +#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */ +#endif + +/* Interval in seconds between keepalive echo requests, 0 to disable. */ +#ifndef LCP_ECHOINTERVAL +#define LCP_ECHOINTERVAL 0 +#endif + +/* Number of unanswered echo requests before failure. */ +#ifndef LCP_MAXECHOFAILS +#define LCP_MAXECHOFAILS 3 +#endif + +/* Max Xmit idle time (in jiffies) before resend flag char. */ +#ifndef PPP_MAXIDLEFLAG +#define PPP_MAXIDLEFLAG 100 +#endif + +/* + * Packet sizes + * + * Note - lcp shouldn't be allowed to negotiate stuff outside these + * limits. See lcp.h in the pppd directory. + * (XXX - these constants should simply be shared by lcp.c instead + * of living in lcp.h) + */ +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#ifndef PPP_MAXMTU +/* #define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN) */ +#define PPP_MAXMTU 1500 /* Largest MTU we allow */ +#endif +#define PPP_MINMTU 64 +#define PPP_MRU 1500 /* default MRU = max length of info field */ +#define PPP_MAXMRU 1500 /* Largest MRU we allow */ +#ifndef PPP_DEFMRU +#define PPP_DEFMRU 296 /* Try for this */ +#endif +#define PPP_MINMRU 128 /* No MRUs below this */ + +#ifndef MAXNAMELEN +#define MAXNAMELEN 256 /* max length of hostname or name for auth */ +#endif +#ifndef MAXSECRETLEN +#define MAXSECRETLEN 256 /* max length of password or secret */ +#endif + +#endif /* PPP_SUPPORT */ + +/* + -------------------------------------- + ---------- Checksum options ---------- + -------------------------------------- +*/ +/** + * CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets. + */ +#ifndef CHECKSUM_GEN_IP +#define CHECKSUM_GEN_IP 1 +#endif + +/** + * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets. + */ +#ifndef CHECKSUM_GEN_UDP +#define CHECKSUM_GEN_UDP 1 +#endif + +/** + * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets. + */ +#ifndef CHECKSUM_GEN_TCP +#define CHECKSUM_GEN_TCP 1 +#endif + +/** + * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets. + */ +#ifndef CHECKSUM_CHECK_IP +#define CHECKSUM_CHECK_IP 1 +#endif + +/** + * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets. + */ +#ifndef CHECKSUM_CHECK_UDP +#define CHECKSUM_CHECK_UDP 1 +#endif + +/** + * CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets. + */ +#ifndef CHECKSUM_CHECK_TCP +#define CHECKSUM_CHECK_TCP 1 +#endif + +/** + * LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from + * application buffers to pbufs. + */ +#ifndef LWIP_CHECKSUM_ON_COPY +#define LWIP_CHECKSUM_ON_COPY 0 +#endif + +/* + --------------------------------------- + ---------- Debugging options ---------- + --------------------------------------- +*/ +/** + * LWIP_DBG_MIN_LEVEL: After masking, the value of the debug is + * compared against this value. If it is smaller, then debugging + * messages are written. + */ +#ifndef LWIP_DBG_MIN_LEVEL +#define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL +#endif + +/** + * LWIP_DBG_TYPES_ON: A mask that can be used to globally enable/disable + * debug messages of certain types. + */ +#ifndef LWIP_DBG_TYPES_ON +#define LWIP_DBG_TYPES_ON LWIP_DBG_ON +#endif + +/** + * ETHARP_DEBUG: Enable debugging in etharp.c. + */ +#ifndef ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +/** + * NETIF_DEBUG: Enable debugging in netif.c. + */ +#ifndef NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +/** + * PBUF_DEBUG: Enable debugging in pbuf.c. + */ +#ifndef PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_LIB_DEBUG: Enable debugging in api_lib.c. + */ +#ifndef API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * API_MSG_DEBUG: Enable debugging in api_msg.c. + */ +#ifndef API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SOCKETS_DEBUG: Enable debugging in sockets.c. + */ +#ifndef SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +/** + * ICMP_DEBUG: Enable debugging in icmp.c. + */ +#ifndef ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IGMP_DEBUG: Enable debugging in igmp.c. + */ +#ifndef IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * INET_DEBUG: Enable debugging in inet.c. + */ +#ifndef INET_DEBUG +#define INET_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifndef IP_DEBUG +#define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. + */ +#ifndef IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +/** + * RAW_DEBUG: Enable debugging in raw.c. + */ +#ifndef RAW_DEBUG +#define RAW_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEM_DEBUG: Enable debugging in mem.c. + */ +#ifndef MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +/** + * MEMP_DEBUG: Enable debugging in memp.c. + */ +#ifndef MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SYS_DEBUG: Enable debugging in sys.c. + */ +#ifndef SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TIMERS_DEBUG: Enable debugging in timers.c. + */ +#ifndef TIMERS_DEBUG +#define TIMERS_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_DEBUG: Enable debugging for TCP. + */ +#ifndef TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. + */ +#ifndef TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. + */ +#ifndef TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit + * timeout. + */ +#ifndef TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. + */ +#ifndef TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. + */ +#ifndef TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. + */ +#ifndef TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. + */ +#ifndef TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. + */ +#ifndef TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +/** + * UDP_DEBUG: Enable debugging in UDP. + */ +#ifndef UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +/** + * TCPIP_DEBUG: Enable debugging in tcpip.c. + */ +#ifndef TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#ifndef PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SLIP_DEBUG: Enable debugging in slipif.c. + */ +#ifndef SLIP_DEBUG +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * DHCP_DEBUG: Enable debugging in dhcp.c. + */ +#ifndef DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +/** + * AUTOIP_DEBUG: Enable debugging in autoip.c. + */ +#ifndef AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. + */ +#ifndef SNMP_MSG_DEBUG +#define SNMP_MSG_DEBUG LWIP_DBG_OFF +#endif + +/** + * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. + */ +#ifndef SNMP_MIB_DEBUG +#define SNMP_MIB_DEBUG LWIP_DBG_OFF +#endif + +/** + * DNS_DEBUG: Enable debugging for DNS. + */ +#ifndef DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +#endif /* __LWIP_OPT_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/pbuf.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/pbuf.h new file mode 100644 index 0000000..3d24db4 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/pbuf.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#ifndef __LWIP_PBUF_H__ +#define __LWIP_PBUF_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Currently, the pbuf_custom code is only needed for one specific configuration + * of IP_FRAG */ +#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) + +#define PBUF_TRANSPORT_HLEN 20 +#define PBUF_IP_HLEN 20 + +typedef enum { + PBUF_TRANSPORT, + PBUF_IP, + PBUF_LINK, + PBUF_RAW +} pbuf_layer; + +typedef enum { + PBUF_RAM, /* pbuf data is stored in RAM */ + PBUF_ROM, /* pbuf data is stored in ROM */ + PBUF_REF, /* pbuf comes from the pbuf pool */ + PBUF_POOL, /* pbuf payload refers to RAM */ +#ifdef EBUF_LWIP + PBUF_ESF_RX /* pbuf payload is from WLAN */ +#endif /* ESF_LWIP */ +} pbuf_type; + + +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x01U +/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a + a pbuf differently */ +#define PBUF_FLAG_IS_CUSTOM 0x02U +/** indicates this pbuf is UDP multicast to be looped back */ +#define PBUF_FLAG_MCASTLOOP 0x04U + +struct pbuf { + /** next pbuf in singly linked pbuf chain */ + struct pbuf *next; + + /** pointer to the actual data in the buffer */ + void *payload; + + /** + * total length of this buffer and all next buffers in chain + * belonging to the same packet. + * + * For non-queue packet chains this is the invariant: + * p->tot_len == p->len + (p->next? p->next->tot_len: 0) + */ + u16_t tot_len; + + /** length of this buffer */ + u16_t len; + + /** pbuf_type as u8_t instead of enum to save space */ + u8_t /*pbuf_type*/ type; + + /** misc flags */ + u8_t flags; + + /** + * the reference count always equals the number of pointers + * that refer to this pbuf. This can be pointers from an application, + * the stack itself, or pbuf->next pointers from a chain. + */ + u16_t ref; + + /* add a pointer for esf_buf */ + void * eb; +}; + +#if LWIP_SUPPORT_CUSTOM_PBUF +/** Prototype for a function to free a custom pbuf */ +typedef void (*pbuf_free_custom_fn)(struct pbuf *p); + +/** A custom pbuf: like a pbuf, but following a function pointer to free it. */ +struct pbuf_custom { + /** The actual pbuf */ + struct pbuf pbuf; + /** This function is called when pbuf_free deallocates this pbuf(_custom) */ + pbuf_free_custom_fn custom_free_function; +}; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ + +/* Initializes the pbuf module. This call is empty for now, but may not be in future. */ +#define pbuf_init() + +struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type)ICACHE_FLASH_ATTR; +#if LWIP_SUPPORT_CUSTOM_PBUF +struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, + struct pbuf_custom *p, void *payload_mem, + u16_t payload_mem_len)ICACHE_FLASH_ATTR; +#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ +void pbuf_realloc(struct pbuf *p, u16_t size)ICACHE_FLASH_ATTR; +u8_t pbuf_header(struct pbuf *p, s16_t header_size)ICACHE_FLASH_ATTR; +void pbuf_ref(struct pbuf *p)ICACHE_FLASH_ATTR; +u8_t pbuf_free(struct pbuf *p)ICACHE_FLASH_ATTR; +u8_t pbuf_clen(struct pbuf *p)ICACHE_FLASH_ATTR; +void pbuf_cat(struct pbuf *head, struct pbuf *tail)ICACHE_FLASH_ATTR; +void pbuf_chain(struct pbuf *head, struct pbuf *tail)ICACHE_FLASH_ATTR; +struct pbuf *pbuf_dechain(struct pbuf *p)ICACHE_FLASH_ATTR; +err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)ICACHE_FLASH_ATTR; +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset)ICACHE_FLASH_ATTR; +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)ICACHE_FLASH_ATTR; +struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer)ICACHE_FLASH_ATTR; +#if LWIP_CHECKSUM_ON_COPY +err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr, + u16_t len, u16_t *chksum)ICACHE_FLASH_ATTR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset)ICACHE_FLASH_ATTR; +u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)ICACHE_FLASH_ATTR; +u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)ICACHE_FLASH_ATTR; +u16_t pbuf_strstr(struct pbuf* p, const char* substr)ICACHE_FLASH_ATTR; + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_PBUF_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/raw.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/raw.h new file mode 100644 index 0000000..c9c4087 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/raw.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_RAW_H__ +#define __LWIP_RAW_H__ + +#include "lwip/opt.h" + +#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct raw_pcb; + +/** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) + * @param pcb the raw_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @return 1 if the packet was 'eaten' (aka. deleted), + * 0 if the packet lives on + * If returning 1, the callback is responsible for freeing the pbuf + * if it's not used any more. + */ +typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p, + ip_addr_t *addr); + +struct raw_pcb { + /* Common members of all PCB types */ + IP_PCB; + + struct raw_pcb *next; + + u8_t protocol; + + /** receive callback function */ + raw_recv_fn recv; + /* user-supplied argument for the recv callback */ + void *recv_arg; +}; + +/* The following functions is the application layer interface to the + RAW code. */ +struct raw_pcb * raw_new (u8_t proto)ICACHE_FLASH_ATTR; +void raw_remove (struct raw_pcb *pcb)ICACHE_FLASH_ATTR; +err_t raw_bind (struct raw_pcb *pcb, ip_addr_t *ipaddr)ICACHE_FLASH_ATTR; +err_t raw_connect (struct raw_pcb *pcb, ip_addr_t *ipaddr)ICACHE_FLASH_ATTR; + +void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)ICACHE_FLASH_ATTR; +err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)ICACHE_FLASH_ATTR; +err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); + +/* The following functions are the lower layer interface to RAW. */ +u8_t raw_input (struct pbuf *p, struct netif *inp)ICACHE_FLASH_ATTR; +#define raw_init() /* Compatibility define, not init needed. */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_RAW */ + +#endif /* __LWIP_RAW_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sio.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sio.h new file mode 100644 index 0000000..228c857 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sio.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + */ + +/* + * This is the interface to the platform specific serial IO module + * It needs to be implemented by those platforms which need SLIP or PPP + */ + +#ifndef __SIO_H__ +#define __SIO_H__ + +#include "lwip/arch.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* If you want to define sio_fd_t elsewhere or differently, + define this in your cc.h file. */ +#ifndef __sio_fd_t_defined +typedef void * sio_fd_t; +#endif + +/* The following functions can be defined to something else in your cc.h file + or be implemented in your custom sio.c file. */ + +#ifndef sio_open +/** + * Opens a serial device for communication. + * + * @param devnum device number + * @return handle to serial device if successful, NULL otherwise + */ +sio_fd_t sio_open(u8_t devnum)ICACHE_FLASH_ATTR; +#endif + +#ifndef sio_send +/** + * Sends a single character to the serial device. + * + * @param c character to send + * @param fd serial device handle + * + * @note This function will block until the character can be sent. + */ +void sio_send(u8_t c, sio_fd_t fd)ICACHE_FLASH_ATTR; +#endif + +#ifndef sio_recv +/** + * Receives a single character from the serial device. + * + * @param fd serial device handle + * + * @note This function will block until a character is received. + */ +u8_t sio_recv(sio_fd_t fd)ICACHE_FLASH_ATTR; +#endif + +#ifndef sio_read +/** + * Reads from the serial device. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received - may be 0 if aborted by sio_read_abort + * + * @note This function will block until data can be received. The blocking + * can be cancelled by calling sio_read_abort(). + */ +u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)ICACHE_FLASH_ATTR; +#endif + +#ifndef sio_tryread +/** + * Tries to read from the serial device. Same as sio_read but returns + * immediately if no data is available and never blocks. + * + * @param fd serial device handle + * @param data pointer to data buffer for receiving + * @param len maximum length (in bytes) of data to receive + * @return number of bytes actually received + */ +u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len)ICACHE_FLASH_ATTR; +#endif + +#ifndef sio_write +/** + * Writes to the serial device. + * + * @param fd serial device handle + * @param data pointer to data to send + * @param len length (in bytes) of data to send + * @return number of bytes actually sent + * + * @note This function will block until all data can be sent. + */ +u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)ICACHE_FLASH_ATTR; +#endif + +#ifndef sio_read_abort +/** + * Aborts a blocking sio_read() call. + * + * @param fd serial device handle + */ +void sio_read_abort(sio_fd_t fd)ICACHE_FLASH_ATTR; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SIO_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp.h new file mode 100644 index 0000000..2ed043d --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp.h @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2001, 2002 Leon Woestenberg + * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Leon Woestenberg + * + */ +#ifndef __LWIP_SNMP_H__ +#define __LWIP_SNMP_H__ + +#include "lwip/opt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lwip/ip_addr.h" + +struct udp_pcb; +struct netif; + +/** + * @see RFC1213, "MIB-II, 6. Definitions" + */ +enum snmp_ifType { + snmp_ifType_other=1, /* none of the following */ + snmp_ifType_regular1822, + snmp_ifType_hdh1822, + snmp_ifType_ddn_x25, + snmp_ifType_rfc877_x25, + snmp_ifType_ethernet_csmacd, + snmp_ifType_iso88023_csmacd, + snmp_ifType_iso88024_tokenBus, + snmp_ifType_iso88025_tokenRing, + snmp_ifType_iso88026_man, + snmp_ifType_starLan, + snmp_ifType_proteon_10Mbit, + snmp_ifType_proteon_80Mbit, + snmp_ifType_hyperchannel, + snmp_ifType_fddi, + snmp_ifType_lapb, + snmp_ifType_sdlc, + snmp_ifType_ds1, /* T-1 */ + snmp_ifType_e1, /* european equiv. of T-1 */ + snmp_ifType_basicISDN, + snmp_ifType_primaryISDN, /* proprietary serial */ + snmp_ifType_propPointToPointSerial, + snmp_ifType_ppp, + snmp_ifType_softwareLoopback, + snmp_ifType_eon, /* CLNP over IP [11] */ + snmp_ifType_ethernet_3Mbit, + snmp_ifType_nsip, /* XNS over IP */ + snmp_ifType_slip, /* generic SLIP */ + snmp_ifType_ultra, /* ULTRA technologies */ + snmp_ifType_ds3, /* T-3 */ + snmp_ifType_sip, /* SMDS */ + snmp_ifType_frame_relay +}; + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +/** SNMP "sysuptime" Interval */ +#define SNMP_SYSUPTIME_INTERVAL 10 + +/** fixed maximum length for object identifier type */ +#define LWIP_SNMP_OBJ_ID_LEN 32 + +/** internal object identifier representation */ +struct snmp_obj_id +{ + u8_t len; + s32_t id[LWIP_SNMP_OBJ_ID_LEN]; +}; + +/* system */ +void snmp_set_sysdesr(u8_t* str, u8_t* len); +void snmp_set_sysobjid(struct snmp_obj_id *oid); +void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid); +void snmp_inc_sysuptime(void); +void snmp_add_sysuptime(u32_t value); +void snmp_get_sysuptime(u32_t *value); +void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen); +void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen); + +/* network interface */ +void snmp_add_ifinoctets(struct netif *ni, u32_t value); +void snmp_inc_ifinucastpkts(struct netif *ni); +void snmp_inc_ifinnucastpkts(struct netif *ni); +void snmp_inc_ifindiscards(struct netif *ni); +void snmp_add_ifoutoctets(struct netif *ni, u32_t value); +void snmp_inc_ifoutucastpkts(struct netif *ni); +void snmp_inc_ifoutnucastpkts(struct netif *ni); +void snmp_inc_ifoutdiscards(struct netif *ni); +void snmp_inc_iflist(void); +void snmp_dec_iflist(void); + +/* ARP (for atTable and ipNetToMediaTable) */ +void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip); +void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip); + +/* IP */ +void snmp_inc_ipinreceives(void); +void snmp_inc_ipinhdrerrors(void); +void snmp_inc_ipinaddrerrors(void); +void snmp_inc_ipforwdatagrams(void); +void snmp_inc_ipinunknownprotos(void); +void snmp_inc_ipindiscards(void); +void snmp_inc_ipindelivers(void); +void snmp_inc_ipoutrequests(void); +void snmp_inc_ipoutdiscards(void); +void snmp_inc_ipoutnoroutes(void); +void snmp_inc_ipreasmreqds(void); +void snmp_inc_ipreasmoks(void); +void snmp_inc_ipreasmfails(void); +void snmp_inc_ipfragoks(void); +void snmp_inc_ipfragfails(void); +void snmp_inc_ipfragcreates(void); +void snmp_inc_iproutingdiscards(void); +void snmp_insert_ipaddridx_tree(struct netif *ni); +void snmp_delete_ipaddridx_tree(struct netif *ni); +void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni); +void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni); + +/* ICMP */ +void snmp_inc_icmpinmsgs(void); +void snmp_inc_icmpinerrors(void); +void snmp_inc_icmpindestunreachs(void); +void snmp_inc_icmpintimeexcds(void); +void snmp_inc_icmpinparmprobs(void); +void snmp_inc_icmpinsrcquenchs(void); +void snmp_inc_icmpinredirects(void); +void snmp_inc_icmpinechos(void); +void snmp_inc_icmpinechoreps(void); +void snmp_inc_icmpintimestamps(void); +void snmp_inc_icmpintimestampreps(void); +void snmp_inc_icmpinaddrmasks(void); +void snmp_inc_icmpinaddrmaskreps(void); +void snmp_inc_icmpoutmsgs(void); +void snmp_inc_icmpouterrors(void); +void snmp_inc_icmpoutdestunreachs(void); +void snmp_inc_icmpouttimeexcds(void); +void snmp_inc_icmpoutparmprobs(void); +void snmp_inc_icmpoutsrcquenchs(void); +void snmp_inc_icmpoutredirects(void); +void snmp_inc_icmpoutechos(void); +void snmp_inc_icmpoutechoreps(void); +void snmp_inc_icmpouttimestamps(void); +void snmp_inc_icmpouttimestampreps(void); +void snmp_inc_icmpoutaddrmasks(void); +void snmp_inc_icmpoutaddrmaskreps(void); + +/* TCP */ +void snmp_inc_tcpactiveopens(void); +void snmp_inc_tcppassiveopens(void); +void snmp_inc_tcpattemptfails(void); +void snmp_inc_tcpestabresets(void); +void snmp_inc_tcpinsegs(void); +void snmp_inc_tcpoutsegs(void); +void snmp_inc_tcpretranssegs(void); +void snmp_inc_tcpinerrs(void); +void snmp_inc_tcpoutrsts(void); + +/* UDP */ +void snmp_inc_udpindatagrams(void); +void snmp_inc_udpnoports(void); +void snmp_inc_udpinerrors(void); +void snmp_inc_udpoutdatagrams(void); +void snmp_insert_udpidx_tree(struct udp_pcb *pcb); +void snmp_delete_udpidx_tree(struct udp_pcb *pcb); + +/* SNMP */ +void snmp_inc_snmpinpkts(void); +void snmp_inc_snmpoutpkts(void); +void snmp_inc_snmpinbadversions(void); +void snmp_inc_snmpinbadcommunitynames(void); +void snmp_inc_snmpinbadcommunityuses(void); +void snmp_inc_snmpinasnparseerrs(void); +void snmp_inc_snmpintoobigs(void); +void snmp_inc_snmpinnosuchnames(void); +void snmp_inc_snmpinbadvalues(void); +void snmp_inc_snmpinreadonlys(void); +void snmp_inc_snmpingenerrs(void); +void snmp_add_snmpintotalreqvars(u8_t value); +void snmp_add_snmpintotalsetvars(u8_t value); +void snmp_inc_snmpingetrequests(void); +void snmp_inc_snmpingetnexts(void); +void snmp_inc_snmpinsetrequests(void); +void snmp_inc_snmpingetresponses(void); +void snmp_inc_snmpintraps(void); +void snmp_inc_snmpouttoobigs(void); +void snmp_inc_snmpoutnosuchnames(void); +void snmp_inc_snmpoutbadvalues(void); +void snmp_inc_snmpoutgenerrs(void); +void snmp_inc_snmpoutgetrequests(void); +void snmp_inc_snmpoutgetnexts(void); +void snmp_inc_snmpoutsetrequests(void); +void snmp_inc_snmpoutgetresponses(void); +void snmp_inc_snmpouttraps(void); +void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); +void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); + +/* LWIP_SNMP support not available */ +/* define everything to be empty */ +#else + +/* system */ +#define snmp_set_sysdesr(str, len) +#define snmp_set_sysobjid(oid); +#define snmp_get_sysobjid_ptr(oid) +#define snmp_inc_sysuptime() +#define snmp_add_sysuptime(value) +#define snmp_get_sysuptime(value) +#define snmp_set_syscontact(ocstr, ocstrlen); +#define snmp_set_sysname(ocstr, ocstrlen); +#define snmp_set_syslocation(ocstr, ocstrlen); + +/* network interface */ +#define snmp_add_ifinoctets(ni,value) +#define snmp_inc_ifinucastpkts(ni) +#define snmp_inc_ifinnucastpkts(ni) +#define snmp_inc_ifindiscards(ni) +#define snmp_add_ifoutoctets(ni,value) +#define snmp_inc_ifoutucastpkts(ni) +#define snmp_inc_ifoutnucastpkts(ni) +#define snmp_inc_ifoutdiscards(ni) +#define snmp_inc_iflist() +#define snmp_dec_iflist() + +/* ARP */ +#define snmp_insert_arpidx_tree(ni,ip) +#define snmp_delete_arpidx_tree(ni,ip) + +/* IP */ +#define snmp_inc_ipinreceives() +#define snmp_inc_ipinhdrerrors() +#define snmp_inc_ipinaddrerrors() +#define snmp_inc_ipforwdatagrams() +#define snmp_inc_ipinunknownprotos() +#define snmp_inc_ipindiscards() +#define snmp_inc_ipindelivers() +#define snmp_inc_ipoutrequests() +#define snmp_inc_ipoutdiscards() +#define snmp_inc_ipoutnoroutes() +#define snmp_inc_ipreasmreqds() +#define snmp_inc_ipreasmoks() +#define snmp_inc_ipreasmfails() +#define snmp_inc_ipfragoks() +#define snmp_inc_ipfragfails() +#define snmp_inc_ipfragcreates() +#define snmp_inc_iproutingdiscards() +#define snmp_insert_ipaddridx_tree(ni) +#define snmp_delete_ipaddridx_tree(ni) +#define snmp_insert_iprteidx_tree(dflt, ni) +#define snmp_delete_iprteidx_tree(dflt, ni) + +/* ICMP */ +#define snmp_inc_icmpinmsgs() +#define snmp_inc_icmpinerrors() +#define snmp_inc_icmpindestunreachs() +#define snmp_inc_icmpintimeexcds() +#define snmp_inc_icmpinparmprobs() +#define snmp_inc_icmpinsrcquenchs() +#define snmp_inc_icmpinredirects() +#define snmp_inc_icmpinechos() +#define snmp_inc_icmpinechoreps() +#define snmp_inc_icmpintimestamps() +#define snmp_inc_icmpintimestampreps() +#define snmp_inc_icmpinaddrmasks() +#define snmp_inc_icmpinaddrmaskreps() +#define snmp_inc_icmpoutmsgs() +#define snmp_inc_icmpouterrors() +#define snmp_inc_icmpoutdestunreachs() +#define snmp_inc_icmpouttimeexcds() +#define snmp_inc_icmpoutparmprobs() +#define snmp_inc_icmpoutsrcquenchs() +#define snmp_inc_icmpoutredirects() +#define snmp_inc_icmpoutechos() +#define snmp_inc_icmpoutechoreps() +#define snmp_inc_icmpouttimestamps() +#define snmp_inc_icmpouttimestampreps() +#define snmp_inc_icmpoutaddrmasks() +#define snmp_inc_icmpoutaddrmaskreps() +/* TCP */ +#define snmp_inc_tcpactiveopens() +#define snmp_inc_tcppassiveopens() +#define snmp_inc_tcpattemptfails() +#define snmp_inc_tcpestabresets() +#define snmp_inc_tcpinsegs() +#define snmp_inc_tcpoutsegs() +#define snmp_inc_tcpretranssegs() +#define snmp_inc_tcpinerrs() +#define snmp_inc_tcpoutrsts() + +/* UDP */ +#define snmp_inc_udpindatagrams() +#define snmp_inc_udpnoports() +#define snmp_inc_udpinerrors() +#define snmp_inc_udpoutdatagrams() +#define snmp_insert_udpidx_tree(pcb) +#define snmp_delete_udpidx_tree(pcb) + +/* SNMP */ +#define snmp_inc_snmpinpkts() +#define snmp_inc_snmpoutpkts() +#define snmp_inc_snmpinbadversions() +#define snmp_inc_snmpinbadcommunitynames() +#define snmp_inc_snmpinbadcommunityuses() +#define snmp_inc_snmpinasnparseerrs() +#define snmp_inc_snmpintoobigs() +#define snmp_inc_snmpinnosuchnames() +#define snmp_inc_snmpinbadvalues() +#define snmp_inc_snmpinreadonlys() +#define snmp_inc_snmpingenerrs() +#define snmp_add_snmpintotalreqvars(value) +#define snmp_add_snmpintotalsetvars(value) +#define snmp_inc_snmpingetrequests() +#define snmp_inc_snmpingetnexts() +#define snmp_inc_snmpinsetrequests() +#define snmp_inc_snmpingetresponses() +#define snmp_inc_snmpintraps() +#define snmp_inc_snmpouttoobigs() +#define snmp_inc_snmpoutnosuchnames() +#define snmp_inc_snmpoutbadvalues() +#define snmp_inc_snmpoutgenerrs() +#define snmp_inc_snmpoutgetrequests() +#define snmp_inc_snmpoutgetnexts() +#define snmp_inc_snmpoutsetrequests() +#define snmp_inc_snmpoutgetresponses() +#define snmp_inc_snmpouttraps() +#define snmp_get_snmpgrpid_ptr(oid) +#define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) + +#endif /* LWIP_SNMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SNMP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_asn1.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_asn1.h new file mode 100644 index 0000000..605fa3f --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_asn1.h @@ -0,0 +1,101 @@ +/** + * @file + * Abstract Syntax Notation One (ISO 8824, 8825) codec. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_ASN1_H__ +#define __LWIP_SNMP_ASN1_H__ + +#include "lwip/opt.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#if LWIP_SNMP + +#ifdef __cplusplus +extern "C" { +#endif + +#define SNMP_ASN1_UNIV (0) /* (!0x80 | !0x40) */ +#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 | 0x40) */ +#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */ + +#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */ +#define SNMP_ASN1_PRIMIT (0) /* (!0x20) */ + +/* universal tags */ +#define SNMP_ASN1_INTEG 2 +#define SNMP_ASN1_OC_STR 4 +#define SNMP_ASN1_NUL 5 +#define SNMP_ASN1_OBJ_ID 6 +#define SNMP_ASN1_SEQ 16 + +/* application specific (SNMP) tags */ +#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */ +#define SNMP_ASN1_COUNTER 1 /* u32_t */ +#define SNMP_ASN1_GAUGE 2 /* u32_t */ +#define SNMP_ASN1_TIMETICKS 3 /* u32_t */ +#define SNMP_ASN1_OPAQUE 4 /* octet string */ + +/* context specific (SNMP) tags */ +#define SNMP_ASN1_PDU_GET_REQ 0 +#define SNMP_ASN1_PDU_GET_NEXT_REQ 1 +#define SNMP_ASN1_PDU_GET_RESP 2 +#define SNMP_ASN1_PDU_SET_REQ 3 +#define SNMP_ASN1_PDU_TRAP 4 + +err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type); +err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length); +err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value); +err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value); +err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid); +err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw); + +void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); +void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); +void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); +void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed); +err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type); +err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length); +err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value); +err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value); +err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident); +err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_ASN1_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_msg.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_msg.h new file mode 100644 index 0000000..1183e3a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_msg.h @@ -0,0 +1,315 @@ +/** + * @file + * SNMP Agent message handling structures. + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_MSG_H__ +#define __LWIP_SNMP_MSG_H__ + +#include "lwip/opt.h" +#include "lwip/snmp.h" +#include "lwip/snmp_structs.h" +#include "lwip/ip_addr.h" +#include "lwip/err.h" + +#if LWIP_SNMP + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* The listen port of the SNMP agent. Clients have to make their requests to + this port. Most standard clients won't work if you change this! */ +#ifndef SNMP_IN_PORT +#define SNMP_IN_PORT 161 +#endif +/* The remote port the SNMP agent sends traps to. Most standard trap sinks won't + work if you change this! */ +#ifndef SNMP_TRAP_PORT +#define SNMP_TRAP_PORT 162 +#endif + +#define SNMP_ES_NOERROR 0 +#define SNMP_ES_TOOBIG 1 +#define SNMP_ES_NOSUCHNAME 2 +#define SNMP_ES_BADVALUE 3 +#define SNMP_ES_READONLY 4 +#define SNMP_ES_GENERROR 5 + +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + +struct snmp_varbind +{ + /* next pointer, NULL for last in list */ + struct snmp_varbind *next; + /* previous pointer, NULL for first in list */ + struct snmp_varbind *prev; + + /* object identifier length (in s32_t) */ + u8_t ident_len; + /* object identifier array */ + s32_t *ident; + + /* object value ASN1 type */ + u8_t value_type; + /* object value length (in u8_t) */ + u8_t value_len; + /* object value */ + void *value; + + /* encoding varbind seq length length */ + u8_t seqlenlen; + /* encoding object identifier length length */ + u8_t olenlen; + /* encoding object value length length */ + u8_t vlenlen; + /* encoding varbind seq length */ + u16_t seqlen; + /* encoding object identifier length */ + u16_t olen; + /* encoding object value length */ + u16_t vlen; +}; + +struct snmp_varbind_root +{ + struct snmp_varbind *head; + struct snmp_varbind *tail; + /* number of variable bindings in list */ + u8_t count; + /* encoding varbind-list seq length length */ + u8_t seqlenlen; + /* encoding varbind-list seq length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_resp_header_lengths +{ + /* encoding error-index length length */ + u8_t erridxlenlen; + /* encoding error-status length length */ + u8_t errstatlenlen; + /* encoding request id length length */ + u8_t ridlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding error-index length */ + u16_t erridxlen; + /* encoding error-status length */ + u16_t errstatlen; + /* encoding request id length */ + u16_t ridlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/** output response message header length fields */ +struct snmp_trap_header_lengths +{ + /* encoding timestamp length length */ + u8_t tslenlen; + /* encoding specific-trap length length */ + u8_t strplenlen; + /* encoding generic-trap length length */ + u8_t gtrplenlen; + /* encoding agent-addr length length */ + u8_t aaddrlenlen; + /* encoding enterprise-id length length */ + u8_t eidlenlen; + /* encoding pdu length length */ + u8_t pdulenlen; + /* encoding community length length */ + u8_t comlenlen; + /* encoding version length length */ + u8_t verlenlen; + /* encoding sequence length length */ + u8_t seqlenlen; + + /* encoding timestamp length */ + u16_t tslen; + /* encoding specific-trap length */ + u16_t strplen; + /* encoding generic-trap length */ + u16_t gtrplen; + /* encoding agent-addr length */ + u16_t aaddrlen; + /* encoding enterprise-id length */ + u16_t eidlen; + /* encoding pdu length */ + u16_t pdulen; + /* encoding community length */ + u16_t comlen; + /* encoding version length */ + u16_t verlen; + /* encoding sequence length */ + u16_t seqlen; +}; + +/* Accepting new SNMP messages. */ +#define SNMP_MSG_EMPTY 0 +/* Search for matching object for variable binding. */ +#define SNMP_MSG_SEARCH_OBJ 1 +/* Perform SNMP operation on in-memory object. + Pass-through states, for symmetry only. */ +#define SNMP_MSG_INTERNAL_GET_OBJDEF 2 +#define SNMP_MSG_INTERNAL_GET_VALUE 3 +#define SNMP_MSG_INTERNAL_SET_TEST 4 +#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5 +#define SNMP_MSG_INTERNAL_SET_VALUE 6 +/* Perform SNMP operation on object located externally. + In theory this could be used for building a proxy agent. + Practical use is for an enterprise spc. app. gateway. */ +#define SNMP_MSG_EXTERNAL_GET_OBJDEF 7 +#define SNMP_MSG_EXTERNAL_GET_VALUE 8 +#define SNMP_MSG_EXTERNAL_SET_TEST 9 +#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10 +#define SNMP_MSG_EXTERNAL_SET_VALUE 11 + +#define SNMP_COMMUNITY_STR_LEN 64 +struct snmp_msg_pstat +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* source IP address */ + ip_addr_t sip; + /* source UDP port */ + u16_t sp; + /* request type */ + u8_t rt; + /* request ID */ + s32_t rid; + /* error status */ + s32_t error_status; + /* error index */ + s32_t error_index; + /* community name (zero terminated) */ + u8_t community[SNMP_COMMUNITY_STR_LEN + 1]; + /* community string length (exclusive zero term) */ + u8_t com_strlen; + /* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */ + u8_t state; + /* saved arguments for MSG_EXTERNAL_x */ + struct mib_external_node *ext_mib_node; + struct snmp_name_ptr ext_name_ptr; + struct obj_def ext_object_def; + struct snmp_obj_id ext_oid; + /* index into input variable binding list */ + u8_t vb_idx; + /* ptr into input variable binding list */ + struct snmp_varbind *vb_ptr; + /* list of variable bindings from input */ + struct snmp_varbind_root invb; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output response lengths used in ASN encoding */ + struct snmp_resp_header_lengths rhl; +}; + +struct snmp_msg_trap +{ + /* lwIP local port (161) binding */ + struct udp_pcb *pcb; + /* destination IP address in network order */ + ip_addr_t dip; + + /* source enterprise ID (sysObjectID) */ + struct snmp_obj_id *enterprise; + /* source IP address, raw network order format */ + u8_t sip_raw[4]; + /* generic trap code */ + u32_t gen_trap; + /* specific trap code */ + u32_t spc_trap; + /* timestamp */ + u32_t ts; + /* list of variable bindings to output */ + struct snmp_varbind_root outvb; + /* output trap lengths used in ASN encoding */ + struct snmp_trap_header_lengths thl; +}; + +/** Agent Version constant, 0 = v1 oddity */ +extern const s32_t snmp_version; +/** Agent default "public" community string */ +extern const char snmp_publiccommunity[7]; + +extern struct snmp_msg_trap trap_msg; + +/** Agent setup, start listening to port 161. */ +void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + +/** Handle an internal (recv) or external (private response) event. */ +void snmp_msg_event(u8_t request_id); +err_t snmp_send_response(struct snmp_msg_pstat *m_stat); +err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_MSG_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_structs.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_structs.h new file mode 100644 index 0000000..0d3b46a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/snmp_structs.h @@ -0,0 +1,268 @@ +/** + * @file + * Generic MIB tree structures. + * + * @todo namespace prefixes + */ + +/* + * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Christiaan Simons + */ + +#ifndef __LWIP_SNMP_STRUCTS_H__ +#define __LWIP_SNMP_STRUCTS_H__ + +#include "lwip/opt.h" + +#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/snmp.h" + +#if SNMP_PRIVATE_MIB +/* When using a private MIB, you have to create a file 'private_mib.h' that contains + * a 'struct mib_array_node mib_private' which contains your MIB. */ +#include "private_mib.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MIB object instance */ +#define MIB_OBJECT_NONE 0 +#define MIB_OBJECT_SCALAR 1 +#define MIB_OBJECT_TAB 2 + +/* MIB access types */ +#define MIB_ACCESS_READ 1 +#define MIB_ACCESS_WRITE 2 + +/* MIB object access */ +#define MIB_OBJECT_READ_ONLY MIB_ACCESS_READ +#define MIB_OBJECT_READ_WRITE (MIB_ACCESS_READ | MIB_ACCESS_WRITE) +#define MIB_OBJECT_WRITE_ONLY MIB_ACCESS_WRITE +#define MIB_OBJECT_NOT_ACCESSIBLE 0 + +/** object definition returned by (get_object_def)() */ +struct obj_def +{ + /* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */ + u8_t instance; + /* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */ + u8_t access; + /* ASN type for this object */ + u8_t asn_type; + /* value length (host length) */ + u16_t v_len; + /* length of instance part of supplied object identifier */ + u8_t id_inst_len; + /* instance part of supplied object identifier */ + s32_t *id_inst_ptr; +}; + +struct snmp_name_ptr +{ + u8_t ident_len; + s32_t *ident; +}; + +/** MIB const scalar (.0) node */ +#define MIB_NODE_SC 0x01 +/** MIB const array node */ +#define MIB_NODE_AR 0x02 +/** MIB array node (mem_malloced from RAM) */ +#define MIB_NODE_RA 0x03 +/** MIB list root node (mem_malloced from RAM) */ +#define MIB_NODE_LR 0x04 +/** MIB node for external objects */ +#define MIB_NODE_EX 0x05 + +/** node "base class" layout, the mandatory fields for a node */ +struct mib_node +{ + /** returns struct obj_def for the given object identifier */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + /** returns object value for the given object identifier, + @note the caller must allocate at least len bytes for the value */ + void (*get_value)(struct obj_def *od, u16_t len, void *value); + /** tests length and/or range BEFORE setting */ + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + /** sets object value, only to be called when set_test() */ + void (*set_value)(struct obj_def *od, u16_t len, void *value); + /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */ + u8_t node_type; + /* array or max list length */ + u16_t maxlength; +}; + +/** derived node for scalars .0 index */ +typedef struct mib_node mib_scalar_node; + +/** derived node, points to a fixed size const array + of sub-identifiers plus a 'child' pointer */ +struct mib_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + const s32_t *objid; + struct mib_node* const *nptr; +}; + +/** derived node, points to a fixed size mem_malloced array + of sub-identifiers plus a 'child' pointer */ +struct mib_ram_array_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* aditional struct members */ + s32_t *objid; + struct mib_node **nptr; +}; + +struct mib_list_node +{ + struct mib_list_node *prev; + struct mib_list_node *next; + s32_t objid; + struct mib_node *nptr; +}; + +/** derived node, points to a doubly linked list + of sub-identifiers plus a 'child' pointer */ +struct mib_list_rootnode +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + struct mib_list_node *head; + struct mib_list_node *tail; + /* counts list nodes in list */ + u16_t count; +}; + +/** derived node, has access functions for mib object in external memory or device + using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */ +struct mib_external_node +{ + /* inherited "base class" members */ + void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value)(struct obj_def *od, u16_t len, void *value); + u8_t (*set_test)(struct obj_def *od, u16_t len, void *value); + void (*set_value)(struct obj_def *od, u16_t len, void *value); + + u8_t node_type; + u16_t maxlength; + + /* additional struct members */ + /** points to an external (in memory) record of some sort of addressing + information, passed to and interpreted by the funtions below */ + void* addr_inf; + /** tree levels under this node */ + u8_t tree_levels; + /** number of objects at this level */ + u16_t (*level_length)(void* addr_inf, u8_t level); + /** compares object sub identifier with external id + return zero when equal, nonzero when unequal */ + s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id); + void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id); + + /** async Questions */ + void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_q)(u8_t rid, struct obj_def *od); + void (*set_test_q)(u8_t rid, struct obj_def *od); + void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Answers */ + void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od); + void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value); + /** async Panic Close (agent returns error reply, + e.g. used for external transaction cleanup) */ + void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident); + void (*get_value_pc)(u8_t rid, struct obj_def *od); + void (*set_test_pc)(u8_t rid, struct obj_def *od); + void (*set_value_pc)(u8_t rid, struct obj_def *od); +}; + +/** export MIB tree from mib2.c */ +extern const struct mib_array_node internet; + +/** dummy function pointers for non-leaf MIB nodes from mib2.c */ +void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od); +void noleafs_get_value(struct obj_def *od, u16_t len, void *value); +u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value); +void noleafs_set_value(struct obj_def *od, u16_t len, void *value); + +void snmp_oidtoip(s32_t *ident, ip_addr_t *ip); +void snmp_iptooid(ip_addr_t *ip, s32_t *ident); +void snmp_ifindextonetif(s32_t ifindex, struct netif **netif); +void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx); + +struct mib_list_node* snmp_mib_ln_alloc(s32_t id); +void snmp_mib_ln_free(struct mib_list_node *ln); +struct mib_list_rootnode* snmp_mib_lrn_alloc(void); +void snmp_mib_lrn_free(struct mib_list_rootnode *lrn); + +s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn); +s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn); +struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n); + +struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np); +struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); +u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident); +u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret); + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNMP */ + +#endif /* __LWIP_SNMP_STRUCTS_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sockets.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sockets.h new file mode 100644 index 0000000..3c8fed2 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sockets.h @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + + +#ifndef __LWIP_SOCKETS_H__ +#define __LWIP_SOCKETS_H__ + +#include "lwip/opt.h" + +#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ + +#include /* for size_t */ + +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* members are in network byte order */ +struct sockaddr_in { + u8_t sin_len; + u8_t sin_family; + u16_t sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +}; + +struct sockaddr { + u8_t sa_len; + u8_t sa_family; + char sa_data[14]; +}; + +#ifndef socklen_t +# define socklen_t u32_t +#endif + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ + +#define SO_DONTLINGER ((int)(~SO_LINGER)) + +/* + * Additional options, not kept in so_options. + */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* Unimplemented: send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + + +/* + * Structure used for manipulating linger option. + */ +struct linger { + int l_onoff; /* option on/off */ + int l_linger; /* linger time */ +}; + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + + +#define AF_UNSPEC 0 +#define AF_INET 2 +#define PF_INET AF_INET +#define PF_UNSPEC AF_UNSPEC + +#define IPPROTO_IP 0 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_UDPLITE 136 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + + +/* + * Options for level IPPROTO_IP + */ +#define IP_TOS 1 +#define IP_TTL 2 + +#if LWIP_TCP +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ +#endif /* LWIP_TCP */ + +#if LWIP_UDP && LWIP_UDPLITE +/* + * Options for level IPPROTO_UDPLITE + */ +#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ +#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ +#endif /* LWIP_UDP && LWIP_UDPLITE*/ + + +#if LWIP_IGMP +/* + * Options and types for UDP multicast traffic handling + */ +#define IP_ADD_MEMBERSHIP 3 +#define IP_DROP_MEMBERSHIP 4 +#define IP_MULTICAST_TTL 5 +#define IP_MULTICAST_IF 6 +#define IP_MULTICAST_LOOP 7 + +typedef struct ip_mreq { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_interface; /* local IP address of interface */ +} ip_mreq; +#endif /* LWIP_IGMP */ + +/* + * The Type of Service provides an indication of the abstract + * parameters of the quality of service desired. These parameters are + * to be used to guide the selection of the actual service parameters + * when transmitting a datagram through a particular network. Several + * networks offer service precedence, which somehow treats high + * precedence traffic as more important than other traffic (generally + * by accepting only traffic above a certain precedence at time of high + * load). The major choice is a three way tradeoff between low-delay, + * high-reliability, and high-throughput. + * The use of the Delay, Throughput, and Reliability indications may + * increase the cost (in some sense) of the service. In many networks + * better performance for one of these parameters is coupled with worse + * performance on another. Except for very unusual cases at most two + * of these three indications should be set. + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * The Network Control precedence designation is intended to be used + * within a network only. The actual use and control of that + * designation is up to each network. The Internetwork Control + * designation is intended for use by gateway control originators only. + * If the actual use of these precedence designations is of concern to + * a particular network, it is the responsibility of that network to + * control the access to, and use of, those precedence designations. + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + + +/* + * Commands for ioctlsocket(), taken from the BSD file fcntl.h. + * lwip_ioctl only supports FIONREAD and FIONBIO, for now + * + * Ioctl's have the command encoded in the lower word, + * and the size of any in or out parameters in the upper + * word. The high 2 bits of the upper word are used + * to encode the in/out status of the parameter; for now + * we restrict parameters to at most 128 bytes. + */ +#if !defined(FIONREAD) || !defined(FIONBIO) +#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ +#define IOC_VOID 0x20000000UL /* no parameters */ +#define IOC_OUT 0x40000000UL /* copy out parameters */ +#define IOC_IN 0x80000000UL /* copy in parameters */ +#define IOC_INOUT (IOC_IN|IOC_OUT) + /* 0x20000000 distinguishes new & + old ioctl's */ +#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) + +#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) + +#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) +#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ + +#ifndef FIONREAD +#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ +#endif +#ifndef FIONBIO +#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ +#endif + +/* Socket I/O Controls: unimplemented */ +#ifndef SIOCSHIWAT +#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ +#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ +#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ +#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ +#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ +#endif + +/* commands for fnctl */ +#ifndef F_GETFL +#define F_GETFL 3 +#endif +#ifndef F_SETFL +#define F_SETFL 4 +#endif + +/* File status flags and file access modes for fnctl, + these are bits in an int. */ +#ifndef O_NONBLOCK +#define O_NONBLOCK 1 /* nonblocking I/O */ +#endif +#ifndef O_NDELAY +#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ +#endif + +#ifndef SHUT_RD + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 +#endif + +/* FD_SET used for lwip_select */ +#ifndef FD_SET + #undef FD_SETSIZE + /* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ + #define FD_SETSIZE MEMP_NUM_NETCONN + #define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7))) + #define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7))) + #define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7))) + #define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p))) + + typedef struct fd_set { + unsigned char fd_bits [(FD_SETSIZE+7)/8]; + } fd_set; + +#endif /* FD_SET */ + +/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include in cc.h */ +#ifndef LWIP_TIMEVAL_PRIVATE +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if LWIP_TIMEVAL_PRIVATE +struct timeval { + long tv_sec; /* seconds */ + long tv_usec; /* and microseconds */ +}; +#endif /* LWIP_TIMEVAL_PRIVATE */ + +void lwip_socket_init(void); + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_shutdown(int s, int how); +int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int lwip_close(int s); +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen); +int lwip_listen(int s, int backlog); +int lwip_recv(int s, void *mem, size_t len, int flags); +int lwip_read(int s, void *mem, size_t len); +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int lwip_send(int s, const void *dataptr, size_t size, int flags); +int lwip_sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int lwip_socket(int domain, int type, int protocol); +int lwip_write(int s, const void *dataptr, size_t size); +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +int lwip_ioctl(int s, long cmd, void *argp); +int lwip_fcntl(int s, int cmd, int val); + +#if LWIP_COMPAT_SOCKETS +#define accept(a,b,c) lwip_accept(a,b,c) +#define bind(a,b,c) lwip_bind(a,b,c) +#define shutdown(a,b) lwip_shutdown(a,b) +#define closesocket(s) lwip_close(s) +#define connect(a,b,c) lwip_connect(a,b,c) +#define getsockname(a,b,c) lwip_getsockname(a,b,c) +#define getpeername(a,b,c) lwip_getpeername(a,b,c) +#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e) +#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e) +#define listen(a,b) lwip_listen(a,b) +#define recv(a,b,c,d) lwip_recv(a,b,c,d) +#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f) +#define send(a,b,c,d) lwip_send(a,b,c,d) +#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f) +#define socket(a,b,c) lwip_socket(a,b,c) +#define select(a,b,c,d,e) lwip_select(a,b,c,d,e) +#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c) + +#if LWIP_POSIX_SOCKETS_IO_NAMES +#define read(a,b,c) lwip_read(a,b,c) +#define write(a,b,c) lwip_write(a,b,c) +#define close(s) lwip_close(s) +#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ + +#endif /* LWIP_COMPAT_SOCKETS */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SOCKET */ + +#endif /* __LWIP_SOCKETS_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/stats.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/stats.h new file mode 100644 index 0000000..4388321 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/stats.h @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_STATS_H__ +#define __LWIP_STATS_H__ + +#include "lwip/opt.h" + +#include "lwip/mem.h" +#include "lwip/memp.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if LWIP_STATS + +#ifndef LWIP_STATS_LARGE +#define LWIP_STATS_LARGE 0 +#endif + +#if LWIP_STATS_LARGE +#define STAT_COUNTER u32_t +#define STAT_COUNTER_F U32_F +#else +#define STAT_COUNTER u16_t +#define STAT_COUNTER_F U16_F +#endif + +struct stats_proto { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER fw; /* Forwarded packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER rterr; /* Routing error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER opterr; /* Error in options. */ + STAT_COUNTER err; /* Misc error. */ + STAT_COUNTER cachehit; +}; + +struct stats_igmp { + STAT_COUNTER xmit; /* Transmitted packets. */ + STAT_COUNTER recv; /* Received packets. */ + STAT_COUNTER drop; /* Dropped packets. */ + STAT_COUNTER chkerr; /* Checksum error. */ + STAT_COUNTER lenerr; /* Invalid length error. */ + STAT_COUNTER memerr; /* Out of memory error. */ + STAT_COUNTER proterr; /* Protocol error. */ + STAT_COUNTER rx_v1; /* Received v1 frames. */ + STAT_COUNTER rx_group; /* Received group-specific queries. */ + STAT_COUNTER rx_general; /* Received general queries. */ + STAT_COUNTER rx_report; /* Received reports. */ + STAT_COUNTER tx_join; /* Sent joins. */ + STAT_COUNTER tx_leave; /* Sent leaves. */ + STAT_COUNTER tx_report; /* Sent reports. */ +}; + +struct stats_mem { +#ifdef LWIP_DEBUG + const char *name; +#endif /* LWIP_DEBUG */ + mem_size_t avail; + mem_size_t used; + mem_size_t max; + STAT_COUNTER err; + STAT_COUNTER illegal; +}; + +struct stats_syselem { + STAT_COUNTER used; + STAT_COUNTER max; + STAT_COUNTER err; +}; + +struct stats_sys { + struct stats_syselem sem; + struct stats_syselem mutex; + struct stats_syselem mbox; +}; + +struct stats_ { +#if LINK_STATS + struct stats_proto link; +#endif +#if ETHARP_STATS + struct stats_proto etharp; +#endif +#if IPFRAG_STATS + struct stats_proto ip_frag; +#endif +#if IP_STATS + struct stats_proto ip; +#endif +#if ICMP_STATS + struct stats_proto icmp; +#endif +#if IGMP_STATS + struct stats_igmp igmp; +#endif +#if UDP_STATS + struct stats_proto udp; +#endif +#if TCP_STATS + struct stats_proto tcp; +#endif +#if MEM_STATS + struct stats_mem mem; +#endif +#if MEMP_STATS + struct stats_mem memp[MEMP_MAX]; +#endif +#if SYS_STATS + struct stats_sys sys; +#endif +}; + +extern struct stats_ lwip_stats; + +void stats_init(void)ICACHE_FLASH_ATTR; + +#define STATS_INC(x) ++lwip_stats.x +#define STATS_DEC(x) --lwip_stats.x +#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \ + if (lwip_stats.x.max < lwip_stats.x.used) { \ + lwip_stats.x.max = lwip_stats.x.used; \ + } \ + } while(0) +#else /* LWIP_STATS */ +#define stats_init() +#define STATS_INC(x) +#define STATS_DEC(x) +#define STATS_INC_USED(x) +#endif /* LWIP_STATS */ + +#if TCP_STATS +#define TCP_STATS_INC(x) STATS_INC(x) +#define TCP_STATS_DISPLAY() stats_display_proto(&lwip_stats.tcp, "TCP") +#else +#define TCP_STATS_INC(x) +#define TCP_STATS_DISPLAY() +#endif + +#if UDP_STATS +#define UDP_STATS_INC(x) STATS_INC(x) +#define UDP_STATS_DISPLAY() stats_display_proto(&lwip_stats.udp, "UDP") +#else +#define UDP_STATS_INC(x) +#define UDP_STATS_DISPLAY() +#endif + +#if ICMP_STATS +#define ICMP_STATS_INC(x) STATS_INC(x) +#define ICMP_STATS_DISPLAY() stats_display_proto(&lwip_stats.icmp, "ICMP") +#else +#define ICMP_STATS_INC(x) +#define ICMP_STATS_DISPLAY() +#endif + +#if IGMP_STATS +#define IGMP_STATS_INC(x) STATS_INC(x) +#define IGMP_STATS_DISPLAY() stats_display_igmp(&lwip_stats.igmp) +#else +#define IGMP_STATS_INC(x) +#define IGMP_STATS_DISPLAY() +#endif + +#if IP_STATS +#define IP_STATS_INC(x) STATS_INC(x) +#define IP_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip, "IP") +#else +#define IP_STATS_INC(x) +#define IP_STATS_DISPLAY() +#endif + +#if IPFRAG_STATS +#define IPFRAG_STATS_INC(x) STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG") +#else +#define IPFRAG_STATS_INC(x) +#define IPFRAG_STATS_DISPLAY() +#endif + +#if ETHARP_STATS +#define ETHARP_STATS_INC(x) STATS_INC(x) +#define ETHARP_STATS_DISPLAY() stats_display_proto(&lwip_stats.etharp, "ETHARP") +#else +#define ETHARP_STATS_INC(x) +#define ETHARP_STATS_DISPLAY() +#endif + +#if LINK_STATS +#define LINK_STATS_INC(x) STATS_INC(x) +#define LINK_STATS_DISPLAY() stats_display_proto(&lwip_stats.link, "LINK") +#else +#define LINK_STATS_INC(x) +#define LINK_STATS_DISPLAY() +#endif + +#if MEM_STATS +#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y +#define MEM_STATS_INC(x) STATS_INC(mem.x) +#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y) +#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y +#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP") +#else +#define MEM_STATS_AVAIL(x, y) +#define MEM_STATS_INC(x) +#define MEM_STATS_INC_USED(x, y) +#define MEM_STATS_DEC_USED(x, y) +#define MEM_STATS_DISPLAY() +#endif + +#if MEMP_STATS +#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y +#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x) +#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x) +#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1) +#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i) +#else +#define MEMP_STATS_AVAIL(x, i, y) +#define MEMP_STATS_INC(x, i) +#define MEMP_STATS_DEC(x, i) +#define MEMP_STATS_INC_USED(x, i) +#define MEMP_STATS_DISPLAY(i) +#endif + +#if SYS_STATS +#define SYS_STATS_INC(x) STATS_INC(sys.x) +#define SYS_STATS_DEC(x) STATS_DEC(sys.x) +#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1) +#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys) +#else +#define SYS_STATS_INC(x) +#define SYS_STATS_DEC(x) +#define SYS_STATS_INC_USED(x) +#define SYS_STATS_DISPLAY() +#endif + +/* Display of statistics */ +#if LWIP_STATS_DISPLAY +void stats_display(void)ICACHE_FLASH_ATTR; +void stats_display_proto(struct stats_proto *proto, char *name)ICACHE_FLASH_ATTR; +void stats_display_igmp(struct stats_igmp *igmp)ICACHE_FLASH_ATTR; +void stats_display_mem(struct stats_mem *mem, char *name)ICACHE_FLASH_ATTR; +void stats_display_memp(struct stats_mem *mem, int index)ICACHE_FLASH_ATTR; +void stats_display_sys(struct stats_sys *sys)ICACHE_FLASH_ATTR; +#else /* LWIP_STATS_DISPLAY */ +#define stats_display() +#define stats_display_proto(proto, name) +#define stats_display_igmp(igmp) +#define stats_display_mem(mem, name) +#define stats_display_memp(mem, index) +#define stats_display_sys(sys) +#endif /* LWIP_STATS_DISPLAY */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_STATS_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sys.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sys.h new file mode 100644 index 0000000..31a9dea --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/sys.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_SYS_H__ +#define __LWIP_SYS_H__ + +#include "lwip/opt.h" + +#include "eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if NO_SYS + +/* For a totally minimal and standalone system, we provide null + definitions of the sys_ functions. */ +typedef u8_t sys_sem_t; +typedef u8_t sys_mutex_t; +typedef u8_t sys_mbox_t; + +#define sys_sem_new(s, c) ERR_OK +#define sys_sem_signal(s) +#define sys_sem_wait(s) +#define sys_arch_sem_wait(s,t) +#define sys_sem_free(s) +#define sys_mutex_new(mu) ERR_OK +#define sys_mutex_lock(mu) +#define sys_mutex_unlock(mu) +#define sys_mutex_free(mu) +#define sys_mbox_new(m, s) ERR_OK +#define sys_mbox_fetch(m,d) +#define sys_mbox_tryfetch(m,d) +#define sys_mbox_post(m,d) +#define sys_mbox_trypost(m,d) +#define sys_mbox_free(m) + +#define sys_thread_new(n,t,a,s,p) + +#define sys_msleep(t) + +#else /* NO_SYS */ + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +#include "lwip/err.h" +#include "arch/sys_arch.h" + +/** Function prototype for thread functions */ +typedef void (*lwip_thread_fn)(void *arg); + +/* Function prototypes for functions to be implemented by platform ports + (in sys_arch.c) */ + +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_COMPAT_MUTEX */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex */ +err_t sys_mutex_new(sys_mutex_t *mutex); +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_COMPAT_MUTEX */ + +/* Semaphore functions: */ + +/** Create a new semaphore + * @param sem pointer to the semaphore to create + * @param count initial count of the semaphore + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); +/** Signals a semaphore + * @param sem the semaphore to signal */ +void sys_sem_signal(sys_sem_t *sem); +/** Wait for a semaphore for the specified timeout + * @param sem the semaphore to wait for + * @param timeout timeout in milliseconds to wait (0 = wait forever) + * @return time (in milliseconds) waited for the semaphore + * or SYS_ARCH_TIMEOUT on timeout */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); +/** Delete a semaphore + * @param sem semaphore to delete */ +void sys_sem_free(sys_sem_t *sem); +/** Wait for a semaphore - forever/no timeout */ +#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif + +/* Time functions. */ +#ifndef sys_msleep +void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ +#endif + +/* Mailbox functions. */ + +/** Create a new mbox of specified size + * @param mbox pointer to the mbox to create + * @param size (miminum) number of messages in this mbox + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg); +/** Try to post a message to an mbox - may fail if full or ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); +/* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */ +#ifndef sys_arch_mbox_tryfetch +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); +#endif +/** For now, we map straight to sys_arch implementation. */ +#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) +/** Delete an mbox + * @param mbox mbox to delete */ +void sys_mbox_free(sys_mbox_t *mbox); +#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif + +/** The only thread function: + * Creates a new thread + * @param name human-readable name for the thread (used for debugging purposes) + * @param thread thread-function + * @param arg parameter passed to 'thread' + * @param stacksize stack size in bytes for the new thread (may be ignored by ports) + * @param prio priority of the new thread (may be ignored by ports) */ +sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio); + +#endif /* NO_SYS */ + +/* sys_init() must be called before anthing else. */ +void sys_init(void)ICACHE_FLASH_ATTR; + +#ifndef sys_jiffies +/** Ticks/jiffies since power up. */ +u32_t sys_jiffies(void)ICACHE_FLASH_ATTR; +#endif + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +static inline u32_t sys_now(void) ICACHE_FLASH_ATTR; +static inline u32_t sys_now(void) +{ + return NOW()/(TIMER_CLK_FREQ/1000); +} + +/* Critical Region Protection */ +/* These functions must be implemented in the sys_arch.c file. + In some implementations they can provide a more light-weight protection + mechanism than using semaphores. Otherwise semaphores can be used for + implementation */ +#ifndef SYS_ARCH_PROTECT +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#if SYS_LIGHTWEIGHT_PROT + +/** SYS_ARCH_DECL_PROTECT + * declare a protection variable. This macro will default to defining a variable of + * type sys_prot_t. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h. + */ +#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev +/** SYS_ARCH_PROTECT + * Perform a "fast" protect. This could be implemented by + * disabling interrupts for an embedded system or by using a semaphore or + * mutex. The implementation should allow calling SYS_ARCH_PROTECT when + * already protected. The old protection level is returned in the variable + * "lev". This macro will default to calling the sys_arch_protect() function + * which should be implemented in sys_arch.c. If a particular port needs a + * different implementation, then this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect() +/** SYS_ARCH_UNPROTECT + * Perform a "fast" set of the protection level to "lev". This could be + * implemented by setting the interrupt level to "lev" within the MACRO or by + * using a semaphore or mutex. This macro will default to calling the + * sys_arch_unprotect() function which should be implemented in + * sys_arch.c. If a particular port needs a different implementation, then + * this macro may be defined in sys_arch.h + */ +#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev) +sys_prot_t sys_arch_protect(void)ICACHE_FLASH_ATTR; +void sys_arch_unprotect(sys_prot_t pval)ICACHE_FLASH_ATTR; + +#else + +#define SYS_ARCH_DECL_PROTECT(lev) +#define SYS_ARCH_PROTECT(lev) lev = os_intr_lock() //fix by ives at 2014.3.24 +#define SYS_ARCH_UNPROTECT(lev) lev = os_intr_unlock() + +#endif /* SYS_LIGHTWEIGHT_PROT */ + +#endif /* SYS_ARCH_PROTECT */ + +/* + * Macros to set/get and increase/decrease variables in a thread-safe way. + * Use these for accessing variable that are used from more than one thread. + */ + +#ifndef SYS_ARCH_INC +#define SYS_ARCH_INC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var += val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_INC */ + +#ifndef SYS_ARCH_DEC +#define SYS_ARCH_DEC(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var -= val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_DEC */ + +#ifndef SYS_ARCH_GET +#define SYS_ARCH_GET(var, ret) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + ret = var; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_GET */ + +#ifndef SYS_ARCH_SET +#define SYS_ARCH_SET(var, val) do { \ + SYS_ARCH_DECL_PROTECT(old_level); \ + SYS_ARCH_PROTECT(old_level); \ + var = val; \ + SYS_ARCH_UNPROTECT(old_level); \ + } while(0) +#endif /* SYS_ARCH_SET */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __LWIP_SYS_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp.h new file mode 100644 index 0000000..909ff9b --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp.h @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_H__ +#define __LWIP_TCP_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct tcp_pcb; + +/** Function prototype for tcp accept callback functions. Called when a new + * connection can be accepted on a listening pcb. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param newpcb The new connection pcb + * @param err An error code if there has been an error accepting. + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err); + +/** Function prototype for tcp receive callback functions. Called when data has + * been received. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which received data + * @param p The received data (or NULL when the connection has been closed!) + * @param err An error code if there has been an error receiving + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, + struct pbuf *p, err_t err); + +/** Function prototype for tcp sent callback functions. Called when sent data has + * been acknowledged by the remote side. Use it to free corresponding resources. + * This also means that the pcb has now space available to send new data. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb for which data has been acknowledged + * @param len The amount of bytes acknowledged + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb, + u16_t len); + +/** Function prototype for tcp poll callback functions. Called periodically as + * specified by @see tcp_poll. + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb tcp pcb + * @return ERR_OK: try to send some data by calling tcp_output + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + */ +typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb); + +/** Function prototype for tcp error callback functions. Called when the pcb + * receives a RST or is unexpectedly closed for any other reason. + * + * @note The corresponding pcb is already freed when this callback is called! + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param err Error code to indicate why the pcb has been closed + * ERR_ABRT: aborted through tcp_abort or by a TCP timer + * ERR_RST: the connection was reset by the remote host + */ +typedef void (*tcp_err_fn)(void *arg, err_t err); + +/** Function prototype for tcp connected callback functions. Called when a pcb + * is connected to the remote side after initiating a connection attempt by + * calling tcp_connect(). + * + * @param arg Additional argument to pass to the callback function (@see tcp_arg()) + * @param tpcb The connection pcb which is connected + * @param err An unused error code, always ERR_OK currently ;-) TODO! + * Only return ERR_ABRT if you have called tcp_abort from within the + * callback function! + * + * @note When a connection attempt fails, the error callback is currently called! + */ +typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); + +enum tcp_state { + CLOSED = 0, + LISTEN = 1, + SYN_SENT = 2, + SYN_RCVD = 3, + ESTABLISHED = 4, + FIN_WAIT_1 = 5, + FIN_WAIT_2 = 6, + CLOSE_WAIT = 7, + CLOSING = 8, + LAST_ACK = 9, + TIME_WAIT = 10 +}; + +#if LWIP_CALLBACK_API + /* Function to call when a listener has been connected. + * @param arg user-supplied argument (tcp_pcb.callback_arg) + * @param pcb a new tcp_pcb that now is connected + * @param err an error argument (TODO: that is current always ERR_OK?) + * @return ERR_OK: accept the new connection, + * any other err_t abortsthe new connection + */ +#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept; +#else /* LWIP_CALLBACK_API */ +#define DEF_ACCEPT_CALLBACK +#endif /* LWIP_CALLBACK_API */ + +/** + * members common to struct tcp_pcb and struct tcp_listen_pcb + */ +#define TCP_PCB_COMMON(type) \ + type *next; /* for the linked list */ \ + enum tcp_state state; /* TCP state */ \ + u8_t prio; \ + void *callback_arg; \ + /* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \ + DEF_ACCEPT_CALLBACK \ + /* ports are in host byte order */ \ + u16_t local_port + + +/* the TCP protocol control block */ +struct tcp_pcb { +/** common PCB members */ + IP_PCB; +/** protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb); + + /* ports are in host byte order */ + u16_t remote_port; + + u8_t flags; +#define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ +#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ +#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ +#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ +#define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */ +#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ +#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ +#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */ + + /* the rest of the fields are in host byte order + as we have to do some math with them */ + /* receiver variables */ + u32_t rcv_nxt; /* next seqno expected */ + u16_t rcv_wnd; /* receiver window available */ + u16_t rcv_ann_wnd; /* receiver window to announce */ + u32_t rcv_ann_right_edge; /* announced right edge of window */ + + /* Timers */ + u32_t tmr; + u8_t polltmr, pollinterval; + + /* Retransmission timer. */ + s16_t rtime; + + u16_t mss; /* maximum segment size */ + + /* RTT (round trip time) estimation variables */ + u32_t rttest; /* RTT estimate in 500ms ticks */ + u32_t rtseq; /* sequence number being timed */ + s16_t sa, sv; /* @todo document this */ + + s16_t rto; /* retransmission time-out */ + u8_t nrtx; /* number of retransmissions */ + + /* fast retransmit/recovery */ + u32_t lastack; /* Highest acknowledged seqno. */ + u8_t dupacks; + + /* congestion avoidance/control variables */ + u16_t cwnd; + u16_t ssthresh; + + /* sender variables */ + u32_t snd_nxt; /* next new seqno to be sent */ + u16_t snd_wnd; /* sender window */ + u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last + window update. */ + u32_t snd_lbb; /* Sequence number of next byte to be buffered. */ + + u16_t acked; + + u16_t snd_buf; /* Available buffer space for sending (in bytes). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3) + u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ + +#if TCP_OVERSIZE + /* Extra bytes available at the end of the last pbuf in unsent. */ + u16_t unsent_oversize; +#endif /* TCP_OVERSIZE */ + + /* These are ordered by sequence number: */ + struct tcp_seg *unsent; /* Unsent (queued) segments. */ + struct tcp_seg *unacked; /* Sent but unacknowledged segments. */ +#if TCP_QUEUE_OOSEQ + struct tcp_seg *ooseq; /* Received out of sequence segments. */ +#endif /* TCP_QUEUE_OOSEQ */ + + struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */ + +#if LWIP_CALLBACK_API + /* Function to be called when more send buffer space is available. */ + tcp_sent_fn sent; + /* Function to be called when (in-sequence) data has arrived. */ + tcp_recv_fn recv; + /* Function to be called when a connection has been set up. */ + tcp_connected_fn connected; + /* Function which is called periodically. */ + tcp_poll_fn poll; + /* Function to be called whenever a fatal error occurs. */ + tcp_err_fn errf; +#endif /* LWIP_CALLBACK_API */ + +#if LWIP_TCP_TIMESTAMPS + u32_t ts_lastacksent; + u32_t ts_recent; +#endif /* LWIP_TCP_TIMESTAMPS */ + + /* idle time before KEEPALIVE is sent */ + u32_t keep_idle; +#if LWIP_TCP_KEEPALIVE + u32_t keep_intvl; + u32_t keep_cnt; +#endif /* LWIP_TCP_KEEPALIVE */ + + /* Persist timer counter */ + u32_t persist_cnt; + /* Persist timer back-off */ + u8_t persist_backoff; + + /* KEEPALIVE counter */ + u8_t keep_cnt_sent; +}; + +struct tcp_pcb_listen { +/* Common members of all PCB types */ + IP_PCB; +/* Protocol specific PCB members */ + TCP_PCB_COMMON(struct tcp_pcb_listen); + +#if TCP_LISTEN_BACKLOG + u8_t backlog; + u8_t accepts_pending; +#endif /* TCP_LISTEN_BACKLOG */ +}; + +#if LWIP_EVENT_API + +enum lwip_event { + LWIP_EVENT_ACCEPT, + LWIP_EVENT_SENT, + LWIP_EVENT_RECV, + LWIP_EVENT_CONNECTED, + LWIP_EVENT_POLL, + LWIP_EVENT_ERR +}; + +err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb, + enum lwip_event, + struct pbuf *p, + u16_t size, + err_t err); + +#endif /* LWIP_EVENT_API */ + +/* Application program's interface: */ +struct tcp_pcb * tcp_new (void)ICACHE_FLASH_ATTR; + +void tcp_arg (struct tcp_pcb *pcb, void *arg) ICACHE_FLASH_ATTR; +void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept) ICACHE_FLASH_ATTR; +void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv) ICACHE_FLASH_ATTR; +void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent)ICACHE_FLASH_ATTR; +void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval)ICACHE_FLASH_ATTR; +void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err)ICACHE_FLASH_ATTR; + +#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss) +#define tcp_sndbuf(pcb) ((pcb)->snd_buf) +#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen) +#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY) +#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY) +#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0) + +#if TCP_LISTEN_BACKLOG +#define tcp_accepted(pcb) do { \ + LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \ + (((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0) +#else /* TCP_LISTEN_BACKLOG */ +#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \ + pcb->state == LISTEN) +#endif /* TCP_LISTEN_BACKLOG */ + +void tcp_recved (struct tcp_pcb *pcb, u16_t len)ICACHE_FLASH_ATTR; +err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port)ICACHE_FLASH_ATTR; +err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port, tcp_connected_fn connected)ICACHE_FLASH_ATTR; + +struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)ICACHE_FLASH_ATTR; +#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG) + +void tcp_abort (struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +err_t tcp_close (struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx)ICACHE_FLASH_ATTR; + +/* Flags for "apiflags" parameter in tcp_write */ +#define TCP_WRITE_FLAG_COPY 0x01 +#define TCP_WRITE_FLAG_MORE 0x02 + +err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len, + u8_t apiflags)ICACHE_FLASH_ATTR; + +void tcp_setprio (struct tcp_pcb *pcb, u8_t prio)ICACHE_FLASH_ATTR; + +#define TCP_PRIO_MIN 1 +#define TCP_PRIO_NORMAL 64 +#define TCP_PRIO_MAX 127 + +extern err_t tcp_output(struct tcp_pcb *pcb); + + +const char* tcp_debug_state_str(enum tcp_state s)ICACHE_FLASH_ATTR; + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp_impl.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp_impl.h new file mode 100644 index 0000000..f906c0d --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcp_impl.h @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCP_IMPL_H__ +#define __LWIP_TCP_IMPL_H__ + +#include "lwip/opt.h" + +#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/tcp.h" +#include "lwip/sys.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/ip.h" +#include "lwip/icmp.h" +#include "lwip/err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Functions for interfacing with TCP: */ + +/* Lower layer interface to TCP: */ +#define tcp_init() /* Compatibility define, no init needed. */ +void tcp_tmr (void)ICACHE_FLASH_ATTR; /* Must be called every + TCP_TMR_INTERVAL + ms. (Typically 250 ms). */ +/* It is also possible to call these two functions at the right + intervals (instead of calling tcp_tmr()). */ +void tcp_slowtmr (void)ICACHE_FLASH_ATTR; +void tcp_fasttmr (void)ICACHE_FLASH_ATTR; + + +/* Only used by IP to pass a TCP segment to TCP: */ +void tcp_input (struct pbuf *p, struct netif *inp)ICACHE_FLASH_ATTR; +/* Used within the TCP code only: */ +struct tcp_pcb * tcp_alloc (u8_t prio)ICACHE_FLASH_ATTR; +void tcp_abandon (struct tcp_pcb *pcb, int reset)ICACHE_FLASH_ATTR; +err_t tcp_send_empty_ack(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +void tcp_rexmit (struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +void tcp_rexmit_rto (struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +void tcp_rexmit_fast (struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; + +/** + * This is the Nagle algorithm: try to combine user data to send as few TCP + * segments as possible. Only send if + * - no previously transmitted data on the connection remains unacknowledged or + * - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or + * - the only unsent segment is at least pcb->mss bytes long (or there is more + * than one unsent segment - with lwIP, this can happen although unsent->len < mss) + * - or if we are in fast-retransmit (TF_INFR) + */ +#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ + ((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \ + (((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \ + ((tpcb)->unsent->len >= (tpcb)->mss))) \ + ) ? 1 : 0) +#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK) + + +#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0) +#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0) +#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0) +#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0) +/* is b<=a<=c? */ +#if 0 /* see bug #10548 */ +#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b)) +#endif +#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c)) +#define TCP_FIN 0x01U +#define TCP_SYN 0x02U +#define TCP_RST 0x04U +#define TCP_PSH 0x08U +#define TCP_ACK 0x10U +#define TCP_URG 0x20U +#define TCP_ECE 0x40U +#define TCP_CWR 0x80U + +#define TCP_FLAGS 0x3fU + +/* Length of the TCP header, excluding options. */ +#define TCP_HLEN 20 + +#ifndef TCP_TMR_INTERVAL +#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ +#endif /* TCP_TMR_INTERVAL */ + +#ifndef TCP_FAST_INTERVAL +#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ +#endif /* TCP_FAST_INTERVAL */ + +#ifndef TCP_SLOW_INTERVAL +#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */ +#endif /* TCP_SLOW_INTERVAL */ + +#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ +#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */ + +#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ + +#ifndef TCP_MSL +#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */ +#endif + +/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ +#ifndef TCP_KEEPIDLE_DEFAULT +#define TCP_KEEPIDLE_DEFAULT 3000UL /* Default KEEPALIVE timer in milliseconds */ +#endif + +#ifndef TCP_KEEPINTVL_DEFAULT +#define TCP_KEEPINTVL_DEFAULT 1000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#endif + +#ifndef TCP_KEEPCNT_DEFAULT +#define TCP_KEEPCNT_DEFAULT 3U /* Default Counter for KEEPALIVE probes */ +#endif + +#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ + +/* Fields are (of course) in network byte order. + * Some fields are converted to host byte order in tcp_input(). + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct tcp_hdr { + PACK_STRUCT_FIELD(u16_t src); //Ô´¶Ë¿Ú + PACK_STRUCT_FIELD(u16_t dest); //Ä¿µÄ¶Ë¿Ú + PACK_STRUCT_FIELD(u32_t seqno); //ÐòºÅ + PACK_STRUCT_FIELD(u32_t ackno); //Ó¦´ðÐòºÅ + PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);//Êײ¿³¤¶È+±£Áôλ+±ê־λ + PACK_STRUCT_FIELD(u16_t wnd); //´°¿Ú´óС + PACK_STRUCT_FIELD(u16_t chksum); //УÑéºÍ + PACK_STRUCT_FIELD(u16_t urgp); //½ô¼±Ö¸Õë +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8) +#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) +#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS) + +#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr)) +#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) +#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) +#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags)) + +#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) +#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) ) + +#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0)) + +/** Flags used on input processing, not on pcb->flags +*/ +#define TF_RESET (u8_t)0x08U /* Connection was reset. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */ +#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ + + +#if LWIP_EVENT_API + +#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_ACCEPT, NULL, 0, err) +#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_SENT, NULL, space, ERR_OK) +#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) +#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_CONNECTED, NULL, 0, (err)) +#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_POLL, NULL, 0, ERR_OK) +#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \ + LWIP_EVENT_ERR, NULL, 0, (err)) + +#else /* LWIP_EVENT_API */ + +#define TCP_EVENT_ACCEPT(pcb,err,ret) \ + do { \ + if((pcb)->accept != NULL) \ + (ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_ARG; \ + } while (0) + +#define TCP_EVENT_SENT(pcb,space,ret) \ + do { \ + if((pcb)->sent != NULL) \ + (ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ + } while (0) + +#define TCP_EVENT_CONNECTED(pcb,err,ret) \ + do { \ + if((pcb)->connected != NULL) \ + (ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_POLL(pcb,ret) \ + do { \ + if((pcb)->poll != NULL) \ + (ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \ + else (ret) = ERR_OK; \ + } while (0) + +#define TCP_EVENT_ERR(errf,arg,err) \ + do { \ + if((errf) != NULL) \ + (errf)((arg),(err)); \ + } while (0) + +#endif /* LWIP_EVENT_API */ + +/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */ +#if TCP_OVERSIZE && defined(LWIP_DEBUG) +#define TCP_OVERSIZE_DBGCHECK 1 +#else +#define TCP_OVERSIZE_DBGCHECK 0 +#endif + +/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */ +#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP) + +/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ +struct tcp_seg { + struct tcp_seg *next; /* used when putting segements on a queue */ + struct pbuf *p; /* buffer containing data + TCP header */ + void *dataptr; /* pointer to the TCP data in the pbuf */ + u16_t len; /* the TCP length of this segment */ +#if TCP_OVERSIZE_DBGCHECK + u16_t oversize_left; /* Extra bytes available at the end of the last + pbuf in unsent (used for asserting vs. + tcp_pcb.unsent_oversized only) */ +#endif /* TCP_OVERSIZE_DBGCHECK */ +#if TCP_CHECKSUM_ON_COPY + u16_t chksum; + u8_t chksum_swapped; +#endif /* TCP_CHECKSUM_ON_COPY */ + u8_t flags; +#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ +#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ +#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is + checksummed into 'chksum' */ + struct tcp_hdr *tcphdr; /* the TCP header */ +}; + +#define LWIP_TCP_OPT_LENGTH(flags) \ + (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \ + (flags & TF_SEG_OPTS_TS ? 12 : 0) + +/** This returns a TCP header option for MSS in an u32_t */ +#define TCP_BUILD_MSS_OPTION(x) (x) = PP_HTONL(((u32_t)2 << 24) | \ + ((u32_t)4 << 16) | \ + (((u32_t)TCP_MSS / 256) << 8) | \ + (TCP_MSS & 255)) + +/* Global variables: */ +extern struct tcp_pcb *tcp_input_pcb; +extern u32_t tcp_ticks; + +/* The TCP PCB lists. */ +union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */ + struct tcp_pcb_listen *listen_pcbs; + struct tcp_pcb *pcbs; +}; +extern struct tcp_pcb *tcp_bound_pcbs; +extern union tcp_listen_pcbs_t tcp_listen_pcbs; +extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a + state in which they accept or send + data. */ +extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */ + +extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */ + +/* Axioms about the above lists: + 1) Every TCP PCB that is not CLOSED is in one of the lists. + 2) A PCB is only in one of the lists. + 3) All PCBs in the tcp_listen_pcbs list is in LISTEN state. + 4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state. +*/ +/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB + with a PCB list or removes a PCB from a list, respectively. */ +#ifndef TCP_DEBUG_PCB_LISTS +#define TCP_DEBUG_PCB_LISTS 0 +#endif +#if TCP_DEBUG_PCB_LISTS +#define TCP_REG(pcbs, npcb) do {\ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \ + for(tcp_tmp_pcb = *(pcbs); \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \ + } \ + LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \ + (npcb)->next = *(pcbs); \ + LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \ + *(pcbs) = (npcb); \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + tcp_timer_needed(); \ + } while(0) +#define TCP_RMV(pcbs, npcb) do { \ + LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \ + if(*(pcbs) == (npcb)) { \ + *(pcbs) = (*pcbs)->next; \ + } else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + (npcb)->next = NULL; \ + LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \ + LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \ + } while(0) + +#else /* LWIP_DEBUG */ + +#define TCP_REG(pcbs, npcb) \ + do { \ + (npcb)->next = *pcbs; \ + *(pcbs) = (npcb); \ + tcp_timer_needed(); \ + } while (0) + +#define TCP_RMV(pcbs, npcb) \ + do { \ + if(*(pcbs) == (npcb)) { \ + (*(pcbs)) = (*pcbs)->next; \ + } \ + else { \ + for(tcp_tmp_pcb = *pcbs; \ + tcp_tmp_pcb != NULL; \ + tcp_tmp_pcb = tcp_tmp_pcb->next) { \ + if(tcp_tmp_pcb->next == (npcb)) { \ + tcp_tmp_pcb->next = (npcb)->next; \ + break; \ + } \ + } \ + } \ + (npcb)->next = NULL; \ + } while(0) + +#endif /* LWIP_DEBUG */ + + +/* Internal functions: */ +struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +void tcp_pcb_purge(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; + +void tcp_segs_free(struct tcp_seg *seg)ICACHE_FLASH_ATTR; +void tcp_seg_free(struct tcp_seg *seg)ICACHE_FLASH_ATTR; +struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg)ICACHE_FLASH_ATTR; + +#define tcp_ack(pcb) \ + do { \ + if((pcb)->flags & TF_ACK_DELAY) { \ + (pcb)->flags &= ~TF_ACK_DELAY; \ + (pcb)->flags |= TF_ACK_NOW; \ + } \ + else { \ + (pcb)->flags |= TF_ACK_DELAY; \ + } \ + } while (0) + +#define tcp_ack_now(pcb) \ + do { \ + (pcb)->flags |= TF_ACK_NOW; \ + } while (0) + +err_t tcp_send_fin(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)ICACHE_FLASH_ATTR; + +void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg)ICACHE_FLASH_ATTR; + +void tcp_rst(u32_t seqno, u32_t ackno, + ip_addr_t *local_ip, ip_addr_t *remote_ip, + u16_t local_port, u16_t remote_port)ICACHE_FLASH_ATTR; + +u32_t tcp_next_iss(void)ICACHE_FLASH_ATTR; + +void tcp_keepalive(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; +void tcp_zero_window_probe(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; + +#if TCP_CALCULATE_EFF_SEND_MSS +u16_t tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)ICACHE_FLASH_ATTR; +#endif /* TCP_CALCULATE_EFF_SEND_MSS */ + +#if LWIP_CALLBACK_API +err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)ICACHE_FLASH_ATTR; +#endif /* LWIP_CALLBACK_API */ + +#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG +void tcp_debug_print(struct tcp_hdr *tcphdr)ICACHE_FLASH_ATTR; +void tcp_debug_print_flags(u8_t flags)ICACHE_FLASH_ATTR; +void tcp_debug_print_state(enum tcp_state s)ICACHE_FLASH_ATTR; +void tcp_debug_print_pcbs(void)ICACHE_FLASH_ATTR; +s16_t tcp_pcbs_sane(void)ICACHE_FLASH_ATTR; +#else +# define tcp_debug_print(tcphdr) +# define tcp_debug_print_flags(flags) +# define tcp_debug_print_state(s) +# define tcp_debug_print_pcbs() +# define tcp_pcbs_sane() 1 +#endif /* TCP_DEBUG */ + +/** External function (implemented in timers.c), called when TCP detects + * that a timer is needed (i.e. active- or time-wait-pcb found). */ +void tcp_timer_needed(void)ICACHE_FLASH_ATTR; + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TCP */ + +#endif /* __LWIP_TCP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcpip.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcpip.h new file mode 100644 index 0000000..995ba8a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/tcpip.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_TCPIP_H__ +#define __LWIP_TCPIP_H__ + +#include "lwip/opt.h" + +#if !NO_SYS /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/api_msg.h" +#include "lwip/netifapi.h" +#include "lwip/pbuf.h" +#include "lwip/api.h" +#include "lwip/sys.h" +#include "lwip/timers.h" +#include "lwip/netif.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Define this to something that triggers a watchdog. This is called from + * tcpip_thread after processing a message. */ +#ifndef LWIP_TCPIP_THREAD_ALIVE +#define LWIP_TCPIP_THREAD_ALIVE() +#endif + +#if LWIP_TCPIP_CORE_LOCKING +/** The global semaphore to lock the stack. */ +extern sys_mutex_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) +#define TCPIP_APIMSG(m) tcpip_apimsg_lock(m) +#define TCPIP_APIMSG_ACK(m) +#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m) +#define TCPIP_NETIFAPI_ACK(m) +#else /* LWIP_TCPIP_CORE_LOCKING */ +#define LOCK_TCPIP_CORE() +#define UNLOCK_TCPIP_CORE() +#define TCPIP_APIMSG(m) tcpip_apimsg(m) +#define TCPIP_APIMSG_ACK(m) sys_sem_signal(&m->conn->op_completed) +#define TCPIP_NETIFAPI(m) tcpip_netifapi(m) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem) +#endif /* LWIP_TCPIP_CORE_LOCKING */ + +/** Function prototype for the init_done function passed to tcpip_init */ +typedef void (*tcpip_init_done_fn)(void *arg); +/** Function prototype for functions passed to tcpip_callback() */ +typedef void (*tcpip_callback_fn)(void *ctx); + +void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg); + +#if LWIP_NETCONN +err_t tcpip_apimsg(struct api_msg *apimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_apimsg_lock(struct api_msg *apimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETCONN */ + +err_t tcpip_input(struct pbuf *p, struct netif *inp); + +#if LWIP_NETIF_API +err_t tcpip_netifapi(struct netifapi_msg *netifapimsg); +#if LWIP_TCPIP_CORE_LOCKING +err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg); +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#endif /* LWIP_NETIF_API */ + +err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block); +#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1) + +/* free pbufs or heap memory from another context without blocking */ +err_t pbuf_free_callback(struct pbuf *p); +err_t mem_free_callback(void *m); + +#if LWIP_TCPIP_TIMEOUT +err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg); +err_t tcpip_untimeout(sys_timeout_handler h, void *arg); +#endif /* LWIP_TCPIP_TIMEOUT */ + +enum tcpip_msg_type { +#if LWIP_NETCONN + TCPIP_MSG_API, +#endif /* LWIP_NETCONN */ + TCPIP_MSG_INPKT, +#if LWIP_NETIF_API + TCPIP_MSG_NETIFAPI, +#endif /* LWIP_NETIF_API */ +#if LWIP_TCPIP_TIMEOUT + TCPIP_MSG_TIMEOUT, + TCPIP_MSG_UNTIMEOUT, +#endif /* LWIP_TCPIP_TIMEOUT */ + TCPIP_MSG_CALLBACK +}; + +struct tcpip_msg { + enum tcpip_msg_type type; + sys_sem_t *sem; + union { +#if LWIP_NETCONN + struct api_msg *apimsg; +#endif /* LWIP_NETCONN */ +#if LWIP_NETIF_API + struct netifapi_msg *netifapimsg; +#endif /* LWIP_NETIF_API */ + struct { + struct pbuf *p; + struct netif *netif; + } inp; + struct { + tcpip_callback_fn function; + void *ctx; + } cb; +#if LWIP_TCPIP_TIMEOUT + struct { + u32_t msecs; + sys_timeout_handler h; + void *arg; + } tmo; +#endif /* LWIP_TCPIP_TIMEOUT */ + } msg; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* !NO_SYS */ + +#endif /* __LWIP_TCPIP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/timers.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/timers.h new file mode 100644 index 0000000..e9db02a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/timers.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * Simon Goldschmidt + * + */ +#ifndef __LWIP_TIMERS_H__ +#define __LWIP_TIMERS_H__ + +#include "lwip/opt.h" + +/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */ +#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) + +#if LWIP_TIMERS + +#include "lwip/err.h" +#include "lwip/sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LWIP_DEBUG_TIMERNAMES +#ifdef LWIP_DEBUG +#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG +#else /* LWIP_DEBUG */ +#define LWIP_DEBUG_TIMERNAMES 0 +#endif /* LWIP_DEBUG*/ +#endif + +/** Function prototype for a timeout callback function. Register such a function + * using sys_timeout(). + * + * @param arg Additional argument to pass to the function - set up by sys_timeout() + */ +typedef void (* sys_timeout_handler)(void *arg); + +struct sys_timeo { + struct sys_timeo *next; + u32_t time; + sys_timeout_handler h; + void *arg; +#if LWIP_DEBUG_TIMERNAMES + const char* handler_name; +#endif /* LWIP_DEBUG_TIMERNAMES */ +}; + +void sys_timeouts_init(void)ICACHE_FLASH_ATTR; + +#if LWIP_DEBUG_TIMERNAMES +void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)ICACHE_FLASH_ATTR; +#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler) +#else /* LWIP_DEBUG_TIMERNAMES */ +void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)ICACHE_FLASH_ATTR; +#endif /* LWIP_DEBUG_TIMERNAMES */ + +void sys_untimeout(sys_timeout_handler handler, void *arg)ICACHE_FLASH_ATTR; +#if NO_SYS +void sys_check_timeouts(void)ICACHE_FLASH_ATTR; +void sys_restart_timeouts(void)ICACHE_FLASH_ATTR; +#else /* NO_SYS */ +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); +#endif /* NO_SYS */ + + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_TIMERS */ +#endif /* __LWIP_TIMERS_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/udp.h b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/udp.h new file mode 100644 index 0000000..cb53d33 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/ESP8266WiFi/src/lwip/udp.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef __LWIP_UDP_H__ +#define __LWIP_UDP_H__ + +#include "lwip/opt.h" + +#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/pbuf.h" +#include "lwip/netif.h" +#include "lwip/ip_addr.h" +#include "lwip/ip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UDP_HLEN 8 + +/* Fields are (of course) in network byte order. */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +struct udp_hdr { + PACK_STRUCT_FIELD(u16_t src); + PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */ + PACK_STRUCT_FIELD(u16_t len); + PACK_STRUCT_FIELD(u16_t chksum); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +#define UDP_FLAGS_NOCHKSUM 0x01U +#define UDP_FLAGS_UDPLITE 0x02U +#define UDP_FLAGS_CONNECTED 0x04U +#define UDP_FLAGS_MULTICAST_LOOP 0x08U + +struct udp_pcb; + +/** Function prototype for udp pcb receive callback functions + * addr and port are in same byte order as in the pcb + * The callback is responsible for freeing the pbuf + * if it's not used any more. + * + * ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf + * makes 'addr' invalid, too. + * + * @param arg user supplied argument (udp_pcb.recv_arg) + * @param pcb the udp_pcb which received data + * @param p the packet buffer that was received + * @param addr the remote IP address from which the packet was received + * @param port the remote port from which the packet was received + */ +typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *addr, u16_t port); + + +struct udp_pcb { +/* Common members of all PCB types */ + IP_PCB; + +/* Protocol specific PCB members */ + + struct udp_pcb *next; + + u8_t flags; + /** ports are in host byte order */ + u16_t local_port, remote_port; + +#if LWIP_IGMP + /** outgoing network interface for multicast packets */ + ip_addr_t multicast_ip; +#endif /* LWIP_IGMP */ + +#if LWIP_UDPLITE + /** used for UDP_LITE only */ + u16_t chksum_len_rx, chksum_len_tx; +#endif /* LWIP_UDPLITE */ + + /** receive callback function */ + udp_recv_fn recv; + /** user-supplied argument for the recv callback */ + void *recv_arg; +}; +/* udp_pcbs export for exernal reference (e.g. SNMP agent) */ +extern struct udp_pcb *udp_pcbs; + +/* The following functions is the application layer interface to the + UDP code. */ +struct udp_pcb * udp_new (void)ICACHE_FLASH_ATTR; +void udp_remove (struct udp_pcb *pcb)ICACHE_FLASH_ATTR; +err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port)ICACHE_FLASH_ATTR; +err_t udp_connect (struct udp_pcb *pcb, ip_addr_t *ipaddr, + u16_t port)ICACHE_FLASH_ATTR; +void udp_disconnect (struct udp_pcb *pcb)ICACHE_FLASH_ATTR; +void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, + void *recv_arg)ICACHE_FLASH_ATTR; +err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif)ICACHE_FLASH_ATTR; +err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port)ICACHE_FLASH_ATTR; +err_t udp_send (struct udp_pcb *pcb, struct pbuf *p)ICACHE_FLASH_ATTR; + +#if LWIP_CHECKSUM_ON_COPY +err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + struct netif *netif, u8_t have_chksum, + u16_t chksum)ICACHE_FLASH_ATTR; +err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, + ip_addr_t *dst_ip, u16_t dst_port, + u8_t have_chksum, u16_t chksum)ICACHE_FLASH_ATTR; +err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p, + u8_t have_chksum, u16_t chksum)ICACHE_FLASH_ATTR; +#endif /* LWIP_CHECKSUM_ON_COPY */ + +#define udp_flags(pcb) ((pcb)->flags) +#define udp_setflags(pcb, f) ((pcb)->flags = (f)) + +/* The following functions are the lower layer interface to UDP. */ +void udp_input (struct pbuf *p, struct netif *inp)ICACHE_FLASH_ATTR; + +#define udp_init() /* Compatibility define, not init needed. */ + +#if UDP_DEBUG +void udp_debug_print(struct udp_hdr *udphdr)ICACHE_FLASH_ATTR; +#else +#define udp_debug_print(udphdr) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_UDP */ + +#endif /* __LWIP_UDP_H__ */ diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/README.adoc b/libraries/MySensors/drivers/ESP8266/Ethernet/README.adoc new file mode 100644 index 0000000..8f890f0 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/README.adoc @@ -0,0 +1,24 @@ += Ethernet Library for Arduino = + +With the Arduino Ethernet Shield, this library allows an Arduino board to connect to the internet. + +For more information about this library please visit us at +http://www.arduino.cc/en/Reference/Ethernet + +== License == + +Copyright (c) 2010 Arduino LLC. 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 diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino new file mode 100644 index 0000000..6fa2787 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -0,0 +1,108 @@ +/* + Advanced Chat Server + + A more advanced server that distributes any incoming messages + to all connected clients but the client the message comes from. + To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + redesigned to make use of operator== 25 Nov 2013 + by Norbert Truchsess + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +IPAddress ip(192,168,1, 177); +IPAddress gateway(192,168,1, 1); +IPAddress subnet(255, 255, 0, 0); + + +// telnet defaults to port 23 +EthernetServer server(23); + +EthernetClient clients[4]; + +void setup() { + // initialize the ethernet device + Ethernet.begin(mac, ip, gateway, subnet); + // start listening for clients + server.begin(); + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + Serial.print("Chat server address:"); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + // when the client sends the first byte, say hello: + if (client) { + + boolean newClient = true; + for (byte i=0;i<4;i++) { + //check whether this client refers to the same socket as one of the existing instances: + if (clients[i]==client) { + newClient = false; + break; + } + } + + if (newClient) { + //check which of the existing clients can be overridden: + for (byte i=0;i<4;i++) { + if (!clients[i] && clients[i]!=client) { + clients[i] = client; + // clead out the input buffer: + client.flush(); + Serial.println("We have a new client"); + client.print("Hello, client number: "); + client.print(i); + client.println(); + break; + } + } + } + + if (client.available() > 0) { + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to all other connected clients: + for (byte i=0;i<4;i++) { + if (clients[i] && (clients[i]!=client)) { + clients[i].write(thisChar); + } + } + // echo the bytes to the server as well: + Serial.write(thisChar); + } + } + for (byte i=0;i<4;i++) { + if (!(clients[i].connected())) { + // client.stop() invalidates the internal socket-descriptor, so next use of == will allways return false; + clients[i].stop(); + } + } +} diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino new file mode 100644 index 0000000..2c85ddd --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -0,0 +1,223 @@ +/* + SCP1000 Barometric Pressure Sensor Display + + Serves the output of a Barometric Pressure Sensor as a web page. + Uses the SPI library. For details on the sensor, see: + http://www.sparkfun.com/commerce/product_info.php?products_id=8161 + http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ + + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: + http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip + + Circuit: + SCP1000 sensor attached to pins 6,7, and 11 - 13: + DRDY: pin 6 + CSB: pin 7 + MOSI: pin 11 + MISO: pin 12 + SCK: pin 13 + + created 31 July 2010 + by Tom Igoe + */ + +#include +// the sensor communicates using SPI, so include the library: +#include + + +// assign a MAC address for the ethernet controller. +// fill in your address here: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +// assign an IP address for the controller: +IPAddress ip(192, 168, 1, 20); +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 255, 0); + + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +EthernetServer server(80); + + +//Sensor's memory register addresses: +const int PRESSURE = 0x1F; //3 most significant bits of pressure +const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure +const int TEMPERATURE = 0x21; //16 bit temperature reading + +// pins used for the connection with the sensor +// the others you need are controlled by the SPI library): +const int dataReadyPin = 6; +const int chipSelectPin = 7; + +float temperature = 0.0; +long pressure = 0; +long lastReadingTime = 0; + +void setup() { + // start the SPI library: + SPI.begin(); + + // start the Ethernet connection and the server: + Ethernet.begin(mac, ip); + server.begin(); + + // initalize the data ready and chip select pins: + pinMode(dataReadyPin, INPUT); + pinMode(chipSelectPin, OUTPUT); + + Serial.begin(9600); + + //Configure SCP1000 for low noise configuration: + writeRegister(0x02, 0x2D); + writeRegister(0x01, 0x03); + writeRegister(0x03, 0x02); + + // give the sensor and Ethernet shield time to set up: + delay(1000); + + //Set the sensor to high resolution mode tp start readings: + writeRegister(0x03, 0x0A); + +} + +void loop() { + // check for a reading no more than once a second. + if (millis() - lastReadingTime > 1000) { + // if there's a reading ready, read it: + // don't do anything until the data ready pin is high: + if (digitalRead(dataReadyPin) == HIGH) { + getData(); + // timestamp the last time you got a reading: + lastReadingTime = millis(); + } + } + + // listen for incoming Ethernet connections: + listenForEthernetClients(); +} + + +void getData() { + Serial.println("Getting reading"); + //Read the temperature data + int tempData = readRegister(0x21, 2); + + // convert the temperature to celsius and display it: + temperature = (float)tempData / 20.0; + + //Read the pressure data highest 3 bits: + byte pressureDataHigh = readRegister(0x1F, 1); + pressureDataHigh &= 0b00000111; //you only needs bits 2 to 0 + + //Read the pressure data lower 16 bits: + unsigned int pressureDataLow = readRegister(0x20, 2); + //combine the two parts into one 19-bit number: + pressure = ((pressureDataHigh << 16) | pressureDataLow) / 4; + + Serial.print("Temperature: "); + Serial.print(temperature); + Serial.println(" degrees C"); + Serial.print("Pressure: " + String(pressure)); + Serial.println(" Pa"); +} + +void listenForEthernetClients() { + // listen for incoming clients + EthernetClient client = server.available(); + if (client) { + Serial.println("Got a client"); + // an http request ends with a blank line + boolean currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + // if you've gotten to the end of the line (received a newline + // character) and the line is blank, the http request has ended, + // so you can send a reply + if (c == '\n' && currentLineIsBlank) { + // send a standard http response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + client.println(); + // print the current readings, in HTML format: + client.print("Temperature: "); + client.print(temperature); + client.print(" degrees C"); + client.println("
"); + client.print("Pressure: " + String(pressure)); + client.print(" Pa"); + client.println("
"); + break; + } + if (c == '\n') { + // you're starting a new line + currentLineIsBlank = true; + } + else if (c != '\r') { + // you've gotten a character on the current line + currentLineIsBlank = false; + } + } + } + // give the web browser time to receive the data + delay(1); + // close the connection: + client.stop(); + } +} + + +//Send a write command to SCP1000 +void writeRegister(byte registerName, byte registerValue) { + // SCP1000 expects the register name in the upper 6 bits + // of the byte: + registerName <<= 2; + // command (read or write) goes in the lower two bits: + registerName |= 0b00000010; //Write command + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + + SPI.transfer(registerName); //Send register location + SPI.transfer(registerValue); //Send value to record into register + + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); +} + + +//Read register from the SCP1000: +unsigned int readRegister(byte registerName, int numBytes) { + byte inByte = 0; // incoming from the SPI read + unsigned int result = 0; // result to return + + // SCP1000 expects the register name in the upper 6 bits + // of the byte: + registerName <<= 2; + // command (read or write) goes in the lower two bits: + registerName &= 0b11111100; //Read command + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + // send the device the register you want to read: + int command = SPI.transfer(registerName); + // send a value of 0 to read the first byte returned: + inByte = SPI.transfer(0x00); + + result = inByte; + // if there's more than one byte returned, + // shift the first byte then get the second byte: + if (numBytes > 1) { + result = inByte << 8; + inByte = SPI.transfer(0x00); + result = result | inByte; + } + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); + // return the result: + return(result); +} diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/ChatServer/ChatServer.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/ChatServer/ChatServer.ino new file mode 100644 index 0000000..927a60e --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/ChatServer/ChatServer.ino @@ -0,0 +1,80 @@ +/* + Chat Server + + A simple server that distributes any incoming messages to all + connected clients. To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 0, 0); + + +// telnet defaults to port 23 +EthernetServer server(23); +boolean alreadyConnected = false; // whether or not the client was connected previously + +void setup() { + // initialize the ethernet device + Ethernet.begin(mac, ip, gateway, subnet); + // start listening for clients + server.begin(); + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + Serial.print("Chat server address:"); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + // when the client sends the first byte, say hello: + if (client) { + if (!alreadyConnected) { + // clead out the input buffer: + client.flush(); + Serial.println("We have a new client"); + client.println("Hello, client!"); + alreadyConnected = true; + } + + if (client.available() > 0) { + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to the client: + server.write(thisChar); + // echo the bytes to the server as well: + Serial.write(thisChar); + } + } +} + + + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino new file mode 100644 index 0000000..a41b774 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -0,0 +1,60 @@ +/* + DHCP-based IP printer + + This sketch uses the DHCP extensions to the Ethernet library + to get an IP address via DHCP and print the address obtained. + using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 12 April 2011 + modified 9 Apr 2012 + by Tom Igoe + + */ + +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +byte mac[] = { + 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 +}; + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +EthernetClient client; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // this check is only needed on the Leonardo: + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // start the Ethernet connection: + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // no point in carrying on, so do nothing forevermore: + for (;;) + ; + } + // print your local IP address: + Serial.print("My IP address: "); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + // print the value of each byte of the IP address: + Serial.print(Ethernet.localIP()[thisByte], DEC); + Serial.print("."); + } + Serial.println(); +} + +void loop() { + +} + + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino new file mode 100644 index 0000000..73cde4b --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/DhcpChatServer/DhcpChatServer.ino @@ -0,0 +1,88 @@ +/* + DHCP Chat Server + + A simple server that distributes any incoming messages to all + connected clients. To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + THis version attempts to get an IP address using DHCP + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 21 May 2011 + modified 9 Apr 2012 + by Tom Igoe + Based on ChatServer example by David A. Mellis + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +byte mac[] = { + 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 +}; +IPAddress ip(192, 168, 1, 177); +IPAddress gateway(192, 168, 1, 1); +IPAddress subnet(255, 255, 0, 0); + +// telnet defaults to port 23 +EthernetServer server(23); +boolean gotAMessage = false; // whether or not you got a message from the client yet + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // this check is only needed on the Leonardo: + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // start the Ethernet connection: + Serial.println("Trying to get an IP address using DHCP"); + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // initialize the ethernet device not using DHCP: + Ethernet.begin(mac, ip, gateway, subnet); + } + // print your local IP address: + Serial.print("My IP address: "); + ip = Ethernet.localIP(); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + // print the value of each byte of the IP address: + Serial.print(ip[thisByte], DEC); + Serial.print("."); + } + Serial.println(); + // start listening for clients + server.begin(); + +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + // when the client sends the first byte, say hello: + if (client) { + if (!gotAMessage) { + Serial.println("We have a new client"); + client.println("Hello, client!"); + gotAMessage = true; + } + + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to the client: + server.write(thisChar); + // echo the bytes to the server as well: + Serial.print(thisChar); + } +} + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/TelnetClient/TelnetClient.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/TelnetClient/TelnetClient.ino new file mode 100644 index 0000000..dcf3e8a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/TelnetClient/TelnetClient.ino @@ -0,0 +1,94 @@ +/* + Telnet client + + This sketch connects to a a telnet server (http://www.google.com) + using an Arduino Wiznet Ethernet shield. You'll need a telnet server + to test this with. + Processing's ChatServer example (part of the network library) works well, + running on port 10002. It can be found as part of the examples + in the Processing application, available at + http://processing.org/ + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 14 Sep 2010 + modified 9 Apr 2012 + by Tom Igoe + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); + +// Enter the IP address of the server you're connecting to: +IPAddress server(1, 1, 1, 1); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 23 is default for telnet; +// if you're using Processing's ChatServer, use port 10002): +EthernetClient client; + +void setup() { + // start the Ethernet connection: + Ethernet.begin(mac, ip); + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.println("connecting..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 10002)) { + Serial.println("connected"); + } + else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } +} + +void loop() +{ + // if there are incoming bytes available + // from the server, read them and print them: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // as long as there are bytes in the serial queue, + // read them and send them out the socket if it's open: + while (Serial.available() > 0) { + char inChar = Serial.read(); + if (client.connected()) { + client.print(inChar); + } + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + // do nothing: + while (true); + } +} + + + + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino new file mode 100644 index 0000000..99de765 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/UDPSendReceiveString/UDPSendReceiveString.ino @@ -0,0 +1,119 @@ +/* + UDPSendReceive.pde: + This sketch receives UDP message strings, prints them to the serial port + and sends an "acknowledge" string back to the sender + + A Processing sketch is included at the end of file that can be used to send + and received messages for testing with a computer. + + created 21 Aug 2010 + by Michael Margolis + + This code is in the public domain. + */ + + +#include // needed for Arduino versions later than 0018 +#include +#include // UDP library from: bjoern@cs.stanford.edu 12/30/2008 + + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); + +unsigned int localPort = 8888; // local port to listen on + +// buffers for receiving and sending data +char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet, +char ReplyBuffer[] = "acknowledged"; // a string to send back + +// An EthernetUDP instance to let us send and receive packets over UDP +EthernetUDP Udp; + +void setup() { + // start the Ethernet and UDP: + Ethernet.begin(mac, ip); + Udp.begin(localPort); + + Serial.begin(9600); +} + +void loop() { + // if there's data available, read a packet + int packetSize = Udp.parsePacket(); + if (packetSize) + { + Serial.print("Received packet of size "); + Serial.println(packetSize); + Serial.print("From "); + IPAddress remote = Udp.remoteIP(); + for (int i = 0; i < 4; i++) + { + Serial.print(remote[i], DEC); + if (i < 3) + { + Serial.print("."); + } + } + Serial.print(", port "); + Serial.println(Udp.remotePort()); + + // read the packet into packetBufffer + Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); + Serial.println("Contents:"); + Serial.println(packetBuffer); + + // send a reply, to the IP address and port that sent us the packet we received + Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); + Udp.write(ReplyBuffer); + Udp.endPacket(); + } + delay(10); +} + + +/* + Processing sketch to run with this example + ===================================================== + + // Processing UDP example to send and receive string data from Arduino + // press any key to send the "Hello Arduino" message + + + import hypermedia.net.*; + + UDP udp; // define the UDP object + + + void setup() { + udp = new UDP( this, 6000 ); // create a new datagram connection on port 6000 + //udp.log( true ); // <-- printout the connection activity + udp.listen( true ); // and wait for incoming message + } + + void draw() + { + } + + void keyPressed() { + String ip = "192.168.1.177"; // the remote IP address + int port = 8888; // the destination port + + udp.send("Hello World", ip, port ); // the message to send + + } + + void receive( byte[] data ) { // <-- default handler + //void receive( byte[] data, String ip, int port ) { // <-- extended handler + + for(int i=0; i < data.length; i++) + print(char(data[i])); + println(); + } + */ + + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino new file mode 100644 index 0000000..25c71c4 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/UdpNtpClient/UdpNtpClient.ino @@ -0,0 +1,142 @@ +/* + + Udp NTP Client + + Get the time from a Network Time Protocol (NTP) time server + Demonstrates use of UDP sendPacket and ReceivePacket + For more on NTP time servers and the messages needed to communicate with them, + see http://en.wikipedia.org/wiki/Network_Time_Protocol + + created 4 Sep 2010 + by Michael Margolis + modified 9 Apr 2012 + by Tom Igoe + + This code is in the public domain. + + */ + +#include +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; + +unsigned int localPort = 8888; // local port to listen for UDP packets + +char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server + +const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message + +byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets + +// A UDP instance to let us send and receive packets over UDP +EthernetUDP Udp; + +void setup() +{ + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // start Ethernet and UDP + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // no point in carrying on, so do nothing forevermore: + for (;;) + ; + } + Udp.begin(localPort); +} + +void loop() +{ + sendNTPpacket(timeServer); // send an NTP packet to a time server + + // wait to see if a reply is available + delay(1000); + if ( Udp.parsePacket() ) { + // We've received a packet, read the data from it + Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer + + //the timestamp starts at byte 40 of the received packet and is four bytes, + // or two words, long. First, esxtract the two words: + + unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); + unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); + // combine the four bytes (two words) into a long integer + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = highWord << 16 | lowWord; + Serial.print("Seconds since Jan 1 1900 = " ); + Serial.println(secsSince1900); + + // now convert NTP time into everyday time: + Serial.print("Unix time = "); + // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: + const unsigned long seventyYears = 2208988800UL; + // subtract seventy years: + unsigned long epoch = secsSince1900 - seventyYears; + // print Unix time: + Serial.println(epoch); + + + // print the hour, minute and second: + Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) + Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) + Serial.print(':'); + if ( ((epoch % 3600) / 60) < 10 ) { + // In the first 10 minutes of each hour, we'll want a leading '0' + Serial.print('0'); + } + Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) + Serial.print(':'); + if ( (epoch % 60) < 10 ) { + // In the first 10 seconds of each minute, we'll want a leading '0' + Serial.print('0'); + } + Serial.println(epoch % 60); // print the second + } + // wait ten seconds before asking for the time again + delay(10000); +} + +// send an NTP request to the time server at the given address +unsigned long sendNTPpacket(char* address) +{ + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + Udp.beginPacket(address, 123); //NTP requests are to port 123 + Udp.write(packetBuffer, NTP_PACKET_SIZE); + Udp.endPacket(); +} + + + + + + + + + + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClient/WebClient.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClient/WebClient.ino new file mode 100644 index 0000000..9afd40e --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClient/WebClient.ino @@ -0,0 +1,88 @@ +/* + Web client + + This sketch connects to a website (http://www.google.com) + using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe, based on work by Adrian McEwen + + */ + +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) +char server[] = "www.google.com"; // name address for Google (using DNS) + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 0, 177); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +EthernetClient client; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // start the Ethernet connection: + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // no point in carrying on, so do nothing forevermore: + // try to congifure using IP address instead of DHCP: + Ethernet.begin(mac, ip); + } + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.println("connecting..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 80)) { + Serial.println("connected"); + // Make a HTTP request: + client.println("GET /search?q=arduino HTTP/1.1"); + client.println("Host: www.google.com"); + client.println("Connection: close"); + client.println(); + } + else { + // kf you didn't get a connection to the server: + Serial.println("connection failed"); + } +} + +void loop() +{ + // if there are incoming bytes available + // from the server, read them and print them: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + + // do nothing forevermore: + while (true); + } +} + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino new file mode 100644 index 0000000..ad3f461 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebClientRepeating/WebClientRepeating.ino @@ -0,0 +1,108 @@ +/* + Repeating Web client + + This sketch connects to a a web server and makes a request + using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or + the Adafruit Ethernet shield, either one will work, as long as it's got + a Wiznet Ethernet module on board. + + This example uses DNS, by assigning the Ethernet client with a MAC address, + IP address, and DNS address. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 19 Apr 2012 + by Tom Igoe + modified 21 Jan 2014 + by Federico Vanzati + + http://www.arduino.cc/en/Tutorial/WebClientRepeating + This code is in the public domain. + + */ + +#include +#include + +// assign a MAC address for the ethernet controller. +// fill in your address here: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +// fill in an available IP address on your network here, +// for manual configuration: +IPAddress ip(192, 168, 1, 177); + +// fill in your Domain Name Server address here: +IPAddress myDns(1, 1, 1, 1); + +// initialize the library instance: +EthernetClient client; + +char server[] = "www.arduino.cc"; +//IPAddress server(64,131,82,241); + +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +const unsigned long postingInterval = 10L * 1000L; // delay between updates, in milliseconds +// the "L" is needed to use long type numbers + +void setup() { + // start serial port: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // give the ethernet module time to boot up: + delay(1000); + // start the Ethernet connection using a fixed IP address and DNS server: + Ethernet.begin(mac, ip, myDns); + // print the Ethernet board/shield's IP address: + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // if there's incoming data from the net connection. + // send it out the serial port. This is for debugging + // purposes only: + if (client.available()) { + char c = client.read(); + Serial.write(c); + } + + // if ten seconds have passed since your last connection, + // then connect again and send data: + if (millis() - lastConnectionTime > postingInterval) { + httpRequest(); + } + +} + +// this method makes a HTTP connection to the server: +void httpRequest() { + // close any connection before send a new request. + // This will free the socket on the WiFi shield + client.stop(); + + // if there's a successful connection: + if (client.connect(server, 80)) { + Serial.println("connecting..."); + // send the HTTP PUT request: + client.println("GET /latest.txt HTTP/1.1"); + client.println("Host: www.arduino.cc"); + client.println("User-Agent: arduino-ethernet"); + client.println("Connection: close"); + client.println(); + + // note the time that the connection was made: + lastConnectionTime = millis(); + } + else { + // if you couldn't make a connection: + Serial.println("connection failed"); + } +} + + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebServer/WebServer.ino b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebServer/WebServer.ino new file mode 100644 index 0000000..d0c585d --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/examples/WebServer/WebServer.ino @@ -0,0 +1,101 @@ +/* + Web Server + + A simple web server that shows the value of the analog input pins. + using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; +IPAddress ip(192, 168, 1, 177); + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +EthernetServer server(80); + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // start the Ethernet connection and the server: + Ethernet.begin(mac, ip); + server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); +} + + +void loop() { + // listen for incoming clients + EthernetClient client = server.available(); + if (client) { + Serial.println("new client"); + // an http request ends with a blank line + boolean currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + Serial.write(c); + // if you've gotten to the end of the line (received a newline + // character) and the line is blank, the http request has ended, + // so you can send a reply + if (c == '\n' && currentLineIsBlank) { + // send a standard http response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + client.println("Connection: close"); // the connection will be closed after completion of the response + client.println("Refresh: 5"); // refresh the page automatically every 5 sec + client.println(); + client.println(""); + client.println(""); + // output the value of each analog input pin + for (int analogChannel = 0; analogChannel < 6; analogChannel++) { + int sensorReading = analogRead(analogChannel); + client.print("analog input "); + client.print(analogChannel); + client.print(" is "); + client.print(sensorReading); + client.println("
"); + } + client.println(""); + break; + } + if (c == '\n') { + // you're starting a new line + currentLineIsBlank = true; + } + else if (c != '\r') { + // you've gotten a character on the current line + currentLineIsBlank = false; + } + } + } + // give the web browser time to receive the data + delay(1); + // close the connection: + client.stop(); + Serial.println("client disconnected"); + } +} + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/keywords.txt b/libraries/MySensors/drivers/ESP8266/Ethernet/keywords.txt new file mode 100644 index 0000000..7b162a5 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/keywords.txt @@ -0,0 +1,37 @@ +####################################### +# Syntax Coloring Map For Ethernet +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Ethernet KEYWORD1 Ethernet +EthernetClient KEYWORD1 EthernetClient +EthernetServer KEYWORD1 EthernetServer +IPAddress KEYWORD1 EthernetIPAddress + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +status KEYWORD2 +connect KEYWORD2 +write KEYWORD2 +available KEYWORD2 +read KEYWORD2 +peek KEYWORD2 +flush KEYWORD2 +stop KEYWORD2 +connected KEYWORD2 +begin KEYWORD2 +beginPacket KEYWORD2 +endPacket KEYWORD2 +parsePacket KEYWORD2 +remoteIP KEYWORD2 +remotePort KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/library.properties b/libraries/MySensors/drivers/ESP8266/Ethernet/library.properties new file mode 100644 index 0000000..8fdc11d --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/library.properties @@ -0,0 +1,9 @@ +name=Ethernet +version=1.0.4 +author=Arduino +maintainer=Arduino +sentence=Enables network connection (local and Internet) using the Arduino Ethernet board or shield. For all Arduino boards. +paragraph=With this library you can use the Arduino Ethernet (shield or board) to connect to Internet. The library provides both Client and server functionalities. The library permits you to connect to a local network also with DHCP and to resolve DNS. +category=Communication +url=http://www.arduino.cc/en/Reference/Ethernet +architectures=* diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.cpp new file mode 100644 index 0000000..4402bad --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.cpp @@ -0,0 +1,481 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#include "utility/w5100.h" + +#include +#include +#include "Dhcp.h" +#include "Arduino.h" +#include "utility/util.h" + +int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) +{ + _dhcpLeaseTime=0; + _dhcpT1=0; + _dhcpT2=0; + _lastCheck=0; + _timeout = timeout; + _responseTimeout = responseTimeout; + + // zero out _dhcpMacAddr + memset(_dhcpMacAddr, 0, 6); + reset_DHCP_lease(); + + memcpy((void*)_dhcpMacAddr, (void*)mac, 6); + _dhcp_state = STATE_DHCP_START; + return request_DHCP_lease(); +} + +void DhcpClass::reset_DHCP_lease(){ + // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp + memset(_dhcpLocalIp, 0, 20); +} + +//return:0 on error, 1 if request is sent and response is received +int DhcpClass::request_DHCP_lease(){ + + uint8_t messageType = 0; + + + + // Pick an initial transaction ID + _dhcpTransactionId = random(1UL, 2000UL); + _dhcpInitialTransactionId = _dhcpTransactionId; + + _dhcpUdpSocket.stop(); + if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) + { + // Couldn't get a socket + return 0; + } + + presend_DHCP(); + + int result = 0; + + unsigned long startTime = millis(); + + while(_dhcp_state != STATE_DHCP_LEASED) + { + if(_dhcp_state == STATE_DHCP_START) + { + _dhcpTransactionId++; + + send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_DISCOVER; + } + else if(_dhcp_state == STATE_DHCP_REREQUEST){ + _dhcpTransactionId++; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + else if(_dhcp_state == STATE_DHCP_DISCOVER) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_OFFER) + { + // We'll use the transaction ID that the offer came with, + // rather than the one we were up to + _dhcpTransactionId = respId; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + } + else if(_dhcp_state == STATE_DHCP_REQUEST) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_ACK) + { + _dhcp_state = STATE_DHCP_LEASED; + result = 1; + //use default lease time if we didn't get it + if(_dhcpLeaseTime == 0){ + _dhcpLeaseTime = DEFAULT_LEASE; + } + //calculate T1 & T2 if we didn't get it + if(_dhcpT1 == 0){ + //T1 should be 50% of _dhcpLeaseTime + _dhcpT1 = _dhcpLeaseTime >> 1; + } + if(_dhcpT2 == 0){ + //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime + _dhcpT2 = _dhcpT1 << 1; + } + _renewInSec = _dhcpT1; + _rebindInSec = _dhcpT2; + } + else if(messageType == DHCP_NAK) + _dhcp_state = STATE_DHCP_START; + } + + if(messageType == 255) + { + messageType = 0; + _dhcp_state = STATE_DHCP_START; + } + + if(result != 1 && ((millis() - startTime) > _timeout)) + break; + } + + // We're done with the socket now + _dhcpUdpSocket.stop(); + _dhcpTransactionId++; + + return result; +} + +void DhcpClass::presend_DHCP() +{ +} + +void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) +{ + uint8_t buffer[32]; + memset(buffer, 0, 32); + IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address + + if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) + { + // FIXME Need to return errors + return; + } + + buffer[0] = DHCP_BOOTREQUEST; // op + buffer[1] = DHCP_HTYPE10MB; // htype + buffer[2] = DHCP_HLENETHERNET; // hlen + buffer[3] = DHCP_HOPS; // hops + + // xid + unsigned long xid = htonl(_dhcpTransactionId); + memcpy(buffer + 4, &(xid), 4); + + // 8, 9 - seconds elapsed + buffer[8] = ((secondsElapsed & 0xff00) >> 8); + buffer[9] = (secondsElapsed & 0x00ff); + + // flags + unsigned short flags = htons(DHCP_FLAGSBROADCAST); + memcpy(buffer + 10, &(flags), 2); + + // ciaddr: already zeroed + // yiaddr: already zeroed + // siaddr: already zeroed + // giaddr: already zeroed + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 28); + + memset(buffer, 0, 32); // clear local buffer + + memcpy(buffer, _dhcpMacAddr, 6); // chaddr + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 16); + + memset(buffer, 0, 32); // clear local buffer + + // leave zeroed out for sname && file + // put in W5100 transmit buffer x 6 (192 bytes) + + for(int i = 0; i < 6; i++) { + _dhcpUdpSocket.write(buffer, 32); + } + + // OPT - Magic Cookie + buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); + buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); + buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); + buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); + + // OPT - message type + buffer[4] = dhcpMessageType; + buffer[5] = 0x01; + buffer[6] = messageType; //DHCP_REQUEST; + + // OPT - client identifier + buffer[7] = dhcpClientIdentifier; + buffer[8] = 0x07; + buffer[9] = 0x01; + memcpy(buffer + 10, _dhcpMacAddr, 6); + + // OPT - host name + buffer[16] = hostName; + buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address + strcpy((char*)&(buffer[18]), HOST_NAME); + + printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); + printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); + printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 30); + + if(messageType == DHCP_REQUEST) + { + buffer[0] = dhcpRequestedIPaddr; + buffer[1] = 0x04; + buffer[2] = _dhcpLocalIp[0]; + buffer[3] = _dhcpLocalIp[1]; + buffer[4] = _dhcpLocalIp[2]; + buffer[5] = _dhcpLocalIp[3]; + + buffer[6] = dhcpServerIdentifier; + buffer[7] = 0x04; + buffer[8] = _dhcpDhcpServerIp[0]; + buffer[9] = _dhcpDhcpServerIp[1]; + buffer[10] = _dhcpDhcpServerIp[2]; + buffer[11] = _dhcpDhcpServerIp[3]; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 12); + } + + buffer[0] = dhcpParamRequest; + buffer[1] = 0x06; + buffer[2] = subnetMask; + buffer[3] = routersOnSubnet; + buffer[4] = dns; + buffer[5] = domainName; + buffer[6] = dhcpT1value; + buffer[7] = dhcpT2value; + buffer[8] = endOption; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 9); + + _dhcpUdpSocket.endPacket(); +} + +uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) +{ + uint8_t type = 0; + uint8_t opt_len = 0; + + unsigned long startTime = millis(); + + while(_dhcpUdpSocket.parsePacket() <= 0) + { + if((millis() - startTime) > responseTimeout) + { + return 255; + } + delay(50); + } + // start reading in the packet + RIP_MSG_FIXED fixedMsg; + _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); + + if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) + { + transactionId = ntohl(fixedMsg.xid); + if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) + { + // Need to read the rest of the packet here regardless + _dhcpUdpSocket.flush(); + return 0; + } + + memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); + + // Skip to the option part + // Doing this a byte at a time so we don't have to put a big buffer + // on the stack (as we don't have lots of memory lying around) + for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) + { + _dhcpUdpSocket.read(); // we don't care about the returned byte + } + + while (_dhcpUdpSocket.available() > 0) + { + switch (_dhcpUdpSocket.read()) + { + case endOption : + break; + + case padOption : + break; + + case dhcpMessageType : + opt_len = _dhcpUdpSocket.read(); + type = _dhcpUdpSocket.read(); + break; + + case subnetMask : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpSubnetMask, 4); + break; + + case routersOnSubnet : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpGatewayIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dns : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpDnsServerIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dhcpServerIdentifier : + opt_len = _dhcpUdpSocket.read(); + if ((_dhcpDhcpServerIp[0] == 0 && _dhcpDhcpServerIp[1] == 0 && + _dhcpDhcpServerIp[2] == 0 && _dhcpDhcpServerIp[3] == 0) || + IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP()) + { + _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); + } + else + { + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + } + break; + + case dhcpT1value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); + _dhcpT1 = ntohl(_dhcpT1); + break; + + case dhcpT2value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); + _dhcpT2 = ntohl(_dhcpT2); + break; + + case dhcpIPaddrLeaseTime : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); + _dhcpLeaseTime = ntohl(_dhcpLeaseTime); + _renewInSec = _dhcpLeaseTime; + break; + + default : + opt_len = _dhcpUdpSocket.read(); + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + break; + } + } + } + + // Need to skip to end of the packet regardless here + _dhcpUdpSocket.flush(); + + return type; +} + + +/* + returns: + 0/DHCP_CHECK_NONE: nothing happened + 1/DHCP_CHECK_RENEW_FAIL: renew failed + 2/DHCP_CHECK_RENEW_OK: renew success + 3/DHCP_CHECK_REBIND_FAIL: rebind fail + 4/DHCP_CHECK_REBIND_OK: rebind success +*/ +int DhcpClass::checkLease(){ + //this uses a signed / unsigned trick to deal with millis overflow + unsigned long now = millis(); + signed long snow = (long)now; + int rc=DHCP_CHECK_NONE; + if (_lastCheck != 0){ + signed long factor; + //calc how many ms past the timeout we are + factor = snow - (long)_secTimeout; + //if on or passed the timeout, reduce the counters + if ( factor >= 0 ){ + //next timeout should be now plus 1000 ms minus parts of second in factor + _secTimeout = snow + 1000 - factor % 1000; + //how many seconds late are we, minimum 1 + factor = factor / 1000 +1; + + //reduce the counters by that mouch + //if we can assume that the cycle time (factor) is fairly constant + //and if the remainder is less than cycle time * 2 + //do it early instead of late + if(_renewInSec < factor*2 ) + _renewInSec = 0; + else + _renewInSec -= factor; + + if(_rebindInSec < factor*2 ) + _rebindInSec = 0; + else + _rebindInSec -= factor; + } + + //if we have a lease but should renew, do it + if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ + _dhcp_state = STATE_DHCP_REREQUEST; + rc = 1 + request_DHCP_lease(); + } + + //if we have a lease or is renewing but should bind, do it + if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ + //this should basically restart completely + _dhcp_state = STATE_DHCP_START; + reset_DHCP_lease(); + rc = 3 + request_DHCP_lease(); + } + } + else{ + _secTimeout = snow + 1000; + } + + _lastCheck = now; + return rc; +} + +IPAddress DhcpClass::getLocalIp() +{ + return IPAddress(_dhcpLocalIp); +} + +IPAddress DhcpClass::getSubnetMask() +{ + return IPAddress(_dhcpSubnetMask); +} + +IPAddress DhcpClass::getGatewayIp() +{ + return IPAddress(_dhcpGatewayIp); +} + +IPAddress DhcpClass::getDhcpServerIp() +{ + return IPAddress(_dhcpDhcpServerIp); +} + +IPAddress DhcpClass::getDnsServerIp() +{ + return IPAddress(_dhcpDnsServerIp); +} + +void DhcpClass::printByte(char * buf, uint8_t n ) { + char *str = &buf[1]; + buf[0]='0'; + do { + unsigned long m = n; + n /= 16; + char c = m - 16 * n; + *str-- = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); +} diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.h new file mode 100644 index 0000000..f59c7e7 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dhcp.h @@ -0,0 +1,178 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#ifndef Dhcp_h +#define Dhcp_h + +#include "EthernetUdp.h" + +/* DHCP state machine. */ +#define STATE_DHCP_START 0 +#define STATE_DHCP_DISCOVER 1 +#define STATE_DHCP_REQUEST 2 +#define STATE_DHCP_LEASED 3 +#define STATE_DHCP_REREQUEST 4 +#define STATE_DHCP_RELEASE 5 + +#define DHCP_FLAGSBROADCAST 0x8000 + +/* UDP port numbers for DHCP */ +#define DHCP_SERVER_PORT 67 /* from server to client */ +#define DHCP_CLIENT_PORT 68 /* from client to server */ + +/* DHCP message OP code */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_HTYPE10MB 1 +#define DHCP_HTYPE100MB 2 + +#define DHCP_HLENETHERNET 6 +#define DHCP_HOPS 0 +#define DHCP_SECS 0 + +#define MAGIC_COOKIE 0x63825363 +#define MAX_DHCP_OPT 16 + +#define HOST_NAME "WIZnet" +#define DEFAULT_LEASE (900) //default lease time in seconds + +#define DHCP_CHECK_NONE (0) +#define DHCP_CHECK_RENEW_FAIL (1) +#define DHCP_CHECK_RENEW_OK (2) +#define DHCP_CHECK_REBIND_FAIL (3) +#define DHCP_CHECK_REBIND_OK (4) + +enum +{ + padOption = 0, + subnetMask = 1, + timerOffset = 2, + routersOnSubnet = 3, + /* timeServer = 4, + nameServer = 5,*/ + dns = 6, + /*logServer = 7, + cookieServer = 8, + lprServer = 9, + impressServer = 10, + resourceLocationServer = 11,*/ + hostName = 12, + /*bootFileSize = 13, + meritDumpFile = 14,*/ + domainName = 15, + /*swapServer = 16, + rootPath = 17, + extentionsPath = 18, + IPforwarding = 19, + nonLocalSourceRouting = 20, + policyFilter = 21, + maxDgramReasmSize = 22, + defaultIPTTL = 23, + pathMTUagingTimeout = 24, + pathMTUplateauTable = 25, + ifMTU = 26, + allSubnetsLocal = 27, + broadcastAddr = 28, + performMaskDiscovery = 29, + maskSupplier = 30, + performRouterDiscovery = 31, + routerSolicitationAddr = 32, + staticRoute = 33, + trailerEncapsulation = 34, + arpCacheTimeout = 35, + ethernetEncapsulation = 36, + tcpDefaultTTL = 37, + tcpKeepaliveInterval = 38, + tcpKeepaliveGarbage = 39, + nisDomainName = 40, + nisServers = 41, + ntpServers = 42, + vendorSpecificInfo = 43, + netBIOSnameServer = 44, + netBIOSdgramDistServer = 45, + netBIOSnodeType = 46, + netBIOSscope = 47, + xFontServer = 48, + xDisplayManager = 49,*/ + dhcpRequestedIPaddr = 50, + dhcpIPaddrLeaseTime = 51, + /*dhcpOptionOverload = 52,*/ + dhcpMessageType = 53, + dhcpServerIdentifier = 54, + dhcpParamRequest = 55, + /*dhcpMsg = 56, + dhcpMaxMsgSize = 57,*/ + dhcpT1value = 58, + dhcpT2value = 59, + /*dhcpClassIdentifier = 60,*/ + dhcpClientIdentifier = 61, + endOption = 255 +}; + +typedef struct __attribute__((packed)) _RIP_MSG_FIXED +{ + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint8_t ciaddr[4]; + uint8_t yiaddr[4]; + uint8_t siaddr[4]; + uint8_t giaddr[4]; + uint8_t chaddr[6]; +}RIP_MSG_FIXED; + +class DhcpClass { +private: + uint32_t _dhcpInitialTransactionId; + uint32_t _dhcpTransactionId; + uint8_t _dhcpMacAddr[6]; + uint8_t _dhcpLocalIp[4]; + uint8_t _dhcpSubnetMask[4]; + uint8_t _dhcpGatewayIp[4]; + uint8_t _dhcpDhcpServerIp[4]; + uint8_t _dhcpDnsServerIp[4]; + uint32_t _dhcpLeaseTime; + uint32_t _dhcpT1, _dhcpT2; + signed long _renewInSec; + signed long _rebindInSec; + signed long _lastCheck; + unsigned long _timeout; + unsigned long _responseTimeout; + unsigned long _secTimeout; + uint8_t _dhcp_state; + EthernetUDP _dhcpUdpSocket; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + void presend_DHCP(); + void send_DHCP_MESSAGE(uint8_t, uint16_t); + void printByte(char *, uint8_t); + + uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); +public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); +}; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.cpp new file mode 100644 index 0000000..62e36f8 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.cpp @@ -0,0 +1,423 @@ +// Arduino DNS client for WizNet5100-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#include "utility/w5100.h" +#include "EthernetUdp.h" +#include "utility/util.h" + +#include "Dns.h" +#include +//#include +#include "Arduino.h" + + +#define SOCKET_NONE 255 +// Various flags and header field values for a DNS message +#define UDP_HEADER_SIZE 8 +#define DNS_HEADER_SIZE 12 +#define TTL_SIZE 4 +#define QUERY_FLAG (0) +#define RESPONSE_FLAG (1<<15) +#define QUERY_RESPONSE_MASK (1<<15) +#define OPCODE_STANDARD_QUERY (0) +#define OPCODE_INVERSE_QUERY (1<<11) +#define OPCODE_STATUS_REQUEST (2<<11) +#define OPCODE_MASK (15<<11) +#define AUTHORITATIVE_FLAG (1<<10) +#define TRUNCATION_FLAG (1<<9) +#define RECURSION_DESIRED_FLAG (1<<8) +#define RECURSION_AVAILABLE_FLAG (1<<7) +#define RESP_NO_ERROR (0) +#define RESP_FORMAT_ERROR (1) +#define RESP_SERVER_FAILURE (2) +#define RESP_NAME_ERROR (3) +#define RESP_NOT_IMPLEMENTED (4) +#define RESP_REFUSED (5) +#define RESP_MASK (15) +#define TYPE_A (0x0001) +#define CLASS_IN (0x0001) +#define LABEL_COMPRESSION_MASK (0xC0) +// Port number that DNS servers listen on +#define DNS_PORT 53 + +// Possible return codes from ProcessResponse +#define SUCCESS 1 +#define TIMED_OUT -1 +#define INVALID_SERVER -2 +#define TRUNCATED -3 +#define INVALID_RESPONSE -4 + +void DNSClient::begin(const IPAddress& aDNSServer) +{ + iDNSServer = aDNSServer; + iRequestId = 0; +} + + +int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult) +{ + // See if we've been given a valid IP address + const char* p =aIPAddrString; + while (*p && + ( (*p == '.') || (*p >= '0') || (*p <= '9') )) + { + p++; + } + + if (*p == '\0') + { + // It's looking promising, we haven't found any invalid characters + p = aIPAddrString; + int segment =0; + int segmentValue =0; + while (*p && (segment < 4)) + { + if (*p == '.') + { + // We've reached the end of a segment + if (segmentValue > 255) + { + // You can't have IP address segments that don't fit in a byte + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + segment++; + segmentValue = 0; + } + } + else + { + // Next digit + segmentValue = (segmentValue*10)+(*p - '0'); + } + p++; + } + // We've reached the end of address, but there'll still be the last + // segment to deal with + if ((segmentValue > 255) || (segment > 3)) + { + // You can't have IP address segments that don't fit in a byte, + // or more than four segments + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + return 1; + } + } + else + { + return 0; + } +} + +int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) +{ + int ret =0; + + // See if it's a numeric IP address + if (inet_aton(aHostname, aResult)) + { + // It is, our work here is done + return 1; + } + + // Check we've got a valid DNS server to use + if (iDNSServer == INADDR_NONE) + { + return INVALID_SERVER; + } + + // Find a socket to use + if (iUdp.begin(1024+(millis() & 0xF)) == 1) + { + // Try up to three times + int retries = 0; +// while ((retries < 3) && (ret <= 0)) + { + // Send DNS request + ret = iUdp.beginPacket(iDNSServer, DNS_PORT); + if (ret != 0) + { + // Now output the request data + ret = BuildRequest(aHostname); + if (ret != 0) + { + // And finally send the request + ret = iUdp.endPacket(); + if (ret != 0) + { + // Now wait for a response + int wait_retries = 0; + ret = TIMED_OUT; + while ((wait_retries < 3) && (ret == TIMED_OUT)) + { + ret = ProcessResponse(5000, aResult); + wait_retries++; + } + } + } + } + retries++; + } + + // We're done with the socket now + iUdp.stop(); + } + + return ret; +} + +uint16_t DNSClient::BuildRequest(const char* aName) +{ + // Build header + // 1 1 1 1 1 1 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ID | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | QDCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ANCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | NSCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ARCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // As we only support one request at a time at present, we can simplify + // some of this header + iRequestId = millis(); // generate a random ID + uint16_t twoByteBuffer; + + // FIXME We should also check that there's enough space available to write to, rather + // FIXME than assume there's enough space (as the code does at present) + iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId)); + + twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(1); // One question record + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = 0; // Zero answer records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // and zero additional records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + // Build question + const char* start =aName; + const char* end =start; + uint8_t len; + // Run through the name being requested + while (*end) + { + // Find out how long this section of the name is + end = start; + while (*end && (*end != '.') ) + { + end++; + } + + if (end-start > 0) + { + // Write out the size of this section + len = end-start; + iUdp.write(&len, sizeof(len)); + // And then write out the section + iUdp.write((uint8_t*)start, end-start); + } + start = end+1; + } + + // We've got to the end of the question name, so + // terminate it with a zero-length section + len = 0; + iUdp.write(&len, sizeof(len)); + // Finally the type and class of question + twoByteBuffer = htons(TYPE_A); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(CLASS_IN); // Internet class of question + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // Success! Everything buffered okay + return 1; +} + + +uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) +{ + uint32_t startTime = millis(); + + // Wait for a response packet + while(iUdp.parsePacket() <= 0) + { + if((millis() - startTime) > aTimeout) + return TIMED_OUT; + delay(50); + } + + // We've had a reply! + // Read the UDP header + uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header + // Check that it's a response from the right server and the right port + if ( (iDNSServer != iUdp.remoteIP()) || + (iUdp.remotePort() != DNS_PORT) ) + { + // It's not from who we expected + return INVALID_SERVER; + } + + // Read through the rest of the response + if (iUdp.available() < DNS_HEADER_SIZE) + { + return TRUNCATED; + } + iUdp.read(header, DNS_HEADER_SIZE); + + uint16_t header_flags = htons(*((uint16_t*)&header[2])); + // Check that it's a response to this request + if ( ( iRequestId != (*((uint16_t*)&header[0])) ) || + ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) ) + { + // Mark the entire packet as read + iUdp.flush(); + return INVALID_RESPONSE; + } + // Check for any errors in the response (or in our request) + // although we don't do anything to get round these + if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) ) + { + // Mark the entire packet as read + iUdp.flush(); + return -5; //INVALID_RESPONSE; + } + + // And make sure we've got (at least) one answer + uint16_t answerCount = htons(*((uint16_t*)&header[6])); + if (answerCount == 0 ) + { + // Mark the entire packet as read + iUdp.flush(); + return -6; //INVALID_RESPONSE; + } + + // Skip over any questions + for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++) + { + // Skip over the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if (len > 0) + { + // Don't need to actually read the data out for the string, just + // advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } while (len != 0); + + // Now jump over the type and class + for (int i =0; i < 4; i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + + // Now we're up to the bit we're interested in, the answer + // There might be more than one answer (although we'll just use the first + // type A answer) and some authority and additional resource records but + // we're going to ignore all of them. + + for (uint16_t i =0; i < answerCount; i++) + { + // Skip the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if ((len & LABEL_COMPRESSION_MASK) == 0) + { + // It's just a normal label + if (len > 0) + { + // And it's got a length + // Don't need to actually read the data out for the string, + // just advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + else + { + // This is a pointer to a somewhere else in the message for the + // rest of the name. We don't care about the name, and RFC1035 + // says that a name is either a sequence of labels ended with a + // 0 length octet or a pointer or a sequence of labels ending in + // a pointer. Either way, when we get here we're at the end of + // the name + // Skip over the pointer + iUdp.read(); // we don't care about the returned byte + // And set len so that we drop out of the name loop + len = 0; + } + } while (len != 0); + + // Check the type and class + uint16_t answerType; + uint16_t answerClass; + iUdp.read((uint8_t*)&answerType, sizeof(answerType)); + iUdp.read((uint8_t*)&answerClass, sizeof(answerClass)); + + // Ignore the Time-To-Live as we don't do any caching + for (int i =0; i < TTL_SIZE; i++) + { + iUdp.read(); // we don't care about the returned byte + } + + // And read out the length of this answer + // Don't need header_flags anymore, so we can reuse it here + iUdp.read((uint8_t*)&header_flags, sizeof(header_flags)); + + if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) ) + { + if (htons(header_flags) != 4) + { + // It's a weird size + // Mark the entire packet as read + iUdp.flush(); + return -9;//INVALID_RESPONSE; + } + iUdp.read(aAddress.raw_address(), 4); + return SUCCESS; + } + else + { + // This isn't an answer type we're after, move onto the next one + for (uint16_t i =0; i < htons(header_flags); i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + + // Mark the entire packet as read + iUdp.flush(); + + // If we get here then we haven't found an answer + return -10;//INVALID_RESPONSE; +} + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.h new file mode 100644 index 0000000..c99f5c3 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Dns.h @@ -0,0 +1,41 @@ +// Arduino DNS client for WizNet5100-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#ifndef DNSClient_h +#define DNSClient_h + +#include + +class DNSClient +{ +public: + // ctor + void begin(const IPAddress& aDNSServer); + + /** Convert a numeric IP address string into a four-byte IP address. + @param aIPAddrString IP address to convert + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int inet_aton(const char *aIPAddrString, IPAddress& aResult); + + /** Resolve the given hostname to an IP address. + @param aHostname Name to be resolved + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int getHostByName(const char* aHostname, IPAddress& aResult); + +protected: + uint16_t BuildRequest(const char* aName); + uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); + + IPAddress iDNSServer; + uint16_t iRequestId; + EthernetUDP iUdp; +}; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.cpp new file mode 100644 index 0000000..3eea69a --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.cpp @@ -0,0 +1,136 @@ +#include "utility/w5100.h" +#include "Ethernet.h" +#include "Dhcp.h" + +// XXX: don't make assumptions about the value of MAX_SOCK_NUM. +uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { + 0, 0, 0, 0 }; +uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { + 0, 0, 0, 0 }; + +int EthernetClass::begin(uint8_t *mac_address) +{ + static DhcpClass s_dhcp; + _dhcp = &s_dhcp; + + + // Initialise the basic info + W5100.init(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac_address); + W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); + SPI.endTransaction(); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP(mac_address); + if(ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + } + + return ret; +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip) +{ + // Assume the DNS server will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress dns_server = local_ip; + dns_server[3] = 1; + begin(mac_address, local_ip, dns_server); +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server) +{ + // Assume the gateway will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress gateway = local_ip; + gateway[3] = 1; + begin(mac_address, local_ip, dns_server, gateway); +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway) +{ + IPAddress subnet(255, 255, 255, 0); + begin(mac_address, local_ip, dns_server, gateway, subnet); +} + +void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) +{ + W5100.init(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac); + W5100.setIPAddress(local_ip.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); + SPI.endTransaction(); + _dnsServerAddress = dns_server; +} + +int EthernetClass::maintain(){ + int rc = DHCP_CHECK_NONE; + if(_dhcp != NULL){ + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + switch ( rc ){ + case DHCP_CHECK_NONE: + //nothing done + break; + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + break; + default: + //this is actually a error, it will retry though + break; + } + } + return rc; +} + +IPAddress EthernetClass::localIP() +{ + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getIPAddress(ret.raw_address()); + SPI.endTransaction(); + return ret; +} + +IPAddress EthernetClass::subnetMask() +{ + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getSubnetMask(ret.raw_address()); + SPI.endTransaction(); + return ret; +} + +IPAddress EthernetClass::gatewayIP() +{ + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getGatewayIp(ret.raw_address()); + SPI.endTransaction(); + return ret; +} + +IPAddress EthernetClass::dnsServerIP() +{ + return _dnsServerAddress; +} + +EthernetClass Ethernet; diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.h new file mode 100644 index 0000000..2a07ff3 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/Ethernet.h @@ -0,0 +1,41 @@ +#ifndef ethernet_h +#define ethernet_h + +#include +//#include "w5100.h" +#include "IPAddress.h" +#include "EthernetClient.h" +#include "EthernetServer.h" +#include "Dhcp.h" + +#define MAX_SOCK_NUM 4 + +class EthernetClass { +private: + IPAddress _dnsServerAddress; + DhcpClass* _dhcp; +public: + static uint8_t _state[MAX_SOCK_NUM]; + static uint16_t _server_port[MAX_SOCK_NUM]; + // Initialise the Ethernet shield to use the provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac_address); + void begin(uint8_t *mac_address, IPAddress local_ip); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + int maintain(); + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + friend class EthernetClient; + friend class EthernetServer; +}; + +extern EthernetClass Ethernet; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.cpp new file mode 100644 index 0000000..1feed4c --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.cpp @@ -0,0 +1,173 @@ +#include "utility/w5100.h" +#include "utility/socket.h" + +extern "C" { + #include "string.h" +} + +#include "Arduino.h" + +#include "Ethernet.h" +#include "EthernetClient.h" +#include "EthernetServer.h" +#include "Dns.h" + +uint16_t EthernetClient::_srcport = 49152; //Use IANA recommended ephemeral port range 49152-65535 + +EthernetClient::EthernetClient() : _sock(MAX_SOCK_NUM) { +} + +EthernetClient::EthernetClient(uint8_t sock) : _sock(sock) { +} + +int EthernetClient::connect(const char* host, uint16_t port) { + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(Ethernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return connect(remote_addr, port); + } else { + return ret; + } +} + +int EthernetClient::connect(IPAddress ip, uint16_t port) { + if (_sock != MAX_SOCK_NUM) + return 0; + + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = socketStatus(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return 0; + + _srcport++; + if (_srcport == 0) _srcport = 49152; //Use IANA recommended ephemeral port range 49152-65535 + socket(_sock, SnMR::TCP, _srcport, 0); + + if (!::connect(_sock, rawIPAddress(ip), port)) { + _sock = MAX_SOCK_NUM; + return 0; + } + + while (status() != SnSR::ESTABLISHED) { + delay(1); + if (status() == SnSR::CLOSED) { + _sock = MAX_SOCK_NUM; + return 0; + } + } + + return 1; +} + +size_t EthernetClient::write(uint8_t b) { + return write(&b, 1); +} + +size_t EthernetClient::write(const uint8_t *buf, size_t size) { + if (_sock == MAX_SOCK_NUM) { + setWriteError(); + return 0; + } + if (!send(_sock, buf, size)) { + setWriteError(); + return 0; + } + return size; +} + +int EthernetClient::available() { + if (_sock != MAX_SOCK_NUM) + return recvAvailable(_sock); + return 0; +} + +int EthernetClient::read() { + uint8_t b; + if ( recv(_sock, &b, 1) > 0 ) + { + // recv worked + return b; + } + else + { + // No data available + return -1; + } +} + +int EthernetClient::read(uint8_t *buf, size_t size) { + return recv(_sock, buf, size); +} + +int EthernetClient::peek() { + uint8_t b; + // Unlike recv, peek doesn't check to see if there's any data available, so we must + if (!available()) + return -1; + ::peek(_sock, &b); + return b; +} + +void EthernetClient::flush() { + ::flush(_sock); +} + +void EthernetClient::stop() { + if (_sock == MAX_SOCK_NUM) + return; + + // attempt to close the connection gracefully (send a FIN to other side) + disconnect(_sock); + unsigned long start = millis(); + + // wait up to a second for the connection to close + uint8_t s; + do { + s = status(); + if (s == SnSR::CLOSED) + break; // exit the loop + delay(1); + } while (millis() - start < 1000); + + // if it hasn't closed, close it forcefully + if (s != SnSR::CLOSED) + close(_sock); + + EthernetClass::_server_port[_sock] = 0; + _sock = MAX_SOCK_NUM; +} + +uint8_t EthernetClient::connected() { + if (_sock == MAX_SOCK_NUM) return 0; + + uint8_t s = status(); + return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT || + (s == SnSR::CLOSE_WAIT && !available())); +} + +uint8_t EthernetClient::status() { + if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED; + return socketStatus(_sock); +} + +// the next function allows us to use the client returned by +// EthernetServer::available() as the condition in an if-statement. + +EthernetClient::operator bool() { + return _sock != MAX_SOCK_NUM; +} + +bool EthernetClient::operator==(const EthernetClient& rhs) { + return _sock == rhs._sock && _sock != MAX_SOCK_NUM && rhs._sock != MAX_SOCK_NUM; +} diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.h new file mode 100644 index 0000000..16e2500 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetClient.h @@ -0,0 +1,41 @@ +#ifndef ethernetclient_h +#define ethernetclient_h +#include "Arduino.h" +#include "Print.h" +#include "Client.h" +#include "IPAddress.h" + +class EthernetClient : public Client { + +public: + EthernetClient(); + EthernetClient(uint8_t sock); + + uint8_t status(); + virtual int connect(IPAddress 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(); + virtual bool operator==(const bool value) { return bool() == value; } + virtual bool operator!=(const bool value) { return bool() != value; } + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; + + friend class EthernetServer; + + using Print::write; + +private: + static uint16_t _srcport; + uint8_t _sock; +}; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.cpp new file mode 100644 index 0000000..cfa813e --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.cpp @@ -0,0 +1,92 @@ +#include "utility/w5100.h" +#include "utility/socket.h" +extern "C" { +#include "string.h" +} + +#include "Ethernet.h" +#include "EthernetClient.h" +#include "EthernetServer.h" + +EthernetServer::EthernetServer(uint16_t port) +{ + _port = port; +} + +void EthernetServer::begin() +{ + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + if (client.status() == SnSR::CLOSED) { + socket(sock, SnMR::TCP, _port, 0); + listen(sock); + EthernetClass::_server_port[sock] = _port; + break; + } + } +} + +void EthernetServer::accept() +{ + int listening = 0; + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + + if (EthernetClass::_server_port[sock] == _port) { + if (client.status() == SnSR::LISTEN) { + listening = 1; + } + else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) { + client.stop(); + } + } + } + + if (!listening) { + begin(); + } +} + +EthernetClient EthernetServer::available() +{ + accept(); + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + if (EthernetClass::_server_port[sock] == _port) { + uint8_t s = client.status(); + if (s == SnSR::ESTABLISHED || s == SnSR::CLOSE_WAIT) { + if (client.available()) { + // XXX: don't always pick the lowest numbered socket. + return client; + } + } + } + } + + return EthernetClient(MAX_SOCK_NUM); +} + +size_t EthernetServer::write(uint8_t b) +{ + return write(&b, 1); +} + +size_t EthernetServer::write(const uint8_t *buffer, size_t size) +{ + size_t n = 0; + + accept(); + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + + if (EthernetClass::_server_port[sock] == _port && + client.status() == SnSR::ESTABLISHED) { + n += client.write(buffer, size); + } + } + + return n; +} diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.h new file mode 100644 index 0000000..86ccafe --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetServer.h @@ -0,0 +1,22 @@ +#ifndef ethernetserver_h +#define ethernetserver_h + +#include "Server.h" + +class EthernetClient; + +class EthernetServer : +public Server { +private: + uint16_t _port; + void accept(); +public: + EthernetServer(uint16_t); + EthernetClient available(); + virtual void begin(); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + using Print::write; +}; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.cpp new file mode 100644 index 0000000..b5dcb78 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.cpp @@ -0,0 +1,218 @@ +/* + * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.c/socket.h + * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#include "utility/w5100.h" +#include "utility/socket.h" +#include "Ethernet.h" +#include "Udp.h" +#include "Dns.h" + +/* Constructor */ +EthernetUDP::EthernetUDP() : _sock(MAX_SOCK_NUM) {} + +/* Start EthernetUDP socket, listening at local port PORT */ +uint8_t EthernetUDP::begin(uint16_t port) { + if (_sock != MAX_SOCK_NUM) + return 0; + + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = socketStatus(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return 0; + + _port = port; + _remaining = 0; + socket(_sock, SnMR::UDP, _port, 0); + + return 1; +} + +/* return number of bytes available in the current packet, + will return zero if parsePacket hasn't been called yet */ +int EthernetUDP::available() { + return _remaining; +} + +/* Release any resources being used by this EthernetUDP instance */ +void EthernetUDP::stop() +{ + if (_sock == MAX_SOCK_NUM) + return; + + close(_sock); + + EthernetClass::_server_port[_sock] = 0; + _sock = MAX_SOCK_NUM; +} + +int EthernetUDP::beginPacket(const char *host, uint16_t port) +{ + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(Ethernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return beginPacket(remote_addr, port); + } else { + return ret; + } +} + +int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) +{ + _offset = 0; + return startUDP(_sock, rawIPAddress(ip), port); +} + +int EthernetUDP::endPacket() +{ + return sendUDP(_sock); +} + +size_t EthernetUDP::write(uint8_t byte) +{ + return write(&byte, 1); +} + +size_t EthernetUDP::write(const uint8_t *buffer, size_t size) +{ + uint16_t bytes_written = bufferData(_sock, _offset, buffer, size); + _offset += bytes_written; + return bytes_written; +} + +int EthernetUDP::parsePacket() +{ + // discard any remaining bytes in the last packet + flush(); + + if (recvAvailable(_sock) > 0) + { + //HACK - hand-parse the UDP packet using TCP recv method + uint8_t tmpBuf[8]; + int ret =0; + //read 8 header bytes and get IP and port from it + ret = recv(_sock,tmpBuf,8); + if (ret > 0) + { + _remoteIP = tmpBuf; + _remotePort = tmpBuf[4]; + _remotePort = (_remotePort << 8) + tmpBuf[5]; + _remaining = tmpBuf[6]; + _remaining = (_remaining << 8) + tmpBuf[7]; + + // When we get here, any remaining bytes are the data + ret = _remaining; + } + return ret; + } + // There aren't any packets available + return 0; +} + +int EthernetUDP::read() +{ + uint8_t byte; + + if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0)) + { + // We read things without any problems + _remaining--; + return byte; + } + + // If we get here, there's no data available + return -1; +} + +int EthernetUDP::read(unsigned char* buffer, size_t len) +{ + + if (_remaining > 0) + { + + int got; + + if (_remaining <= len) + { + // data should fit in the buffer + got = recv(_sock, buffer, _remaining); + } + else + { + // too much data for the buffer, + // grab as much as will fit + got = recv(_sock, buffer, len); + } + + if (got > 0) + { + _remaining -= got; + return got; + } + + } + + // If we get here, there's no data available or recv failed + return -1; + +} + +int EthernetUDP::peek() +{ + uint8_t b; + // Unlike recv, peek doesn't check to see if there's any data available, so we must. + // If the user hasn't called parsePacket yet then return nothing otherwise they + // may get the UDP header + if (!_remaining) + return -1; + ::peek(_sock, &b); + return b; +} + +void EthernetUDP::flush() +{ + // could this fail (loop endlessly) if _remaining > 0 and recv in read fails? + // should only occur if recv fails after telling us the data is there, lets + // hope the w5100 always behaves :) + + while (_remaining) + { + read(); + } +} + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.h new file mode 100644 index 0000000..8a6b7ab --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/EthernetUdp.h @@ -0,0 +1,99 @@ +/* + * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.c/socket.h + * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + * + * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) + * 1) UDP does not guarantee the order in which assembled UDP packets are received. This + * might not happen often in practice, but in larger network topologies, a UDP + * packet can be received out of sequence. + * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being + * aware of it. Again, this may not be a concern in practice on small local networks. + * For more information, see http://www.cafeaulait.org/course/week12/35.html + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#ifndef ethernetudp_h +#define ethernetudp_h + +#include + +#define UDP_TX_PACKET_MAX_SIZE 24 + +class EthernetUDP : public UDP { +private: + uint8_t _sock; // socket ID for Wiz5100 + uint16_t _port; // local port to listen on + IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed + uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + uint16_t _offset; // offset into the packet being sent + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed + +public: + EthernetUDP(); // Constructor + virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() { return _remoteIP; }; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() { return _remotePort; }; +}; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.cpp new file mode 100644 index 0000000..9254b74 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.cpp @@ -0,0 +1,469 @@ +#include "w5100.h" +#include "socket.h" + +static uint16_t local_port; + +/** + * @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it. + * @return 1 for success else 0. + */ +uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) +{ + if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE)) + { + close(s); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnMR(s, protocol | flag); + if (port != 0) { + W5100.writeSnPORT(s, port); + } + else { + local_port++; // if don't set the source port, set local_port number. + W5100.writeSnPORT(s, local_port); + } + + W5100.execCmdSn(s, Sock_OPEN); + SPI.endTransaction(); + return 1; + } + + return 0; +} + + +uint8_t socketStatus(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + uint8_t status = W5100.readSnSR(s); + SPI.endTransaction(); + return status; +} + + +/** + * @brief This function close the socket and parameter is "s" which represent the socket number + */ +void close(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.execCmdSn(s, Sock_CLOSE); + W5100.writeSnIR(s, 0xFF); + SPI.endTransaction(); +} + + +/** + * @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer. + * @return 1 for success else 0. + */ +uint8_t listen(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + if (W5100.readSnSR(s) != SnSR::INIT) { + SPI.endTransaction(); + return 0; + } + W5100.execCmdSn(s, Sock_LISTEN); + SPI.endTransaction(); + return 1; +} + + +/** + * @brief This function established the connection for the channel in Active (client) mode. + * This function waits for the untill the connection is established. + * + * @return 1 for success else 0. + */ +uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port) +{ + if + ( + ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) || + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + (port == 0x00) + ) + return 0; + + // set destination IP + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + W5100.execCmdSn(s, Sock_CONNECT); + SPI.endTransaction(); + + return 1; +} + + + +/** + * @brief This function used for disconnect the socket and parameter is "s" which represent the socket number + * @return 1 for success else 0. + */ +void disconnect(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.execCmdSn(s, Sock_DISCON); + SPI.endTransaction(); +} + + +/** + * @brief This function used to send the data in TCP mode + * @return 1 for success else 0. + */ +uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len) +{ + uint8_t status=0; + uint16_t ret=0; + uint16_t freesize=0; + + if (len > W5100.SSIZE) + ret = W5100.SSIZE; // check size not to exceed MAX size. + else + ret = len; + + // if freebuf is available, start. + do + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + freesize = W5100.getTXFreeSize(s); + status = W5100.readSnSR(s); + SPI.endTransaction(); + if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT)) + { + ret = 0; + break; + } + yield(); + } + while (freesize < ret); + + // copy data + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + /* m2008.01 [bj] : reduce code */ + if ( W5100.readSnSR(s) == SnSR::CLOSED ) + { + SPI.endTransaction(); + close(s); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + return ret; +} + + +/** + * @brief This function is an application I/F function which is used to receive the data in TCP mode. + * It continues to wait for data as much as the application wants to receive. + * + * @return received data size for success else -1. + */ +int16_t recv(SOCKET s, uint8_t *buf, int16_t len) +{ + // Check how much data is available + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + int16_t ret = W5100.getRXReceivedSize(s); + if ( ret == 0 ) + { + // No data available. + uint8_t status = W5100.readSnSR(s); + if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT ) + { + // The remote end has closed its side of the connection, so this is the eof state + ret = 0; + } + else + { + // The connection is still up, but there's no data waiting to be read + ret = -1; + } + } + else if (ret > len) + { + ret = len; + } + + if ( ret > 0 ) + { + W5100.recv_data_processing(s, buf, ret); + W5100.execCmdSn(s, Sock_RECV); + } + SPI.endTransaction(); + return ret; +} + + +int16_t recvAvailable(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + int16_t ret = W5100.getRXReceivedSize(s); + SPI.endTransaction(); + return ret; +} + + +/** + * @brief Returns the first byte in the receive queue (no checking) + * + * @return + */ +uint16_t peek(SOCKET s, uint8_t *buf) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.recv_data_processing(s, buf, 1, 1); + SPI.endTransaction(); + return 1; +} + + +/** + * @brief This function is an application I/F function which is used to send the data for other then TCP mode. + * Unlike TCP transmission, The peer's destination address and the port is needed. + * + * @return This function return send data size for success else -1. + */ +uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port) +{ + uint16_t ret=0; + + if (len > W5100.SSIZE) ret = W5100.SSIZE; // check size not to exceed MAX size. + else ret = len; + + if + ( + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + ((port == 0x00)) ||(ret == 0) + ) + { + /* +2008.01 [bj] : added return value */ + ret = 0; + } + else + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + + // copy data + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* +2008.01 [bj]: clear interrupt */ + W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */ + SPI.endTransaction(); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + } + return ret; +} + + +/** + * @brief This function is an application I/F function which is used to receive the data in other then + * TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well. + * + * @return This function return received data size for success else -1. + */ +uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port) +{ + uint8_t head[8]; + uint16_t data_len=0; + uint16_t ptr=0; + + if ( len > 0 ) + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + ptr = W5100.readSnRX_RD(s); + switch (W5100.readSnMR(s) & 0x07) + { + case SnMR::UDP : + W5100.read_data(s, ptr, head, 0x08); + ptr += 8; + // read peer's IP address, port number. + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + *port = head[4]; + *port = (*port << 8) + head[5]; + data_len = head[6]; + data_len = (data_len << 8) + head[7]; + + W5100.read_data(s, ptr, buf, data_len); // data copy. + ptr += data_len; + + W5100.writeSnRX_RD(s, ptr); + break; + + case SnMR::IPRAW : + W5100.read_data(s, ptr, head, 0x06); + ptr += 6; + + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + data_len = head[4]; + data_len = (data_len << 8) + head[5]; + + W5100.read_data(s, ptr, buf, data_len); // data copy. + ptr += data_len; + + W5100.writeSnRX_RD(s, ptr); + break; + + case SnMR::MACRAW: + W5100.read_data(s, ptr, head, 2); + ptr+=2; + data_len = head[0]; + data_len = (data_len<<8) + head[1] - 2; + + W5100.read_data(s, ptr, buf, data_len); + ptr += data_len; + W5100.writeSnRX_RD(s, ptr); + break; + + default : + break; + } + W5100.execCmdSn(s, Sock_RECV); + SPI.endTransaction(); + } + return data_len; +} + +/** + * @brief Wait for buffered transmission to complete. + */ +void flush(SOCKET s) { + // TODO +} + +uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len) +{ + uint16_t ret=0; + + if (len > W5100.SSIZE) + ret = W5100.SSIZE; // check size not to exceed MAX size. + else + ret = len; + + if (ret == 0) + return 0; + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* in case of igmp, if send fails, then socket closed */ + /* if you want change, remove this code. */ + SPI.endTransaction(); + close(s); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + return ret; +} + +uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len) +{ + uint16_t ret =0; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + if (len > W5100.getTXFreeSize(s)) + { + ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size. + } + else + { + ret = len; + } + W5100.send_data_processing_offset(s, offset, buf, ret); + SPI.endTransaction(); + return ret; +} + +int startUDP(SOCKET s, uint8_t* addr, uint16_t port) +{ + if + ( + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + ((port == 0x00)) + ) + { + return 0; + } + else + { + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + SPI.endTransaction(); + return 1; + } +} + +int sendUDP(SOCKET s) +{ + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* +2008.01 [bj]: clear interrupt */ + W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT)); + SPI.endTransaction(); + return 0; + } + SPI.endTransaction(); + yield(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + } + + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + SPI.endTransaction(); + + /* Sent ok */ + return 1; +} + diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.h new file mode 100644 index 0000000..37ba854 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/socket.h @@ -0,0 +1,44 @@ +#ifndef _SOCKET_H_ +#define _SOCKET_H_ + +#include "utility/w5100.h" + +extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode) +extern uint8_t socketStatus(SOCKET s); +extern void close(SOCKET s); // Close socket +extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection) +extern void disconnect(SOCKET s); // disconnect the connection +extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection) +extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP) +extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP) +extern int16_t recvAvailable(SOCKET s); +extern uint16_t peek(SOCKET s, uint8_t *buf); +extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW) +extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW) +extern void flush(SOCKET s); // Wait for transmission to complete + +extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len); + +// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a +// number of calls before being sent +/* + @brief This function sets up a UDP datagram, the data for which will be provided by one + or more calls to bufferData and then finally sent with sendUDP. + @return 1 if the datagram was successfully set up, or 0 if there was an error +*/ +extern int startUDP(SOCKET s, uint8_t* addr, uint16_t port); +/* + @brief This function copies up to len bytes of data from buf into a UDP datagram to be + sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. + @return Number of bytes successfully buffered +*/ +uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len); +/* + @brief Send a UDP datagram built up from a sequence of startUDP followed by one or more + calls to bufferData. + @return 1 if the datagram was successfully sent, or 0 if there was an error +*/ +int sendUDP(SOCKET s); + +#endif +/* _SOCKET_H_ */ diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/util.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/util.h new file mode 100644 index 0000000..33d32a9 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/util.h @@ -0,0 +1,14 @@ +#ifndef UTIL_H +#define UTIL_H + +#define htons(x) ( ((x)<< 8 & 0xFF00) | \ + ((x)>> 8 & 0x00FF) ) +#define ntohs(x) htons(x) + +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.cpp b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.cpp new file mode 100644 index 0000000..d0a9bb2 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2010 by Arduino LLC. All rights reserved. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include +#include + +#include "w5100.h" + +// W5100 controller instance +W5100Class W5100; + +#define TX_RX_MAX_BUF_SIZE 2048 +#define TX_BUF 0x1100 +#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE) + +#define TXBUF_BASE 0x4000 +#define RXBUF_BASE 0x6000 + +void W5100Class::init(void) +{ + delay(300); + +#if defined(ARDUINO_ARCH_AVR) + SPI.begin(); + initSS(); +#else + SPI.begin(SPI_CS); + // Set clock to 4Mhz (W5100 should support up to about 14Mhz) + SPI.setClockDivider(SPI_CS, 21); + SPI.setDataMode(SPI_CS, SPI_MODE0); +#endif + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + writeMR(1< SSIZE) + { + // Wrap around circular buffer + uint16_t size = SSIZE - offset; + write(dstAddr, data, size); + write(SBASE[s], data + size, len - size); + } + else { + write(dstAddr, data, len); + } + + ptr += len; + writeSnTX_WR(s, ptr); +} + + +void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) +{ + uint16_t ptr; + ptr = readSnRX_RD(s); + read_data(s, ptr, data, len); + if (!peek) + { + ptr += len; + writeSnRX_RD(s, ptr); + } +} + +void W5100Class::read_data(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len) +{ + uint16_t size; + uint16_t src_mask; + uint16_t src_ptr; + + src_mask = src & RMASK; + src_ptr = RBASE[s] + src_mask; + + if( (src_mask + len) > RSIZE ) + { + size = RSIZE - src_mask; + read(src_ptr, (uint8_t *)dst, size); + dst += size; + read(RBASE[s], (uint8_t *) dst, len - size); + } + else + read(src_ptr, (uint8_t *) dst, len); +} + + +uint8_t W5100Class::write(uint16_t _addr, uint8_t _data) +{ +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_data); + resetSS(); +#else + SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _data); +#endif + return 1; +} + +uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len) +{ + for (uint16_t i=0; i<_len; i++) + { +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + SPI.transfer(_buf[i]); + resetSS(); +#else + SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _buf[i]); + _addr++; +#endif + } + return _len; +} + +uint8_t W5100Class::read(uint16_t _addr) +{ +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + uint8_t _data = SPI.transfer(0); + resetSS(); +#else + SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + uint8_t _data = SPI.transfer(SPI_CS, 0); +#endif + return _data; +} + +uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len) +{ + for (uint16_t i=0; i<_len; i++) + { +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + _buf[i] = SPI.transfer(0); + resetSS(); +#else + SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + _buf[i] = SPI.transfer(SPI_CS, 0); + _addr++; +#endif + } + return _len; +} + +void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) { + // Send command to socket + writeSnCR(s, _cmd); + // Wait for command to complete + while (readSnCR(s)) + ; +} diff --git a/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.h b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.h new file mode 100644 index 0000000..fd9ea35 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/Ethernet/src/utility/w5100.h @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2010 by Arduino LLC. All rights reserved. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef W5100_H_INCLUDED +#define W5100_H_INCLUDED + +#include + +#define SPI_CS 10 + +#if defined(ARDUINO_ARCH_AVR) +#define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0) +#else +#define SPI_ETHERNET_SETTINGS SPI_CS,SPISettings(4000000, MSBFIRST, SPI_MODE0) +#endif + +#define MAX_SOCK_NUM 4 + +typedef uint8_t SOCKET; + +#define IDM_OR 0x8000 +#define IDM_AR0 0x8001 +#define IDM_AR1 0x8002 +#define IDM_DR 0x8003 +/* +class MR { +public: + static const uint8_t RST = 0x80; + static const uint8_t PB = 0x10; + static const uint8_t PPPOE = 0x08; + static const uint8_t LB = 0x04; + static const uint8_t AI = 0x02; + static const uint8_t IND = 0x01; +}; +*/ +/* +class IR { +public: + static const uint8_t CONFLICT = 0x80; + static const uint8_t UNREACH = 0x40; + static const uint8_t PPPoE = 0x20; + static const uint8_t SOCK0 = 0x01; + static const uint8_t SOCK1 = 0x02; + static const uint8_t SOCK2 = 0x04; + static const uint8_t SOCK3 = 0x08; + static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); }; +}; +*/ + +class SnMR { +public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x01; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; +}; + +enum SockCMD { + Sock_OPEN = 0x01, + Sock_LISTEN = 0x02, + Sock_CONNECT = 0x04, + Sock_DISCON = 0x08, + Sock_CLOSE = 0x10, + Sock_SEND = 0x20, + Sock_SEND_MAC = 0x21, + Sock_SEND_KEEP = 0x22, + Sock_RECV = 0x40 +}; + +/*class SnCmd { +public: + static const uint8_t OPEN = 0x01; + static const uint8_t LISTEN = 0x02; + static const uint8_t CONNECT = 0x04; + static const uint8_t DISCON = 0x08; + static const uint8_t CLOSE = 0x10; + static const uint8_t SEND = 0x20; + static const uint8_t SEND_MAC = 0x21; + static const uint8_t SEND_KEEP = 0x22; + static const uint8_t RECV = 0x40; +}; +*/ + +class SnIR { +public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; +}; + +class SnSR { +public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; +}; + +class IPPROTO { +public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; +}; + +class W5100Class { + +public: + void init(); + + /** + * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. + * + * It calculate the actual physical address where one has to read + * the data from Receive buffer. Here also take care of the condition while it exceed + * the Rx memory uper-bound of socket. + */ + void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); + + /** + * @brief This function is being called by send() and sendto() function also. + * + * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer + * register. User should read upper byte first and lower byte later to get proper value. + */ + void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); + /** + * @brief A copy of send_data_processing that uses the provided ptr for the + * write offset. Only needed for the "streaming" UDP API, where + * a single UDP packet is built up over a number of calls to + * send_data_processing_ptr, because TX_WR doesn't seem to get updated + * correctly in those scenarios + * @param ptr value to use in place of TX_WR. If 0, then the value is read + * in from TX_WR + * @return New value for ptr, to be used in the next call + */ +// FIXME Update documentation + void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); + + /** + * @brief This function is being called by recv() also. + * + * This function read the Rx read pointer register + * and after copy the data from receive buffer update the Rx write pointer register. + * User should read upper byte first and lower byte later to get proper value. + */ + void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); + + inline void setGatewayIp(uint8_t *_addr); + inline void getGatewayIp(uint8_t *_addr); + + inline void setSubnetMask(uint8_t *_addr); + inline void getSubnetMask(uint8_t *_addr); + + inline void setMACAddress(uint8_t * addr); + inline void getMACAddress(uint8_t * addr); + + inline void setIPAddress(uint8_t * addr); + inline void getIPAddress(uint8_t * addr); + + inline void setRetransmissionTime(uint16_t timeout); + inline void setRetransmissionCount(uint8_t _retry); + + void execCmdSn(SOCKET s, SockCMD _cmd); + + uint16_t getTXFreeSize(SOCKET s); + uint16_t getRXReceivedSize(SOCKET s); + + + // W5100 Registers + // --------------- +private: + static uint8_t write(uint16_t _addr, uint8_t _data); + static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); + static uint8_t read(uint16_t addr); + static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + +#define __GP_REGISTER8(name, address) \ + static inline void write##name(uint8_t _data) { \ + write(address, _data); \ + } \ + static inline uint8_t read##name() { \ + return read(address); \ + } +#define __GP_REGISTER16(name, address) \ + static void write##name(uint16_t _data) { \ + write(address, _data >> 8); \ + write(address+1, _data & 0xFF); \ + } \ + static uint16_t read##name() { \ + uint16_t res = read(address); \ + res = (res << 8) + read(address + 1); \ + return res; \ + } +#define __GP_REGISTER_N(name, address, size) \ + static uint16_t write##name(uint8_t *_buff) { \ + return write(address, _buff, size); \ + } \ + static uint16_t read##name(uint8_t *_buff) { \ + return read(address, _buff, size); \ + } + +public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017); // Timeout address + __GP_REGISTER8 (RCR, 0x0019); // Retry count + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number + __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode + __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode + +#undef __GP_REGISTER8 +#undef __GP_REGISTER16 +#undef __GP_REGISTER_N + + // W5100 Socket registers + // ---------------------- +private: + static inline uint8_t readSn(SOCKET _s, uint16_t _addr); + static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); + static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + + static const uint16_t CH_BASE = 0x0400; + static const uint16_t CH_SIZE = 0x0100; + +#define __SOCKET_REGISTER8(name, address) \ + static inline void write##name(SOCKET _s, uint8_t _data) { \ + writeSn(_s, address, _data); \ + } \ + static inline uint8_t read##name(SOCKET _s) { \ + return readSn(_s, address); \ + } +#define __SOCKET_REGISTER16(name, address) \ + static void write##name(SOCKET _s, uint16_t _data) { \ + writeSn(_s, address, _data >> 8); \ + writeSn(_s, address+1, _data & 0xFF); \ + } \ + static uint16_t read##name(SOCKET _s) { \ + uint16_t res = readSn(_s, address); \ + uint16_t res2 = readSn(_s,address + 1); \ + res = res << 8; \ + res2 = res2 & 0xFF; \ + res = res | res2; \ + return res; \ + } +#define __SOCKET_REGISTER_N(name, address, size) \ + static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ + return writeSn(_s, address, _buff, size); \ + } \ + static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ + return readSn(_s, address, _buff, size); \ + } + +public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + +#undef __SOCKET_REGISTER8 +#undef __SOCKET_REGISTER16 +#undef __SOCKET_REGISTER_N + + +private: + static const uint8_t RST = 7; // Reset BIT + + static const int SOCKETS = 4; + static const uint16_t SMASK = 0x07FF; // Tx buffer MASK + static const uint16_t RMASK = 0x07FF; // Rx buffer MASK +public: + static const uint16_t SSIZE = 2048; // Max Tx buffer size +private: + static const uint16_t RSIZE = 2048; // Max Rx buffer size + uint16_t SBASE[SOCKETS]; // Tx buffer base address + uint16_t RBASE[SOCKETS]; // Rx buffer base address + +private: +#if defined(ARDUINO_ARCH_AVR) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + inline static void initSS() { DDRB |= _BV(4); }; + inline static void setSS() { PORTB &= ~_BV(4); }; + inline static void resetSS() { PORTB |= _BV(4); }; +#elif defined(__AVR_ATmega32U4__) + inline static void initSS() { DDRB |= _BV(6); }; + inline static void setSS() { PORTB &= ~_BV(6); }; + inline static void resetSS() { PORTB |= _BV(6); }; +#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) + inline static void initSS() { DDRB |= _BV(0); }; + inline static void setSS() { PORTB &= ~_BV(0); }; + inline static void resetSS() { PORTB |= _BV(0); }; +#else + inline static void initSS() { DDRB |= _BV(2); }; + inline static void setSS() { PORTB &= ~_BV(2); }; + inline static void resetSS() { PORTB |= _BV(2); }; +#endif +#endif // ARDUINO_ARCH_AVR +}; + +extern W5100Class W5100; + +uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) { + return read(CH_BASE + _s * CH_SIZE + _addr); +} + +uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { + return write(CH_BASE + _s * CH_SIZE + _addr, _data); +} + +uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +void W5100Class::getGatewayIp(uint8_t *_addr) { + readGAR(_addr); +} + +void W5100Class::setGatewayIp(uint8_t *_addr) { + writeGAR(_addr); +} + +void W5100Class::getSubnetMask(uint8_t *_addr) { + readSUBR(_addr); +} + +void W5100Class::setSubnetMask(uint8_t *_addr) { + writeSUBR(_addr); +} + +void W5100Class::getMACAddress(uint8_t *_addr) { + readSHAR(_addr); +} + +void W5100Class::setMACAddress(uint8_t *_addr) { + writeSHAR(_addr); +} + +void W5100Class::getIPAddress(uint8_t *_addr) { + readSIPR(_addr); +} + +void W5100Class::setIPAddress(uint8_t *_addr) { + writeSIPR(_addr); +} + +void W5100Class::setRetransmissionTime(uint16_t _timeout) { + writeRTR(_timeout); +} + +void W5100Class::setRetransmissionCount(uint8_t _retry) { + writeRCR(_retry); +} + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/SPI/SPI.cpp b/libraries/MySensors/drivers/ESP8266/SPI/SPI.cpp new file mode 100644 index 0000000..4e73021 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/SPI/SPI.cpp @@ -0,0 +1,454 @@ +/* + SPI.cpp - SPI library for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 + */ + +#include "SPI.h" +#include "HardwareSerial.h" + +typedef union { + uint32_t regValue; + struct { + unsigned regL :6; + unsigned regH :6; + unsigned regN :6; + unsigned regPre :13; + unsigned regEQU :1; + }; +} spiClk_t; + +SPIClass SPI; + +SPIClass::SPIClass() { + useHwCs = false; +} + +void SPIClass::begin() { + pinMode(SCK, SPECIAL); ///< GPIO14 + pinMode(MISO, SPECIAL); ///< GPIO12 + pinMode(MOSI, SPECIAL); ///< GPIO13 + + SPI1C = 0; + setFrequency(1000000); ///< 1MHz + SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; + SPI1U1 = (7 << SPILMOSI) | (7 << SPILMISO); + SPI1C1 = 0; +} + +void SPIClass::end() { + pinMode(SCK, INPUT); + pinMode(MISO, INPUT); + pinMode(MOSI, INPUT); + if(useHwCs) { + pinMode(SS, INPUT); + } +} + +void SPIClass::setHwCs(bool use) { + if(use) { + pinMode(SS, SPECIAL); ///< GPIO15 + SPI1U |= (SPIUCSSETUP | SPIUCSHOLD); + } else { + if(useHwCs) { + pinMode(SS, INPUT); + SPI1U &= ~(SPIUCSSETUP | SPIUCSHOLD); + } + } + useHwCs = use; +} + +void SPIClass::beginTransaction(SPISettings settings) { + while(SPI1CMD & SPIBUSY) {} + setFrequency(settings._clock); + setBitOrder(settings._bitOrder); + setDataMode(settings._dataMode); +} + +void SPIClass::endTransaction() { +} + +void SPIClass::setDataMode(uint8_t dataMode) { + + /** + SPI_MODE0 0x00 - CPOL: 0 CPHA: 0 + SPI_MODE1 0x01 - CPOL: 0 CPHA: 1 + SPI_MODE2 0x10 - CPOL: 1 CPHA: 0 + SPI_MODE3 0x11 - CPOL: 1 CPHA: 1 + */ + + bool CPOL = (dataMode & 0x10); ///< CPOL (Clock Polarity) + bool CPHA = (dataMode & 0x01); ///< CPHA (Clock Phase) + + if(CPHA) { + SPI1U |= (SPIUSME); + } else { + SPI1U &= ~(SPIUSME); + } + + if(CPOL) { + //todo How set CPOL??? + } + +} + +void SPIClass::setBitOrder(uint8_t bitOrder) { + if(bitOrder == MSBFIRST) { + SPI1C &= ~(SPICWBO | SPICRBO); + } else { + SPI1C |= (SPICWBO | SPICRBO); + } +} + +/** + * calculate the Frequency based on the register value + * @param reg + * @return + */ +static uint32_t ClkRegToFreq(spiClk_t * reg) { + return (ESP8266_CLOCK / ((reg->regPre + 1) * (reg->regN + 1))); +} + +void SPIClass::setFrequency(uint32_t freq) { + static uint32_t lastSetFrequency = 0; + static uint32_t lastSetRegister = 0; + + if(freq >= ESP8266_CLOCK) { + setClockDivider(0x80000000); + return; + } + + if(lastSetFrequency == freq && lastSetRegister == SPI1CLK) { + // do nothing (speed optimization) + return; + } + + const spiClk_t minFreqReg = { 0x7FFFF000 }; + uint32_t minFreq = ClkRegToFreq((spiClk_t*) &minFreqReg); + if(freq < minFreq) { + // use minimum possible clock + setClockDivider(minFreqReg.regValue); + lastSetRegister = SPI1CLK; + lastSetFrequency = freq; + return; + } + + uint8_t calN = 1; + + spiClk_t bestReg = { 0 }; + int32_t bestFreq = 0; + + // find the best match + while(calN <= 0x3F) { // 0x3F max for N + + spiClk_t reg = { 0 }; + int32_t calFreq; + int32_t calPre; + int8_t calPreVari = -2; + + reg.regN = calN; + + while(calPreVari++ <= 1) { // test different variants for Pre (we calculate in int so we miss the decimals, testing is the easyest and fastest way) + calPre = (((ESP8266_CLOCK / (reg.regN + 1)) / freq) - 1) + calPreVari; + if(calPre > 0x1FFF) { + reg.regPre = 0x1FFF; // 8191 + } else if(calPre <= 0) { + reg.regPre = 0; + } else { + reg.regPre = calPre; + } + + reg.regL = ((reg.regN + 1) / 2); + // reg.regH = (reg.regN - reg.regL); + + // test calculation + calFreq = ClkRegToFreq(®); + //os_printf("-----[0x%08X][%d]\t EQU: %d\t Pre: %d\t N: %d\t H: %d\t L: %d = %d\n", reg.regValue, freq, reg.regEQU, reg.regPre, reg.regN, reg.regH, reg.regL, calFreq); + + if(calFreq == (int32_t) freq) { + // accurate match use it! + memcpy(&bestReg, ®, sizeof(bestReg)); + break; + } else if(calFreq < (int32_t) freq) { + // never go over the requested frequency + if(abs(freq - calFreq) < abs(freq - bestFreq)) { + bestFreq = calFreq; + memcpy(&bestReg, ®, sizeof(bestReg)); + } + } + } + if(calFreq == (int32_t) freq) { + // accurate match use it! + break; + } + calN++; + } + + // os_printf("[0x%08X][%d]\t EQU: %d\t Pre: %d\t N: %d\t H: %d\t L: %d\t - Real Frequency: %d\n", bestReg.regValue, freq, bestReg.regEQU, bestReg.regPre, bestReg.regN, bestReg.regH, bestReg.regL, ClkRegToFreq(&bestReg)); + + setClockDivider(bestReg.regValue); + lastSetRegister = SPI1CLK; + lastSetFrequency = freq; + +} + +void SPIClass::setClockDivider(uint32_t clockDiv) { + if(clockDiv == 0x80000000) { + GPMUX |= (1 << 9); // Set bit 9 if sysclock required + } else { + GPMUX &= ~(1 << 9); + } + SPI1CLK = clockDiv; +} + +inline void SPIClass::setDataBits(uint16_t bits) { + const uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); + bits--; + SPI1U1 = ((SPI1U1 & mask) | ((bits << SPILMOSI) | (bits << SPILMISO))); +} + +uint8_t SPIClass::transfer(uint8_t data) { + while(SPI1CMD & SPIBUSY) {} + // reset to 8Bit mode + setDataBits(8); + SPI1W0 = data; + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} + return (uint8_t) (SPI1W0 & 0xff); +} + +uint16_t SPIClass::transfer16(uint16_t data) { + union { + uint16_t val; + struct { + uint8_t lsb; + uint8_t msb; + }; + } in, out; + in.val = data; + + if((SPI1C & (SPICWBO | SPICRBO))) { + //MSBFIRST + out.msb = transfer(in.msb); + out.lsb = transfer(in.lsb); + } else { + //LSBFIRST + out.lsb = transfer(in.lsb); + out.msb = transfer(in.msb); + } + return out.val; +} + +void SPIClass::write(uint8_t data) { + while(SPI1CMD & SPIBUSY) {} + // reset to 8Bit mode + setDataBits(8); + SPI1W0 = data; + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} +} + +void SPIClass::write16(uint16_t data) { + write16(data, !(SPI1C & (SPICWBO | SPICRBO))); +} + +void SPIClass::write16(uint16_t data, bool msb) { + while(SPI1CMD & SPIBUSY) {} + // Set to 16Bits transfer + setDataBits(16); + if(msb) { + // MSBFIRST Byte first + SPI1W0 = (data >> 8) | (data << 8); + SPI1CMD |= SPIBUSY; + } else { + // LSBFIRST Byte first + SPI1W0 = data; + SPI1CMD |= SPIBUSY; + } + while(SPI1CMD & SPIBUSY) {} +} + +void SPIClass::write32(uint32_t data) { + write32(data, !(SPI1C & (SPICWBO | SPICRBO))); +} + +void SPIClass::write32(uint32_t data, bool msb) { + while(SPI1CMD & SPIBUSY) {} + // Set to 32Bits transfer + setDataBits(32); + if(msb) { + union { + uint32_t l; + uint8_t b[4]; + } data_; + data_.l = data; + // MSBFIRST Byte first + SPI1W0 = (data_.b[3] | (data_.b[2] << 8) | (data_.b[1] << 16) | (data_.b[0] << 24)); + SPI1CMD |= SPIBUSY; + } else { + // LSBFIRST Byte first + SPI1W0 = data; + SPI1CMD |= SPIBUSY; + } + while(SPI1CMD & SPIBUSY) {} +} + +/** + * Note: + * data need to be aligned to 32Bit + * or you get an Fatal exception (9) + * @param data uint8_t * + * @param size uint32_t + */ +void SPIClass::writeBytes(uint8_t * data, uint32_t size) { + while(size) { + if(size > 64) { + writeBytes_(data, 64); + size -= 64; + data += 64; + } else { + writeBytes_(data, size); + size = 0; + } + } +} + +void SPIClass::writeBytes_(uint8_t * data, uint8_t size) { + while(SPI1CMD & SPIBUSY) {} + // Set Bits to transfer + setDataBits(size * 8); + + volatile uint32_t * fifoPtr = &SPI1W0; + uint32_t * dataPtr = (uint32_t*) data; + uint8_t dataSize = ((size + 3) / 4); + + while(dataSize--) { + *fifoPtr = *dataPtr; + dataPtr++; + fifoPtr++; + } + + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} +} + + +/** + * Note: + * data need to be aligned to 32Bit + * or you get an Fatal exception (9) + * @param data uint8_t * + * @param size uint8_t max for size is 64Byte + * @param repeat uint32_t + */ +void SPIClass::writePattern(uint8_t * data, uint8_t size, uint32_t repeat) { + if(size > 64) return; //max Hardware FIFO + + uint32_t byte = (size * repeat); + uint8_t r = (64 / size); + + while(byte) { + if(byte > 64) { + writePattern_(data, size, r); + byte -= 64; + } else { + writePattern_(data, size, (byte / size)); + byte = 0; + } + } +} + +void SPIClass::writePattern_(uint8_t * data, uint8_t size, uint8_t repeat) { + uint8_t bytes = (size * repeat); + uint8_t buffer[64]; + uint8_t * bufferPtr = &buffer[0]; + uint8_t * dataPtr; + uint8_t dataSize = bytes; + for(uint8_t i = 0; i < repeat; i++) { + dataSize = size; + dataPtr = data; + while(dataSize--) { + *bufferPtr = *dataPtr; + dataPtr++; + bufferPtr++; + } + } + + writeBytes(&buffer[0], bytes); +} + +/** + * Note: + * in and out need to be aligned to 32Bit + * or you get an Fatal exception (9) + * @param out uint8_t * + * @param in uint8_t * + * @param size uint32_t + */ +void SPIClass::transferBytes(uint8_t * out, uint8_t * in, uint32_t size) { + while(size) { + if(size > 64) { + transferBytes_(out, in, 64); + size -= 64; + if(out) out += 64; + if(in) in += 64; + } else { + transferBytes_(out, in, size); + size = 0; + } + } +} + +void SPIClass::transferBytes_(uint8_t * out, uint8_t * in, uint8_t size) { + while(SPI1CMD & SPIBUSY) {} + // Set in/out Bits to transfer + + setDataBits(size * 8); + + volatile uint32_t * fifoPtr = &SPI1W0; + uint8_t dataSize = ((size + 3) / 4); + + if(out) { + uint32_t * dataPtr = (uint32_t*) out; + while(dataSize--) { + *fifoPtr = *dataPtr; + dataPtr++; + fifoPtr++; + } + } else { + // no out data only read fill with dummy data! + while(dataSize--) { + *fifoPtr = 0xFFFFFFFF; + fifoPtr++; + } + } + + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} + + if(in) { + volatile uint8_t * fifoPtr8 = (volatile uint8_t *) &SPI1W0; + dataSize = size; + while(dataSize--) { + *in = *fifoPtr8; + in++; + fifoPtr8++; + } + } +} + diff --git a/libraries/MySensors/drivers/ESP8266/SPI/SPI.h b/libraries/MySensors/drivers/ESP8266/SPI/SPI.h new file mode 100644 index 0000000..141f30e --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/SPI/SPI.h @@ -0,0 +1,85 @@ +/* + SPI.h - SPI library for esp8266 + + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + + 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 +*/ +#ifndef _SPI_H_INCLUDED +#define _SPI_H_INCLUDED + +#include +#include + +#define SPI_HAS_TRANSACTION + +// This defines are not representing the real Divider of the ESP8266 +// the Defines match to an AVR Arduino on 16MHz for better compatibility +#define SPI_CLOCK_DIV2 0x00101001 //8 MHz +#define SPI_CLOCK_DIV4 0x00241001 //4 MHz +#define SPI_CLOCK_DIV8 0x004c1001 //2 MHz +#define SPI_CLOCK_DIV16 0x009c1001 //1 MHz +#define SPI_CLOCK_DIV32 0x013c1001 //500 KHz +#define SPI_CLOCK_DIV64 0x027c1001 //250 KHz +#define SPI_CLOCK_DIV128 0x04fc1001 //125 KHz + +const uint8_t SPI_MODE0 = 0x00; ///< CPOL: 0 CPHA: 0 +const uint8_t SPI_MODE1 = 0x01; ///< CPOL: 0 CPHA: 1 +const uint8_t SPI_MODE2 = 0x10; ///< CPOL: 1 CPHA: 0 +const uint8_t SPI_MODE3 = 0x11; ///< CPOL: 1 CPHA: 1 + +class SPISettings { +public: + SPISettings() :_clock(1000000), _bitOrder(LSBFIRST), _dataMode(SPI_MODE0){} + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) :_clock(clock), _bitOrder(bitOrder), _dataMode(dataMode){} + uint32_t _clock; + uint8_t _bitOrder; + uint8_t _dataMode; +}; + +class SPIClass { +public: + SPIClass(); + void begin(); + void end(); + void setHwCs(bool use); + void setBitOrder(uint8_t bitOrder); + void setDataMode(uint8_t dataMode); + void setFrequency(uint32_t freq); + void setClockDivider(uint32_t clockDiv); + void beginTransaction(SPISettings settings); + uint8_t transfer(uint8_t data); + uint16_t transfer16(uint16_t data); + void write(uint8_t data); + void write16(uint16_t data); + void write16(uint16_t data, bool msb); + void write32(uint32_t data); + void write32(uint32_t data, bool msb); + void writeBytes(uint8_t * data, uint32_t size); + void writePattern(uint8_t * data, uint8_t size, uint32_t repeat); + void transferBytes(uint8_t * out, uint8_t * in, uint32_t size); + void endTransaction(void); +private: + bool useHwCs; + void writeBytes_(uint8_t * data, uint8_t size); + void writePattern_(uint8_t * data, uint8_t size, uint8_t repeat); + void transferBytes_(uint8_t * out, uint8_t * in, uint8_t size); + inline void setDataBits(uint16_t bits); +}; + +extern SPIClass SPI; + +#endif diff --git a/libraries/MySensors/drivers/ESP8266/SPI/keywords.txt b/libraries/MySensors/drivers/ESP8266/SPI/keywords.txt new file mode 100644 index 0000000..fa76165 --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/SPI/keywords.txt @@ -0,0 +1,36 @@ +####################################### +# Syntax Coloring Map SPI +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SPI KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 +transfer KEYWORD2 +setBitOrder KEYWORD2 +setDataMode KEYWORD2 +setClockDivider KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +SPI_CLOCK_DIV4 LITERAL1 +SPI_CLOCK_DIV16 LITERAL1 +SPI_CLOCK_DIV64 LITERAL1 +SPI_CLOCK_DIV128 LITERAL1 +SPI_CLOCK_DIV2 LITERAL1 +SPI_CLOCK_DIV8 LITERAL1 +SPI_CLOCK_DIV32 LITERAL1 +SPI_CLOCK_DIV64 LITERAL1 +SPI_MODE0 LITERAL1 +SPI_MODE1 LITERAL1 +SPI_MODE2 LITERAL1 +SPI_MODE3 LITERAL1 \ No newline at end of file diff --git a/libraries/MySensors/drivers/ESP8266/SPI/library.properties b/libraries/MySensors/drivers/ESP8266/SPI/library.properties new file mode 100644 index 0000000..bbe0ddb --- /dev/null +++ b/libraries/MySensors/drivers/ESP8266/SPI/library.properties @@ -0,0 +1,8 @@ +name=SPI +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Enables the communication with devices that use the Serial Peripheral Interface (SPI) Bus. For all Arduino boards, BUT Arduino DUE. +paragraph= +url=http://arduino.cc/en/Reference/SPI +architectures=esp8266 diff --git a/libraries/MySensors/drivers/RF24/RF24_config.h b/libraries/MySensors/drivers/RF24/RF24_config.h index 08a23cc..23f78e4 100644 --- a/libraries/MySensors/drivers/RF24/RF24_config.h +++ b/libraries/MySensors/drivers/RF24/RF24_config.h @@ -39,7 +39,7 @@ #include #define _SPI uspi #elif defined MY_SOFTSPI - #include "drivers/DigitalIO/DigitalIO.h" + #include "drivers/AVR/DigitalIO/DigitalIO.h" // change these pins to your liking const uint8_t SOFT_SPI_MISO_PIN = MY_SOFT_SPI_MOSI_PIN; @@ -50,7 +50,7 @@ #define _SPI spi #else - #include "drivers/SPI/SPI.h" + #include "drivers/AVR/SPI/SPI.h" #define _SPI SPI #endif #endif diff --git a/libraries/MySensors/drivers/SPIFlash/SPIFlash.h b/libraries/MySensors/drivers/SPIFlash/SPIFlash.h index e6e1d04..0c0e827 100644 --- a/libraries/MySensors/drivers/SPIFlash/SPIFlash.h +++ b/libraries/MySensors/drivers/SPIFlash/SPIFlash.h @@ -42,7 +42,7 @@ #include "pins_arduino.h" #endif -#include "drivers/SPI/SPI.h" +#include "drivers/AVR/SPI/SPI.h" /// IMPORTANT: NAND FLASH memory requires erase before write, because /// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 34ee906..687468c 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -92,7 +92,7 @@ #define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 // The port you want to contact on controller (client mode) #define MY_CONTROLLER_PORT 5003 - + // The MAC address can be anything you want but should be unique on your network. // Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. // Note that most of the Ardunio examples use "DEAD BEEF FEED" for the MAC address. diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino index 099226f..7687d7b 100644 --- a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -31,6 +31,10 @@ //#define MY_SOFTSPI //#define MY_OTA_FIRMWARE_FEATURE +#define MY_SIGNING_SOFT + +// #define MY_GATEWAY_SERIAL // REMOVE-ME +// #define MY_GATEWAY_PROTOCOL_DEFAULT // REMOVE-ME #define MY_RADIO_NRF24 // MY_RADIO_RFM69 #include @@ -49,8 +53,6 @@ MyMessage msg(CHILD_ID, V_TRIPPED); void setup() { - dataDallback(); - // Send the sketch version information to the gateway and Controller sendSketchInfo("Motion Sensor", "1.0"); From 76f208abe773a8edba1f8dee22f76f6f13fee6cb Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Sun, 13 Sep 2015 18:26:18 +0200 Subject: [PATCH 12/43] Clean up Ethernet defines a bit Setting MY_CONTROLLER_IP_ADDRESS turns on client mode. Setting MY_IP_ADDRESS turns off DHCP mode --- libraries/MySensors/MySensor.h | 17 ++++++++++------- .../core/MyGatewayTransportEthernet.cpp | 4 ++-- .../EthernetGateway/EthernetGateway.ino | 11 +++-------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 3327516..f368f9f 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -26,7 +26,7 @@ #include "MyConfig.h" -#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100_CLIENT) || defined(MY_GATEWAY_W5100_SERVER) +#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) #define MY_GATEWAY_FEATURE #define MY_NODE_TYPE "gateway" #elif defined(MY_REPEATER_FEATURE) @@ -102,7 +102,7 @@ // We assume that a gateway having a radio also should act as repeater #define MY_REPEATER_FEATURE #endif - #if defined(MY_GATEWAY_W5100_CLIENT) || defined(MY_GATEWAY_W5100_SERVER) + #if defined(MY_GATEWAY_W5100) #include "drivers/AVR/Ethernet_W5100/utility/socket.cpp" #include "drivers/AVR/Ethernet_W5100/utility/w5100.cpp" #include "drivers/AVR/Ethernet_W5100/DNS.cpp" @@ -110,19 +110,22 @@ #include "drivers/AVR/Ethernet_W5100/EthernetUdp.cpp" #include "drivers/AVR/Ethernet_W5100/IPAddress.cpp" + #if defined(MY_CONTROLLER_IP_ADDRESS) + #define MY_GATEWAY_CLIENT_MODE + #endif + #if !defined(MY_PORT) - #error You must define MY_PORT + #error You must define MY_PORT (cotroller or gatway port to open) #endif #if !defined(USE_UDP) #include "drivers/AVR/Ethernet_W5100/EthernetServer.cpp" #endif - #if defined(MY_GATEWAY_W5100_CLIENT) && !defined(MY_CONTROLLER_IP_ADDRESS) - #error You must define MY_CONTROLLER_IP_ADDRESS when acting as client - #endif - #if defined(MY_GATEWAY_W5100_CLIENT) + #if defined(MY_GATEWAY_CLIENT_MODE) #include "drivers/AVR/Ethernet_W5100/EthernetClient.cpp" #include "core/MyGatewayTransportEthernet.cpp" + #else + // What do we do here? #endif #elif defined(MY_GATEWAY_SERIAL) #include "core/MyGatewayTransportSerial.cpp" diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp index 83fa9b1..18bd233 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp @@ -66,13 +66,13 @@ bool gatewayTransportSend(MyMessage &message) else { _ethernetMsg = protocolFormat(message); #ifdef MY_USE_UDP - _ethernetServer.beginPacket(_ethernetControllerIP, MY_CONTROLLER_PORT); + _ethernetServer.beginPacket(_ethernetControllerIP, MY_PORT); _ethernetServer.write(_ethernetMsg, strlen(_ethernetMsg)); // returns 1 if the packet was sent successfully return _ethernetServer.endPacket(); #else EthernetClient client; - if (client.connect(_ethernetControllerIP, MY_CONTROLLER_PORT)) { + if (client.connect(_ethernetControllerIP, MY_PORT)) { client.write(_ethernetMsg, strlen(_ethernetMsg)); client.stop(); return true; diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 687468c..3dd66d8 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -63,10 +63,8 @@ #define MY_RADIO_NRF24 -// W5100 Ethernet in client mode (node opens conmection to controller) -#define MY_GATEWAY_W5100_CLIENT -// W5100 Ethernet in client mode (controller opens conmection to node) -//#define MY_GATEWAY_W5100_SERVER +// W5100 Ethernet gateway +#define MY_GATEWAY_W5100 // Set default gateway protocol (http://www.mysensors.org/download/serial_api_15) #define MY_GATEWAY_PROTOCOL_DEFAULT @@ -88,10 +86,8 @@ // The port to keep open on node server mode / or port to contact in client mode #define MY_PORT 5003 -// Controller ip address (client mode) +// Controller ip address (enables client mode). Undefine this to act as sever. #define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 -// The port you want to contact on controller (client mode) -#define MY_CONTROLLER_PORT 5003 // The MAC address can be anything you want but should be unique on your network. // Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use. @@ -124,7 +120,6 @@ void setup() { - dataCallback(); } void loop() { From b66513affcd5e3ceaff58d3e085ce7c1225220ce Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Sun, 13 Sep 2015 23:51:10 +0200 Subject: [PATCH 13/43] ENC28J60 Ethernet gateway --- libraries/MySensors/MySensor.h | 33 ++++-- libraries/MySensors/core/MyProtocol.cpp | 23 ---- .../MySensors/drivers/AVR/Ethernet_UIP/README | 2 +- .../AdvancedChatServer/AdvancedChatServer.ino | 1 + .../examples/EchoServer/EchoServer.ino | 1 + .../examples/TcpClient/TcpClient.ino | 1 + .../examples/TcpServer/TcpServer.ino | 1 + .../examples/UdpClient/UdpClient.ino | 1 + .../examples/UdpServer/UdpServer.ino | 1 + .../AVR/Ethernet_UIP/library.properties | 4 +- .../AVR/Ethernet_UIP/{ => src}/Dhcp.cpp | 0 .../drivers/AVR/Ethernet_UIP/{ => src}/Dhcp.h | 0 .../AVR/Ethernet_UIP/{ => src}/Dns.cpp | 0 .../drivers/AVR/Ethernet_UIP/{ => src}/Dns.h | 2 +- .../AVR/Ethernet_UIP/{ => src}/UIPClient.cpp | 0 .../AVR/Ethernet_UIP/{ => src}/UIPClient.h | 0 .../Ethernet_UIP/{ => src}/UIPEthernet.cpp | 0 .../AVR/Ethernet_UIP/{ => src}/UIPEthernet.h | 0 .../AVR/Ethernet_UIP/{ => src}/UIPServer.cpp | 0 .../AVR/Ethernet_UIP/{ => src}/UIPServer.h | 0 .../AVR/Ethernet_UIP/{ => src}/UIPUdp.cpp | 0 .../AVR/Ethernet_UIP/{ => src}/UIPUdp.h | 0 .../Ethernet_UIP/{ => src}/ethernet_comp.h | 0 .../{ => src}/utility/Enc28J60Network.cpp | 112 ++++++++++++++++-- .../{ => src}/utility/Enc28J60Network.h | 9 +- .../{ => src}/utility/clock-arch.c | 0 .../{ => src}/utility/clock-arch.h | 0 .../Ethernet_UIP/{ => src}/utility/enc28j60.h | 0 .../{ => src}/utility/mempool.cpp | 0 .../Ethernet_UIP/{ => src}/utility/mempool.h | 0 .../{ => src}/utility/mempool_conf.h | 0 .../Ethernet_UIP/{ => src}/utility/uip-conf.h | 0 .../AVR/Ethernet_UIP/{ => src}/utility/uip.c | 112 +++++++++--------- .../AVR/Ethernet_UIP/{ => src}/utility/uip.h | 0 .../Ethernet_UIP/{ => src}/utility/uip_arch.h | 0 .../Ethernet_UIP/{ => src}/utility/uip_arp.c | 0 .../Ethernet_UIP/{ => src}/utility/uip_arp.h | 0 .../{ => src}/utility/uip_clock.h | 0 .../{ => src}/utility/uip_debug.cpp | 0 .../{ => src}/utility/uip_debug.h | 0 .../{ => src}/utility/uip_timer.c | 0 .../{ => src}/utility/uip_timer.h | 0 .../{ => src}/utility/uipethernet-conf.h | 0 .../Ethernet_UIP/{ => src}/utility/uipopt.h | 0 .../AVR/Ethernet_UIP/{ => src}/utility/util.h | 0 .../AVR/Ethernet_UIP/tests/perl/tcpclient.pl | 34 ------ .../AVR/Ethernet_UIP/tests/perl/tcpserver.pl | 53 --------- .../AVR/Ethernet_UIP/tests/perl/udpclient.pl | 26 ---- .../AVR/Ethernet_UIP/tests/perl/udpserver.pl | 40 ------- .../EthernetGateway/EthernetGateway.ino | 5 +- 50 files changed, 206 insertions(+), 255 deletions(-) delete mode 100644 libraries/MySensors/core/MyProtocol.cpp rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/Dhcp.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/Dhcp.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/Dns.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/Dns.h (98%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPClient.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPClient.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPEthernet.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPEthernet.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPServer.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPServer.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPUdp.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/UIPUdp.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/ethernet_comp.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/Enc28J60Network.cpp (87%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/Enc28J60Network.h (92%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/clock-arch.c (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/clock-arch.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/enc28j60.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/mempool.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/mempool.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/mempool_conf.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip-conf.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip.c (96%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_arch.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_arp.c (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_arp.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_clock.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_debug.cpp (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_debug.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_timer.c (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uip_timer.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uipethernet-conf.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/uipopt.h (100%) rename libraries/MySensors/drivers/AVR/Ethernet_UIP/{ => src}/utility/util.h (100%) delete mode 100644 libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpclient.pl delete mode 100644 libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpserver.pl delete mode 100644 libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpclient.pl delete mode 100644 libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpserver.pl diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index f368f9f..4b54a51 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -26,7 +26,7 @@ #include "MyConfig.h" -#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) +#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) || defined(MY_GATEWAY_ENC28J60) #define MY_GATEWAY_FEATURE #define MY_NODE_TYPE "gateway" #elif defined(MY_REPEATER_FEATURE) @@ -102,6 +102,13 @@ // We assume that a gateway having a radio also should act as repeater #define MY_REPEATER_FEATURE #endif + #if defined(MY_CONTROLLER_IP_ADDRESS) + #define MY_GATEWAY_CLIENT_MODE + #endif + #if !defined(MY_PORT) + #error You must define MY_PORT (cotroller or gatway port to open) + #endif + #if defined(MY_GATEWAY_W5100) #include "drivers/AVR/Ethernet_W5100/utility/socket.cpp" #include "drivers/AVR/Ethernet_W5100/utility/w5100.cpp" @@ -110,13 +117,6 @@ #include "drivers/AVR/Ethernet_W5100/EthernetUdp.cpp" #include "drivers/AVR/Ethernet_W5100/IPAddress.cpp" - #if defined(MY_CONTROLLER_IP_ADDRESS) - #define MY_GATEWAY_CLIENT_MODE - #endif - - #if !defined(MY_PORT) - #error You must define MY_PORT (cotroller or gatway port to open) - #endif #if !defined(USE_UDP) #include "drivers/AVR/Ethernet_W5100/EthernetServer.cpp" #endif @@ -127,6 +127,23 @@ #else // What do we do here? #endif + #elif defined(MY_GATEWAY_ENC28J60) + #undef MY_USE_UDP // Will not fit (or compile) on ENC28J60 + #include "drivers/AVR/Ethernet_UIP/src/utility/uipethernet-conf.h" + #include "drivers/AVR/Ethernet_UIP/src/utility/uip-conf.h" + #include "drivers/AVR/Ethernet_UIP/src/UIPEthernet.h" + #include "drivers/AVR/Ethernet_UIP/src/utility/Enc28J60Network.cpp" + #include "drivers/AVR/Ethernet_UIP/src/utility/mempool_conf.h" + #include "drivers/AVR/Ethernet_UIP/src/utility/mempool.cpp" + #include "drivers/AVR/Ethernet_UIP/src/UIPEthernet.cpp" + #include "drivers/AVR/Ethernet_UIP/src/UIPServer.cpp" + #include "drivers/AVR/Ethernet_UIP/src/UIPClient.cpp" + #include "drivers/AVR/Ethernet_UIP/src/utility/clock-arch.c" + #include "drivers/AVR/Ethernet_UIP/src/utility/uip_timer.c" + #include "drivers/AVR/Ethernet_UIP/src/utility/uip.c" + #include "drivers/AVR/Ethernet_UIP/src/utility/uip_arp.c" + + #include "core/MyGatewayTransportEthernet.cpp" #elif defined(MY_GATEWAY_SERIAL) #include "core/MyGatewayTransportSerial.cpp" #endif diff --git a/libraries/MySensors/core/MyProtocol.cpp b/libraries/MySensors/core/MyProtocol.cpp deleted file mode 100644 index f0a473a..0000000 --- a/libraries/MySensors/core/MyProtocol.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/** - * The MySensors Arduino library handles the wireless radio link and protocol - * between your home built sensors/actuators and HA controller of choice. - * The sensors forms a self healing radio network with optional repeaters. Each - * repeater and gateway builds a routing tables in EEPROM which keeps track of the - * network topology allowing messages to be routed to nodes. - * - * Created by Henrik Ekblad - * Copyright (C) 2013-2015 Sensnology AB - * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors - * - * Documentation: http://www.mysensors.org - * Support Forum: http://forum.mysensors.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "MyProtocol.h" - -MyProtocol::MyProtocol() { -} diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/README b/libraries/MySensors/drivers/AVR/Ethernet_UIP/README index 321b334..c7368c6 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/README +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/README @@ -1,4 +1,4 @@ -This is UIPEthernet version 1.09 +This is UIPEthernet version 1.59 An plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. Just include 'UIPEthernet.h' instead of 'Ethernet.h' and use all your code written for the stock Arduino Ethernet lib! diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino index bc2f094..7b3b132 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -20,6 +20,7 @@ */ +#include #include // Enter a MAC address and IP address for your controller below. diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/EchoServer/EchoServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/EchoServer/EchoServer.ino index 62d66e4..8603001 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/EchoServer/EchoServer.ino +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/EchoServer/EchoServer.ino @@ -18,6 +18,7 @@ * Adaption to Enc28J60 by Norbert Truchsess */ +#include #include // The connection_data struct needs to be defined in an external file. #include diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpClient/TcpClient.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpClient/TcpClient.ino index dca685c..444b36a 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpClient/TcpClient.ino +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpClient/TcpClient.ino @@ -16,6 +16,7 @@ * Copyright (C) 2013 by Norbert Truchsess */ +#include #include EthernetClient client; diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpServer/TcpServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpServer/TcpServer.ino index 10512ec..b8a1e6d 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpServer/TcpServer.ino +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/TcpServer/TcpServer.ino @@ -18,6 +18,7 @@ * Adaption to Enc28J60 by Norbert Truchsess */ +#include #include EthernetServer server = EthernetServer(1000); diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpClient/UdpClient.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpClient/UdpClient.ino index aad56b4..f549c48 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpClient/UdpClient.ino +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpClient/UdpClient.ino @@ -16,6 +16,7 @@ * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) */ +#include #include EthernetUDP udp; diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpServer/UdpServer.ino b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpServer/UdpServer.ino index 3b12d75..06b94be 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpServer/UdpServer.ino +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/examples/UdpServer/UdpServer.ino @@ -14,6 +14,7 @@ * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) */ +#include #include EthernetUDP udp; diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/library.properties b/libraries/MySensors/drivers/AVR/Ethernet_UIP/library.properties index 158ae31..cd8c551 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/library.properties +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/library.properties @@ -4,7 +4,7 @@ email=Norbert Truchsess sentence=Ethernet library for ENC28J60 paragraph=implements the same API as stock Ethernet-lib. Just replace the include of Ethernet.h with UIPEthernet.h url=https://github.com/ntruchsess/arduino_uip -architectures=avr -version=1.04 +architectures=* +version=1.50 dependencies= core-dependencies=arduino (>=1.5.0) diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dhcp.cpp similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dhcp.cpp diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dhcp.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/Dhcp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dhcp.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dns.cpp similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dns.cpp diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dns.h similarity index 98% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dns.h index 4913ca8..1b6bb3d 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/Dns.h +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/Dns.h @@ -5,7 +5,7 @@ #ifndef DNSClient_h #define DNSClient_h -#include +#include "UIPUdp.h" class DNSClient { diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.cpp similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.cpp diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPClient.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.cpp similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.cpp diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPEthernet.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.cpp similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.cpp diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPServer.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPUdp.cpp similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPUdp.cpp diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPUdp.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/UIPUdp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPUdp.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/ethernet_comp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/ethernet_comp.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/ethernet_comp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/ethernet_comp.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/Enc28J60Network.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/Enc28J60Network.cpp similarity index 87% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/Enc28J60Network.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/Enc28J60Network.cpp index c7c66fb..9c154cd 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/Enc28J60Network.cpp +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/Enc28J60Network.cpp @@ -25,8 +25,19 @@ #include "Enc28J60Network.h" #include "Arduino.h" +#if ENC28J60_USE_SPILIB +#include +#endif + extern "C" { -#include + #if defined(ARDUINO_ARCH_AVR) + // AVR-specific code + #include + #elif defined(ARDUINO_ARCH_SAM) + // SAM-specific code + #else + // generic, non-platform specific code + #endif #include "enc28j60.h" #include "uip.h" } @@ -40,7 +51,15 @@ extern "C" { // set CS to 1 = passive #define CSPASSIVE digitalWrite(ENC28J60_CONTROL_CS, HIGH) // +#if defined(ARDUINO_ARCH_AVR) #define waitspi() while(!(SPSR&(1<tcpstateflags != UIP_CLOSED && conn->lport == htons(lastport)) { goto again; @@ -427,8 +427,8 @@ uip_connect(uip_ipaddr_t *ripaddr, u16_t rport) } conn = 0; - for(c = 0; c < UIP_CONNS; ++c) { - cconn = &uip_conns[c]; + for(cc = 0; cc < UIP_CONNS; ++cc) { + cconn = &uip_conns[cc]; if(cconn->tcpstateflags == UIP_CLOSED) { conn = cconn; break; @@ -482,17 +482,17 @@ uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) lastport = 4096; } - for(c = 0; c < UIP_UDP_CONNS; ++c) { - if(uip_udp_conns[c].lport == htons(lastport)) { + for(cc = 0; cc < UIP_UDP_CONNS; ++cc) { + if(uip_udp_conns[cc].lport == htons(lastport)) { goto again; } } conn = 0; - for(c = 0; c < UIP_UDP_CONNS; ++c) { - if(uip_udp_conns[c].lport == 0) { - conn = &uip_udp_conns[c]; + for(cc = 0; cc < UIP_UDP_CONNS; ++cc) { + if(uip_udp_conns[cc].lport == 0) { + conn = &uip_udp_conns[cc]; break; } } @@ -517,9 +517,9 @@ uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) void uip_unlisten(u16_t port) { - for(c = 0; c < UIP_LISTENPORTS; ++c) { - if(uip_listenports[c] == port) { - uip_listenports[c] = 0; + for(cc = 0; cc < UIP_LISTENPORTS; ++cc) { + if(uip_listenports[cc] == port) { + uip_listenports[cc] = 0; return; } } @@ -528,9 +528,9 @@ uip_unlisten(u16_t port) void uip_listen(u16_t port) { - for(c = 0; c < UIP_LISTENPORTS; ++c) { - if(uip_listenports[c] == 0) { - uip_listenports[c] = port; + for(cc = 0; cc < UIP_LISTENPORTS; ++cc) { + if(uip_listenports[cc] == 0) { + uip_listenports[cc] = port; return; } } @@ -1206,8 +1206,8 @@ uip_process(u8_t flag) tmp16 = BUF->destport; /* Next, check listening connections. */ - for(c = 0; c < UIP_LISTENPORTS; ++c) { - if(tmp16 == uip_listenports[c]) + for(cc = 0; cc < UIP_LISTENPORTS; ++cc) { + if(tmp16 == uip_listenports[cc]) goto found_listen; } @@ -1227,21 +1227,21 @@ uip_process(u8_t flag) BUF->tcpoffset = 5 << 4; /* Flip the seqno and ackno fields in the TCP header. */ - c = BUF->seqno[3]; + cc = BUF->seqno[3]; BUF->seqno[3] = BUF->ackno[3]; - BUF->ackno[3] = c; + BUF->ackno[3] = cc; - c = BUF->seqno[2]; + cc = BUF->seqno[2]; BUF->seqno[2] = BUF->ackno[2]; - BUF->ackno[2] = c; + BUF->ackno[2] = cc; - c = BUF->seqno[1]; + cc = BUF->seqno[1]; BUF->seqno[1] = BUF->ackno[1]; - BUF->ackno[1] = c; + BUF->ackno[1] = cc; - c = BUF->seqno[0]; + cc = BUF->seqno[0]; BUF->seqno[0] = BUF->ackno[0]; - BUF->ackno[0] = c; + BUF->ackno[0] = cc; /* We also have to increase the sequence number we are acknowledging. If the least significant byte overflowed, we need @@ -1277,15 +1277,15 @@ uip_process(u8_t flag) CLOSED connections are found. Thanks to Eddie C. Dost for a very nice algorithm for the TIME_WAIT search. */ uip_connr = 0; - for(c = 0; c < UIP_CONNS; ++c) { - if(uip_conns[c].tcpstateflags == UIP_CLOSED) { - uip_connr = &uip_conns[c]; + for(cc = 0; cc < UIP_CONNS; ++cc) { + if(uip_conns[cc].tcpstateflags == UIP_CLOSED) { + uip_connr = &uip_conns[cc]; break; } - if(uip_conns[c].tcpstateflags == UIP_TIME_WAIT) { + if(uip_conns[cc].tcpstateflags == UIP_TIME_WAIT) { if(uip_connr == 0 || - uip_conns[c].timer > uip_connr->timer) { - uip_connr = &uip_conns[c]; + uip_conns[cc].timer > uip_connr->timer) { + uip_connr = &uip_conns[cc]; } } } @@ -1325,19 +1325,19 @@ uip_process(u8_t flag) /* Parse the TCP MSS option, if present. */ if((BUF->tcpoffset & 0xf0) > 0x50) { - for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { - opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; + for(cc = 0; cc < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + cc]; if(opt == TCP_OPT_END) { /* End of options. */ break; } else if(opt == TCP_OPT_NOOP) { - ++c; + ++cc; /* NOP option. */ } else if(opt == TCP_OPT_MSS && - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + cc] == TCP_OPT_MSS_LEN) { /* An MSS option with the right option length. */ - tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | - (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; + tmp16 = ((u16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + cc] << 8) | + (u16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + cc]; uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; @@ -1346,12 +1346,12 @@ uip_process(u8_t flag) } else { /* All other options have a length field, so that we easily can skip past them. */ - if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + cc] == 0) { /* If the length field is zero, the options are malformed and we don't process them further. */ break; } - c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + cc += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + cc]; } } } @@ -1395,11 +1395,11 @@ uip_process(u8_t flag) } /* Calculated the length of the data, if the application has sent any data to us. */ - c = (BUF->tcpoffset >> 4) << 2; + cc = (BUF->tcpoffset >> 4) << 2; /* uip_len will contain the length of the actual TCP data. This is calculated by subtracing the length of the TCP header (in c) and the length of the IP header (20 bytes). */ - uip_len = uip_len - c - UIP_IPH_LEN; + uip_len = uip_len - cc - UIP_IPH_LEN; /* First, check if the sequence number of the incoming packet is what we're expecting next. If not, we send out an ACK with the @@ -1494,19 +1494,19 @@ uip_process(u8_t flag) /* Parse the TCP MSS option, if present. */ if((BUF->tcpoffset & 0xf0) > 0x50) { - for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { - opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; + for(cc = 0; cc < ((BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + cc]; if(opt == TCP_OPT_END) { /* End of options. */ break; } else if(opt == TCP_OPT_NOOP) { - ++c; + ++cc; /* NOP option. */ } else if(opt == TCP_OPT_MSS && - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + cc] == TCP_OPT_MSS_LEN) { /* An MSS option with the right option length. */ - tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + cc] << 8) | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + cc]; uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; @@ -1515,12 +1515,12 @@ uip_process(u8_t flag) } else { /* All other options have a length field, so that we easily can skip past them. */ - if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + cc] == 0) { /* If the length field is zero, the options are malformed and we don't process them further. */ break; } - c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + cc += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + cc]; } } } diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arch.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arch.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arch.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arch.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.c similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.c rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.c diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_arp.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_clock.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_clock.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_clock.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_clock.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_debug.cpp similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.cpp rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_debug.cpp diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_debug.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_debug.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_debug.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_timer.c similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.c rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_timer.c diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_timer.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uip_timer.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_timer.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipethernet-conf.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uipethernet-conf.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipethernet-conf.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uipethernet-conf.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipopt.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uipopt.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/uipopt.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uipopt.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/util.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/util.h similarity index 100% rename from libraries/MySensors/drivers/AVR/Ethernet_UIP/utility/util.h rename to libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/util.h diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpclient.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpclient.pl deleted file mode 100644 index e6884dc..0000000 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpclient.pl +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/perl -#tcpclient.pl - -use IO::Socket::INET; - -# flush after every write -$| = 1; - -my ($socket,$client_socket); - -# creating object interface of IO::Socket::INET modules which internally creates -# socket, binds and connects to the TCP server running on the specific port. -$socket = new IO::Socket::INET ( -PeerHost => '192.168.0.6', -PeerPort => '1000', -Proto => 'tcp', -) or die "ERROR in Socket Creation : $!\n"; - -print "TCP Connection Success.\n"; - -# write on the socket to server. -$data = "DATA from Client"; -print $socket "$data\n"; -# we can also send the data through IO::Socket::INET module, -# $socket->send($data); - -# read the socket data sent by server. -$data = <$socket>; -# we can also read from socket through recv() in IO::Socket::INET -# $socket->recv($data,1024); -print "Received from Server : $data\n"; - -sleep (10); -$socket->close(); \ No newline at end of file diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpserver.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpserver.pl deleted file mode 100644 index 17405a3..0000000 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/tcpserver.pl +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl -#tcpserver.pl - -use IO::Socket::INET; - -# flush after every write -$| = 1; - -my ($socket,$client_socket); -my ($peeraddress,$peerport); - -# creating object interface of IO::Socket::INET modules which internally does -# socket creation, binding and listening at the specified port address. -$socket = new IO::Socket::INET ( -LocalHost => '192.168.0.1', -LocalPort => '5000', -Proto => 'tcp', -Listen => 5, -Reuse => 1 -) or die "ERROR in Socket Creation : $!\n"; - -print "SERVER Waiting for client connection on port 5000\n"; - -while(1) -{ - # waiting for new client connection. - $client_socket = $socket->accept(); - - # get the host and port number of newly connected client. - $peer_address = $client_socket->peerhost(); - $peer_port = $client_socket->peerport(); - - print "Accepted New Client Connection From : $peer_address, $peer_port\n "; - - # read operation on the newly accepted client - $data = <$client_socket>; - # we can also read from socket through recv() in IO::Socket::INET - # $client_socket->recv($data,1024); - print "Received from Client : $data\n"; - - # write operation on the newly accepted client. - $data = "DATA from Server"; - print $client_socket "$data\n"; - # we can also send the data through IO::Socket::INET module, - # $client_socket->send($data); - - sleep(1); - - $client_socket->close(); -} - -$socket->close(); - diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpclient.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpclient.pl deleted file mode 100644 index bc9e6a2..0000000 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpclient.pl +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/perl -#udpclient.pl - -use IO::Socket::INET; - -# flush after every write -$| = 1; - -my ($socket,$data); - -# We call IO::Socket::INET->new() to create the UDP Socket -# and bind with the PeerAddr. -$socket = new IO::Socket::INET ( -PeerAddr => '192.168.0.6:5000', -Proto => 'udp' -) or die "ERROR in Socket Creation : $!\n"; -#send operation -$data = "data from client"; -$socket->send($data); - -#read operation -$data = <$socket>; -print "Data received from socket : $data\n "; - -sleep(10); -$socket->close(); diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpserver.pl b/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpserver.pl deleted file mode 100644 index e728a46..0000000 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/tests/perl/udpserver.pl +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/perl -#udpserver.pl - -use IO::Socket::INET; - -# flush after every write -$| = 1; - -my ($socket,$received_data); -my ($peeraddress,$peerport); - -# we call IO::Socket::INET->new() to create the UDP Socket and bound -# to specific port number mentioned in LocalPort and there is no need to provide -# LocalAddr explicitly as in TCPServer. -$socket = new IO::Socket::INET ( -LocalPort => '5000', -Proto => 'udp', -) or die "ERROR in Socket Creation : $!\n"; - -while(1) -{ -# read operation on the socket -$socket->recv($recieved_data,1024); - -#get the peerhost and peerport at which the recent data received. -$peer_address = $socket->peerhost(); -$peer_port = $socket->peerport(); -print "($peer_address , $peer_port) said : $recieved_data\n"; - -#send the data to the client at which the read/write operations done recently. -$data = "data from server\n"; - -$socket->send($data); - -print $socket "$data"; - -} - -$socket->close(); - diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 3dd66d8..79c1e08 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -63,8 +63,9 @@ #define MY_RADIO_NRF24 -// W5100 Ethernet gateway -#define MY_GATEWAY_W5100 +// Enable gateway type +//#define MY_GATEWAY_W5100 +#define MY_GATEWAY_ENC28J60 // Set default gateway protocol (http://www.mysensors.org/download/serial_api_15) #define MY_GATEWAY_PROTOCOL_DEFAULT From ba9288506494ee318113514f63ea78027675f4e9 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Mon, 14 Sep 2015 15:52:43 +0200 Subject: [PATCH 14/43] Document MyConfig.h --- libraries/MySensors/MyConfig.h | 56 +++++++++++++++---- libraries/MySensors/MySensor.h | 17 +++--- .../EthernetGateway/EthernetGateway.ino | 4 +- .../examples/MotionSensor/MotionSensor.ino | 7 ++- 4 files changed, 60 insertions(+), 24 deletions(-) diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index c8323be..818eae5 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -22,6 +22,11 @@ #define MyConfig_h #include + +/********************************** +* Serial and debug options +***********************************/ + // Enables this in sketch to show debug prints. This option will add a lot to the size of the // final sketch but is helpful to see what is actually is happening during development //#define MY_DEBUG @@ -34,11 +39,21 @@ #undef MY_DEBUG #endif -// Serial output baud rate (for debug prints and serial gateway) +// Serial output baud rate (debug prints and serial gateway speed) #ifndef MY_BAUD_RATE #define MY_BAUD_RATE 115200 #endif +/********************************** +* Radio selection and modes +***********************************/ + +// Selecting radio transport is optional (for a gateway node). + +//#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + + // Node id defaults to AUTO (tries to fetch id from controller) #ifndef MY_NODE_ID #define MY_NODE_ID AUTO @@ -57,7 +72,7 @@ ***********************************/ // Enable MY_OTA_FIRMWARE_FEATURE in sketch to allow safe over-the-air firmware updates. -// This feature requires external flash and the DualOptiBoot bootloader. +// This feature requires external flash and the DualOptiBoot boot-loader. // Note: You can still have OTA FW updates without external flash but it // requires the MYSBootloader and disabled MY_OTA_FIRMWARE_FEATURE //#define MY_OTA_FIRMWARE_FEATURE @@ -174,22 +189,22 @@ * NRF24L01 Driver Defaults ***********************************/ #ifndef MY_RF24_CE_PIN -#define MY_RF24_CE_PIN 9 +#define MY_RF24_CE_PIN 9 #endif #ifndef MY_RF24_CS_PIN -#define MY_RF24_CS_PIN 10 +#define MY_RF24_CS_PIN 10 #endif #ifndef MY_RF24_PA_LEVEL -#define MY_RF24_PA_LEVEL RF24_PA_MAX +#define MY_RF24_PA_LEVEL RF24_PA_MAX #endif // RF channel for the sensor net, 0-127 #ifndef MY_RF24_CHANNEL -#define MY_RF24_CHANNEL 76 +#define MY_RF24_CHANNEL 76 #endif //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps #ifndef MY_RF24_DATARATE -#define MY_RF24_DATARATE RF24_250KBPS +#define MY_RF24_DATARATE RF24_250KBPS #endif // This is also act as base value for sensor nodeId addresses. Change this (or channel) if you have more than one sensor network. #ifndef MY_RF24_BASE_RADIO_ID @@ -246,11 +261,26 @@ #endif /************************************** -* Gateway Transport Ethernet Defaults +* Ethernet Gateway Transport Defaults ***************************************/ -// Enable to use DHCP for getting IP address. If not defined, static IP is expected -//#define MY_IP_ADDRESS_VIA_DHCP +// The gateway options available +//#define MY_GATEWAY_W5100 +//#define MY_GATEWAY_ENC28J60 +//#define MY_GATEWAY_ESP8266 + +// The port to open on controller or gateway +#ifndef MY_PORT +#define MY_PORT 5003 +#endif + +// Static ip address of gateway (if this is disabled, DHCP will be used) +//#define MY_IP_ADDRESS 192,168,178,66 + +// Enables UDP mode for Ethernet gateway (W5100) +//#define MY_USE_UDP + +// DHCP, default renewal setting #ifndef MY_IP_RENEWAL_INTERVAL #define MY_IP_RENEWAL_INTERVAL 60000 #endif @@ -258,7 +288,9 @@ #ifndef MY_MAC_ADDRESS #define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED #endif -// Enable to use UDP instead of plain Ethernet -//#define MY_USE_UDP + +// Controller ip-address, if this is defined, gateway will act as a client trying to contact controller on MY_PORT. +// If MY_CONTROLLER_IP_ADDRESS is left un-defined, gateway acts as server allowing incoming connections. +//#define MY_CONTROLLER_IP_ADDRESS 192, 168, 178, 254 #endif diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 4b54a51..7f80bda 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -35,8 +35,6 @@ #define MY_NODE_TYPE "sensor" #endif -// CORE - // HARDWARE #if defined(ARDUINO_ARCH_ESP8266) @@ -184,14 +182,17 @@ extern void setup(); extern void loop(); -// Initialize library and call sketch functions +#include +// Initialize library and handle sketch functions like we want to int main() { - begin(); - setup(); + init(); // Init Arduino + begin(); // Startup MySensors library + setup(); // Call sketch setup while(1) { - // We handle incoming message processing here - process(); - loop(); + process(); // Process incoming data + loop(); // Call sketch loop + if (serialEventRun) serialEventRun(); } + return 0; } #endif diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 79c1e08..29f6870 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -64,8 +64,8 @@ // Enable gateway type -//#define MY_GATEWAY_W5100 -#define MY_GATEWAY_ENC28J60 + + // Set default gateway protocol (http://www.mysensors.org/download/serial_api_15) #define MY_GATEWAY_PROTOCOL_DEFAULT diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino index 7687d7b..35483f6 100644 --- a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -28,14 +28,17 @@ */ //#define MY_DEBUG + +#define MY_RADIO_NRF24 // MY_RADIO_RFM69 + //#define MY_SOFTSPI //#define MY_OTA_FIRMWARE_FEATURE -#define MY_SIGNING_SOFT +//#define MY_SIGNING_SOFT +//#define MY_REPEATER_FEATURE // #define MY_GATEWAY_SERIAL // REMOVE-ME // #define MY_GATEWAY_PROTOCOL_DEFAULT // REMOVE-ME -#define MY_RADIO_NRF24 // MY_RADIO_RFM69 #include From 4f4f0605c09cc1222607d51343e16728ee0e7d67 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Tue, 15 Sep 2015 00:28:47 +0200 Subject: [PATCH 15/43] Split out some more components to make core class cleaner --- libraries/MySensors/MyConfig.h | 4 +- libraries/MySensors/MySensor.h | 75 +- .../MySensors/core/MyGatewayTransport.cpp | 56 ++ libraries/MySensors/core/MyGatewayTransport.h | 24 +- .../core/MyGatewayTransportEthernet.cpp | 2 +- .../core/MyGatewayTransportSerial.cpp | 2 +- libraries/MySensors/core/MyInclusionMode.cpp | 59 ++ libraries/MySensors/core/MyInclusionMode.h | 35 + libraries/MySensors/core/MyLeds.cpp | 99 +++ libraries/MySensors/core/MyLeds.h | 54 ++ libraries/MySensors/core/MySensorCore.cpp | 820 +----------------- libraries/MySensors/core/MySensorCore.h | 133 +-- libraries/MySensors/core/MySigning.cpp | 5 + libraries/MySensors/core/MySigning.h | 6 + libraries/MySensors/core/MyTransport.cpp | 547 ++++++++++++ libraries/MySensors/core/MyTransport.h | 78 +- libraries/MySensors/core/MyTransportNRF24.h | 8 - libraries/MySensors/core/MyTransportRFM69.h | 8 - libraries/MySensors/drivers/pubsubclient | 1 + .../EthernetGateway/EthernetGateway.ino | 6 +- .../examples/MotionSensor/MotionSensor.ino | 7 +- 21 files changed, 1096 insertions(+), 933 deletions(-) create mode 100644 libraries/MySensors/core/MyGatewayTransport.cpp create mode 100644 libraries/MySensors/core/MyInclusionMode.cpp create mode 100644 libraries/MySensors/core/MyInclusionMode.h create mode 100644 libraries/MySensors/core/MyLeds.cpp create mode 100644 libraries/MySensors/core/MyLeds.h create mode 100644 libraries/MySensors/core/MyTransport.cpp create mode 160000 libraries/MySensors/drivers/pubsubclient diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index 818eae5..dc014fc 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -95,9 +95,9 @@ // but now can be used in any sensor node. Also the LEDs can now be // disabled in the gateway. -//#define MY_WITH_LEDS_BLINKING +//#define MY_LEDS_BLINKING_FEATURE -// The following setting allows you to inverse the blinking feature WITH_LEDS_BLINKING +// The following setting allows you to inverse the blinking feature MY_LEDS_BLINKING_FEATURE // When WITH_LEDS_BLINKING_INVERSE is enabled LEDSs are normally turned on and switches // off when blinking diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 7f80bda..62951a9 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -45,6 +45,19 @@ #include "core/MyHwATMega328.cpp" #endif +// LEDS +#if defined(MY_LEDS_BLINKING_FEATURE) + #include "core/MyLeds.cpp" +#else + #include "core/MyLeds.h" +#endif + +// INCLUSION MODE +#if defined(MY_INCLUSION_MODE_FEATURE) + #include "core/MyInclusionMode.cpp" +#endif + + // SIGNING #if defined(MY_SIGNING_ATSHA204) || defined(MY_SIGNING_SOFT) #include "MySigning.cpp" @@ -60,42 +73,21 @@ #endif #endif -// RADIO -#if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) - #define MY_RADIO_FEATURE - // SOFTSPI - #ifdef MY_SOFTSPI - #if defined(ARDUINO_ARCH_ESP8266) - #error Soft SPI is not available on ESP8266 - #endif - #include "drivers/AVR/DigitalIO/SoftI2cMaster.cpp" - #include "drivers/AVR/DigitalIO/PinIO.cpp" - #endif - - // FLASH - #ifdef MY_OTA_FIRMWARE_FEATURE - #include "drivers/SPIFlash/SPIFlash.cpp" - SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); - #endif - - #if defined(MY_RADIO_NRF24) - #include "drivers/RF24/RF24.cpp" - #include "core/MyTransportNRF24.cpp" - #elif defined(MY_RADIO_RFM69) - #include "drivers/RFM69/RFM69.cpp" - #include "core/MyTransportRFM69.cpp" - #endif -#endif // GATEWAY - TRANSPORT #if defined(MY_GATEWAY_FEATURE) + // GATEWAY - COMMON FUNCTIONS + #include "core/MyGatewayTransport.cpp" + // GATEWAY - PROTOCOL #if defined(MY_GATEWAY_PROTOCOL_DEFAULT) #include "core/MyProtocolDefault.cpp" #else #error No gateway protocol specified! #endif + + // GATEWAY - CONFIGURATION #if defined(MY_RADIO_FEATURE) // We assume that a gateway having a radio also should act as repeater #define MY_REPEATER_FEATURE @@ -108,6 +100,7 @@ #endif #if defined(MY_GATEWAY_W5100) + // GATEWAY - W5100 #include "drivers/AVR/Ethernet_W5100/utility/socket.cpp" #include "drivers/AVR/Ethernet_W5100/utility/w5100.cpp" #include "drivers/AVR/Ethernet_W5100/DNS.cpp" @@ -126,6 +119,7 @@ // What do we do here? #endif #elif defined(MY_GATEWAY_ENC28J60) + // GATEWAY - ENC28J60 #undef MY_USE_UDP // Will not fit (or compile) on ENC28J60 #include "drivers/AVR/Ethernet_UIP/src/utility/uipethernet-conf.h" #include "drivers/AVR/Ethernet_UIP/src/utility/uip-conf.h" @@ -143,6 +137,7 @@ #include "core/MyGatewayTransportEthernet.cpp" #elif defined(MY_GATEWAY_SERIAL) + // GATEWAY - SERIAL #include "core/MyGatewayTransportSerial.cpp" #endif #else @@ -175,6 +170,34 @@ #define MY_IS_GATEWAY false #endif +// RADIO +#if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) + #define MY_RADIO_FEATURE + // SOFTSPI + #ifdef MY_SOFTSPI + #if defined(ARDUINO_ARCH_ESP8266) + #error Soft SPI is not available on ESP8266 + #endif + #include "drivers/AVR/DigitalIO/SoftI2cMaster.cpp" + #include "drivers/AVR/DigitalIO/PinIO.cpp" + #endif + + // FLASH + #ifdef MY_OTA_FIRMWARE_FEATURE + #include "drivers/SPIFlash/SPIFlash.cpp" + SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); + #endif + #include "core/MyTransport.cpp" + #if defined(MY_RADIO_NRF24) + #include "drivers/RF24/RF24.cpp" + #include "core/MyTransportNRF24.cpp" + #elif defined(MY_RADIO_RFM69) + #include "drivers/RFM69/RFM69.cpp" + #include "core/MyTransportRFM69.cpp" + #endif +#endif + + #include "core/MyMessage.cpp" #include "core/MySensorCore.cpp" diff --git a/libraries/MySensors/core/MyGatewayTransport.cpp b/libraries/MySensors/core/MyGatewayTransport.cpp new file mode 100644 index 0000000..0072946 --- /dev/null +++ b/libraries/MySensors/core/MyGatewayTransport.cpp @@ -0,0 +1,56 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Tomas Hozza + * Copyright (C) 2015 Tomas Hozza + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "MyGatewayTransport.h" + +inline void gatewayTransportProcess() { + if (gatewayTransportAvailable()) { + MyMessage &_msg = gatewayTransportReceive(); + if (_msg.destination == GATEWAY_ADDRESS) { + // Check if sender requests an ack back. + if (mGetRequestAck(_msg)) { + // Copy message + _msgTmp = _msg; + mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetAck(_msgTmp, true); + _msgTmp.sender = _nc.nodeId; + _msgTmp.destination = _msg.sender; + gatewayTransportSend(_msgTmp); + } + if (mGetCommand(_msg) == C_INTERNAL) { + if (_msg.type == I_VERSION) { + // Request for version. Create the response + gatewayTransportSend(buildGw(_msg, I_VERSION).set(LIBRARY_VERSION)); + #ifdef MY_INCLUSION_MODE_FEATURE + } else if (_msg.type == I_INCLUSION_MODE) { + // Request to change inclusion mode + inclusionModeSet(atoi(_msg.data) == 1); + #endif + } else { + processInternalMessages(); + } + } else { + // Call incoming message callback if available + if (_msgCallback != NULL) { + _msgCallback(_msg); + } + } + } + } +} diff --git a/libraries/MySensors/core/MyGatewayTransport.h b/libraries/MySensors/core/MyGatewayTransport.h index 4df3244..e971bd1 100644 --- a/libraries/MySensors/core/MyGatewayTransport.h +++ b/libraries/MySensors/core/MyGatewayTransport.h @@ -23,19 +23,33 @@ #include "MyConfig.h" #include "MyMessage.h" #include "MyProtocol.h" +#include "MySensorCore.h" + +// Common gateway functions + +void gatewayTransportProcess(); +// Gateway "interface" functions -// initialize the driver -bool gatewayTransportBegin(); +/** + * initialize the driver + */ +bool gatewayTransportInit(); -// Send message to controller +/** + * Send message to controller + */ bool gatewayTransportSend(MyMessage &message); -// Check if a new message is available from controller +/* + * Check if a new message is available from controller + */ bool gatewayTransportAvailable(); -// Pick up last message received from controller +/* + * Pick up last message received from controller + */ MyMessage& gatewayTransportReceive(); #endif /* MyGatewayTransportEthernet_h */ diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp index 18bd233..8e661fd 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.cpp +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.cpp @@ -35,7 +35,7 @@ MyMessage _ethernetMsg; #endif /* USE_UDP */ -bool gatewayTransportBegin() { +bool gatewayTransportInit() { #ifdef MY_IP_ADDRESS Ethernet.begin(_ethernetGatewayMAC, _ethernetGatewayIP); #else diff --git a/libraries/MySensors/core/MyGatewayTransportSerial.cpp b/libraries/MySensors/core/MyGatewayTransportSerial.cpp index 313efac..390dc17 100644 --- a/libraries/MySensors/core/MyGatewayTransportSerial.cpp +++ b/libraries/MySensors/core/MyGatewayTransportSerial.cpp @@ -26,7 +26,7 @@ MyMessage _serialMsg; -bool gatewayTransportBegin() { +bool gatewayTransportInit() { return true; } diff --git a/libraries/MySensors/core/MyInclusionMode.cpp b/libraries/MySensors/core/MyInclusionMode.cpp new file mode 100644 index 0000000..604983a --- /dev/null +++ b/libraries/MySensors/core/MyInclusionMode.cpp @@ -0,0 +1,59 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "MyInclusionMode.h" + +unsigned long _inclusionStartTime; +bool _inclusionMode; + +inline void inclusionInit() { + _inclusionMode = false; + #if defined(MY_INCLUSION_BUTTON_FEATURE) + // Setup digital in that triggers inclusion mode + pinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); + digitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); + #endif + +} + + +void inclusionModeSet(boolean newMode) { + if (newMode != inclusionMode) { + _inclusionMode = newMode; + // Send back mode change to controller + gatewayTransportSend(buildGw(_msg, I_INCLUSION_MODE).set(_inclusionMode?1:0)); + if (_inclusionMode) { + _inclusionStartTime = hwMillis(); + } + } +} + +inline void inclusionProcess() { + #ifdef MY_INCLUSION_BUTTON_FEATURE + if (!inclusionMode && digitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == LOW) { + // Start inclusion mode + inclusionModeSet(true); + } + #endif + + if (_inclusionMode && hwMillis()-_inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { + // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode + inclusionModeSet(false); + } +} diff --git a/libraries/MySensors/core/MyInclusionMode.h b/libraries/MySensors/core/MyInclusionMode.h new file mode 100644 index 0000000..03ac12b --- /dev/null +++ b/libraries/MySensors/core/MyInclusionMode.h @@ -0,0 +1,35 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyInclusionMode_h +#define MyInclusionMode_h + +#include "MySensorCore.h" + +unsigned long inclusionStartTime; +bool inclusionMode; + +extern bool gatewayTransportSend(MyMessage &message); + +void inclusionInit(); +void inclusionModeSet(boolean newMode); +void inclusionProcess(); + + +#endif diff --git a/libraries/MySensors/core/MyLeds.cpp b/libraries/MySensors/core/MyLeds.cpp new file mode 100644 index 0000000..10ce2f5 --- /dev/null +++ b/libraries/MySensors/core/MyLeds.cpp @@ -0,0 +1,99 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "MyLeds.h" + +// these variables don't need to be volatile, since we are not using interrupts +uint8_t _countRx; +uint8_t _countTx; +uint8_t _countErr; +unsigned long _blink_next_time; + +inline void ledsInit() { + // Setup led pins + pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); + pinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); + pinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); + + // Set initial state of leds + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); + + // initialize counters + _countRx = 0; + _countTx = 0; + _countErr = 0; +} + +inline void ledsProcess() { + // Just return if it is not the time... + // http://playground.arduino.cc/Code/TimingRollover + if ((long)(hwMillis() - _blink_next_time) < 0) + return; + else + _blink_next_time = hwMillis() + MY_DEFAULT_LED_BLINK_PERIOD; + + // do the actual blinking + if(_countRx && _countRx != 255) { + // switch led on + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_ON); + } + else if(!_countRx) { + // switching off + hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); + } + if(_countRx != 255) + --_countRx; + + if(_countTx && _countTx != 255) { + // switch led on + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_ON); + } + else if(!_countTx) { + // switching off + hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); + } + if(_countTx != 255) + --_countTx; + + if(_countErr && _countErr != 255) { + // switch led on + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_ON); + } + else if(!_countErr) { + // switching off + hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); + } + if(_countErr != 255) + --_countErr; +} + +void ledsBlinkRx(uint8_t cnt) { + if(_countRx == 255) { _countRx = cnt; } +} + +void ledsBlinkTx(uint8_t cnt) { + if(_countTx == 255) { _countTx = cnt; } +} + +void ledsBlinkErr(uint8_t cnt) { + if(_countErr == 255) { _countErr = cnt; } +} + diff --git a/libraries/MySensors/core/MyLeds.h b/libraries/MySensors/core/MyLeds.h new file mode 100644 index 0000000..6549f36 --- /dev/null +++ b/libraries/MySensors/core/MyLeds.h @@ -0,0 +1,54 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef MyLeds_h +#define MyLeds_h + + +#ifdef WITH_LEDS_BLINKING_INVERSE +#define LED_ON 0x1 +#define LED_OFF 0x0 +#else +#define LED_ON 0x0 +#define LED_OFF 0x1 +#endif + +#ifdef MY_LEDS_BLINKING_FEATURE + #define ledBlinkTx(x,...) ledsBlinkTx(x) + #define ledBlinkRx(x,...) ledsBlinkRx(x) + #define ledBlinkErr(x,...) ledsBlinkErr(x) + + /** + * Blink with LEDs + * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms + */ + void ledsInit(); + void ledsBlinkRx(uint8_t cnt); + void ledsBlinkTx(uint8_t cnt); + void ledsBlinkErr(uint8_t cnt); + void ledsProcess(); // do the actual blinking + +#else + // Remove led functions if feature is disabled + #define ledBlinkTx(x,...) + #define ledBlinkRx(x,...) + #define ledBlinkErr(x,...) +#endif + +#endif diff --git a/libraries/MySensors/core/MySensorCore.cpp b/libraries/MySensors/core/MySensorCore.cpp index 0d8b496..da576b6 100644 --- a/libraries/MySensors/core/MySensorCore.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -17,41 +17,12 @@ * version 2 as published by the Free Software Foundation. */ - - #include "MySensorCore.h" - -NodeConfig _nc; // Essential settings for node to work ControllerConfig _cc; // Configuration coming from controller -#ifdef MY_OTA_FIRMWARE_FEATURE -NodeFirmwareConfig _fc; -bool _fwUpdateOngoing; -unsigned long _fwLastRequestTime; -uint16_t _fwBlock; -uint8_t _fwRetry; -#endif - -#ifdef MY_RADIO_FEATURE -bool _autoFindParent; -uint8_t _failedTransmissions; -#endif - +NodeConfig _nc; // Essential settings for node to work MyMessage _msg; // Buffer for incoming messages. -MyMessage _msgTmp ; // Buffer for temporary messages (acks and nonces among others). - -#ifdef MY_LEDS_BLINKING_FEATURE -// these variables don't need to be volatile, since we are not using interrupts -uint8_t _countRx; -uint8_t _countTx; -uint8_t _countErr; -unsigned long _blink_next_time; -#endif - -#ifdef MY_SIGNING_FEATURE -uint16_t _doSign[16]; // Bitfield indicating which sensors require signed communication -MyMessage _msgSign; // Buffer for message to sign. -#endif +MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others). #ifdef MY_DEBUG char convBuf[MAX_PAYLOAD*2+1]; @@ -62,124 +33,30 @@ void (*_timeCallback)(unsigned long); // Callback for requested time messages void (*_msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. -#define DISTANCE_INVALID (0xFF) +void process() { + hwWatchdogReset(); -#ifdef MY_SIGNING_FEATURE -// Macros for manipulating signing requirement table -#define DO_SIGN(node) (node == 0 ? (~_doSign[0]&1) : (~_doSign[node>>4]&(node%16))) -#define SET_SIGN(node) (node == 0 ? (_doSign[0]&=~1) : (_doSign[node>>4]&=~(node%16))) -#define CLEAR_SIGN(node) (node == 0 ? (_doSign[0]|=1) : (_doSign[node>>4]|=(node%16))) -#endif + #if defined (MY_LEDS_BLINKING_FEATURE) + ledsProcess(); + #endif -// Inline function and macros -static inline MyMessage& build(MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { - msg.sender = sender; - msg.destination = destination; - msg.sensor = sensor; - msg.type = type; - mSetCommand(msg,command); - mSetRequestAck(msg,enableAck); - mSetAck(msg,false); - return msg; + #if defined(MY_INCLUSION_MODE_FEATURE) + inclusionProcess(); + #endif + + #if defined(MY_GATEWAY_FEATURE) + gatewayTransportProcess(); + #endif + + #if defined(MY_RADIO_FEATURE) + transportProcess(); + #endif } -static inline MyMessage& buildGw(MyMessage &msg, uint8_t type) { - msg.sender = GATEWAY_ADDRESS; - msg.destination = GATEWAY_ADDRESS; - msg.sensor = 0; - msg.type = type; - mSetCommand(msg, C_INTERNAL); - mSetRequestAck(msg, false); - mSetAck(msg, false); - return msg; -} static inline bool isValidParent( const uint8_t parent ) { return parent != AUTO; } -static inline bool isValidDistance( const uint8_t distance ) { - return distance != DISTANCE_INVALID; -} - - - -#ifdef MY_OTA_FIRMWARE_FEATURE -// do a crc16 on the whole received firmware -bool isValidFirmware() { - // init crc - uint16_t crc = ~0; - for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) { - crc ^= _flash.readByte(i + FIRMWARE_START_OFFSET); - for (int8_t j = 0; j < 8; ++j) { - if (crc & 1) - crc = (crc >> 1) ^ 0xA001; - else - crc = (crc >> 1); - } - } - return crc == _fc.crc; -} - -#endif - -#ifdef MY_LEDS_BLINKING_FEATURE -void handleLedsBlinking() { - static unsigned long next_time = hwMillis() + MY_DEFAULT_LED_BLINK_PERIOD; - - // Just return if it is not the time... - // http://playground.arduino.cc/Code/TimingRollover - if ((long)(hwMillis() - _blink_next_time) < 0) - return; - else - _blink_next_time = hwMillis() + ledBlinkPeriod; - - // do the actual blinking - if(_countRx && _countRx != 255) { - // switch led on - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_ON); - } - else if(!_countRx) { - // switching off - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); - } - if(_countRx != 255) - --_countRx; - - if(_countTx && _countTx != 255) { - // switch led on - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_ON); - } - else if(!_countTx) { - // switching off - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); - } - if(_countTx != 255) - --_countTx; - - if(_countErr && _countErr != 255) { - // switch led on - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_ON); - } - else if(!_countErr) { - // switching off - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); - } - if(_countErr != 255) - --_countErr; -} - -void rxBlink(uint8_t cnt) { - if(_countRx == 255) { _countRx = cnt; } -} - -void txBlink(uint8_t cnt) { - if(_countTx == 255) { _countTx = cnt; } -} - -void errBlink(uint8_t cnt) { - if(_countErr == 255) { _countErr = cnt; } -} -#endif void dataCallback(void (*msgCallback)(const MyMessage &)) { @@ -187,29 +64,21 @@ void dataCallback(void (*msgCallback)(const MyMessage &)) { } void begin() { - - #if defined(MY_INCLUSION_MODE_FEATURE) - inclusionMode = false; - #endif - - #ifndef MY_DISABLED_SERIAL + #if defined(MY_DISABLED_SERIAL) hwInit(); #endif - #ifdef MY_GATEWAY_FEATURE - #if defined(MY_INCLUSION_MODE_FEATURE) && defined(MY_INCLUSION_BUTTON_FEATURE) - // Setup digital in that triggers inclusion mode - pinMode(MY_INCLUSION_MODE_BUTTON_PIN, INPUT); - digitalWrite(MY_INCLUSION_MODE_BUTTON_PIN, HIGH); + #if defined(MY_GATEWAY_FEATURE) + #if defined(MY_INCLUSION_BUTTON_FEATURE) + inclusionInit(); #endif - // initialize the transport driver - if (!gatewayTransportBegin()) { + + // initialize the transport driver + if (!gatewayTransportInit()) { debug(PSTR("transport driver init fail\n")); while(1); // Nothing more we can do } - #endif - #if defined(MY_GATEWAY_FEATURE) gatewayTransportSend(buildGw(_msg, I_GATEWAY_READY).set("Gateway startup complete.")); #endif @@ -223,27 +92,14 @@ void begin() { } #endif - #ifdef MY_SIGNING_FEATURE + #if defined(MY_SIGNING_FEATURE) // Read out the signing requirements from EEPROM hwReadConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(_doSign)); #endif -#ifdef MY_LEDS_BLINKING_FEATURE - // Setup led pins - pinMode(MY_DEFAULT_RX_LED_PIN, OUTPUT); - pinMode(MY_DEFAULT_TX_LED_PIN, OUTPUT); - pinMode(MY_DEFAULT_ERR_LED_PIN, OUTPUT); - - // Set initial state of leds - hwDigitalWrite(MY_DEFAULT_RX_LED_PIN, LED_OFF); - hwDigitalWrite(MY_DEFAULT_TX_LED_PIN, LED_OFF); - hwDigitalWrite(MY_DEFAULT_ERR_LED_PIN, LED_OFF); - - // initialize counters - _countRx = 0; - _countTx = 0; - _countErr = 0; -#endif + #if defined(MY_LEDS_BLINKING_FEATURE) + ledsInit(); + #endif // Read latest received controller configuration from EEPROM hwReadConfigBlock((void*)&_cc, (void*)EEPROM_CONTROLLER_CONFIG_ADDRESS, sizeof(ControllerConfig)); @@ -277,7 +133,7 @@ void begin() { _nc.distance = 1; } else if (!isValidParent(_nc.parentNodeId)) { // Auto find parent, but parent in eeprom is invalid. Try find one. - findParentNode(); + transportFindParentNode(); } if (MY_NODE_ID != AUTO) { @@ -287,12 +143,12 @@ void begin() { hwWriteConfig(EEPROM_NODE_ID_ADDRESS, MY_NODE_ID); } else if (_nc.nodeId == AUTO && isValidParent(_nc.parentNodeId)) { // Try to fetch node-id from gateway - requestNodeId(); + transportRequestNodeId(); } #endif #if defined(MY_RADIO_FEATURE) - setupNode(); + transportSetupNode(); #endif debug(PSTR("%s started, id=%d, parent=%d, distance=%d\n"), MY_NODE_TYPE, _nc.nodeId, _nc.parentNodeId, _nc.distance); } @@ -308,271 +164,23 @@ ControllerConfig getConfig() { return _cc; } -#if defined(MY_RADIO_FEATURE) -void requestNodeId() { - debug(PSTR("req id\n")); - transportSetAddress(_nc.nodeId); - build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set(""); - sendWrite(_nc.parentNodeId, _msg); - wait(2000); -} -#endif - -#if defined(MY_RADIO_FEATURE) - - -void setupNode() { - // Open reading pipe for messages directed to this node (set write pipe to same) - transportSetAddress(_nc.nodeId); - // Present node and request config - #ifndef MY_GATEWAY_FEATURE - if (_nc.nodeId != AUTO) { - #ifdef MY_SIGNING_FEATURE - // Notify gateway (and possibly controller) about the signing preferences of this node - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(signer.requestSignatures())); - - // If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages - if (signer.requestSignatures()) { - wait(2000); - } - #endif - - // Send presentation for this radio node - #ifdef MY_REPEATER_FEATURE - present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); - #else - present(NODE_SENSOR_ID, S_ARDUINO_NODE); - #endif - // Send a configuration exchange request to controller - // Node sends parent node. Controller answers with latest node configuration - // which is picked up in process() - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG, false).set(_nc.parentNodeId)); - - // Wait configuration reply. - wait(2000); - - #ifdef MY_OTA_FIRMWARE_FEATURE - RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)_msg.data; - mSetLength(_msg, sizeof(RequestFirmwareConfig)); - mSetCommand(_msg, C_STREAM); - mSetPayloadType(_msg,P_CUSTOM); - // copy node settings to reqFWConfig - memcpy(reqFWConfig,&_fc,sizeof(NodeFirmwareConfig)); - // add bootloader information - reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; - _fwUpdateOngoing = false; - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); - #endif - } - #endif -} -#endif - -#if defined(MY_RADIO_FEATURE) -void findParentNode() { - static boolean findingParentNode = false; - - if (findingParentNode) - return; - findingParentNode = true; - - _failedTransmissions = 0; - - // Set distance to max - _nc.distance = 255; - - // Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to) - debug(PSTR("find parent\n")); - - build(_msg, _nc.nodeId, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT, false).set(""); - // Write msg, but suppress recursive parent search - sendWrite(BROADCAST_ADDRESS, _msg); - - // Wait for ping response. - wait(2000); - findingParentNode = false; -} -#endif - - boolean sendRoute(MyMessage &message) { - #if defined(MY_GATEWAY_FEATURE) if (message.destination == _nc.nodeId) { // This is a message sent from a sensor attached on the gateway node. // Pass it directly to the gateway transport layer. - #ifdef MY_LEDS_BLINKING_FEATURE - txBlink(1); - #endif + ledBlinkTx(1); return gatewayTransportSend(message); } #endif - - #if defined(MY_RADIO_FEATURE) - uint8_t sender = message.sender; - uint8_t dest = message.destination; - uint8_t last = message.last; - bool ok; - - // If we still don't have any parent id, re-request and skip this message. - if (_nc.parentNodeId == AUTO) { - findParentNode(); - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return false; - } - - // If we still don't have any node id, re-request and skip this message. - if (_nc.nodeId == AUTO) { - requestNodeId(); - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return false; - } - - mSetVersion(message, PROTOCOL_VERSION); - - #ifdef MY_SIGNING_FEATURE - // If destination is known to require signed messages and we are the sender, sign this message unless it is an ACK or a handshake message - if (DO_SIGN(message.destination) && message.sender == _nc.nodeId && !mGetAck(message) && mGetLength(message) && - (mGetCommand(message) != C_INTERNAL || - (message.type != I_GET_NONCE && message.type != I_GET_NONCE_RESPONSE && message.type != I_REQUEST_SIGNING && - message.type != I_ID_REQUEST && message.type != I_ID_RESPONSE && - message.type != I_FIND_PARENT && message.type != I_FIND_PARENT_RESPONSE))) { - bool signOk = false; - // Send nonce-request - if (!sendRoute(build(_msgTmp, _nc.nodeId, message.destination, message.sensor, C_INTERNAL, I_GET_NONCE, false).set(""))) { - debug(PSTR("nonce tr err\n")); - return false; - } - // We have to wait for the nonce to arrive before we can sign our original message - // Other messages could come in-between. We trust process() takes care of them - unsigned long enter = hwMillis(); - _msgSign = message; // Copy the message to sign since message buffer might be touched in process() - while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS) { - if (process()) { - if (mGetCommand(getLastMessage()) == C_INTERNAL && getLastMessage().type == I_GET_NONCE_RESPONSE) { - // Proceed with signing if nonce has been received - if (signer.putNonce(getLastMessage()) && signer.signMsg(_msgSign)) { - message = _msgSign; // Write the signed message back - signOk = true; - } - break; - } - } - } - if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { - debug(PSTR("nonce tmo\n")); - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return false; - } - if (!signOk) { - debug(PSTR("sign fail\n")); - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return false; - } - // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed, - // or signature will become invalid and the message rejected by the receiver - } else mSetSigned(message, 0); // Message is not supposed to be signed, make sure it is marked unsigned - #endif - - if (dest == GATEWAY_ADDRESS || !MY_IS_REPEATER) { - // Store this address in routing table (if repeater) - #if defined (MY_IS_REPEATER) - hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); - #endif - // If destination is the gateway or if we aren't a repeater, let - // our parent take care of the message - ok = sendWrite(_nc.parentNodeId, message); - } else { - // Relay the message - uint8_t route = hwReadConfig(EEPROM_ROUTES_ADDRESS+dest); - if (route > GATEWAY_ADDRESS && route < BROADCAST_ADDRESS) { - // This message should be forwarded to a child node. If we send message - // to this nodes pipe then all children will receive it because the are - // all listening to this nodes pipe. - // - // +----B - // -A - // +----C------D - // - // We're node C, Message comes from A and has destination D - // - // Message destination is not gateway and is in routing table for this node. - // Send it downstream - return sendWrite(route, message); - } else if (sender == GATEWAY_ADDRESS && dest == BROADCAST_ADDRESS) { - // Node has not yet received any id. We need to send it - // by doing a broadcast sending, - return sendWrite(BROADCAST_ADDRESS, message); - } else if (MY_IS_GATEWAY) { - // Destination isn't in our routing table and isn't a broadcast address - // Nothing to do here - return false; - } else { - // A message comes from a child node and we have no - // route for it. - // - // +----B - // -A - // +----C------D <-- Message comes from D - // - // We're node C - // - // Message should be passed to node A (this nodes relay) - - // This message should be routed back towards sensor net gateway - ok = sendWrite(_nc.parentNodeId, message); - // Add this child to our "routing table" if it not already exist - hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); - } - } - - if (!ok) { - // Failure when sending to parent node. The parent node might be down and we - // need to find another route to gateway. - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - _failedTransmissions++; - if (_autoFindParent && _failedTransmissions > SEARCH_FAILURES) { - findParentNode(); - } - } else { - _failedTransmissions = 0; - } - return ok; + transportSendRoute(message); #else return false; #endif } -#ifdef MY_RADIO_FEATURE -boolean sendWrite(uint8_t to, MyMessage &message) { - mSetVersion(message, PROTOCOL_VERSION); - uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message); - message.last = _nc.nodeId; - #ifdef MY_LEDS_BLINKING_FEATURE - txBlink(1); - #endif - bool ok = transportSend(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length)); - - debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,st=%s:%s\n"), - message.sender,message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, - mGetPayloadType(message), mGetLength(message), mGetSigned(message), to==BROADCAST_ADDRESS ? "bc" : (ok ? "ok":"fail"), message.getString(convBuf)); - - return ok; -} -#endif - bool send(MyMessage &message, bool enableAck) { message.sender = _nc.nodeId; mSetCommand(message,C_SET); @@ -611,320 +219,7 @@ void requestTime(void (* timeCallback)(unsigned long)) { sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, false).set("")); } -void process() { - hwWatchdogReset(); - - #ifdef MY_LEDS_BLINKING_FEATURE - handleLedsBlinking(); - #endif - - #ifdef MY_INCLUSION_MODE_FEATURE - checkInclusionMode(); - #endif - - #if defined (MY_GATEWAY_FEATURE) - if (gatewayTransportAvailable()) { - MyMessage &_msg = gatewayTransportReceive(); - if (_msg.destination == GATEWAY_ADDRESS) { - // Check if sender requests an ack back. - if (mGetRequestAck(_msg)) { - // Copy message - _msgTmp = _msg; - mSetRequestAck(_msgTmp, false); // Reply without ack flag (otherwise we would end up in an eternal loop) - mSetAck(_msgTmp, true); - _msgTmp.sender = _nc.nodeId; - _msgTmp.destination = _msg.sender; - gatewayTransportSend(_msgTmp); - } - if (mGetCommand(_msg) == C_INTERNAL) { - if (_msg.type == I_VERSION) { - // Request for version. Create the response - gatewayTransportSend(buildGw(_msg, I_VERSION).set(LIBRARY_VERSION)); - #ifdef MY_INCLUSION_MODE_FEATURE - } else if (_msg.type == I_INCLUSION_MODE) { - // Request to change inclusion mode - setInclusionMode(atoi(_msg.data) == 1); - #endif - } else { - processInternalMessages(); - } - } else { - // Call incoming message callback if available - if (_msgCallback != NULL) { - _msgCallback(_msg); - } - } - } - } - #endif - - #if defined(MY_RADIO_FEATURE) - uint8_t to = 0; - if (!transportAvailable(&to)) - { - #ifdef MY_OTA_FIRMWARE_FEATURE - unsigned long enter = hwMillis(); - if (_fwUpdateOngoing && (enter - _fwLastRequestTime > MY_OTA_RETRY_DELAY)) { - if (!_fwRetry) { - debug(PSTR("fw upd fail\n")); - // Give up. We have requested MY_OTA_RETRY times without any packet in return. - _fwUpdateOngoing = false; - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return; - } - _fwRetry--; - _fwLastRequestTime = enter; - // Time to (re-)request firmware block from controller - RequestFWBlock *firmwareRequest = (RequestFWBlock *)_msg.data; - mSetLength(_msg, sizeof(RequestFWBlock)); - firmwareRequest->type = _fc.type; - firmwareRequest->version = _fc.version; - firmwareRequest->block = (_fwBlock - 1); - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false)); - } - #endif - return; - } - - #ifdef MY_SIGNING_FEATURE - (void)signer.checkTimer(); // Manage signing timeout - #endif - - uint8_t len = transportReceive((uint8_t *)&_msg); - (void)len; //until somebody makes use of 'len' - #ifdef MY_LEDS_BLINKING_FEATURE - rxBlink(1); - #endif - - #ifdef MY_SIGNING_FEATURE - // Before processing message, reject unsigned messages if signing is required and check signature (if it is signed and addressed to us) - // Note that we do not care at all about any signature found if we do not require signing, nor do we care about ACKs (they are never signed) - if (signer.requestSignatures() && _msg.destination == _nc.nodeId && mGetLength(_msg) && !mGetAck(_msg) && - (mGetCommand(_msg) != C_INTERNAL || - (_msg.type != I_GET_NONCE_RESPONSE && _msg.type != I_GET_NONCE && _msg.type != I_REQUEST_SIGNING && - _msg.type != I_ID_REQUEST && _msg.type != I_ID_RESPONSE && - _msg.type != I_FIND_PARENT && _msg.type != I_FIND_PARENT_RESPONSE))) { - if (!mGetSigned(_msg)) { - // Got unsigned message that should have been signed - debug(PSTR("no sign\n")); - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return; - } - else if (!signer.verifyMsg(_msg)) { - debug(PSTR("verify fail\n")); - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return; // This signed message has been tampered with! - } - } - #endif - - // Add string termination, good if we later would want to print it. - _msg.data[mGetLength(_msg)] = '\0'; - debug(PSTR("read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"), - _msg.sender, _msg.last, _msg.destination, _msg.sensor, mGetCommand(_msg), _msg.type, mGetPayloadType(_msg), mGetLength(_msg), mGetSigned(_msg), _msg.getString(convBuf)); - mSetSigned(_msg,0); // Clear the sign-flag now as verification (and debug printing) is completed - - if(!(mGetVersion(_msg) == PROTOCOL_VERSION)) { - debug(PSTR("ver mismatch\n")); - #ifdef MY_LEDS_BLINKING_FEATURE - errBlink(1); - #endif - return; - } - - uint8_t command = mGetCommand(_msg); - uint8_t type = _msg.type; - uint8_t sender = _msg.sender; - uint8_t last = _msg.last; - uint8_t destination = _msg.destination; - - if (destination == _nc.nodeId) { - // This message is addressed to this node - - if (MY_IS_REPEATER && last != _nc.parentNodeId) { - // Message is from one of the child nodes. Add it to routing table. - hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); - } - - // Check if sender requests an ack back. - if (mGetRequestAck(_msg)) { - // Copy message - _msgTmp = _msg; - mSetRequestAck(_msgTmp,false); // Reply without ack flag (otherwise we would end up in an eternal loop) - mSetAck(_msgTmp,true); - _msgTmp.sender = _nc.nodeId; - _msgTmp.destination = _msg.sender; - sendRoute(_msgTmp); - } - - if (command == C_INTERNAL) { - if (type == I_FIND_PARENT_RESPONSE) { - if (_autoFindParent) { - // We've received a reply to a FIND_PARENT message. Check if the distance is - // shorter than we already have. - uint8_t distance = _msg.getByte(); - if (isValidDistance(distance)) - { - // Distance to gateway is one more for us w.r.t. parent - distance++; - if (isValidDistance(distance) && (distance < _nc.distance)) { - // Found a neighbor closer to GW than previously found - _nc.distance = distance; - _nc.parentNodeId = _msg.sender; - hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, _nc.parentNodeId); - hwWriteConfig(EEPROM_DISTANCE_ADDRESS, _nc.distance); - debug(PSTR("parent=%d, d=%d\n"), _nc.parentNodeId, _nc.distance); - } - } - } - return; - #ifdef MY_SIGNING_FEATURE - } else if (type == I_GET_NONCE) { - if (signer.getNonce(_msg)) { - sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_GET_NONCE_RESPONSE, false)); - } - return false; // Nonce exchange is an internal MySensor protocol message, no need to inform caller about this - } else if (type == I_REQUEST_SIGNING) { - if (_msg.getBool()) { - // We received an indicator that the sender require us to sign all messages we send to it - SET_SIGN(_msg.sender); - } else { - // We received an indicator that the sender does not require us to sign all messages we send to it - CLEAR_SIGN(_msg.sender); - } - // Save updated table - hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(_doSign)); - - // Inform sender about our preference if we are a gateway, but only require signing if the sender required signing - // We do not currently want a gateway to require signing from all nodes in a network just because it wants one node - // to sign it's messages - if (MY_GATEWAY_FEATURE) { - if (signer.requestSignatures() && DO_SIGN(_msg.sender)) - sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(true)); - else - sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); - } - return; // Signing request is an internal MySensor protocol message, no need to inform caller about this - } else if (type == I_GET_NONCE_RESPONSE) { - return; // Just pass along nonce silently (no need to call callback for these) - #endif - } else if (sender == GATEWAY_ADDRESS) { - if (type == I_ID_RESPONSE && _nc.nodeId == AUTO) { - _nc.nodeId = _msg.getByte(); - if (_nc.nodeId == AUTO) { - // sensor net gateway will return max id if all sensor id are taken - debug(PSTR("full\n")); - while (1); // Wait here. Nothing else we can do... - } - setupNode(); - // Write id to EEPROM - hwWriteConfig(EEPROM_NODE_ID_ADDRESS, _nc.nodeId); - debug(PSTR("id=%d\n"), _nc.nodeId); - } else { - processInternalMessages(); - } - return; - } - } - #ifdef MY_OTA_FIRMWARE_FEATURE - else if (command == C_STREAM) { - if (type == ST_FIRMWARE_CONFIG_RESPONSE) { - NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)_msg.data; - // compare with current node configuration, if they differ, start fw fetch process - if (memcmp(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) { - debug(PSTR("fw update\n")); - // copy new FW config - memcpy(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig)); - // Init flash - if (!_flash.initialize()) { - debug(PSTR("flash init fail\n")); - _fwUpdateOngoing = false; - } else { - // erase lower 32K -> max flash size for ATMEGA328 - _flash.blockErase32K(0); - // wait until flash erased - while ( _flash.busy() ); - _fwBlock = _fc.blocks; - _fwUpdateOngoing = true; - // reset flags - _fwRetry = MY_OTA_RETRY+1; - _fwLastRequestTime = 0; - } - return ; - } else debug(PSTR("fw update skipped\n")); - } else if (type == ST_FIRMWARE_RESPONSE) { - if (_fwUpdateOngoing) { - // Save block to flash - debug(PSTR("fw block %d\n"), _fwBlock); - // extract FW block - ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)_msg.data; - // write to flash - _flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); - // wait until flash written - while ( _flash.busy() ); - _fwBlock--; - if (!_fwBlock) { - // We're finished! Do a checksum and reboot. - _fwUpdateOngoing = false; - if (isValidFirmware()) { - debug(PSTR("fw checksum ok\n")); - // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) - uint16_t fwsize = FIRMWARE_BLOCK_SIZE * _fc.blocks; - uint8_t OTAbuffer[10] = {'F','L','X','I','M','G',':',(fwsize >> 8),fwsize,':'}; - _flash.writeBytes(0, OTAbuffer, 10); - // Write the new firmware config to eeprom - hwWriteConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); - hwReboot(); - } else { - debug(PSTR("fw checksum fail\n")); - } - } - // reset flags - _fwRetry = MY_OTA_RETRY+1; - _fwLastRequestTime = 0; - } else { - debug(PSTR("No fw update ongoing\n")); - } - return; - } - - } - #endif - // Call incoming message callback if available - if (_msgCallback != NULL) { - _msgCallback(_msg); - } - return; - } else if (MY_IS_REPEATER && _nc.nodeId != AUTO) { - // If this node have an id, relay the message - if (command == C_INTERNAL && type == I_FIND_PARENT) { - if (sender != _nc.parentNodeId) { - if (_nc.distance == DISTANCE_INVALID) - findParentNode(); - - if (_nc.distance != DISTANCE_INVALID) { - // Relaying nodes should always answer ping messages - // Wait a random delay of 0-2 seconds to minimize collision - // between ping ack messages from other relaying nodes - wait(hwMillis() & 0x3ff); - sendWrite(sender, build(_msg, _nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false).set(_nc.distance)); - } - } - } else if (to == _nc.nodeId) { - // We should try to relay this message to another node - sendRoute(_msg); - } - } - #endif -} - - +// Message delivered through _msg void processInternalMessages() { bool isMetric; uint8_t type = _msg.type; @@ -938,8 +233,12 @@ void processInternalMessages() { isMetric = _msg.getString()[0] == 'M' ; _cc.isMetric = isMetric; hwWriteConfig(EEPROM_CONTROLLER_CONFIG_ADDRESS, isMetric); - } else if (type == I_CHILDREN) { - if (MY_IS_REPEATER && _msg.getString()[0] == 'C') { + } else if (type == I_TIME && _timeCallback != NULL) { + // Deliver time to callback + _timeCallback(_msg.getULong()); + } + #if defined(MY_REPEATER_FEATURE) + if (type == I_CHILDREN && _msg.getString()[0] == 'C') { // Clears child relay data for this node debug(PSTR("clear\n")); uint8_t i = 255; @@ -950,26 +249,19 @@ void processInternalMessages() { hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, 0xFF); hwWriteConfig(EEPROM_DISTANCE_ADDRESS, 0xFF); // Find parent node - findParentNode(); + transportFindParentNode(); sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); } - } else if (type == I_TIME) { - if (_timeCallback != NULL) { - // Deliver time to callback - _timeCallback(_msg.getULong()); - } - } + #endif } -#if defined (MY_REPEATER_FEATURE) void saveState(uint8_t pos, uint8_t value) { hwWriteConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos, value); } uint8_t loadState(uint8_t pos) { return hwReadConfig(EEPROM_LOCAL_CONFIG_ADDRESS+pos); } -#endif void wait(unsigned long ms) { unsigned long enter = hwMillis(); @@ -1029,31 +321,5 @@ int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode } -#ifdef MY_INCLUSION_MODE_FEATURE -void setInclusionMode(boolean newMode) { - if (newMode != inclusionMode) { - inclusionMode = newMode; - // Send back mode change to controller - gatewayTransportSend(buildGw(_msg, I_INCLUSION_MODE).set(inclusionMode?1:0)); - if (inclusionMode) { - inclusionStartTime = hwMillis(); - } - } -} - -void checkInclusionMode() { - #ifdef MY_INCLUSION_BUTTON_FEATURE - if (!inclusionMode && digitalRead(MY_INCLUSION_MODE_BUTTON_PIN) == LOW) { - // Start inclusion mode - setInclusionMode(true); - } - #endif - - if (inclusionMode && hwMillis()-inclusionStartTime>MY_INCLUSION_MODE_DURATION*1000L) { - // inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode - setInclusionMode(false); - } -} -#endif diff --git a/libraries/MySensors/core/MySensorCore.h b/libraries/MySensors/core/MySensorCore.h index 24a7874..ce9ed5d 100644 --- a/libraries/MySensors/core/MySensorCore.h +++ b/libraries/MySensors/core/MySensorCore.h @@ -35,24 +35,12 @@ #include #include - - - #ifdef MY_DEBUG #define debug(x,...) hwDebugPrint(x, ##__VA_ARGS__) #else #define debug(x,...) #endif -#ifdef WITH_LEDS_BLINKING_INVERSE -#define LED_ON 0x1 -#define LED_OFF 0x0 -#else -#define LED_ON 0x0 -#define LED_OFF 0x1 -#endif - - // EEPROM start address for mysensors library data #define EEPROM_START 0 // EEPROM location of node id @@ -70,8 +58,8 @@ #define EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2) #define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS+32) // First free address for sketch static configuration -// Search for a new parent node after this many transmission failures -#define SEARCH_FAILURES 5 +// This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data). +#define GATEWAY_ADDRESS ((uint8_t)0) struct NodeConfig @@ -86,65 +74,15 @@ struct ControllerConfig { }; -// Size of each firmware block -#define FIRMWARE_BLOCK_SIZE 16 -// Number of times a firmware block should be requested before giving up -#define FIRMWARE_MAX_REQUESTS 5 -// Number of times to request a fw block before giving up -#define MY_OTA_RETRY 5 -// Number of millisecons before re-request a fw block -#define MY_OTA_RETRY_DELAY 500 -// Start offset for firmware in flash (DualOptiboot wants to keeps a signature first) -#define FIRMWARE_START_OFFSET 10 -// Bootloader version -#define MY_OTA_BOOTLOADER_MAJOR_VERSION 3 -#define MY_OTA_BOOTLOADER_MINOR_VERSION 0 -#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION) - - -// FW config structure, stored in eeprom -typedef struct { - uint16_t type; - uint16_t version; - uint16_t blocks; - uint16_t crc; -} __attribute__((packed)) NodeFirmwareConfig; - -typedef struct { - uint16_t type; - uint16_t version; - uint16_t blocks; - uint16_t crc; - uint16_t BLVersion; -} __attribute__((packed)) RequestFirmwareConfig; - -typedef struct { - uint16_t type; - uint16_t version; - uint16_t block; -} __attribute__((packed)) RequestFWBlock; - -typedef struct { - uint16_t type; - uint16_t version; - uint16_t block; - uint8_t data[FIRMWARE_BLOCK_SIZE]; -} __attribute__((packed)) ReplyFWBlock; - - - /** -* Begin operation of the MySensors library +* Set the callback method for incoming messages * -* Call this in setup(), before calling any other sensor net library methods. -* @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. Default is NULL. +* @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. */ - - void dataCallback(void (* msgCallback)(const MyMessage &)=NULL); /** - * Return the nodes nodeId. + * Return this nodes id. */ uint8_t getNodeId(); @@ -284,47 +222,46 @@ bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0); int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); - /****** PRIVATE ********/ + void begin(); void process(void); void processInternalMessages(); -#ifdef MY_LEDS_BLINKING_FEATURE - /** - * Blink with LEDs - * @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms - */ - void rxBlink(uint8_t cnt); - void txBlink(uint8_t cnt); - void errBlink(uint8_t cnt); - void handleLedsBlinking(); // do the actual blinking -#endif - -#ifdef MY_OTA_FIRMWARE_FEATURE - // do a crc16 on the whole received firmware - bool isValidFirmware(); -#endif - - -#ifdef MY_INCLUSION_MODE_FEATURE - void setInclusionMode(bool newMode); - void checkInclusionMode(); - unsigned long inclusionStartTime; - bool inclusionMode; -#endif - - boolean sendRoute(MyMessage &message); -#if defined(MY_RADIO_FEATURE) - boolean sendWrite(uint8_t dest, MyMessage &message); - void requestNodeId(); - void setupNode(); - void findParentNode(); + +extern NodeConfig _nc; +extern MyMessage _msg; // Buffer for incoming messages. +extern MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others). +extern void (*_msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. +#ifdef MY_DEBUG + extern char convBuf[MAX_PAYLOAD*2+1]; #endif +// Inline function and macros +static inline MyMessage& build(MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) { + msg.sender = sender; + msg.destination = destination; + msg.sensor = sensor; + msg.type = type; + mSetCommand(msg,command); + mSetRequestAck(msg,enableAck); + mSetAck(msg,false); + return msg; +} + +static inline MyMessage& buildGw(MyMessage &msg, uint8_t type) { + msg.sender = GATEWAY_ADDRESS; + msg.destination = GATEWAY_ADDRESS; + msg.sensor = 0; + msg.type = type; + mSetCommand(msg, C_INTERNAL); + mSetRequestAck(msg, false); + mSetAck(msg, false); + return msg; +} #endif diff --git a/libraries/MySensors/core/MySigning.cpp b/libraries/MySensors/core/MySigning.cpp index 03c3ee3..ad0d78c 100644 --- a/libraries/MySensors/core/MySigning.cpp +++ b/libraries/MySensors/core/MySigning.cpp @@ -19,6 +19,11 @@ #include "MySigning.h" + +uint16_t _doSign[16]; // Bitfield indicating which sensors require signed communication +MyMessage _msgSign; // Buffer for message to sign. + + MySigning::MySigning(bool requestSignatures) : _requestSignatures(requestSignatures) { } diff --git a/libraries/MySensors/core/MySigning.h b/libraries/MySensors/core/MySigning.h index e65d546..637b281 100644 --- a/libraries/MySensors/core/MySigning.h +++ b/libraries/MySensors/core/MySigning.h @@ -30,6 +30,12 @@ #include #include "MyMessage.h" + +// Macros for manipulating signing requirement table +#define DO_SIGN(node) (node == 0 ? (~_doSign[0]&1) : (~_doSign[node>>4]&(node%16))) +#define SET_SIGN(node) (node == 0 ? (_doSign[0]&=~1) : (_doSign[node>>4]&=~(node%16))) +#define CLEAR_SIGN(node) (node == 0 ? (_doSign[0]|=1) : (_doSign[node>>4]|=(node%16))) + class MySigning { public: diff --git a/libraries/MySensors/core/MyTransport.cpp b/libraries/MySensors/core/MyTransport.cpp new file mode 100644 index 0000000..309bc4d --- /dev/null +++ b/libraries/MySensors/core/MyTransport.cpp @@ -0,0 +1,547 @@ +/** + * The MySensors Arduino library handles the wireless radio link and protocol + * between your home built sensors/actuators and HA controller of choice. + * The sensors forms a self healing radio network with optional repeaters. Each + * repeater and gateway builds a routing tables in EEPROM which keeps track of the + * network topology allowing messages to be routed to nodes. + * + * Created by Henrik Ekblad + * Copyright (C) 2013-2015 Sensnology AB + * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors + * + * Documentation: http://www.mysensors.org + * Support Forum: http://forum.mysensors.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + + +#include "MyTransport.h" + +bool _autoFindParent; +uint8_t _failedTransmissions; + + +#ifdef MY_OTA_FIRMWARE_FEATURE + NodeFirmwareConfig _fc; + bool _fwUpdateOngoing; + unsigned long _fwLastRequestTime; + uint16_t _fwBlock; + uint8_t _fwRetry; +#endif + + +static inline bool isValidDistance( const uint8_t distance ) { + return distance != DISTANCE_INVALID; +} + + +inline void transportProcess() { + uint8_t to = 0; + if (!transportAvailable(&to)) + { + #ifdef MY_OTA_FIRMWARE_FEATURE + unsigned long enter = hwMillis(); + if (_fwUpdateOngoing && (enter - _fwLastRequestTime > MY_OTA_RETRY_DELAY)) { + if (!_fwRetry) { + debug(PSTR("fw upd fail\n")); + // Give up. We have requested MY_OTA_RETRY times without any packet in return. + _fwUpdateOngoing = false; + ledBlinkErr(1); + return; + } + _fwRetry--; + _fwLastRequestTime = enter; + // Time to (re-)request firmware block from controller + RequestFWBlock *firmwareRequest = (RequestFWBlock *)_msg.data; + mSetLength(_msg, sizeof(RequestFWBlock)); + firmwareRequest->type = _fc.type; + firmwareRequest->version = _fc.version; + firmwareRequest->block = (_fwBlock - 1); + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false)); + } + #endif + return; + } + + #ifdef MY_SIGNING_FEATURE + (void)signer.checkTimer(); // Manage signing timeout + #endif + + uint8_t len = transportReceive((uint8_t *)&_msg); + (void)len; //until somebody makes use of 'len' + ledBlinkRx(1); + + #ifdef MY_SIGNING_FEATURE + // Before processing message, reject unsigned messages if signing is required and check signature (if it is signed and addressed to us) + // Note that we do not care at all about any signature found if we do not require signing, nor do we care about ACKs (they are never signed) + if (signer.requestSignatures() && _msg.destination == _nc.nodeId && mGetLength(_msg) && !mGetAck(_msg) && + (mGetCommand(_msg) != C_INTERNAL || + (_msg.type != I_GET_NONCE_RESPONSE && _msg.type != I_GET_NONCE && _msg.type != I_REQUEST_SIGNING && + _msg.type != I_ID_REQUEST && _msg.type != I_ID_RESPONSE && + _msg.type != I_FIND_PARENT && _msg.type != I_FIND_PARENT_RESPONSE))) { + if (!mGetSigned(_msg)) { + // Got unsigned message that should have been signed + debug(PSTR("no sign\n")); + ledBlinkErr(1); + return; + } + else if (!signer.verifyMsg(_msg)) { + debug(PSTR("verify fail\n")); + ledBlinkErr(1); + return; // This signed message has been tampered with! + } + } + #endif + + // Add string termination, good if we later would want to print it. + _msg.data[mGetLength(_msg)] = '\0'; + debug(PSTR("read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"), + _msg.sender, _msg.last, _msg.destination, _msg.sensor, mGetCommand(_msg), _msg.type, mGetPayloadType(_msg), mGetLength(_msg), mGetSigned(_msg), _msg.getString(convBuf)); + mSetSigned(_msg,0); // Clear the sign-flag now as verification (and debug printing) is completed + + if(!(mGetVersion(_msg) == PROTOCOL_VERSION)) { + debug(PSTR("ver mismatch\n")); + ledBlinkErr(1); + return; + } + + uint8_t command = mGetCommand(_msg); + uint8_t type = _msg.type; + uint8_t sender = _msg.sender; + uint8_t last = _msg.last; + uint8_t destination = _msg.destination; + + if (destination == _nc.nodeId) { + // This message is addressed to this node + + #if defined(MY_REPEATER_FEATURE) + if (last != _nc.parentNodeId) { + // Message is from one of the child nodes. Add it to routing table. + hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); + } + #endif + + // Check if sender requests an ack back. + if (mGetRequestAck(_msg)) { + // Copy message + _msgTmp = _msg; + mSetRequestAck(_msgTmp,false); // Reply without ack flag (otherwise we would end up in an eternal loop) + mSetAck(_msgTmp,true); + _msgTmp.sender = _nc.nodeId; + _msgTmp.destination = _msg.sender; + sendRoute(_msgTmp); + } + + if (command == C_INTERNAL) { + if (type == I_FIND_PARENT_RESPONSE) { + if (_autoFindParent) { + // We've received a reply to a FIND_PARENT message. Check if the distance is + // shorter than we already have. + uint8_t distance = _msg.getByte(); + if (isValidDistance(distance)) + { + // Distance to gateway is one more for us w.r.t. parent + distance++; + if (isValidDistance(distance) && (distance < _nc.distance)) { + // Found a neighbor closer to GW than previously found + _nc.distance = distance; + _nc.parentNodeId = _msg.sender; + hwWriteConfig(EEPROM_PARENT_NODE_ID_ADDRESS, _nc.parentNodeId); + hwWriteConfig(EEPROM_DISTANCE_ADDRESS, _nc.distance); + debug(PSTR("parent=%d, d=%d\n"), _nc.parentNodeId, _nc.distance); + } + } + } + return; + #ifdef MY_SIGNING_FEATURE + } else if (type == I_GET_NONCE) { + if (signer.getNonce(_msg)) { + sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_GET_NONCE_RESPONSE, false)); + } + return false; // Nonce exchange is an internal MySensor protocol message, no need to inform caller about this + } else if (type == I_REQUEST_SIGNING) { + if (_msg.getBool()) { + // We received an indicator that the sender require us to sign all messages we send to it + SET_SIGN(_msg.sender); + } else { + // We received an indicator that the sender does not require us to sign all messages we send to it + CLEAR_SIGN(_msg.sender); + } + // Save updated table + hwWriteConfigBlock((void*)_doSign, (void*)EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS, sizeof(_doSign)); + + // Inform sender about our preference if we are a gateway, but only require signing if the sender required signing + // We do not currently want a gateway to require signing from all nodes in a network just because it wants one node + // to sign it's messages + if (MY_GATEWAY_FEATURE) { + if (signer.requestSignatures() && DO_SIGN(_msg.sender)) + sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(true)); + else + sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); + } + return; // Signing request is an internal MySensor protocol message, no need to inform caller about this + } else if (type == I_GET_NONCE_RESPONSE) { + return; // Just pass along nonce silently (no need to call callback for these) + #endif + } else if (sender == GATEWAY_ADDRESS) { + if (type == I_ID_RESPONSE && _nc.nodeId == AUTO) { + _nc.nodeId = _msg.getByte(); + if (_nc.nodeId == AUTO) { + // sensor net gateway will return max id if all sensor id are taken + debug(PSTR("full\n")); + while (1); // Wait here. Nothing else we can do... + } + transportSetupNode(); + // Write id to EEPROM + hwWriteConfig(EEPROM_NODE_ID_ADDRESS, _nc.nodeId); + debug(PSTR("id=%d\n"), _nc.nodeId); + } else { + processInternalMessages(); + } + return; + } + } + #ifdef MY_OTA_FIRMWARE_FEATURE + else if (command == C_STREAM) { + if (type == ST_FIRMWARE_CONFIG_RESPONSE) { + NodeFirmwareConfig *firmwareConfigResponse = (NodeFirmwareConfig *)_msg.data; + // compare with current node configuration, if they differ, start fw fetch process + if (memcmp(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig))) { + debug(PSTR("fw update\n")); + // copy new FW config + memcpy(&_fc,firmwareConfigResponse,sizeof(NodeFirmwareConfig)); + // Init flash + if (!_flash.initialize()) { + debug(PSTR("flash init fail\n")); + _fwUpdateOngoing = false; + } else { + // erase lower 32K -> max flash size for ATMEGA328 + _flash.blockErase32K(0); + // wait until flash erased + while ( _flash.busy() ); + _fwBlock = _fc.blocks; + _fwUpdateOngoing = true; + // reset flags + _fwRetry = MY_OTA_RETRY+1; + _fwLastRequestTime = 0; + } + return ; + } else debug(PSTR("fw update skipped\n")); + } else if (type == ST_FIRMWARE_RESPONSE) { + if (_fwUpdateOngoing) { + // Save block to flash + debug(PSTR("fw block %d\n"), _fwBlock); + // extract FW block + ReplyFWBlock *firmwareResponse = (ReplyFWBlock *)_msg.data; + // write to flash + _flash.writeBytes( ((_fwBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET, firmwareResponse->data, FIRMWARE_BLOCK_SIZE); + // wait until flash written + while ( _flash.busy() ); + _fwBlock--; + if (!_fwBlock) { + // We're finished! Do a checksum and reboot. + _fwUpdateOngoing = false; + if (transportIsValidFirmware()) { + debug(PSTR("fw checksum ok\n")); + // All seems ok, write size and signature to flash (DualOptiboot will pick this up and flash it) + uint16_t fwsize = FIRMWARE_BLOCK_SIZE * _fc.blocks; + uint8_t OTAbuffer[10] = {'F','L','X','I','M','G',':',(fwsize >> 8),fwsize,':'}; + _flash.writeBytes(0, OTAbuffer, 10); + // Write the new firmware config to eeprom + hwWriteConfigBlock((void*)&_fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(NodeFirmwareConfig)); + hwReboot(); + } else { + debug(PSTR("fw checksum fail\n")); + } + } + // reset flags + _fwRetry = MY_OTA_RETRY+1; + _fwLastRequestTime = 0; + } else { + debug(PSTR("No fw update ongoing\n")); + } + return; + } + + } + #endif + // Call incoming message callback if available + if (_msgCallback != NULL) { + _msgCallback(_msg); + } + return; + } + #if defined(MY_REPEATER_FEATURE) + if (_nc.nodeId != AUTO) { + // If this node have an id, relay the message + if (command == C_INTERNAL && type == I_FIND_PARENT) { + if (sender != _nc.parentNodeId) { + if (_nc.distance == DISTANCE_INVALID) + transportFindParentNode(); + + if (_nc.distance != DISTANCE_INVALID) { + // Relaying nodes should always answer ping messages + // Wait a random delay of 0-2 seconds to minimize collision + // between ping ack messages from other relaying nodes + wait(hwMillis() & 0x3ff); + sendWrite(sender, build(_msg, _nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false).set(_nc.distance)); + } + } + } else if (to == _nc.nodeId) { + // We should try to relay this message to another node + sendRoute(_msg); + } + } + #endif +} + +#ifdef MY_OTA_FIRMWARE_FEATURE +// do a crc16 on the whole received firmware +bool transportIsValidFirmware() { + // init crc + uint16_t crc = ~0; + for (uint16_t i = 0; i < _fc.blocks * FIRMWARE_BLOCK_SIZE; ++i) { + crc ^= _flash.readByte(i + FIRMWARE_START_OFFSET); + for (int8_t j = 0; j < 8; ++j) { + if (crc & 1) + crc = (crc >> 1) ^ 0xA001; + else + crc = (crc >> 1); + } + } + return crc == _fc.crc; +} + +#endif + + +boolean transportSendWrite(uint8_t to, MyMessage &message) { + mSetVersion(message, PROTOCOL_VERSION); + uint8_t length = mGetSigned(message) ? MAX_MESSAGE_LENGTH : mGetLength(message); + message.last = _nc.nodeId; + ledBlinkTx(1); + bool ok = transportSend(to, &message, min(MAX_MESSAGE_LENGTH, HEADER_SIZE + length)); + + debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,st=%s:%s\n"), + message.sender,message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, + mGetPayloadType(message), mGetLength(message), mGetSigned(message), to==BROADCAST_ADDRESS ? "bc" : (ok ? "ok":"fail"), message.getString(convBuf)); + + return ok; +} + + +boolean transportSendRoute(MyMessage &message) { + uint8_t sender = message.sender; + uint8_t dest = message.destination; + uint8_t last = message.last; + bool ok; + + // If we still don't have any parent id, re-request and skip this message. + if (_nc.parentNodeId == AUTO) { + transportFindParentNode(); + ledBlinkErr(1); + return false; + } + + // If we still don't have any node id, re-request and skip this message. + if (_nc.nodeId == AUTO) { + transportRequestNodeId(); + ledBlinkErr(1); + return false; + } + + mSetVersion(message, PROTOCOL_VERSION); + + #ifdef MY_SIGNING_FEATURE + // If destination is known to require signed messages and we are the sender, sign this message unless it is an ACK or a handshake message + if (DO_SIGN(message.destination) && message.sender == _nc.nodeId && !mGetAck(message) && mGetLength(message) && + (mGetCommand(message) != C_INTERNAL || + (message.type != I_GET_NONCE && message.type != I_GET_NONCE_RESPONSE && message.type != I_REQUEST_SIGNING && + message.type != I_ID_REQUEST && message.type != I_ID_RESPONSE && + message.type != I_FIND_PARENT && message.type != I_FIND_PARENT_RESPONSE))) { + bool signOk = false; + // Send nonce-request + if (!sendRoute(build(_msgTmp, _nc.nodeId, message.destination, message.sensor, C_INTERNAL, I_GET_NONCE, false).set(""))) { + debug(PSTR("nonce tr err\n")); + return false; + } + // We have to wait for the nonce to arrive before we can sign our original message + // Other messages could come in-between. We trust process() takes care of them + unsigned long enter = hwMillis(); + _msgSign = message; // Copy the message to sign since message buffer might be touched in process() + while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS) { + if (process()) { + if (mGetCommand(getLastMessage()) == C_INTERNAL && getLastMessage().type == I_GET_NONCE_RESPONSE) { + // Proceed with signing if nonce has been received + if (signer.putNonce(getLastMessage()) && signer.signMsg(_msgSign)) { + message = _msgSign; // Write the signed message back + signOk = true; + } + break; + } + } + } + if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { + debug(PSTR("nonce tmo\n")); + ledBlinkErr(1); + return false; + } + if (!signOk) { + debug(PSTR("sign fail\n")); + ledBlinkErr(1); + return false; + } + // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed, + // or signature will become invalid and the message rejected by the receiver + } else { + mSetSigned(message, 0); // Message is not supposed to be signed, make sure it is marked unsigned + } + #endif + + if (dest == GATEWAY_ADDRESS || !MY_IS_REPEATER) { + // Store this address in routing table (if repeater) + #if defined (MY_IS_REPEATER) + hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); + #endif + // If destination is the gateway or if we aren't a repeater, let + // our parent take care of the message + ok = transportSendWrite(_nc.parentNodeId, message); + } else { + // Relay the message + uint8_t route = hwReadConfig(EEPROM_ROUTES_ADDRESS+dest); + if (route > GATEWAY_ADDRESS && route < BROADCAST_ADDRESS) { + // This message should be forwarded to a child node. If we send message + // to this nodes pipe then all children will receive it because the are + // all listening to this nodes pipe. + // + // +----B + // -A + // +----C------D + // + // We're node C, Message comes from A and has destination D + // + // Message destination is not gateway and is in routing table for this node. + // Send it downstream + return transportSendWrite(route, message); + } else if (sender == GATEWAY_ADDRESS && dest == BROADCAST_ADDRESS) { + // Node has not yet received any id. We need to send it + // by doing a broadcast sending, + return transportSendWrite(BROADCAST_ADDRESS, message); + } else if (MY_IS_GATEWAY) { + // Destination isn't in our routing table and isn't a broadcast address + // Nothing to do here + return false; + } else { + // A message comes from a child node and we have no + // route for it. + // + // +----B + // -A + // +----C------D <-- Message comes from D + // + // We're node C + // + // Message should be passed to node A (this nodes relay) + + // This message should be routed back towards sensor net gateway + ok = transportSendWrite(_nc.parentNodeId, message); + // Add this child to our "routing table" if it not already exist + hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); + } + } + + if (!ok) { + // Failure when sending to parent node. The parent node might be down and we + // need to find another route to gateway. + ledBlinkErr(1); + _failedTransmissions++; + if (_autoFindParent && _failedTransmissions > SEARCH_FAILURES) { + transportFindParentNode(); + } + } else { + _failedTransmissions = 0; + } + return ok; +} + + +void transportRequestNodeId() { + debug(PSTR("req id\n")); + transportSetAddress(_nc.nodeId); + build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_ID_REQUEST, false).set(""); + transportSendWrite(_nc.parentNodeId, _msg); + wait(2000); +} + +void transportSetupNode() { + // Open reading pipe for messages directed to this node (set write pipe to same) + transportSetAddress(_nc.nodeId); + // Present node and request config + #ifndef MY_GATEWAY_FEATURE + if (_nc.nodeId != AUTO) { + #ifdef MY_SIGNING_FEATURE + // Notify gateway (and possibly controller) about the signing preferences of this node + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(signer.requestSignatures())); + + // If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages + if (signer.requestSignatures()) { + wait(2000); + } + #endif + + // Send presentation for this radio node + #ifdef MY_REPEATER_FEATURE + present(NODE_SENSOR_ID, S_ARDUINO_REPEATER_NODE); + #else + present(NODE_SENSOR_ID, S_ARDUINO_NODE); + #endif + // Send a configuration exchange request to controller + // Node sends parent node. Controller answers with latest node configuration + // which is picked up in process() + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG, false).set(_nc.parentNodeId)); + + // Wait configuration reply. + wait(2000); + + #ifdef MY_OTA_FIRMWARE_FEATURE + RequestFirmwareConfig *reqFWConfig = (RequestFirmwareConfig *)_msg.data; + mSetLength(_msg, sizeof(RequestFirmwareConfig)); + mSetCommand(_msg, C_STREAM); + mSetPayloadType(_msg,P_CUSTOM); + // copy node settings to reqFWConfig + memcpy(reqFWConfig,&_fc,sizeof(NodeFirmwareConfig)); + // add bootloader information + reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; + _fwUpdateOngoing = false; + sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); + #endif + } + #endif +} + +void transportFindParentNode() { + static boolean findingParentNode = false; + + if (findingParentNode) + return; + findingParentNode = true; + + _failedTransmissions = 0; + + // Set distance to max + _nc.distance = 255; + + // Send ping message to BROADCAST_ADDRESS (to which all relaying nodes and gateway listens and should reply to) + debug(PSTR("find parent\n")); + + build(_msg, _nc.nodeId, BROADCAST_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT, false).set(""); + // Write msg, but suppress recursive parent search + transportSendWrite(BROADCAST_ADDRESS, _msg); + + // Wait for ping response. + wait(2000); + findingParentNode = false; +} diff --git a/libraries/MySensors/core/MyTransport.h b/libraries/MySensors/core/MyTransport.h index 503f8c1..f72ea8f 100644 --- a/libraries/MySensors/core/MyTransport.h +++ b/libraries/MySensors/core/MyTransport.h @@ -21,13 +21,87 @@ #define MyTransport_h #include +#include "MySensorCore.h" + +// Size of each firmware block +#define FIRMWARE_BLOCK_SIZE 16 +// Number of times a firmware block should be requested before giving up +#define FIRMWARE_MAX_REQUESTS 5 +// Number of times to request a fw block before giving up +#define MY_OTA_RETRY 5 +// Number of millisecons before re-request a fw block +#define MY_OTA_RETRY_DELAY 500 +// Start offset for firmware in flash (DualOptiboot wants to keeps a signature first) +#define FIRMWARE_START_OFFSET 10 +// Bootloader version +#define MY_OTA_BOOTLOADER_MAJOR_VERSION 3 +#define MY_OTA_BOOTLOADER_MINOR_VERSION 0 +#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION) + +// Search for a new parent node after this many transmission failures +#define SEARCH_FAILURES 5 + + +// FW config structure, stored in eeprom +typedef struct { + uint16_t type; + uint16_t version; + uint16_t blocks; + uint16_t crc; +} __attribute__((packed)) NodeFirmwareConfig; + +typedef struct { + uint16_t type; + uint16_t version; + uint16_t blocks; + uint16_t crc; + uint16_t BLVersion; +} __attribute__((packed)) RequestFirmwareConfig; + +typedef struct { + uint16_t type; + uint16_t version; + uint16_t block; +} __attribute__((packed)) RequestFWBlock; + +typedef struct { + uint16_t type; + uint16_t version; + uint16_t block; + uint8_t data[FIRMWARE_BLOCK_SIZE]; +} __attribute__((packed)) ReplyFWBlock; + + #define AUTO 0xFF // 0-254. Id 255 is reserved for auto initialization of nodeId. #define NODE_SENSOR_ID 0xFF // Node child id is always created for when a node -// This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data). -#define GATEWAY_ADDRESS ((uint8_t)0) #define BROADCAST_ADDRESS ((uint8_t)0xFF) +// invalid distance when searching for parent +#define DISTANCE_INVALID (0xFF) + +// Common functions in all radio drivers +#ifdef MY_OTA_FIRMWARE_FEATURE + // do a crc16 on the whole received firmware + bool transportIsValidFirmware(); +#endif + + +void transportProcess(); +void transportRequestNodeId(); +void transportSetupNode(); +void transportFindParentNode(); +boolean transportSendRoute(MyMessage &message); +boolean transportSendWrite(uint8_t to, MyMessage &message); + +// "Interface" functions for radio driver +bool transportInit(); +void transportSetAddress(uint8_t address); +uint8_t transportGetAddress(); +bool transportSend(uint8_t to, const void* data, uint8_t len); +bool transportAvailable(uint8_t *to); +uint8_t transportReceive(void* data); +void transportPowerDown(); #endif diff --git a/libraries/MySensors/core/MyTransportNRF24.h b/libraries/MySensors/core/MyTransportNRF24.h index 0d0bcf8..3f895c5 100644 --- a/libraries/MySensors/core/MyTransportNRF24.h +++ b/libraries/MySensors/core/MyTransportNRF24.h @@ -32,12 +32,4 @@ #define CURRENT_NODE_PIPE ((uint8_t)1) #define BROADCAST_PIPE ((uint8_t)2) -bool transportInit(); -void transportSetAddress(uint8_t address); -uint8_t transportGetAddress(); -bool transportSend(uint8_t to, const void* data, uint8_t len); -bool transportAvailable(uint8_t *to); -uint8_t transportReceive(void* data); -void transportPowerDown(); - #endif diff --git a/libraries/MySensors/core/MyTransportRFM69.h b/libraries/MySensors/core/MyTransportRFM69.h index 36ef1a9..ec3227d 100644 --- a/libraries/MySensors/core/MyTransportRFM69.h +++ b/libraries/MySensors/core/MyTransportRFM69.h @@ -27,12 +27,4 @@ #include "drivers/SPI/SPI.h" -bool transportInit(); -void transportSetAddress(uint8_t address); -uint8_t transportGetAddress(); -bool transportSend(uint8_t to, const void* data, uint8_t len); -bool transportAvailable(uint8_t *to); -uint8_t transportReceive(void* data); -void transportPowerDown(); - #endif diff --git a/libraries/MySensors/drivers/pubsubclient b/libraries/MySensors/drivers/pubsubclient new file mode 160000 index 0000000..2f97e4a --- /dev/null +++ b/libraries/MySensors/drivers/pubsubclient @@ -0,0 +1 @@ +Subproject commit 2f97e4a558a0fb38b4ac20a93b1a1b609771bb51 diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index 29f6870..f8e3992 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -64,8 +64,8 @@ // Enable gateway type - - +#define MY_GATEWAY_W5100 +//#define MY_GATEWAY_W5100 // Set default gateway protocol (http://www.mysensors.org/download/serial_api_15) #define MY_GATEWAY_PROTOCOL_DEFAULT @@ -96,7 +96,7 @@ #define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED // Flash leds on rx/tx/err -#define MY_WITH_LEDS_BLINKING +#define MY_LEDS_BLINKING_FEATURE // Set blinking period #define MY_DEFAULT_LED_BLINK_PERIOD 300 diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino index 35483f6..d07b2a7 100644 --- a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -37,8 +37,11 @@ //#define MY_SIGNING_SOFT //#define MY_REPEATER_FEATURE -// #define MY_GATEWAY_SERIAL // REMOVE-ME -// #define MY_GATEWAY_PROTOCOL_DEFAULT // REMOVE-ME +//#define MY_INCLUSION_MODE_FEATURE +//#define MY_INCLUSION_BUTTON_FEATURE +//#define MY_GATEWAY_SERIAL // REMOVE-ME +//#define MY_GATEWAY_PROTOCOL_DEFAULT // REMOVE-ME +//#define MY_LEDS_BLINKING_FEATURE #include From ada872f30f806926afcba036a6ed040b1dff072b Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Wed, 16 Sep 2015 00:18:26 +0200 Subject: [PATCH 16/43] Fixed: Software signing --- libraries/MySensors/MyConfig.h | 25 +- libraries/MySensors/MySensor.h | 60 ++-- .../MySensors/core/MyProtocolDefault.cpp | 8 +- libraries/MySensors/core/MySensorCore.cpp | 38 +-- libraries/MySensors/core/MySensorCore.h | 17 +- libraries/MySensors/core/MySigning.cpp | 8 - libraries/MySensors/core/MySigning.h | 90 +++--- .../MySensors/core/MySigningAtsha204.cpp | 29 +- libraries/MySensors/core/MySigningAtsha204.h | 20 +- .../MySensors/core/MySigningAtsha204Soft.cpp | 189 ++++++------ .../MySensors/core/MySigningAtsha204Soft.h | 44 +-- libraries/MySensors/core/MyTransport.cpp | 270 +++++++++--------- libraries/MySensors/core/MyTransport.h | 3 + .../examples/MotionSensor/MotionSensor.ino | 4 +- .../SecureActuator/SecureActuator.ino | 77 ++--- 15 files changed, 413 insertions(+), 469 deletions(-) diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index dc014fc..f765a38 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -148,7 +148,7 @@ * Message Signing Settings ***********************************/ -// Enable one of these in sketch to use signing functionality +// Enable one of these in sketch to use the signing functionality //#define MY_SIGNING_ATSHA204 //#define MY_SIGNING_SOFT @@ -168,21 +168,26 @@ // Note that a node can still transmit a non-salted message (i.e. have white listing disabled) // to a node that has white listing enabled (assuming the receiver does not have a matching entry // for the sender in it's white list) -//#define MY_SECURE_NODE_WHITELISTING +//#define MY_SIGNING_NODE_WHITELIST {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} -// MySigningAtsha204 default setting -#ifndef MY_ATSHA204_PIN -#define MY_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached +// Atsha204 default pin setting +#ifndef MY_SIGNING_ATSHA204_PIN +#define MY_SIGNING_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached #endif -// MySigningAtsha204Soft default settings -#ifndef MY_RANDOMSEED_PIN -#define MY_RANDOMSEED_PIN 7 // A7 - Pin used for random generation (do not connect anything to this) +// Pin used for random generation in soft signing (do not connect anything to this when enabled) +#ifndef MY_SIGNING_SOFT_RANDOMSEED_PIN +#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 // A7 - +#endif + +// Set the soft_serial value to an arbitrary value for proper security +#ifndef MY_SIGNING_SOFT_SERIAL +#define MY_SIGNING_SOFT_SERIAL 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09 #endif // Key to use for HMAC calculation in MySigningAtsha204Soft (32 bytes) -#ifndef MY_HMAC_KEY -#define MY_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +#ifndef MY_SIGNING_SOFT_HMAC_KEY +#define MY_SIGNING_SOFT_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 #endif /********************************** diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 62951a9..151ab7e 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -25,6 +25,7 @@ // #pragma message(VAR_NAME_VALUE(MY_GATEWAY_FEATURE)) #include "MyConfig.h" +#include "core/MySensorCore.h" #if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) || defined(MY_GATEWAY_ENC28J60) #define MY_GATEWAY_FEATURE @@ -60,16 +61,19 @@ // SIGNING #if defined(MY_SIGNING_ATSHA204) || defined(MY_SIGNING_SOFT) - #include "MySigning.cpp" + // SIGNING COMMON FUNCTIONS + #include "core/MySigning.cpp" #define MY_SIGNING_FEATURE + #if defined(MY_SIGNING_ATSHA204) && defined(MY_SIGNING_SOFT) + #error Only one signing engine can be activated + #endif + #if defined(MY_SIGNING_ATSHA204) - #include "MySigningAtsha204.cpp" + #include "core/MySigningAtsha204.cpp" #include "drivers/ATSHA204/ATSHA204.cpp" - MySigningAtsha204 signer; #elif defined(MY_SIGNING_SOFT) - #include "MySigningAtsha204Soft.cpp" + #include "core/MySigningAtsha204Soft.cpp" #include "drivers/ATSHA204/sha256.cpp" - MySigningAtsha204Soft signer; #endif #endif @@ -144,31 +148,6 @@ #undef MY_GATEWAY_FEATURE #endif -// Make sure to disable child features when parent feature is disabled -#if !defined(MY_RADIO_FEATURE) - #undef MY_OTA_FIRMWARE_FEATURE - #undef MY_REPEATER_FEATURE - #undef MY_SECURE_NODE_WHITELISTING - #undef MY_SIGNING_FEATURE -#endif - -#if !defined(MY_GATEWAY_FEATURE) - #undef MY_INCLUSION_MODE_FEATURE - #undef MY_INCLUSION_BUTTON_FEATURE -#endif - -// Defines used in code for if-statements -#if defined(MY_REPEATER_FEATURE) - #define MY_IS_REPEATER true -#else - #define MY_IS_REPEATER false -#endif - -#if defined(MY_GATEWAY_FEATURE) - #define MY_IS_GATEWAY true -#else - #define MY_IS_GATEWAY false -#endif // RADIO #if defined(MY_RADIO_NRF24) || defined(MY_RADIO_RFM69) @@ -188,6 +167,9 @@ SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); #endif #include "core/MyTransport.cpp" + #if defined(MY_RADIO_NRF24) && defined(MY_RADIO_RFM69) + #error Only one radio driver can be activated + #endif #if defined(MY_RADIO_NRF24) #include "drivers/RF24/RF24.cpp" #include "core/MyTransportNRF24.cpp" @@ -197,6 +179,20 @@ #endif #endif +// Make sure to disable child features when parent feature is disabled +#if !defined(MY_RADIO_FEATURE) + #undef MY_OTA_FIRMWARE_FEATURE + #undef MY_REPEATER_FEATURE + #undef MY_SIGNING_NODE_WHITELISTING + #undef MY_SIGNING_FEATURE +#endif + +#if !defined(MY_GATEWAY_FEATURE) + #undef MY_INCLUSION_MODE_FEATURE + #undef MY_INCLUSION_BUTTON_FEATURE +#endif + + #include "core/MyMessage.cpp" @@ -209,10 +205,10 @@ extern void loop(); // Initialize library and handle sketch functions like we want to int main() { init(); // Init Arduino - begin(); // Startup MySensors library + _begin(); // Startup MySensors library setup(); // Call sketch setup while(1) { - process(); // Process incoming data + _process(); // Process incoming data loop(); // Call sketch loop if (serialEventRun) serialEventRun(); } diff --git a/libraries/MySensors/core/MyProtocolDefault.cpp b/libraries/MySensors/core/MyProtocolDefault.cpp index 727b337..d4a54c1 100644 --- a/libraries/MySensors/core/MyProtocolDefault.cpp +++ b/libraries/MySensors/core/MyProtocolDefault.cpp @@ -21,8 +21,8 @@ #include "MyProtocolDefault.h" #include "MyTransport.h" -char fmtBuffer[MAX_FORMAT_BUFFER_LENGTH]; -char convBuffer[MAX_PAYLOAD*2+1]; +char _fmtBuffer[MAX_FORMAT_BUFFER_LENGTH]; +char _convBuffer[MAX_PAYLOAD*2+1]; bool protocolParse(MyMessage &message, char *inputString) { char *str, *p, *value=NULL; @@ -91,8 +91,8 @@ bool protocolParse(MyMessage &message, char *inputString) { } char * protocolFormat(MyMessage &message) { - snprintf_P(fmtBuffer, MAX_FORMAT_BUFFER_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuffer)); - return fmtBuffer; + snprintf_P(_fmtBuffer, MAX_FORMAT_BUFFER_LENGTH, PSTR("%d;%d;%d;%d;%d;%s\n"), message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(_convBuffer)); + return _fmtBuffer; } uint8_t protocolH2i(char c) { diff --git a/libraries/MySensors/core/MySensorCore.cpp b/libraries/MySensors/core/MySensorCore.cpp index da576b6..e05db79 100644 --- a/libraries/MySensors/core/MySensorCore.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -25,7 +25,7 @@ MyMessage _msg; // Buffer for incoming messages. MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others). #ifdef MY_DEBUG - char convBuf[MAX_PAYLOAD*2+1]; + char _convBuf[MAX_PAYLOAD*2+1]; #endif uint16_t _heartbeat; @@ -33,9 +33,10 @@ void (*_timeCallback)(unsigned long); // Callback for requested time messages void (*_msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. -void process() { +void _process() { hwWatchdogReset(); + #if defined (MY_LEDS_BLINKING_FEATURE) ledsProcess(); #endif @@ -59,11 +60,11 @@ static inline bool isValidParent( const uint8_t parent ) { } -void dataCallback(void (*msgCallback)(const MyMessage &)) { +void setIncomingCallback(void (*msgCallback)(const MyMessage &)) { _msgCallback = msgCallback; } -void begin() { +void _begin() { #if defined(MY_DISABLED_SERIAL) hwInit(); #endif @@ -165,7 +166,7 @@ ControllerConfig getConfig() { } -boolean sendRoute(MyMessage &message) { +boolean _sendRoute(MyMessage &message) { #if defined(MY_GATEWAY_FEATURE) if (message.destination == _nc.nodeId) { // This is a message sent from a sensor attached on the gateway node. @@ -185,42 +186,42 @@ bool send(MyMessage &message, bool enableAck) { message.sender = _nc.nodeId; mSetCommand(message,C_SET); mSetRequestAck(message,enableAck); - return sendRoute(message); + return _sendRoute(message); } void sendBatteryLevel(uint8_t value, bool enableAck) { - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, enableAck).set(value)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_BATTERY_LEVEL, enableAck).set(value)); } void sendHeartbeat(void) { - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT, false).set(_heartbeat++)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_HEARTBEAT, false).set(_heartbeat++)); } void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool enableAck) { - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, enableAck).set(childSensorId==NODE_SENSOR_ID?LIBRARY_VERSION:description)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, childSensorId, C_PRESENTATION, sensorType, enableAck).set(childSensorId==NODE_SENSOR_ID?LIBRARY_VERSION:description)); } void sendSketchInfo(const char *name, const char *version, bool enableAck) { if (name != NULL) { - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, enableAck).set(name)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_NAME, enableAck).set(name)); } if (version != NULL) { - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, enableAck).set(version)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_SKETCH_VERSION, enableAck).set(version)); } } void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination) { - sendRoute(build(_msg, _nc.nodeId, destination, childSensorId, C_REQ, variableType, false).set("")); + _sendRoute(build(_msg, _nc.nodeId, destination, childSensorId, C_REQ, variableType, false).set("")); } void requestTime(void (* timeCallback)(unsigned long)) { _timeCallback = timeCallback; - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, false).set("")); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_TIME, false).set("")); } // Message delivered through _msg -void processInternalMessages() { +void _processInternalMessages() { bool isMetric; uint8_t type = _msg.type; @@ -250,7 +251,7 @@ void processInternalMessages() { hwWriteConfig(EEPROM_DISTANCE_ADDRESS, 0xFF); // Find parent node transportFindParentNode(); - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CHILDREN,false).set("")); } #endif } @@ -266,7 +267,7 @@ uint8_t loadState(uint8_t pos) { void wait(unsigned long ms) { unsigned long enter = hwMillis(); while (hwMillis() - enter < ms) { - process(); + _process(); } } @@ -274,7 +275,8 @@ void sleep(unsigned long ms) { #if defined(MY_OTA_FIRMWARE_FEATURE) if (_fwUpdateOngoing) { // Do not sleep node while fw update is ongoing - process(); + _process(); + return; } else { #endif #if defined(MY_RADIO_FEATURE) @@ -290,7 +292,6 @@ bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) { #if defined(MY_OTA_FIRMWARE_FEATURE) if (_fwUpdateOngoing) { // Do not sleep node while fw update is ongoing - process(); return false; } else { #endif @@ -307,7 +308,6 @@ int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode #if defined(MY_OTA_FIRMWARE_FEATURE) if (_fwUpdateOngoing) { // Do not sleep node while fw update is ongoing - process(); return -1; } else { #endif diff --git a/libraries/MySensors/core/MySensorCore.h b/libraries/MySensors/core/MySensorCore.h index ce9ed5d..202019b 100644 --- a/libraries/MySensors/core/MySensorCore.h +++ b/libraries/MySensors/core/MySensorCore.h @@ -79,7 +79,7 @@ struct ControllerConfig { * * @param incomingMessageCallback Callback function for incoming messages from other nodes or controller and request responses. */ -void dataCallback(void (* msgCallback)(const MyMessage &)=NULL); +void setIncomingCallback(void (* msgCallback)(const MyMessage &)=NULL); /** * Return this nodes id. @@ -175,11 +175,6 @@ void saveState(uint8_t pos, uint8_t value); */ uint8_t loadState(uint8_t pos); -/** -* Returns the last received message -*/ -MyMessage& getLastMessage(void); - /** @@ -224,20 +219,20 @@ int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode /****** PRIVATE ********/ -void begin(); +void _begin(); -void process(void); +void _process(void); -void processInternalMessages(); +void _processInternalMessages(); -boolean sendRoute(MyMessage &message); +boolean _sendRoute(MyMessage &message); extern NodeConfig _nc; extern MyMessage _msg; // Buffer for incoming messages. extern MyMessage _msgTmp; // Buffer for temporary messages (acks and nonces among others). extern void (*_msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway. #ifdef MY_DEBUG - extern char convBuf[MAX_PAYLOAD*2+1]; + extern char _convBuf[MAX_PAYLOAD*2+1]; #endif // Inline function and macros diff --git a/libraries/MySensors/core/MySigning.cpp b/libraries/MySensors/core/MySigning.cpp index ad0d78c..e6350c8 100644 --- a/libraries/MySensors/core/MySigning.cpp +++ b/libraries/MySensors/core/MySigning.cpp @@ -23,11 +23,3 @@ uint16_t _doSign[16]; // Bitfield indicating which sensors require signed communication MyMessage _msgSign; // Buffer for message to sign. - -MySigning::MySigning(bool requestSignatures) : _requestSignatures(requestSignatures) { -} - - -bool MySigning::requestSignatures() { - return _requestSignatures; -} diff --git a/libraries/MySensors/core/MySigning.h b/libraries/MySensors/core/MySigning.h index 637b281..2e430c1 100644 --- a/libraries/MySensors/core/MySigning.h +++ b/libraries/MySensors/core/MySigning.h @@ -29,65 +29,57 @@ #include #include "MyMessage.h" +#include "drivers/ATSHA204/ATSHA204.h" +#ifdef MY_SIGNING_NODE_WHITELISTING +typedef struct { + uint8_t nodeId; + uint8_t serial[SHA204_SERIAL_SZ]; +} whitelist_entry_t; +#endif // Macros for manipulating signing requirement table #define DO_SIGN(node) (node == 0 ? (~_doSign[0]&1) : (~_doSign[node>>4]&(node%16))) #define SET_SIGN(node) (node == 0 ? (_doSign[0]&=~1) : (_doSign[node>>4]&=~(node%16))) #define CLEAR_SIGN(node) (node == 0 ? (_doSign[0]|=1) : (_doSign[node>>4]|=(node%16))) +#define NUM_OF(x) (sizeof(x)/sizeof(x[0])) -class MySigning -{ -public: - // MySigning constructor. - // Different parameters would be needed depending on signing backend (e.g. pins connected etc.). - // Keeping these parameters as #define's in MyConfig to streamline the driver interface. - // @param requestSignatures Set this to true if you want destination node to sign all messages sent to this node. Default is not to require signing. - MySigning(bool requestSignatures=false); +// Stores signing identifier and a new nonce in provided message for signing operations. +// All space in message payload buffer is used for signing identifier and nonce. +// Returns false if subsystem is busy processing an ongoing signing operation. +// If successful, this marks the start of a signing operation at the receiving side so +// implementation is expected to do any necessary initializations within this call. +bool signerGetNonce(MyMessage &msg); - // Returns the current requestSignature setting - bool requestSignatures(); +// Check timeout of verification session. +// Nonce will be purged if it takes too long for a signed message to be sent to the receiver. +// This function should be called on regular intervals. +bool signerCheckTimer(void); - // Stores signing identifier and a new nonce in provided message for signing operations. - // All space in message payload buffer is used for signing identifier and nonce. - // Returns false if subsystem is busy processing an ongoing signing operation. - // If successful, this marks the start of a signing operation at the receiving side so - // implementation is expected to do any necessary initializations within this call. - virtual bool getNonce(MyMessage &msg) = 0; +// Get nonce from provided message and store for signing operations. +// Returns false if subsystem is busy processing an ongoing signing operation. +// Returns false if signing identifier found in message is not supported by the used backend. +// If successful, this marks the start of a signing operation at the sending side so +// implementation is expected to do any necessary initializations within this call. +bool signerPutNonce(MyMessage &msg); - // Check timeout of verification session. - // Nonce will be purged if it takes too long for a signed message to be sent to the receiver. - // This function should be called on regular intervals. - virtual bool checkTimer(void) = 0; +// Signs provided message. All remaining space in message payload buffer is used for signing +// identifier and signature. +// Nonce used for signature calculation is the one generated previously using getNonce(). +// Nonce will be cleared when this function is called to prevent re-use of nonce. +// Returns false if subsystem is busy processing an ongoing signing operation. +// Returns false if not two bytes or more of free payload space is left in provided message. +// This ends a signing operation at the sending side so implementation is expected to do any +// deinitializations and enter a power saving state within this call. +bool signerSignMsg(MyMessage &msg); - // Get nonce from provided message and store for signing operations. - // Returns false if subsystem is busy processing an ongoing signing operation. - // Returns false if signing identifier found in message is not supported by the used backend. - // If successful, this marks the start of a signing operation at the sending side so - // implementation is expected to do any necessary initializations within this call. - virtual bool putNonce(MyMessage &msg) = 0; - - // Signs provided message. All remaining space in message payload buffer is used for signing - // identifier and signature. - // Nonce used for signature calculation is the one generated previously using getNonce(). - // Nonce will be cleared when this function is called to prevent re-use of nonce. - // Returns false if subsystem is busy processing an ongoing signing operation. - // Returns false if not two bytes or more of free payload space is left in provided message. - // This ends a signing operation at the sending side so implementation is expected to do any - // deinitializations and enter a power saving state within this call. - virtual bool signMsg(MyMessage &msg) = 0; - - // Verifies signature in provided message. - // Nonce used for verification is the one previously set using putNonce(). - // Nonce will be cleared when this function is called to prevent re-use of nonce. - // Returns false if subsystem is busy processing an ongoing signing operation. - // Returns false if signing identifier found in message is not supported by the used backend. - // This ends a signing operation at the receiving side so implementation is expected to do any - // deinitializations and enter a power saving state within this call. - virtual bool verifyMsg(MyMessage &msg) = 0; - - public: - bool _requestSignatures; -}; +// Verifies signature in provided message. +// Nonce used for verification is the one previously set using putNonce(). +// Nonce will be cleared when this function is called to prevent re-use of nonce. +// Returns false if subsystem is busy processing an ongoing signing operation. +// Returns false if signing identifier found in message is not supported by the used backend. +// This ends a signing operation at the receiving side so implementation is expected to do any +// deinitializations and enter a power saving state within this call. +bool signerVerifyMsg(MyMessage &msg); #endif diff --git a/libraries/MySensors/core/MySigningAtsha204.cpp b/libraries/MySensors/core/MySigningAtsha204.cpp index 06d1b45..4796388 100644 --- a/libraries/MySensors/core/MySigningAtsha204.cpp +++ b/libraries/MySensors/core/MySigningAtsha204.cpp @@ -34,6 +34,25 @@ // Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected) //#define DEBUG_SIGNING +uint8_t atshaPin=MY_ATSHA204_PIN); +ATSHA204Class atsha204; +unsigned long timestamp; +bool verification_ongoing; +uint8_t current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1]; +uint8_t temp_message[SHA_MSG_SIZE]; +uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; +uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; +void calculateSignature(MyMessage &msg); +uint8_t* sha256(const uint8_t* data, size_t sz); + +#ifdef MY_SIGNING_NODE_WHITELISTING + uint8_t nof_whitelist_entries=0; + const uint8_t whitelist_entry_t* the_whitelist=NULL, + uint8_t whitlist_sz; + const whitelist_entry_t* whitelist; +#endif + + #ifdef DEBUG_SIGNING #define DEBUG_SIGNING_PRINTLN(args) Serial.println(args) #else @@ -60,14 +79,14 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, MySigningAtsha204::MySigningAtsha204(bool requestSignatures, -#ifdef MY_SECURE_NODE_WHITELISTING +#ifdef MY_SIGNING_NODE_WHITELISTING uint8_t nof_whitelist_entries, const whitelist_entry_t* the_whitelist, #endif uint8_t atshaPin) : MySigning(requestSignatures), atsha204(atshaPin), -#ifdef MY_SECURE_NODE_WHITELISTING +#ifdef MY_SIGNING_NODE_WHITELISTING whitelist(the_whitelist), whitlist_sz(nof_whitelist_entries), #endif @@ -142,7 +161,7 @@ bool MySigningAtsha204::signMsg(MyMessage &msg) { mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated calculateSignature(msg); -#ifdef MY_SECURE_NODE_WHITELISTING +#ifdef MY_SIGNING_NODE_WHITELISTING // Salt the signature with the senders nodeId and the unique serial of the ATSHA device memcpy(current_nonce, &rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed current_nonce[32] = msg.sender; @@ -180,7 +199,7 @@ bool MySigningAtsha204::verifyMsg(MyMessage &msg) { DEBUG_SIGNING_PRINTBUF(F("SIM:"), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); // SIM = Signature in message calculateSignature(msg); // Get signature of message -#ifdef MY_SECURE_NODE_WHITELISTING +#ifdef MY_SIGNING_NODE_WHITELISTING // Look up the senders nodeId in our whitelist and salt the signature with that data for (int j=0; j < whitlist_sz; j++) { if (whitelist[j].nodeId == msg.sender) { @@ -200,7 +219,7 @@ bool MySigningAtsha204::verifyMsg(MyMessage &msg) { // Compare the caluclated signature with the provided signature if (memcmp(&msg.data[mGetLength(msg)], &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) { DEBUG_SIGNING_PRINTBUF(F("SNOK:"), &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); // SNOK = Signature bad -#ifdef MY_SECURE_NODE_WHITELISTING +#ifdef MY_SIGNING_NODE_WHITELISTING DEBUG_SIGNING_PRINTLN(F("W?")); // W? = Is the sender whitelisted? #endif return false; diff --git a/libraries/MySensors/core/MySigningAtsha204.h b/libraries/MySensors/core/MySigningAtsha204.h index 1242db7..fe353f7 100644 --- a/libraries/MySensors/core/MySigningAtsha204.h +++ b/libraries/MySensors/core/MySigningAtsha204.h @@ -33,7 +33,7 @@ #include "drivers/ATSHA204/ATSHA204.h" #include -#ifdef MY_SECURE_NODE_WHITELISTING +#ifdef MY_SIGNING_NODE_WHITELISTING typedef struct { uint8_t nodeId; uint8_t serial[SHA204_SERIAL_SZ]; @@ -47,29 +47,13 @@ class MySigningAtsha204 : public MySigning { public: MySigningAtsha204(bool requestSignatures=true, -#ifdef MY_SECURE_NODE_WHITELISTING - uint8_t nof_whitelist_entries=0, const whitelist_entry_t* the_whitelist=NULL, -#endif - uint8_t atshaPin=MY_ATSHA204_PIN); + bool getNonce(MyMessage &msg); bool checkTimer(void); bool putNonce(MyMessage &msg); bool signMsg(MyMessage &msg); bool verifyMsg(MyMessage &msg); private: - ATSHA204Class atsha204; - unsigned long timestamp; - bool verification_ongoing; - uint8_t current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1]; - uint8_t temp_message[SHA_MSG_SIZE]; - uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; - uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; - void calculateSignature(MyMessage &msg); - uint8_t* sha256(const uint8_t* data, size_t sz); -#ifdef MY_SECURE_NODE_WHITELISTING - uint8_t whitlist_sz; - const whitelist_entry_t* whitelist; -#endif }; #endif diff --git a/libraries/MySensors/core/MySigningAtsha204Soft.cpp b/libraries/MySensors/core/MySigningAtsha204Soft.cpp index fc52085..d5e8b09 100644 --- a/libraries/MySensors/core/MySigningAtsha204Soft.cpp +++ b/libraries/MySensors/core/MySigningAtsha204Soft.cpp @@ -35,6 +35,20 @@ #define SIGNING_IDENTIFIER (1) + +Sha256Class _signing_sha256; +unsigned long _signing_timestamp; +bool _signing_verification_ongoing = false; +uint8_t _signing_current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH]; +uint8_t _signing_temp_message[32]; +static uint8_t _signing_hmac_key[32] = { MY_SIGNING_SOFT_HMAC_KEY }; +uint8_t _signing_hmac[32]; + +#ifdef MY_SIGNING_NODE_WHITELISTING + const uint8_t _signing_node_serial_info[SHA204_SERIAL_SZ] = {MY_SIGNING_SOFT_SERIAL}; + const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; +#endif + // Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected) //#define DEBUG_SIGNING @@ -63,81 +77,60 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, #define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #endif -// Initialize hmacKey from MyConfig.h (codebender didn't like static initialization in constructor) -uint8_t MySigningAtsha204Soft::hmacKey[32] = { MY_HMAC_KEY }; -MySigningAtsha204Soft::MySigningAtsha204Soft(bool requestSignatures, -#ifdef MY_SECURE_NODE_WHITELISTING - uint8_t nof_whitelist_entries, const whitelist_entry_t* the_whitelist, - const uint8_t* the_serial, -#endif - uint8_t randomseedPin) - : - MySigning(requestSignatures), -#ifdef MY_SECURE_NODE_WHITELISTING - whitlist_sz(nof_whitelist_entries), - whitelist(the_whitelist), - node_serial_info(the_serial), -#endif - Sha256(), - verification_ongoing(false), - rndPin(randomseedPin) -{ -} - -bool MySigningAtsha204Soft::getNonce(MyMessage &msg) { +bool signerGetNonce(MyMessage &msg) { // Set randomseed - randomSeed(analogRead(rndPin)); + randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN)); // We used a basic whitening technique that takes the first byte of a new random value and builds up a 32-byte random value // This 32-byte random value is then hashed (SHA256) to produce the resulting nonce - Sha256.init(); + _signing_sha256.init(); for (int i = 0; i < 32; i++) { - Sha256.write(random(255)); + _signing_sha256.write(random(255)); } - memcpy(current_nonce, Sha256.result(), MAX_PAYLOAD); + memcpy(_signing_current_nonce, _signing_sha256.result(), MAX_PAYLOAD); // We set the part of the 32-byte nonce that does not fit into a message to 0xAA - memset(¤t_nonce[MAX_PAYLOAD], 0xAA, sizeof(current_nonce)-MAX_PAYLOAD); + memset(&_signing_current_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_current_nonce)-MAX_PAYLOAD); // Replace the first byte in the nonce with our signing identifier - current_nonce[0] = SIGNING_IDENTIFIER; + _signing_current_nonce[0] = SIGNING_IDENTIFIER; // Transfer the first part of the nonce to the message - msg.set(current_nonce, MAX_PAYLOAD); - verification_ongoing = true; - timestamp = millis(); // Set timestamp to determine when to purge nonce + msg.set(_signing_current_nonce, MAX_PAYLOAD); + _signing_verification_ongoing = true; + _signing_timestamp = millis(); // Set timestamp to determine when to purge nonce // Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover) // Note that if message is "too" quick, and arrives before turnover, it will be rejected // but this is consider such a rare case that it is accepted and rejects are 'safe' - if (timestamp + MY_VERIFICATION_TIMEOUT_MS < millis()) timestamp = 0; + if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < millis()) _signing_timestamp = 0; return true; } -bool MySigningAtsha204Soft::checkTimer() { - if (verification_ongoing) { - if (millis() < timestamp || millis() > timestamp + MY_VERIFICATION_TIMEOUT_MS) { +bool signerCheckTimer() { + if (_signing_verification_ongoing) { + if (millis() < _signing_timestamp || millis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { DEBUG_SIGNING_PRINTLN(F("VT")); // VT = Verification timeout // Purge nonce - memset(current_nonce, 0xAA, 32); - verification_ongoing = false; + memset(_signing_current_nonce, 0xAA, 32); + _signing_verification_ongoing = false; return false; } } return true; } -bool MySigningAtsha204Soft::putNonce(MyMessage &msg) { +bool signerPutNonce(MyMessage &msg) { if (((uint8_t*)msg.getCustom())[0] != SIGNING_IDENTIFIER) { DEBUG_SIGNING_PRINTLN(F("ISI")); // ISI = Incorrect signing identifier return false; } - memcpy(current_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); + memcpy(_signing_current_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); return true; } -bool MySigningAtsha204Soft::signMsg(MyMessage &msg) { +bool signerSignMsg(MyMessage &msg) { // If we cannot fit any signature in the message, refuse to sign it if (mGetLength(msg) > MAX_PAYLOAD-2) { DEBUG_SIGNING_PRINTLN(F("MTOL")); // Message too large for signature to fit @@ -146,38 +139,38 @@ bool MySigningAtsha204Soft::signMsg(MyMessage &msg) { // Calculate signature of message mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated - calculateSignature(msg); + signerCalculateSignature(msg); -#ifdef MY_SECURE_NODE_WHITELISTING +#ifdef MY_SIGNING_NODE_WHITELISTING // Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided - Sha256.init(); - for (int i=0; i<32; i++) Sha256.write(hmac[i]); - Sha256.write(msg.sender); - for (int i=0; i -#ifdef MY_SECURE_NODE_WHITELISTING -typedef struct { - uint8_t nodeId; - uint8_t serial[SHA204_SERIAL_SZ]; -} whitelist_entry_t; -#endif + // This implementation is the pure software variant of the ATSHA204. // It is designed to work fully compliant with nodes using ATSHA204 in the network // and therefore uses the same signing identifier as ATSHA204. -// Because it is completly software based, the quality of the generated random numbers +// Because it is completely software based, the quality of the generated random numbers // is weaker though. Random numbers are generated using the Arduino library and seed // is sampled from an analog pin. This pin should unconnected in the hardware. -// The pin is selected using MY_RANDOMSEED_PIN in MyConfig.h. -class MySigningAtsha204Soft : public MySigning -{ -public: - MySigningAtsha204Soft(bool requestSignatures=true, -#ifdef MY_SECURE_NODE_WHITELISTING - uint8_t nof_whitelist_entries=0, const whitelist_entry_t* the_whitelist=NULL, - const uint8_t* the_serial=NULL, //SHA204_SERIAL_SZ sized buffer expected if provided -#endif - uint8_t randomseedPin=MY_RANDOMSEED_PIN); - bool getNonce(MyMessage &msg); - bool checkTimer(void); - bool putNonce(MyMessage &msg); - bool signMsg(MyMessage &msg); - bool verifyMsg(MyMessage &msg); -private: - Sha256Class Sha256; - unsigned long timestamp; - bool verification_ongoing; - uint8_t current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH]; - uint8_t temp_message[32]; - static uint8_t hmacKey[32]; - uint8_t rndPin; - uint8_t hmac[32]; - void calculateSignature(MyMessage &msg); -#ifdef MY_SECURE_NODE_WHITELISTING - uint8_t whitlist_sz; - const whitelist_entry_t* whitelist; - const uint8_t* node_serial_info; -#endif -}; +// The pin is selected using MY_SIGNING_SOFT_RANDOMSEED_PIN in MyConfig.h. + +void signerCalculateSignature(MyMessage &msg); + #endif diff --git a/libraries/MySensors/core/MyTransport.cpp b/libraries/MySensors/core/MyTransport.cpp index 309bc4d..626e9e8 100644 --- a/libraries/MySensors/core/MyTransport.cpp +++ b/libraries/MySensors/core/MyTransport.cpp @@ -23,6 +23,9 @@ bool _autoFindParent; uint8_t _failedTransmissions; +#ifdef MY_SIGNING_FEATURE + bool _signingNonceStatus; +#endif #ifdef MY_OTA_FIRMWARE_FEATURE NodeFirmwareConfig _fc; @@ -60,14 +63,14 @@ inline void transportProcess() { firmwareRequest->type = _fc.type; firmwareRequest->version = _fc.version; firmwareRequest->block = (_fwBlock - 1); - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_REQUEST, false)); } #endif return; } #ifdef MY_SIGNING_FEATURE - (void)signer.checkTimer(); // Manage signing timeout + (void)signerCheckTimer(); // Manage signing timeout #endif uint8_t len = transportReceive((uint8_t *)&_msg); @@ -77,29 +80,31 @@ inline void transportProcess() { #ifdef MY_SIGNING_FEATURE // Before processing message, reject unsigned messages if signing is required and check signature (if it is signed and addressed to us) // Note that we do not care at all about any signature found if we do not require signing, nor do we care about ACKs (they are never signed) - if (signer.requestSignatures() && _msg.destination == _nc.nodeId && mGetLength(_msg) && !mGetAck(_msg) && - (mGetCommand(_msg) != C_INTERNAL || - (_msg.type != I_GET_NONCE_RESPONSE && _msg.type != I_GET_NONCE && _msg.type != I_REQUEST_SIGNING && - _msg.type != I_ID_REQUEST && _msg.type != I_ID_RESPONSE && - _msg.type != I_FIND_PARENT && _msg.type != I_FIND_PARENT_RESPONSE))) { - if (!mGetSigned(_msg)) { - // Got unsigned message that should have been signed - debug(PSTR("no sign\n")); - ledBlinkErr(1); - return; + #ifdef MY_SIGNING_REQUEST_SIGNATURES + if (_msg.destination == _nc.nodeId && mGetLength(_msg) && !mGetAck(_msg) && + (mGetCommand(_msg) != C_INTERNAL || + (_msg.type != I_GET_NONCE_RESPONSE && _msg.type != I_GET_NONCE && _msg.type != I_REQUEST_SIGNING && + _msg.type != I_ID_REQUEST && _msg.type != I_ID_RESPONSE && + _msg.type != I_FIND_PARENT && _msg.type != I_FIND_PARENT_RESPONSE))) { + if (!mGetSigned(_msg)) { + // Got unsigned message that should have been signed + debug(PSTR("no sign\n")); + ledBlinkErr(1); + return; + } + else if (!signerVerifyMsg(_msg)) { + debug(PSTR("verify fail\n")); + ledBlinkErr(1); + return; // This signed message has been tampered with! + } } - else if (!signer.verifyMsg(_msg)) { - debug(PSTR("verify fail\n")); - ledBlinkErr(1); - return; // This signed message has been tampered with! - } - } + #endif #endif // Add string termination, good if we later would want to print it. _msg.data[mGetLength(_msg)] = '\0'; debug(PSTR("read: %d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d:%s\n"), - _msg.sender, _msg.last, _msg.destination, _msg.sensor, mGetCommand(_msg), _msg.type, mGetPayloadType(_msg), mGetLength(_msg), mGetSigned(_msg), _msg.getString(convBuf)); + _msg.sender, _msg.last, _msg.destination, _msg.sensor, mGetCommand(_msg), _msg.type, mGetPayloadType(_msg), mGetLength(_msg), mGetSigned(_msg), _msg.getString(_convBuf)); mSetSigned(_msg,0); // Clear the sign-flag now as verification (and debug printing) is completed if(!(mGetVersion(_msg) == PROTOCOL_VERSION)) { @@ -132,7 +137,7 @@ inline void transportProcess() { mSetAck(_msgTmp,true); _msgTmp.sender = _nc.nodeId; _msgTmp.destination = _msg.sender; - sendRoute(_msgTmp); + _sendRoute(_msgTmp); } if (command == C_INTERNAL) { @@ -158,10 +163,10 @@ inline void transportProcess() { return; #ifdef MY_SIGNING_FEATURE } else if (type == I_GET_NONCE) { - if (signer.getNonce(_msg)) { - sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_GET_NONCE_RESPONSE, false)); + if (signerGetNonce(_msg)) { + _sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_GET_NONCE_RESPONSE, false)); } - return false; // Nonce exchange is an internal MySensor protocol message, no need to inform caller about this + return; // Nonce exchange is an internal MySensor protocol message, no need to inform caller about this } else if (type == I_REQUEST_SIGNING) { if (_msg.getBool()) { // We received an indicator that the sender require us to sign all messages we send to it @@ -176,14 +181,22 @@ inline void transportProcess() { // Inform sender about our preference if we are a gateway, but only require signing if the sender required signing // We do not currently want a gateway to require signing from all nodes in a network just because it wants one node // to sign it's messages - if (MY_GATEWAY_FEATURE) { - if (signer.requestSignatures() && DO_SIGN(_msg.sender)) - sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(true)); - else - sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); - } + #if defined (MY_GATEWAY_FEATURE) + #ifdef MY_SIGNING_REQUEST_SIGNATURES + if (DO_SIGN(_msg.sender)) + _sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(true)); + else + _sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); + #else + _sendRoute(build(_msg, _nc.nodeId, _msg.sender, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); + #endif + #endif return; // Signing request is an internal MySensor protocol message, no need to inform caller about this } else if (type == I_GET_NONCE_RESPONSE) { + // Proceed with signing if nonce has been received + if (signerPutNonce(_msg) && signerSignMsg(_msgSign)) { + _signingNonceStatus = SIGN_OK; + } return; // Just pass along nonce silently (no need to call callback for these) #endif } else if (sender == GATEWAY_ADDRESS) { @@ -199,7 +212,7 @@ inline void transportProcess() { hwWriteConfig(EEPROM_NODE_ID_ADDRESS, _nc.nodeId); debug(PSTR("id=%d\n"), _nc.nodeId); } else { - processInternalMessages(); + _processInternalMessages(); } return; } @@ -292,7 +305,7 @@ inline void transportProcess() { } } else if (to == _nc.nodeId) { // We should try to relay this message to another node - sendRoute(_msg); + _sendRoute(_msg); } } #endif @@ -327,7 +340,7 @@ boolean transportSendWrite(uint8_t to, MyMessage &message) { debug(PSTR("send: %d-%d-%d-%d s=%d,c=%d,t=%d,pt=%d,l=%d,sg=%d,st=%s:%s\n"), message.sender,message.last, to, message.destination, message.sensor, mGetCommand(message), message.type, - mGetPayloadType(message), mGetLength(message), mGetSigned(message), to==BROADCAST_ADDRESS ? "bc" : (ok ? "ok":"fail"), message.getString(convBuf)); + mGetPayloadType(message), mGetLength(message), mGetSigned(message), to==BROADCAST_ADDRESS ? "bc" : (ok ? "ok":"fail"), message.getString(_convBuf)); return ok; } @@ -356,103 +369,101 @@ boolean transportSendRoute(MyMessage &message) { mSetVersion(message, PROTOCOL_VERSION); #ifdef MY_SIGNING_FEATURE - // If destination is known to require signed messages and we are the sender, sign this message unless it is an ACK or a handshake message - if (DO_SIGN(message.destination) && message.sender == _nc.nodeId && !mGetAck(message) && mGetLength(message) && - (mGetCommand(message) != C_INTERNAL || - (message.type != I_GET_NONCE && message.type != I_GET_NONCE_RESPONSE && message.type != I_REQUEST_SIGNING && - message.type != I_ID_REQUEST && message.type != I_ID_RESPONSE && - message.type != I_FIND_PARENT && message.type != I_FIND_PARENT_RESPONSE))) { - bool signOk = false; - // Send nonce-request - if (!sendRoute(build(_msgTmp, _nc.nodeId, message.destination, message.sensor, C_INTERNAL, I_GET_NONCE, false).set(""))) { - debug(PSTR("nonce tr err\n")); - return false; - } - // We have to wait for the nonce to arrive before we can sign our original message - // Other messages could come in-between. We trust process() takes care of them - unsigned long enter = hwMillis(); - _msgSign = message; // Copy the message to sign since message buffer might be touched in process() - while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS) { - if (process()) { - if (mGetCommand(getLastMessage()) == C_INTERNAL && getLastMessage().type == I_GET_NONCE_RESPONSE) { - // Proceed with signing if nonce has been received - if (signer.putNonce(getLastMessage()) && signer.signMsg(_msgSign)) { - message = _msgSign; // Write the signed message back - signOk = true; - } - break; - } + // If destination is known to require signed messages and we are the sender, sign this message unless it is an ACK or a handshake message + if (DO_SIGN(message.destination) && message.sender == _nc.nodeId && !mGetAck(message) && mGetLength(message) && + (mGetCommand(message) != C_INTERNAL || + (message.type != I_GET_NONCE && message.type != I_GET_NONCE_RESPONSE && message.type != I_REQUEST_SIGNING && + message.type != I_ID_REQUEST && message.type != I_ID_RESPONSE && + message.type != I_FIND_PARENT && message.type != I_FIND_PARENT_RESPONSE))) { + bool signing = SIGN_WAITING_FOR_NONCE; + // Send nonce-request + if (!_sendRoute(build(_msgTmp, _nc.nodeId, message.destination, message.sensor, C_INTERNAL, I_GET_NONCE, false).set(""))) { + debug(PSTR("nonce tr err\n")); + return false; } + // We have to wait for the nonce to arrive before we can sign our original message + // Other messages could come in-between. We trust process() takes care of them + unsigned long enter = hwMillis(); + _msgSign = message; // Copy the message to sign since message buffer might be touched in process() + + while (hwMillis() - enter < MY_VERIFICATION_TIMEOUT_MS && _signingNonceStatus==SIGN_WAITING_FOR_NONCE) { + _process(); + } + if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { + debug(PSTR("nonce tmo\n")); + ledBlinkErr(1); + return false; + } + if (_signingNonceStatus == SIGN_OK) { + message = _msgSign; // Write the signed message back + } else { + debug(PSTR("sign fail\n")); + ledBlinkErr(1); + return false; + } + // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed, + // or signature will become invalid and the message rejected by the receiver + } else { + mSetSigned(message, 0); // Message is not supposed to be signed, make sure it is marked unsigned } - if (hwMillis() - enter > MY_VERIFICATION_TIMEOUT_MS) { - debug(PSTR("nonce tmo\n")); - ledBlinkErr(1); - return false; - } - if (!signOk) { - debug(PSTR("sign fail\n")); - ledBlinkErr(1); - return false; - } - // After this point, only the 'last' member of the message structure is allowed to be altered if the message has been signed, - // or signature will become invalid and the message rejected by the receiver - } else { - mSetSigned(message, 0); // Message is not supposed to be signed, make sure it is marked unsigned - } #endif - if (dest == GATEWAY_ADDRESS || !MY_IS_REPEATER) { - // Store this address in routing table (if repeater) - #if defined (MY_IS_REPEATER) - hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); - #endif - // If destination is the gateway or if we aren't a repeater, let - // our parent take care of the message + + #if !defined(MY_REPEATER_FEATURE) + // None repeating node... We can only send to our parent ok = transportSendWrite(_nc.parentNodeId, message); - } else { - // Relay the message - uint8_t route = hwReadConfig(EEPROM_ROUTES_ADDRESS+dest); - if (route > GATEWAY_ADDRESS && route < BROADCAST_ADDRESS) { - // This message should be forwarded to a child node. If we send message - // to this nodes pipe then all children will receive it because the are - // all listening to this nodes pipe. - // - // +----B - // -A - // +----C------D - // - // We're node C, Message comes from A and has destination D - // - // Message destination is not gateway and is in routing table for this node. - // Send it downstream - return transportSendWrite(route, message); - } else if (sender == GATEWAY_ADDRESS && dest == BROADCAST_ADDRESS) { - // Node has not yet received any id. We need to send it - // by doing a broadcast sending, - return transportSendWrite(BROADCAST_ADDRESS, message); - } else if (MY_IS_GATEWAY) { - // Destination isn't in our routing table and isn't a broadcast address - // Nothing to do here - return false; - } else { - // A message comes from a child node and we have no - // route for it. - // - // +----B - // -A - // +----C------D <-- Message comes from D - // - // We're node C - // - // Message should be passed to node A (this nodes relay) - - // This message should be routed back towards sensor net gateway - ok = transportSendWrite(_nc.parentNodeId, message); - // Add this child to our "routing table" if it not already exist + #else + if (dest == GATEWAY_ADDRESS) { + // Store this address in routing table (if repeater) hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); - } - } + // If destination is the gateway or if we aren't a repeater, let + // our parent take care of the message + ok = transportSendWrite(_nc.parentNodeId, message); + } else { + // Relay the message + uint8_t route = hwReadConfig(EEPROM_ROUTES_ADDRESS+dest); + if (route > GATEWAY_ADDRESS && route < BROADCAST_ADDRESS) { + // This message should be forwarded to a child node. If we send message + // to this nodes pipe then all children will receive it because the are + // all listening to this nodes pipe. + // + // +----B + // -A + // +----C------D + // + // We're node C, Message comes from A and has destination D + // + // Message destination is not gateway and is in routing table for this node. + // Send it downstream + return transportSendWrite(route, message); + } else if (sender == GATEWAY_ADDRESS && dest == BROADCAST_ADDRESS) { + // Node has not yet received any id. We need to send it + // by doing a broadcast sending, + return transportSendWrite(BROADCAST_ADDRESS, message); + } + #if defined (MY_GATEWAY_FEATURE) + // Destination isn't in our routing table and isn't a broadcast address + // Nothing to do here + return false; + # else + // A message comes from a child node and we have no + // route for it. + // + // +----B + // -A + // +----C------D <-- Message comes from D + // + // We're node C + // + // Message should be passed to node A (this nodes relay) + // This message should be routed back towards sensor net gateway + ok = transportSendWrite(_nc.parentNodeId, message); + // Add this child to our "routing table" if it not already exist + hwWriteConfig(EEPROM_ROUTES_ADDRESS+sender, last); + #endif + } + #endif if (!ok) { // Failure when sending to parent node. The parent node might be down and we // need to find another route to gateway. @@ -484,12 +495,13 @@ void transportSetupNode() { if (_nc.nodeId != AUTO) { #ifdef MY_SIGNING_FEATURE // Notify gateway (and possibly controller) about the signing preferences of this node - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(signer.requestSignatures())); - - // If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages - if (signer.requestSignatures()) { + #if defined(MY_SIGNING_REQUEST_SIGNATURES) + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(true)); + // If we do require signing, wait for the gateway to tell us how it prefer us to transmit our messages wait(2000); - } + #else + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_REQUEST_SIGNING, false).set(false)); + #endif #endif // Send presentation for this radio node @@ -501,7 +513,7 @@ void transportSetupNode() { // Send a configuration exchange request to controller // Node sends parent node. Controller answers with latest node configuration // which is picked up in process() - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG, false).set(_nc.parentNodeId)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_INTERNAL, I_CONFIG, false).set(_nc.parentNodeId)); // Wait configuration reply. wait(2000); @@ -516,7 +528,7 @@ void transportSetupNode() { // add bootloader information reqFWConfig->BLVersion = MY_OTA_BOOTLOADER_VERSION; _fwUpdateOngoing = false; - sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); + _sendRoute(build(_msg, _nc.nodeId, GATEWAY_ADDRESS, NODE_SENSOR_ID, C_STREAM, ST_FIRMWARE_CONFIG_REQUEST, false)); #endif } #endif diff --git a/libraries/MySensors/core/MyTransport.h b/libraries/MySensors/core/MyTransport.h index f72ea8f..827430b 100644 --- a/libraries/MySensors/core/MyTransport.h +++ b/libraries/MySensors/core/MyTransport.h @@ -41,6 +41,9 @@ // Search for a new parent node after this many transmission failures #define SEARCH_FAILURES 5 +// Status when waiting for signing nonce in process +enum { SIGN_WAITING_FOR_NONCE = 0, SIGN_OK = 1 }; + // FW config structure, stored in eeprom typedef struct { diff --git a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino index d07b2a7..d48131c 100644 --- a/libraries/MySensors/examples/MotionSensor/MotionSensor.ino +++ b/libraries/MySensors/examples/MotionSensor/MotionSensor.ino @@ -29,7 +29,9 @@ //#define MY_DEBUG -#define MY_RADIO_NRF24 // MY_RADIO_RFM69 +// Enable and select radio type +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 //#define MY_SOFTSPI //#define MY_OTA_FIRMWARE_FEATURE diff --git a/libraries/MySensors/examples/SecureActuator/SecureActuator.ino b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino index cb69354..76a80ea 100644 --- a/libraries/MySensors/examples/SecureActuator/SecureActuator.ino +++ b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino @@ -25,79 +25,62 @@ * Example sketch showing how to securely control locks. * This example will remember lock state even after power failure. */ + +// Enable and select radio type +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 +// Select soft/hardware signing method +#define MY_SIGNING_SOFT // Software signing enabled +//#define MY_SIGNING_ATSHA204 // Hardware signing using ATSHA204A + +// Enable node whitelisting +#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} +// Enable this if you want destination node to sign all messages sent to this node. Default is not to require signing. +#define MY_SIGNING_REQUEST_SIGNATURES + + +// SETTINGS FOR MY_SIGNING_SOFT +// Set the soft_serial value to an arbitrary value for proper security (9 bytes) +#define MY_SIGNING_SOFT_SERIAL 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09 +// Key to use for HMAC calculation in soft signing (32 bytes) +#define MY_SIGNING_SOFT_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + +#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 + +// SETTINGS FOR MY_SIGNING_ATSHA204 +#define MY_SIGNING_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached -#define USE_SOFTWARE_ATSHA // Disable to use ATSHA204A circuit -#include -#include #include -#include -#ifdef USE_SOFTWARE_ATSHA -#include -#else -#include -#endif + #define LOCK_1 3 // Arduino Digital I/O pin number for first lock (second on pin+1 etc) #define NOF_LOCKS 1 // Total number of attached locks #define LOCK_LOCK 1 // GPIO value to write to lock attached lock #define LOCK_UNLOCK 0 // GPIO value to write to unlock attached lock -MyTransportNRF24 radio; // NRFRF24L01 radio driver -MyHwATMega328 hw; // Select AtMega328 hardware profile -#ifdef MY_SIGNING_FEATURE -#ifdef MY_SECURE_NODE_WHITELISTING -#ifdef USE_SOFTWARE_ATSHA -// Change the soft_serial value to an arbitrary value for proper security -uint8_t soft_serial[SHA204_SERIAL_SZ] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09}; -#endif -// We only use one whitelist entry (the gateway) -whitelist_entry_t node_whitelist[] = { - { .nodeId = GATEWAY_ADDRESS, - .serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01} } -}; -#ifdef USE_SOFTWARE_ATSHA -MySigningAtsha204Soft signer(true, 1, node_whitelist, soft_serial); // Message signing driver -#else -MySigningAtsha204 signer(true, 1, node_whitelist); -#endif -#else -#ifdef USE_SOFTWARE_ATSHA -MySigningAtsha204Soft signer; -#else -MySigningAtsha204 signer; -#endif -#endif -MySensor gw(radio, hw, signer); -#else -// WARNING! SecureActuator cannot possibly be secure without signing enabled -MySensor gw(radio, hw); -#endif void setup() { // Initialize library and add callback for incoming messages (signing is required) - gw.begin(incomingMessage, AUTO); + setIncomingCallback(incomingMessage); // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Secure Lock", "1.0"); + sendSketchInfo("Secure Lock", "1.0"); // Fetch lock status for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS;lock++, pin++) { // Register all locks to gw (they will be created as child devices) - gw.present(lock, S_LOCK, "SecureActuator", false); + present(lock, S_LOCK, "SecureActuator", false); // Then set lock pins in output mode pinMode(pin, OUTPUT); // Set lock to last known state (using eeprom storage) - digitalWrite(pin, gw.loadState(lock)?LOCK_LOCK:LOCK_UNLOCK); + digitalWrite(pin, loadState(lock)?LOCK_LOCK:LOCK_UNLOCK); } } - void loop() { - // Alway process incoming messages whenever possible - gw.process(); } void incomingMessage(const MyMessage &message) { @@ -106,7 +89,7 @@ void incomingMessage(const MyMessage &message) { // Change relay state digitalWrite(message.sensor-1+LOCK_1, message.getBool()?LOCK_LOCK:LOCK_UNLOCK); // Store state in eeprom - gw.saveState(message.sensor, message.getBool()); + saveState(message.sensor, message.getBool()); // Write some debug info Serial.print("Incoming change for lock:"); Serial.print(message.sensor); From 6cf6255e5041f91eff2dfef1c054dffba183c606 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Thu, 17 Sep 2015 07:24:12 +0200 Subject: [PATCH 17/43] Fix: ATSHA204, serial gw, ethernet warnings --- libraries/MySensors/MySensor.h | 26 ++- .../MySensors/core/MyGatewayTransport.cpp | 2 +- .../core/MyGatewayTransportEthernet.h | 2 +- .../MySensors/core/MyGatewayTransportSerial.h | 2 +- ...colDefault.cpp => MyProtocolMySensors.cpp} | 2 +- ...rotocolDefault.h => MyProtocolMySensors.h} | 0 libraries/MySensors/core/MySensorCore.cpp | 31 ++-- libraries/MySensors/core/MySensorCore.h | 2 + .../MySensors/core/MySigningAtsha204.cpp | 171 ++++++++---------- libraries/MySensors/core/MySigningAtsha204.h | 21 +-- libraries/MySensors/core/MySigningNone.cpp | 13 +- libraries/MySensors/core/MySigningNone.h | 10 - libraries/MySensors/core/MyTransport.cpp | 2 +- libraries/MySensors/core/MyTransport.h | 1 - libraries/MySensors/core/MyTransportRFM69.h | 1 - libraries/MySensors/core/Version.h | 2 +- .../AVR/Ethernet_UIP/src/UIPClient.cpp | 8 +- .../drivers/AVR/Ethernet_UIP/src/UIPClient.h | 6 +- .../AVR/Ethernet_UIP/src/UIPEthernet.h | 1 + .../drivers/AVR/Ethernet_UIP/src/UIPServer.h | 4 +- .../AVR/Ethernet_UIP/src/utility/uip.c | 1 + .../AVR/Ethernet_UIP/src/utility/uip_arp.c | 1 + libraries/MySensors/drivers/RFM69/RFM69.cpp | 2 +- .../AirQualitySensor/AirQualitySensor.ino | 20 +- .../EthernetGateway/EthernetGateway.ino | 15 +- .../examples/RelayActuator/RelayActuator.ino | 39 ++-- .../SecureActuator/SecureActuator.ino | 10 +- .../examples/SerialGateway/SerialGateway.ino | 65 +++---- 28 files changed, 206 insertions(+), 254 deletions(-) rename libraries/MySensors/core/{MyProtocolDefault.cpp => MyProtocolMySensors.cpp} (98%) rename libraries/MySensors/core/{MyProtocolDefault.h => MyProtocolMySensors.h} (100%) diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index 151ab7e..b4ef368 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -19,15 +19,14 @@ #ifndef MySensor_h #define MySensor_h -#define VALUE_TO_STRING(x) #x -#define VALUE(x) VALUE_TO_STRING(x) -#define VAR_NAME_VALUE(var) #var "=" VALUE(var) -// #pragma message(VAR_NAME_VALUE(MY_GATEWAY_FEATURE)) +/* { dg-warning "import is a deprecated GCC extension" "deprecated" {target *-*-* } 0 } */ + + #include "MyConfig.h" #include "core/MySensorCore.h" -#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) || defined(MY_GATEWAY_ENC28J60) +#if defined(MY_GATEWAY_SERIAL) || defined(MY_GATEWAY_W5100) || defined(MY_GATEWAY_ENC28J60) || defined(ARDUINO_ARCH_ESP8266) #define MY_GATEWAY_FEATURE #define MY_NODE_TYPE "gateway" #elif defined(MY_REPEATER_FEATURE) @@ -41,6 +40,8 @@ #if defined(ARDUINO_ARCH_ESP8266) #include "drivers/ESP8266/SPI/SPI.cpp" #include "core/MyHwESP8266.cpp" + // For ESP8266, we always enable gateway feature + #define MY_GATEWAY_ESP8266 #elif defined(ARDUINO_ARCH_AVR) #include "drivers/AVR/SPI/SPI.cpp" #include "core/MyHwATMega328.cpp" @@ -84,9 +85,14 @@ // GATEWAY - COMMON FUNCTIONS #include "core/MyGatewayTransport.cpp" + // We currently only support one protocol, enable it. + #if !defined(MY_GATEWAY_PROTOCOL_DEFAULT) + #define MY_GATEWAY_PROTOCOL_DEFAULT + #endif + // GATEWAY - PROTOCOL #if defined(MY_GATEWAY_PROTOCOL_DEFAULT) - #include "core/MyProtocolDefault.cpp" + #include "core/MyProtocolMySensors.cpp" #else #error No gateway protocol specified! #endif @@ -102,8 +108,10 @@ #if !defined(MY_PORT) #error You must define MY_PORT (cotroller or gatway port to open) #endif + #if defined(MY_GATEWAY_ESP8266) + // GATEWAY - ESP8266 - #if defined(MY_GATEWAY_W5100) + #elif defined(MY_GATEWAY_W5100) // GATEWAY - W5100 #include "drivers/AVR/Ethernet_W5100/utility/socket.cpp" #include "drivers/AVR/Ethernet_W5100/utility/w5100.cpp" @@ -192,7 +200,9 @@ #undef MY_INCLUSION_BUTTON_FEATURE #endif - +#if !defined(MY_GATEWAY_FEATURE) && !defined(MY_RADIO_FEATURE) + #error No radio or gateway feature activated. This means nowhere to send messages! Pretty pointless. +#endif #include "core/MyMessage.cpp" diff --git a/libraries/MySensors/core/MyGatewayTransport.cpp b/libraries/MySensors/core/MyGatewayTransport.cpp index 0072946..d0615cc 100644 --- a/libraries/MySensors/core/MyGatewayTransport.cpp +++ b/libraries/MySensors/core/MyGatewayTransport.cpp @@ -43,7 +43,7 @@ inline void gatewayTransportProcess() { inclusionModeSet(atoi(_msg.data) == 1); #endif } else { - processInternalMessages(); + _processInternalMessages(); } } else { // Call incoming message callback if available diff --git a/libraries/MySensors/core/MyGatewayTransportEthernet.h b/libraries/MySensors/core/MyGatewayTransportEthernet.h index c7cd7f9..c949d81 100644 --- a/libraries/MySensors/core/MyGatewayTransportEthernet.h +++ b/libraries/MySensors/core/MyGatewayTransportEthernet.h @@ -23,7 +23,7 @@ #include "MyConfig.h" #include "MyMessage.h" #include "MyProtocol.h" -#include "MyProtocolDefault.h" +#include "MyProtocolMySensors.h" #include "MyGatewayTransport.h" diff --git a/libraries/MySensors/core/MyGatewayTransportSerial.h b/libraries/MySensors/core/MyGatewayTransportSerial.h index 7dabf02..8b81905 100644 --- a/libraries/MySensors/core/MyGatewayTransportSerial.h +++ b/libraries/MySensors/core/MyGatewayTransportSerial.h @@ -23,7 +23,7 @@ #include "MyMessage.h" #include "MyGatewayTransport.h" #include "MyProtocol.h" -#include "MyProtocolDefault.h" +#include "MyProtocolMySensors.h" #define MAX_RECEIVE_LENGTH 100 // Maximum message length for messages coming from controller diff --git a/libraries/MySensors/core/MyProtocolDefault.cpp b/libraries/MySensors/core/MyProtocolMySensors.cpp similarity index 98% rename from libraries/MySensors/core/MyProtocolDefault.cpp rename to libraries/MySensors/core/MyProtocolMySensors.cpp index d4a54c1..2fa527a 100644 --- a/libraries/MySensors/core/MyProtocolDefault.cpp +++ b/libraries/MySensors/core/MyProtocolMySensors.cpp @@ -18,7 +18,7 @@ */ #include "MyProtocol.h" -#include "MyProtocolDefault.h" +#include "MyProtocolMySensors.h" #include "MyTransport.h" char _fmtBuffer[MAX_FORMAT_BUFFER_LENGTH]; diff --git a/libraries/MySensors/core/MyProtocolDefault.h b/libraries/MySensors/core/MyProtocolMySensors.h similarity index 100% rename from libraries/MySensors/core/MyProtocolDefault.h rename to libraries/MySensors/core/MyProtocolMySensors.h diff --git a/libraries/MySensors/core/MySensorCore.cpp b/libraries/MySensors/core/MySensorCore.cpp index e05db79..3452c66 100644 --- a/libraries/MySensors/core/MySensorCore.cpp +++ b/libraries/MySensors/core/MySensorCore.cpp @@ -54,21 +54,32 @@ void _process() { #endif } - +#if defined(MY_RADIO_FEATURE) static inline bool isValidParent( const uint8_t parent ) { return parent != AUTO; } - +#endif void setIncomingCallback(void (*msgCallback)(const MyMessage &)) { _msgCallback = msgCallback; } void _begin() { - #if defined(MY_DISABLED_SERIAL) + #if !defined(MY_DISABLED_SERIAL) hwInit(); #endif + #if defined(MY_RADIO_FEATURE) + _failedTransmissions = 0; + + // Setup radio + if (!transportInit()) { + debug(PSTR("radio init fail\n")); + while(1); // Nothing more we can do + } + #endif + + #if defined(MY_GATEWAY_FEATURE) #if defined(MY_INCLUSION_BUTTON_FEATURE) inclusionInit(); @@ -83,15 +94,6 @@ void _begin() { gatewayTransportSend(buildGw(_msg, I_GATEWAY_READY).set("Gateway startup complete.")); #endif - #if defined(MY_RADIO_FEATURE) - _failedTransmissions = 0; - - // Setup radio - if (!transportInit()) { - debug(PSTR("radio init fail\n")); - while(1); // Nothing more we can do - } - #endif #if defined(MY_SIGNING_FEATURE) // Read out the signing requirements from EEPROM @@ -114,7 +116,7 @@ void _begin() { _nc.parentNodeId = GATEWAY_ADDRESS; _nc.distance = 0; _nc.nodeId = GATEWAY_ADDRESS; - #else + #elif defined(MY_RADIO_FEATURE) // Read settings from eeprom hwReadConfigBlock((void*)&_nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(NodeConfig)); // Read latest received controller configuration from EEPROM @@ -151,6 +153,7 @@ void _begin() { #if defined(MY_RADIO_FEATURE) transportSetupNode(); #endif + debug(PSTR("%s started, id=%d, parent=%d, distance=%d\n"), MY_NODE_TYPE, _nc.nodeId, _nc.parentNodeId, _nc.distance); } @@ -176,7 +179,7 @@ boolean _sendRoute(MyMessage &message) { } #endif #if defined(MY_RADIO_FEATURE) - transportSendRoute(message); + return transportSendRoute(message); #else return false; #endif diff --git a/libraries/MySensors/core/MySensorCore.h b/libraries/MySensors/core/MySensorCore.h index 202019b..e2665e3 100644 --- a/libraries/MySensors/core/MySensorCore.h +++ b/libraries/MySensors/core/MySensorCore.h @@ -60,6 +60,8 @@ // This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data). #define GATEWAY_ADDRESS ((uint8_t)0) +// Node child is always created/presented when a node is started +#define NODE_SENSOR_ID 0xFF struct NodeConfig diff --git a/libraries/MySensors/core/MySigningAtsha204.cpp b/libraries/MySensors/core/MySigningAtsha204.cpp index 4796388..ae32dc2 100644 --- a/libraries/MySensors/core/MySigningAtsha204.cpp +++ b/libraries/MySensors/core/MySigningAtsha204.cpp @@ -34,25 +34,20 @@ // Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected) //#define DEBUG_SIGNING -uint8_t atshaPin=MY_ATSHA204_PIN); -ATSHA204Class atsha204; -unsigned long timestamp; -bool verification_ongoing; -uint8_t current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1]; -uint8_t temp_message[SHA_MSG_SIZE]; -uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; -uint8_t tx_buffer[SHA204_CMD_SIZE_MAX]; -void calculateSignature(MyMessage &msg); -uint8_t* sha256(const uint8_t* data, size_t sz); +ATSHA204Class atsha204(MY_SIGNING_ATSHA204_PIN); +unsigned long _signing_timestamp; +bool _signing_verification_ongoing = false; +uint8_t _signing_current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1]; +uint8_t _signing_temp_message[SHA_MSG_SIZE]; +uint8_t _singning_rx_buffer[SHA204_RSP_SIZE_MAX]; +uint8_t _singning_tx_buffer[SHA204_CMD_SIZE_MAX]; #ifdef MY_SIGNING_NODE_WHITELISTING - uint8_t nof_whitelist_entries=0; - const uint8_t whitelist_entry_t* the_whitelist=NULL, - uint8_t whitlist_sz; - const whitelist_entry_t* whitelist; + const whitelist_entry_t _signing_whitelist[] = MY_SIGNING_NODE_WHITELISTING; #endif + #ifdef DEBUG_SIGNING #define DEBUG_SIGNING_PRINTLN(args) Serial.println(args) #else @@ -78,79 +73,63 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, #endif -MySigningAtsha204::MySigningAtsha204(bool requestSignatures, -#ifdef MY_SIGNING_NODE_WHITELISTING - uint8_t nof_whitelist_entries, const whitelist_entry_t* the_whitelist, -#endif - uint8_t atshaPin) - : - MySigning(requestSignatures), - atsha204(atshaPin), -#ifdef MY_SIGNING_NODE_WHITELISTING - whitelist(the_whitelist), - whitlist_sz(nof_whitelist_entries), -#endif - verification_ongoing(false) -{ -} - -bool MySigningAtsha204::getNonce(MyMessage &msg) { +bool signerGetNonce(MyMessage &msg) { // Generate random number for use as nonce // We used a basic whitening technique that takes the first byte of a new random value and builds up a 32-byte random value // This 32-byte random value is then hashed (SHA256) to produce the resulting nonce for (int i = 0; i < 32; i++) { if (atsha204.sha204m_execute(SHA204_RANDOM, RANDOM_NO_SEED_UPDATE, 0, 0, NULL, - RANDOM_COUNT, tx_buffer, RANDOM_RSP_SIZE, rx_buffer) != SHA204_SUCCESS) { + RANDOM_COUNT, _singning_tx_buffer, RANDOM_RSP_SIZE, _singning_rx_buffer) != SHA204_SUCCESS) { DEBUG_SIGNING_PRINTLN(F("FTGN")); // FTGN = Failed to generate nonce return false; } - current_nonce[i] = rx_buffer[SHA204_BUFFER_POS_DATA]; + _signing_current_nonce[i] = _singning_rx_buffer[SHA204_BUFFER_POS_DATA]; } - memcpy(current_nonce, sha256(current_nonce, 32), MAX_PAYLOAD); + memcpy(_signing_current_nonce, signerSha256(_signing_current_nonce, 32), MAX_PAYLOAD); // We set the part of the 32-byte nonce that does not fit into a message to 0xAA - memset(¤t_nonce[MAX_PAYLOAD], 0xAA, sizeof(current_nonce)-MAX_PAYLOAD); + memset(&_signing_current_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_current_nonce)-MAX_PAYLOAD); // Replace the first byte in the nonce with our signing identifier - current_nonce[0] = SIGNING_IDENTIFIER; + _signing_current_nonce[0] = SIGNING_IDENTIFIER; // Transfer the first part of the nonce to the message - msg.set(current_nonce, MAX_PAYLOAD); - verification_ongoing = true; - timestamp = millis(); // Set timestamp to determine when to purge nonce + msg.set(_signing_current_nonce, MAX_PAYLOAD); + _signing_verification_ongoing = true; + _signing_timestamp = millis(); // Set timestamp to determine when to purge nonce // Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover) // Note that if message is "too" quick, and arrives before turnover, it will be rejected // but this is consider such a rare case that it is accepted and rejects are 'safe' - if (timestamp + MY_VERIFICATION_TIMEOUT_MS < millis()) timestamp = 0; + if (_signing_timestamp + MY_VERIFICATION_TIMEOUT_MS < millis()) _signing_timestamp = 0; return true; } -bool MySigningAtsha204::checkTimer() { - if (verification_ongoing) { - if (millis() < timestamp || millis() > timestamp + MY_VERIFICATION_TIMEOUT_MS) { +bool signerCheckTimer() { + if (_signing_verification_ongoing) { + if (millis() < _signing_timestamp || millis() > _signing_timestamp + MY_VERIFICATION_TIMEOUT_MS) { DEBUG_SIGNING_PRINTLN(F("VT")); // VT = Verification timeout // Purge nonce - memset(current_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); - verification_ongoing = false; + memset(_signing_current_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); + _signing_verification_ongoing = false; return false; } } return true; } -bool MySigningAtsha204::putNonce(MyMessage &msg) { +bool signerPutNonce(MyMessage &msg) { if (((uint8_t*)msg.getCustom())[0] != SIGNING_IDENTIFIER) { DEBUG_SIGNING_PRINTLN(F("ISI")); // ISI = Incorrect signing identifier return false; } - memcpy(current_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); + memcpy(_signing_current_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD); // We set the part of the 32-byte nonce that does not fit into a message to 0xAA - memset(¤t_nonce[MAX_PAYLOAD], 0xAA, sizeof(current_nonce)-MAX_PAYLOAD); + memset(&_signing_current_nonce[MAX_PAYLOAD], 0xAA, sizeof(_signing_current_nonce)-MAX_PAYLOAD); return true; } -bool MySigningAtsha204::signMsg(MyMessage &msg) { +bool signerSignMsg(MyMessage &msg) { // If we cannot fit any signature in the message, refuse to sign it if (mGetLength(msg) > MAX_PAYLOAD-2) { DEBUG_SIGNING_PRINTLN(F("MTOL")); // Message too large for signature to fit @@ -159,37 +138,37 @@ bool MySigningAtsha204::signMsg(MyMessage &msg) { // Calculate signature of message mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated - calculateSignature(msg); + signerCalculateSignature(msg); #ifdef MY_SIGNING_NODE_WHITELISTING // Salt the signature with the senders nodeId and the unique serial of the ATSHA device - memcpy(current_nonce, &rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed - current_nonce[32] = msg.sender; - atsha204.getSerialNumber(¤t_nonce[33]); - (void)sha256(current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place + memcpy(_signing_current_nonce, &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed + _signing_current_nonce[32] = msg.sender; + atsha204.getSerialNumber(&_signing_current_nonce[33]); + (void)signerSha256(_signing_current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place DEBUG_SIGNING_PRINTLN(F("SWS")); // SWS = Signature whitelist salted #endif // Overwrite the first byte in the signature with the signing identifier - rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; + _singning_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; // Transfer as much signature data as the remaining space in the message permits - memcpy(&msg.data[mGetLength(msg)], &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); + memcpy(&msg.data[mGetLength(msg)], &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); return true; } -bool MySigningAtsha204::verifyMsg(MyMessage &msg) { - if (!verification_ongoing) { +bool signerVerifyMsg(MyMessage &msg) { + if (!_signing_verification_ongoing) { DEBUG_SIGNING_PRINTLN(F("NAVS")); // NAVS = No active verification session return false; } else { // Make sure we have not expired - if (!checkTimer()) { + if (!signerCheckTimer()) { return false; } - verification_ongoing = false; + _signing_verification_ongoing = false; if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) { DEBUG_SIGNING_PRINTLN(F("ISI")); // ISI = Incorrect signing identifier @@ -197,28 +176,28 @@ bool MySigningAtsha204::verifyMsg(MyMessage &msg) { } DEBUG_SIGNING_PRINTBUF(F("SIM:"), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); // SIM = Signature in message - calculateSignature(msg); // Get signature of message + signerCalculateSignature(msg); // Get signature of message #ifdef MY_SIGNING_NODE_WHITELISTING // Look up the senders nodeId in our whitelist and salt the signature with that data - for (int j=0; j < whitlist_sz; j++) { - if (whitelist[j].nodeId == msg.sender) { + for (int j=0; j < NUM_OF(_signing_whitelist); j++) { + if (_signing_whitelist[j].nodeId == msg.sender) { DEBUG_SIGNING_PRINTLN(F("SIW")); // SIW = Sender found in whitelist - memcpy(current_nonce, &rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed - current_nonce[32] = msg.sender; - memcpy(¤t_nonce[33], whitelist[j].serial, SHA204_SERIAL_SZ); - (void)sha256(current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place + memcpy(_signing_current_nonce, &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed + _signing_current_nonce[32] = msg.sender; + memcpy(&_signing_current_nonce[33], _signing_whitelist[j].serial, SHA204_SERIAL_SZ); + (void)signerSha256(_signing_current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place break; } } #endif // Overwrite the first byte in the signature with the signing identifier - rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; + _singning_rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER; // Compare the caluclated signature with the provided signature - if (memcmp(&msg.data[mGetLength(msg)], &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) { - DEBUG_SIGNING_PRINTBUF(F("SNOK:"), &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); // SNOK = Signature bad + if (memcmp(&msg.data[mGetLength(msg)], &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) { + DEBUG_SIGNING_PRINTBUF(F("SNOK:"), &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); // SNOK = Signature bad #ifdef MY_SIGNING_NODE_WHITELISTING DEBUG_SIGNING_PRINTLN(F("W?")); // W? = Is the sender whitelisted? #endif @@ -230,60 +209,60 @@ bool MySigningAtsha204::verifyMsg(MyMessage &msg) { } } -// Helper to calculate signature of msg (returned in rx_buffer[SHA204_BUFFER_POS_DATA]) -void MySigningAtsha204::calculateSignature(MyMessage &msg) { - memset(temp_message, 0, 32); - memcpy(temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); +// Helper to calculate signature of msg (returned in _singning_rx_buffer[SHA204_BUFFER_POS_DATA]) +void signerCalculateSignature(MyMessage &msg) { + memset(_signing_temp_message, 0, 32); + memcpy(_signing_temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); // Program the data to sign into the ATSHA204 DEBUG_SIGNING_PRINTBUF(F("MSG:"), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); // MSG = Message to sign - DEBUG_SIGNING_PRINTBUF(F("CNC:"), current_nonce, 32); // CNC = Current nonce - (void)atsha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, temp_message, - WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer); + DEBUG_SIGNING_PRINTBUF(F("CNC:"), _signing_current_nonce, 32); // CNC = Current nonce + (void)atsha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, _signing_temp_message, + WRITE_COUNT_LONG, _singning_tx_buffer, WRITE_RSP_SIZE, _singning_rx_buffer); // Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations) - (void)atsha204.sha204m_execute(SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0, NONCE_NUMIN_SIZE_PASSTHROUGH, current_nonce, - NONCE_COUNT_LONG, tx_buffer, NONCE_RSP_SIZE_SHORT, rx_buffer); + (void)atsha204.sha204m_execute(SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0, NONCE_NUMIN_SIZE_PASSTHROUGH, _signing_current_nonce, + NONCE_COUNT_LONG, _singning_tx_buffer, NONCE_RSP_SIZE_SHORT, _singning_rx_buffer); // Purge nonce when used - memset(current_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); + memset(_signing_current_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH); // Generate digest of data and nonce (void)atsha204.sha204m_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL, - GENDIG_COUNT_DATA, tx_buffer, GENDIG_RSP_SIZE, rx_buffer); + GENDIG_COUNT_DATA, _singning_tx_buffer, GENDIG_RSP_SIZE, _singning_rx_buffer); // Calculate HMAC of message+nonce digest and secret key (void)atsha204.sha204m_execute(SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0, 0, NULL, - HMAC_COUNT, tx_buffer, HMAC_RSP_SIZE, rx_buffer); + HMAC_COUNT, _singning_tx_buffer, HMAC_RSP_SIZE, _singning_rx_buffer); // Put device back to sleep atsha204.sha204c_sleep(); - DEBUG_SIGNING_PRINTBUF(F("HMAC:"), &rx_buffer[SHA204_BUFFER_POS_DATA], 32); + DEBUG_SIGNING_PRINTBUF(F("HMAC:"), &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], 32); } // Helper to calculate a generic SHA256 digest of provided buffer (only supports one block) -// The pointer to the hash is returned, but the hash is also stored in rx_buffer[SHA204_BUFFER_POS_DATA]) -uint8_t* MySigningAtsha204::sha256(const uint8_t* data, size_t sz) { +// The pointer to the hash is returned, but the hash is also stored in _singning_rx_buffer[SHA204_BUFFER_POS_DATA]) +uint8_t* signerSha256(const uint8_t* data, size_t sz) { // Initiate SHA256 calculator (void)atsha204.sha204m_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL, - SHA_COUNT_SHORT, tx_buffer, SHA_RSP_SIZE_SHORT, rx_buffer); + SHA_COUNT_SHORT, _singning_tx_buffer, SHA_RSP_SIZE_SHORT, _singning_rx_buffer); // Calculate a hash - memset(temp_message, 0x00, SHA_MSG_SIZE); - memcpy(temp_message, data, sz); - temp_message[sz] = 0x80; + memset(_signing_temp_message, 0x00, SHA_MSG_SIZE); + memcpy(_signing_temp_message, data, sz); + _signing_temp_message[sz] = 0x80; // Write length data to the last bytes - temp_message[SHA_MSG_SIZE-2] = (sz >> 5); - temp_message[SHA_MSG_SIZE-1] = (sz << 3); - DEBUG_SIGNING_PRINTBUF(F("DTH:"), temp_message, SHA_MSG_SIZE); // DTH = Data to hash - (void)atsha204.sha204m_execute(SHA204_SHA, SHA_CALC, 0, SHA_MSG_SIZE, temp_message, - SHA_COUNT_LONG, tx_buffer, SHA_RSP_SIZE_LONG, rx_buffer); + _signing_temp_message[SHA_MSG_SIZE-2] = (sz >> 5); + _signing_temp_message[SHA_MSG_SIZE-1] = (sz << 3); + DEBUG_SIGNING_PRINTBUF(F("DTH:"), _signing_temp_message, SHA_MSG_SIZE); // DTH = Data to hash + (void)atsha204.sha204m_execute(SHA204_SHA, SHA_CALC, 0, SHA_MSG_SIZE, _signing_temp_message, + SHA_COUNT_LONG, _singning_tx_buffer, SHA_RSP_SIZE_LONG, _singning_rx_buffer); // Put device back to sleep atsha204.sha204c_sleep(); - DEBUG_SIGNING_PRINTBUF(F("SHA:"), &rx_buffer[SHA204_BUFFER_POS_DATA], 32); - return &rx_buffer[SHA204_BUFFER_POS_DATA]; + DEBUG_SIGNING_PRINTBUF(F("SHA:"), &_singning_rx_buffer[SHA204_BUFFER_POS_DATA], 32); + return &_singning_rx_buffer[SHA204_BUFFER_POS_DATA]; } #endif // #if defined(ARDUINO_ARCH_AVR) diff --git a/libraries/MySensors/core/MySigningAtsha204.h b/libraries/MySensors/core/MySigningAtsha204.h index fe353f7..da9bee3 100644 --- a/libraries/MySensors/core/MySigningAtsha204.h +++ b/libraries/MySensors/core/MySigningAtsha204.h @@ -33,27 +33,14 @@ #include "drivers/ATSHA204/ATSHA204.h" #include -#ifdef MY_SIGNING_NODE_WHITELISTING -typedef struct { - uint8_t nodeId; - uint8_t serial[SHA204_SERIAL_SZ]; -} whitelist_entry_t; -#endif + // The ATSHA204 is capable of generating proper random numbers for nonce // and can calculate HMAC-SHA256 signatures. This is enterprise- // level of security and ought to implement the signing needs for anybody. -class MySigningAtsha204 : public MySigning -{ -public: - MySigningAtsha204(bool requestSignatures=true, - bool getNonce(MyMessage &msg); - bool checkTimer(void); - bool putNonce(MyMessage &msg); - bool signMsg(MyMessage &msg); - bool verifyMsg(MyMessage &msg); -private: -}; +void signerCalculateSignature(MyMessage &msg); +uint8_t* signerSha256(const uint8_t* data, size_t sz); + #endif diff --git a/libraries/MySensors/core/MySigningNone.cpp b/libraries/MySensors/core/MySigningNone.cpp index d9aa5ab..7edbad6 100644 --- a/libraries/MySensors/core/MySigningNone.cpp +++ b/libraries/MySensors/core/MySigningNone.cpp @@ -59,24 +59,21 @@ static void DEBUG_NONE_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, ui #define DEBUG_NONE_PRINTBUF(str, buf, sz) #endif -MySigningNone::MySigningNone() : MySigning() { -} - -bool MySigningNone::getNonce(MyMessage &msg) { +bool signerGetNonce(MyMessage &msg) { (void)msg; return true; } -bool MySigningNone::checkTimer() { +bool signerCheckTimer() { return true; } -bool MySigningNone::putNonce(MyMessage &msg) { +bool signerPutNonce(MyMessage &msg) { (void)msg; return true; } -bool MySigningNone::signMsg(MyMessage &msg) { +bool signerSignMsg(MyMessage &msg) { // If we cannot fit any signature in the message, refuse to sign it if (mGetLength(msg) > MAX_PAYLOAD-2) { DEBUG_SIGNING_PRINTLN(F("MTOL")); // Message too large for signature to fit @@ -87,7 +84,7 @@ bool MySigningNone::signMsg(MyMessage &msg) { return true; } -bool MySigningNone::verifyMsg(MyMessage &msg) { +bool signerVerifyMsg(MyMessage &msg) { if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) return false; else diff --git a/libraries/MySensors/core/MySigningNone.h b/libraries/MySensors/core/MySigningNone.h index 4b27103..4f7a32f 100644 --- a/libraries/MySensors/core/MySigningNone.h +++ b/libraries/MySensors/core/MySigningNone.h @@ -37,15 +37,5 @@ // It does check SIGNING_IDENTIFIER byte to avoid illegal mixing of signing back-ends in // the network (as seen by this node) and it does verify proper execution order on the API. // The "none" driver rejects all other back-ends. -class MySigningNone : public MySigning -{ -public: - MySigningNone(); - bool getNonce(MyMessage &msg); - bool checkTimer(void); - bool putNonce(MyMessage &msg); - bool signMsg(MyMessage &msg); - bool verifyMsg(MyMessage &msg); -}; #endif diff --git a/libraries/MySensors/core/MyTransport.cpp b/libraries/MySensors/core/MyTransport.cpp index 626e9e8..8e21b94 100644 --- a/libraries/MySensors/core/MyTransport.cpp +++ b/libraries/MySensors/core/MyTransport.cpp @@ -300,7 +300,7 @@ inline void transportProcess() { // Wait a random delay of 0-2 seconds to minimize collision // between ping ack messages from other relaying nodes wait(hwMillis() & 0x3ff); - sendWrite(sender, build(_msg, _nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false).set(_nc.distance)); + transportSendWrite(sender, build(_msg, _nc.nodeId, sender, NODE_SENSOR_ID, C_INTERNAL, I_FIND_PARENT_RESPONSE, false).set(_nc.distance)); } } } else if (to == _nc.nodeId) { diff --git a/libraries/MySensors/core/MyTransport.h b/libraries/MySensors/core/MyTransport.h index 827430b..c9b540d 100644 --- a/libraries/MySensors/core/MyTransport.h +++ b/libraries/MySensors/core/MyTransport.h @@ -77,7 +77,6 @@ typedef struct { #define AUTO 0xFF // 0-254. Id 255 is reserved for auto initialization of nodeId. -#define NODE_SENSOR_ID 0xFF // Node child id is always created for when a node #define BROADCAST_ADDRESS ((uint8_t)0xFF) diff --git a/libraries/MySensors/core/MyTransportRFM69.h b/libraries/MySensors/core/MyTransportRFM69.h index ec3227d..967a7b3 100644 --- a/libraries/MySensors/core/MyTransportRFM69.h +++ b/libraries/MySensors/core/MyTransportRFM69.h @@ -24,7 +24,6 @@ #include "MyTransport.h" #include #include "drivers/RFM69/RFM69.h" -#include "drivers/SPI/SPI.h" #endif diff --git a/libraries/MySensors/core/Version.h b/libraries/MySensors/core/Version.h index c782265..5f64530 100644 --- a/libraries/MySensors/core/Version.h +++ b/libraries/MySensors/core/Version.h @@ -6,6 +6,6 @@ #ifndef Version_h #define Version_h -#define LIBRARY_VERSION "1.5" +#define LIBRARY_VERSION "1.6" #endif diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.cpp b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.cpp index d199cfe..b832d0a 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.cpp +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.cpp @@ -19,10 +19,10 @@ extern "C" { -#import "utility/uip-conf.h" -#import "utility/uip.h" -#import "utility/uip_arp.h" -#import "string.h" +#include "utility/uip-conf.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +#include "string.h" } #include "UIPEthernet.h" #include "UIPClient.h" diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.h index 6c0c006..40838bb 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.h +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPClient.h @@ -22,11 +22,11 @@ #include "ethernet_comp.h" #include "Print.h" -#import "Client.h" -#import "utility/mempool.h" +#include "Client.h" +#include "utility/mempool.h" extern "C" { - #import "utility/uip.h" + #include "utility/uip.h" } #define UIP_SOCKET_DATALEN UIP_TCP_MSS diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.h index c68d578..dd3f412 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.h +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPEthernet.h @@ -58,6 +58,7 @@ extern "C" uip_ethaddr.addr[4] = eaddr[4];\ uip_ethaddr.addr[5] = eaddr[5];} while(0) +#undef BUF #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) class UIPEthernetClass diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.h b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.h index 0cc0619..eea81d2 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.h +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/UIPServer.h @@ -20,8 +20,8 @@ #define UIPSERVER_H #include "ethernet_comp.h" -#import "Server.h" -#import "UIPClient.h" +#include "Server.h" +#include "UIPClient.h" class UIPServer : public Server { diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip.c index 8421bda..c8ea98d 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip.c +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip.c @@ -223,6 +223,7 @@ static u16_t tmp16; /* Macros. */ +#undef BUF #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) #define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) diff --git a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.c b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.c index 44ca7c4..f220ff5 100644 --- a/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.c +++ b/libraries/MySensors/drivers/AVR/Ethernet_UIP/src/utility/uip_arp.c @@ -113,6 +113,7 @@ static u8_t i, c; static u8_t arptime; static u8_t tmpage; +#undef BUF #define BUF ((struct arp_hdr *)&uip_buf[0]) #define IPBUF ((struct ethip_hdr *)&uip_buf[0]) /*-----------------------------------------------------------------------------------*/ diff --git a/libraries/MySensors/drivers/RFM69/RFM69.cpp b/libraries/MySensors/drivers/RFM69/RFM69.cpp index f7e63e7..8d154f0 100644 --- a/libraries/MySensors/drivers/RFM69/RFM69.cpp +++ b/libraries/MySensors/drivers/RFM69/RFM69.cpp @@ -31,7 +31,7 @@ // ********************************************************************************** #include "RFM69.h" #include "RFM69registers.h" -#include "drivers/SPI/SPI.h" +#include "drivers/AVR/SPI/SPI.h" volatile byte RFM69::DATA[RF69_MAX_DATA_LEN]; volatile byte RFM69::_mode; // current transceiver state diff --git a/libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino b/libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino index c956655..310295c 100644 --- a/libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino +++ b/libraries/MySensors/examples/AirQualitySensor/AirQualitySensor.ino @@ -34,9 +34,14 @@ * */ -#include +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + #include -#include #define CHILD_ID_MQ 0 /************************Hardware Related Macros************************************/ @@ -76,19 +81,16 @@ float SmokeCurve[3] ={2.3,0.53,-0.44}; //two points are taken from //data format:{ x, y, slope}; point1: (lg200, 0.53), point2:(lg10000,-0.22) -MySensor gw; MyMessage msg(CHILD_ID_MQ, V_LEVEL); void setup() { - gw.begin(); - // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Air Quality Sensor", "1.0"); + sendSketchInfo("Air Quality Sensor", "1.0"); // Register all sensors to gateway (they will be created as child devices) - gw.present(CHILD_ID_MQ, S_AIR_QUALITY); + present(CHILD_ID_MQ, S_AIR_QUALITY); Ro = MQCalibration(MQ_SENSOR_ANALOG_PIN); //Calibrating the sensor. Please make sure the sensor is in clean air //when you perform the calibration @@ -113,11 +115,11 @@ void loop() Serial.print("\n"); if (valMQ != lastMQ) { - gw.send(msg.set((int)ceil(valMQ))); + send(msg.set((int)ceil(valMQ))); lastMQ = ceil(valMQ); } - gw.sleep(SLEEP_TIME); //sleep for: sleepTime + sleep(SLEEP_TIME); //sleep for: sleepTime } /****************** MQResistanceCalculation **************************************** diff --git a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino index f8e3992..9fd07aa 100644 --- a/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino +++ b/libraries/MySensors/examples/EthernetGateway/EthernetGateway.ino @@ -56,19 +56,16 @@ * */ -// Enable debug prints to console +// Enable debug prints to serial monitor #define MY_DEBUG -// This node has a NR24L01+ radio attached -#define MY_RADIO_NRF24 +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 - -// Enable gateway type +// Enable gateway transportation type #define MY_GATEWAY_W5100 -//#define MY_GATEWAY_W5100 - -// Set default gateway protocol (http://www.mysensors.org/download/serial_api_15) -#define MY_GATEWAY_PROTOCOL_DEFAULT +//#define MY_GATEWAY_ENC28J60 // Enable Soft SPI for radio (note different radio wiring required) // Useful for W5100 which sometimes have hard time co-operate with radio on the same spi bus. diff --git a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino index db05836..c652166 100644 --- a/libraries/MySensors/examples/RelayActuator/RelayActuator.ino +++ b/libraries/MySensors/examples/RelayActuator/RelayActuator.ino @@ -27,51 +27,46 @@ * http://www.mysensors.org/build/relay */ -#include -#include -#include -#include +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 + +// Enable repeater functionality for this node +#define MY_REPEATER_FEATURE + #include -#include #define RELAY_1 3 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) #define NUMBER_OF_RELAYS 1 // Total number of attached relays #define RELAY_ON 1 // GPIO value to write to turn on attached relay #define RELAY_OFF 0 // GPIO value to write to turn off attached relay -// NRFRF24L01 radio driver (set low transmit power by default) -MyTransportNRF24 radio(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); -//MyTransportRFM69 radio; -// Message signing driver (none default) -//MySigningNone signer; -// Select AtMega328 hardware profile -MyHwATMega328 hw; -// Construct MySensors library -MySensor gw(radio, hw); - void setup() { // Initialize library and add callback for incoming messages - gw.begin(incomingMessage, AUTO, true); + setIncomingCallback(incomingMessage); + // Send the sketch version information to the gateway and Controller - gw.sendSketchInfo("Relay", "1.0"); + sendSketchInfo("Relay", "1.0"); // Fetch relay status for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) { // Register all sensors to gw (they will be created as child devices) - gw.present(sensor, S_LIGHT); + present(sensor, S_LIGHT); // Then set relay pins in output mode pinMode(pin, OUTPUT); // Set relay to last known state (using eeprom storage) - digitalWrite(pin, gw.loadState(sensor)?RELAY_ON:RELAY_OFF); + digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF); } } void loop() { - // Alway process incoming messages whenever possible - gw.process(); + } void incomingMessage(const MyMessage &message) { @@ -80,7 +75,7 @@ void incomingMessage(const MyMessage &message) { // Change relay state digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF); // Store state in eeprom - gw.saveState(message.sensor, message.getBool()); + saveState(message.sensor, message.getBool()); // Write some debug info Serial.print("Incoming change for sensor:"); Serial.print(message.sensor); diff --git a/libraries/MySensors/examples/SecureActuator/SecureActuator.ino b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino index 76a80ea..589c0bc 100644 --- a/libraries/MySensors/examples/SecureActuator/SecureActuator.ino +++ b/libraries/MySensors/examples/SecureActuator/SecureActuator.ino @@ -26,7 +26,10 @@ * This example will remember lock state even after power failure. */ -// Enable and select radio type +// Enable debug prints to serial monitor +#define MY_DEBUG + +// Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 @@ -35,9 +38,9 @@ //#define MY_SIGNING_ATSHA204 // Hardware signing using ATSHA204A // Enable node whitelisting -#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} +//#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} // Enable this if you want destination node to sign all messages sent to this node. Default is not to require signing. -#define MY_SIGNING_REQUEST_SIGNATURES +//#define MY_SIGNING_REQUEST_SIGNATURES // SETTINGS FOR MY_SIGNING_SOFT @@ -51,7 +54,6 @@ // SETTINGS FOR MY_SIGNING_ATSHA204 #define MY_SIGNING_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached - #include diff --git a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino index 0566f3c..6e94b95 100644 --- a/libraries/MySensors/examples/SerialGateway/SerialGateway.ino +++ b/libraries/MySensors/examples/SerialGateway/SerialGateway.ino @@ -1,4 +1,4 @@ -/** + /** * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each @@ -36,57 +36,44 @@ * */ -#include -#include -#include -#include -#include -#include +// Enable debug prints to serial monitor +#define MY_DEBUG -#include -#include -#include -#include +// Enable and select radio type attached +#define MY_RADIO_NRF24 +//#define MY_RADIO_RFM69 -#define INCLUSION_MODE_TIME 60 // Number of seconds inclusion mode is enabled -#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button -#define RADIO_ERROR_LED_PIN 4 // Error led pin -#define RADIO_RX_LED_PIN 6 // Receive led pin -#define RADIO_TX_LED_PIN 5 // the PCB, on board LED +// Enable serial gateway +#define MY_GATEWAY_SERIAL -// NRFRF24L01 radio driver (set low transmit power by default) -MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); -//MyTransportRFM69 transport; +// Flash leds on rx/tx/err +#define MY_LEDS_BLINKING_FEATURE +// Set blinking period +#define MY_DEFAULT_LED_BLINK_PERIOD 300 -// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) -//MySigningNone signer; -//MySigningAtsha204Soft signer; -//MySigningAtsha204 signer; +// Enable inclusion mode +#define MY_INCLUSION_MODE_FEATURE +// Enable Inclusion mode button on gateway +#define MY_INCLUSION_BUTTON_FEATURE +// Set inclusion mode duration (in seconds) +#define MY_INCLUSION_MODE_DURATION 60 +// Digital pin used for inclusion mode button +#define MY_INCLUSION_MODE_BUTTON_PIN 3 -// Hardware profile -MyHwATMega328 hw; +#define MY_DEFAULT_ERR_LED_PIN 7 // Error led pin +#define MY_DEFAULT_RX_LED_PIN 8 // Receive led pin +#define MY_DEFAULT_TX_LED_PIN 9 // the PCB, on board LED -// Controller Transport profile -MyProtocolDefault protocol; -MyGatewayTransportSerial ctrlTransport(protocol); - -// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h) -// To use LEDs blinking, uncomment MY_LEDS_BLINKING_FEATURE in MyConfig.h -#ifdef MY_LEDS_BLINKING_FEATURE -MyGateway gw(ctrlTransport, transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN); -#else -MyGateway gw(ctrlTransport, transport, hw /*, signer*/); -#endif +#include void setup() { - gw.begin(NULL); - + // Nothing to do here } void loop() { - gw.process(); + // Nothing to do here } From 5c39f022c0db5e0280be1c1412f51be7d435cd60 Mon Sep 17 00:00:00 2001 From: Henrik Ekblad Date: Thu, 17 Sep 2015 22:04:38 +0200 Subject: [PATCH 18/43] Add: NRF24L01 AES Encryption Thanks @fleinze. Source: https://github.com/fleinze/MySensors/tree/Encryption/libraries/MySensors --- libraries/MySensors/MyConfig.h | 10 + libraries/MySensors/MySensor.h | 3 + libraries/MySensors/core/MyTransportNRF24.cpp | 29 +- libraries/MySensors/core/MyTransportNRF24.h | 3 + libraries/MySensors/drivers/AES/AES.cpp | 598 ++ libraries/MySensors/drivers/AES/AES.h | 415 ++ libraries/MySensors/drivers/AES/AES_config.h | 44 + libraries/MySensors/drivers/AES/Doxyfile | 2372 ++++++++ libraries/MySensors/drivers/AES/Makefile | 62 + libraries/MySensors/drivers/AES/README.MD | 91 + .../drivers/AES/examples/aes/aes.pde | 63 + .../AES/examples/test_vectors/RESOURCES | 16 + .../examples/test_vectors/known_answers.txt | 5321 +++++++++++++++++ .../examples/test_vectors/test_vectors.pde | 191 + .../drivers/AES/examples_Rpi/Makefile | 39 + .../drivers/AES/examples_Rpi/RESOURCES | 16 + .../drivers/AES/examples_Rpi/aes.cpp | 47 + .../AES/examples_Rpi/known_answers.txt | 5321 +++++++++++++++++ .../drivers/AES/examples_Rpi/test_vectors.cpp | 183 + libraries/MySensors/drivers/AES/keywords.txt | 7 + libraries/MySensors/drivers/AES/printf.h | 59 + .../EthernetGateway/EthernetGateway.ino | 6 +- 22 files changed, 14893 insertions(+), 3 deletions(-) create mode 100644 libraries/MySensors/drivers/AES/AES.cpp create mode 100644 libraries/MySensors/drivers/AES/AES.h create mode 100644 libraries/MySensors/drivers/AES/AES_config.h create mode 100644 libraries/MySensors/drivers/AES/Doxyfile create mode 100644 libraries/MySensors/drivers/AES/Makefile create mode 100644 libraries/MySensors/drivers/AES/README.MD create mode 100644 libraries/MySensors/drivers/AES/examples/aes/aes.pde create mode 100644 libraries/MySensors/drivers/AES/examples/test_vectors/RESOURCES create mode 100644 libraries/MySensors/drivers/AES/examples/test_vectors/known_answers.txt create mode 100644 libraries/MySensors/drivers/AES/examples/test_vectors/test_vectors.pde create mode 100644 libraries/MySensors/drivers/AES/examples_Rpi/Makefile create mode 100644 libraries/MySensors/drivers/AES/examples_Rpi/RESOURCES create mode 100644 libraries/MySensors/drivers/AES/examples_Rpi/aes.cpp create mode 100644 libraries/MySensors/drivers/AES/examples_Rpi/known_answers.txt create mode 100644 libraries/MySensors/drivers/AES/examples_Rpi/test_vectors.cpp create mode 100644 libraries/MySensors/drivers/AES/keywords.txt create mode 100644 libraries/MySensors/drivers/AES/printf.h diff --git a/libraries/MySensors/MyConfig.h b/libraries/MySensors/MyConfig.h index f765a38..ff46d42 100644 --- a/libraries/MySensors/MyConfig.h +++ b/libraries/MySensors/MyConfig.h @@ -193,6 +193,16 @@ /********************************** * NRF24L01 Driver Defaults ***********************************/ + +// Enables RF24 encryption (all nodes and gateway must have this enabled) +//#define MY_RF24_ENABLE_ENCRYPTION + +// Default encrytion key. Override in sketch if needed. +#ifndef MY_RF24_CE_PIN +#define MY_RF24_ENCRYPTKEY 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16 +#endif + +// Default pin settings. Override in sketch if needed. #ifndef MY_RF24_CE_PIN #define MY_RF24_CE_PIN 9 #endif diff --git a/libraries/MySensors/MySensor.h b/libraries/MySensors/MySensor.h index b4ef368..4ba828d 100644 --- a/libraries/MySensors/MySensor.h +++ b/libraries/MySensors/MySensor.h @@ -179,6 +179,9 @@ #error Only one radio driver can be activated #endif #if defined(MY_RADIO_NRF24) + #if defined(MY_RF24_ENABLE_ENCRYPTION) + #include "drivers/AES/AES.cpp" + #endif #include "drivers/RF24/RF24.cpp" #include "core/MyTransportNRF24.cpp" #elif defined(MY_RADIO_RFM69) diff --git a/libraries/MySensors/core/MyTransportNRF24.cpp b/libraries/MySensors/core/MyTransportNRF24.cpp index 91e9fc2..ab44888 100644 --- a/libraries/MySensors/core/MyTransportNRF24.cpp +++ b/libraries/MySensors/core/MyTransportNRF24.cpp @@ -22,6 +22,11 @@ RF24 _rf24(MY_RF24_CE_PIN, MY_RF24_CS_PIN); uint8_t _address; uint8_t _paLevel; +#if defined(MY_RF24_ENABLE_ENCRYPTION) + AES _aes; + uint8_t _dataenc[32] = {0}; + uint8_t _psk[] = { MY_RF24_ENCRYPTKEY }; +#endif bool transportInit() { // Start up the radio library @@ -42,6 +47,12 @@ bool transportInit() { // All nodes listen to broadcast pipe (for FIND_PARENT_RESPONSE messages) _rf24.openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS)); + + + #if defined(MY_RF24_ENABLE_ENCRYPTION) + _aes.set_key(_psk, 16); //set up AES-key + #endif + return true; } @@ -57,11 +68,23 @@ uint8_t transportGetAddress() { } bool transportSend(uint8_t to, const void* data, uint8_t len) { + #if defined(MY_RF24_ENABLE_ENCRYPTION) + memcpy(_dataenc,data,len); // copy input data because it is read-only + + _aes.set_IV(0);//not sure if necessary + len = len > 16 ? 32 : 16; + _aes.cbc_encrypt(_dataenc, _dataenc, len/16); //encrypt + #endif + // Make sure radio has powered up _rf24.powerUp(); _rf24.stopListening(); _rf24.openWritingPipe(TO_ADDR(to)); - bool ok = _rf24.write(data, len, to == BROADCAST_ADDRESS); + #if defined(MY_RF24_ENABLE_ENCRYPTION) + bool ok = _rf24.write(_dataenc, len, to == BROADCAST_ADDRESS); + #else + bool ok = _rf24.write(data, len, to == BROADCAST_ADDRESS); + #endif _rf24.startListening(); return ok; } @@ -80,6 +103,10 @@ bool transportAvailable(uint8_t *to) { uint8_t transportReceive(void* data) { uint8_t len = _rf24.getDynamicPayloadSize(); _rf24.read(data, len); + #if defined(MY_RF24_ENABLE_ENCRYPTION) + _aes.set_IV(0);//not sure if necessary + _aes.cbc_decrypt((byte*)(data), (byte*)(data), len>16?2:1); // decrypt + #endif return len; } diff --git a/libraries/MySensors/core/MyTransportNRF24.h b/libraries/MySensors/core/MyTransportNRF24.h index 3f895c5..a852848 100644 --- a/libraries/MySensors/core/MyTransportNRF24.h +++ b/libraries/MySensors/core/MyTransportNRF24.h @@ -25,6 +25,9 @@ #include #include "drivers/RF24/RF24.h" #include "drivers/RF24/RF24_config.h" +#if defined(MY_RF24_ENABLE_ENCRYPTION) +#include "drivers/AES/AES.h" +#endif #define TO_ADDR(x) (MY_RF24_BASE_RADIO_ID + x) diff --git a/libraries/MySensors/drivers/AES/AES.cpp b/libraries/MySensors/drivers/AES/AES.cpp new file mode 100644 index 0000000..cd5d306 --- /dev/null +++ b/libraries/MySensors/drivers/AES/AES.cpp @@ -0,0 +1,598 @@ +#include "AES.h" + +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state (there are options to use 32-bit types if available). + + The combination of mix columns and byte substitution used here is based on + that developed by Karl Malbrain. His contribution is acknowledged. + */ + +/* This version derived by Mark Tillotson 2012-01-23, tidied up, slimmed down + and tailored to 8-bit microcontroller abilities and Arduino datatypes. + + The s-box and inverse s-box were retained as tables (0.5kB PROGMEM) but all + the other transformations are coded to save table space. Many efficiency + improvments to the routines mix_sub_columns() and inv_mix_sub_columns() + (mainly common sub-expression elimination). + + Only the routines with precalculated subkey schedule are retained (together + with set_key() - this does however mean each AES object takes 240 bytes of + RAM, alas) + + The CBC routines side-effect the iv argument (so that successive calls work + together correctly). + + All the encryption and decryption routines work with plain == cipher for + in-place encryption, note. + +*/ + + +/* functions for finite field multiplication in the AES Galois field */ + +/* code was modified by george spanos + * 16/12/14 + */ + +// GF(2^8) stuff + +#define WPOLY 0x011B +#define DPOLY 0x008D + +const static byte s_fwd [0x100] PROGMEM = +{ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +} ; + +const static byte s_inv [0x100] PROGMEM = +{ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, +} ; + +// times 2 in the GF(2^8) +#define f2(x) ((x) & 0x80 ? (x << 1) ^ WPOLY : x << 1) +#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) + +static byte s_box (byte x) +{ + // return fwd_affine (pgm_read_byte (&inv [x])) ; + return pgm_read_byte (& s_fwd [x]) ; +} + +// Inverse Sbox +static byte is_box (byte x) +{ + // return pgm_read_byte (&inv [inv_affine (x)]) ; + return pgm_read_byte (& s_inv [x]) ; +} + + +static void xor_block (byte * d, byte * s) +{ + for (byte i = 0 ; i < N_BLOCK ; i += 4) + { + *d++ ^= *s++ ; // some unrolling + *d++ ^= *s++ ; + *d++ ^= *s++ ; + *d++ ^= *s++ ; + } +} + +static void copy_and_key (byte * d, byte * s, byte * k) +{ + for (byte i = 0 ; i < N_BLOCK ; i += 4) + { + *d++ = *s++ ^ *k++ ; // some unrolling + *d++ = *s++ ^ *k++ ; + *d++ = *s++ ^ *k++ ; + *d++ = *s++ ^ *k++ ; + } +} + +// #define add_round_key(d, k) xor_block (d, k) + +/* SUB ROW PHASE */ + +static void shift_sub_rows (byte st [N_BLOCK]) +{ + st [0] = s_box (st [0]) ; st [4] = s_box (st [4]) ; + st [8] = s_box (st [8]) ; st [12] = s_box (st [12]) ; + + byte tt = st [1] ; + st [1] = s_box (st [5]) ; st [5] = s_box (st [9]) ; + st [9] = s_box (st [13]) ; st [13] = s_box (tt) ; + + tt = st[2] ; st [2] = s_box (st [10]) ; st [10] = s_box (tt) ; + tt = st[6] ; st [6] = s_box (st [14]) ; st [14] = s_box (tt) ; + + tt = st[15] ; + st [15] = s_box (st [11]) ; st [11] = s_box (st [7]) ; + st [7] = s_box (st [3]) ; st [3] = s_box (tt) ; +} + +static void inv_shift_sub_rows (byte st[N_BLOCK]) +{ + st [0] = is_box (st[0]) ; st [4] = is_box (st [4]); + st [8] = is_box (st[8]) ; st [12] = is_box (st [12]); + + byte tt = st[13] ; + st [13] = is_box (st [9]) ; st [9] = is_box (st [5]) ; + st [5] = is_box (st [1]) ; st [1] = is_box (tt) ; + + tt = st [2] ; st [2] = is_box (st [10]) ; st [10] = is_box (tt) ; + tt = st [6] ; st [6] = is_box (st [14]) ; st [14] = is_box (tt) ; + + tt = st [3] ; + st [3] = is_box (st [7]) ; st [7] = is_box (st [11]) ; + st [11] = is_box (st [15]) ; st [15] = is_box (tt) ; +} + +/* SUB COLUMNS PHASE */ + +static void mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) +{ + byte j = 5 ; + byte k = 10 ; + byte l = 15 ; + for (byte i = 0 ; i < N_BLOCK ; i += N_COL) + { + byte a = st [i] ; + byte b = st [j] ; j = (j+N_COL) & 15 ; + byte c = st [k] ; k = (k+N_COL) & 15 ; + byte d = st [l] ; l = (l+N_COL) & 15 ; + byte a1 = s_box (a), b1 = s_box (b), c1 = s_box (c), d1 = s_box (d) ; + byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; + dt[i] = a2 ^ b2^b1 ^ c1 ^ d1 ; + dt[i+1] = a1 ^ b2 ^ c2^c1 ^ d1 ; + dt[i+2] = a1 ^ b1 ^ c2 ^ d2^d1 ; + dt[i+3] = a2^a1 ^ b1 ^ c1 ^ d2 ; + } +} + +static void inv_mix_sub_columns (byte dt[N_BLOCK], byte st[N_BLOCK]) +{ + for (byte i = 0 ; i < N_BLOCK ; i += N_COL) + { + byte a1 = st [i] ; + byte b1 = st [i+1] ; + byte c1 = st [i+2] ; + byte d1 = st [i+3] ; + byte a2 = f2(a1), b2 = f2(b1), c2 = f2(c1), d2 = f2(d1) ; + byte a4 = f2(a2), b4 = f2(b2), c4 = f2(c2), d4 = f2(d2) ; + byte a8 = f2(a4), b8 = f2(b4), c8 = f2(c4), d8 = f2(d4) ; + byte a9 = a8 ^ a1,b9 = b8 ^ b1,c9 = c8 ^ c1,d9 = d8 ^ d1 ; + byte ac = a8 ^ a4,bc = b8 ^ b4,cc = c8 ^ c4,dc = d8 ^ d4 ; + + dt[i] = is_box (ac^a2 ^ b9^b2 ^ cc^c1 ^ d9) ; + dt[(i+5)&15] = is_box (a9 ^ bc^b2 ^ c9^c2 ^ dc^d1) ; + dt[(i+10)&15] = is_box (ac^a1 ^ b9 ^ cc^c2 ^ d9^d2) ; + dt[(i+15)&15] = is_box (a9^a2 ^ bc^b1 ^ c9 ^ dc^d2) ; + } +} + +/******************************************************************************/ + +AES::AES(){ + byte ar_iv[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; + memcpy(iv,ar_iv,8); + memcpy(iv+8,ar_iv,8); + arr_pad[0] = 0x01; + arr_pad[1] = 0x02; + arr_pad[2] = 0x03; + arr_pad[3] = 0x04; + arr_pad[4] = 0x05; + arr_pad[5] = 0x06; + arr_pad[6] = 0x07; + arr_pad[7] = 0x08; + arr_pad[8] = 0x09; + arr_pad[9] = 0x0a; + arr_pad[10] = 0x0b; + arr_pad[11] = 0x0c; + arr_pad[12] = 0x0d; + arr_pad[13] = 0x0e; + arr_pad[14] = 0x0f; +} + +/******************************************************************************/ + +byte AES::set_key (byte key [], int keylen) +{ + byte hi ; + switch (keylen) + { + case 16: + case 128: + keylen = 16; // 10 rounds + round = 10 ; + break; + case 24: + case 192: + keylen = 24; // 12 rounds + round = 12 ; + break; + case 32: + case 256: + keylen = 32; // 14 rounds + round = 14 ; + break; + default: + round = 0; + return AES_FAILURE; + } + hi = (round + 1) << 4 ; + copy_n_bytes (key_sched, key, keylen) ; + byte t[4] ; + byte next = keylen ; + for (byte cc = keylen, rc = 1 ; cc < hi ; cc += N_COL) + { + for (byte i = 0 ; i < N_COL ; i++) + t[i] = key_sched [cc-4+i] ; + if (cc == next) + { + next += keylen ; + byte ttt = t[0] ; + t[0] = s_box (t[1]) ^ rc ; + t[1] = s_box (t[2]) ; + t[2] = s_box (t[3]) ; + t[3] = s_box (ttt) ; + rc = f2 (rc) ; + } + else if (keylen == 32 && (cc & 31) == 16) + { + for (byte i = 0 ; i < 4 ; i++) + t[i] = s_box (t[i]) ; + } + byte tt = cc - keylen ; + for (byte i = 0 ; i < N_COL ; i++) + key_sched [cc + i] = key_sched [tt + i] ^ t[i] ; + } + return AES_SUCCESS ; +} + +/******************************************************************************/ + +void AES::clean () +{ + for (byte i = 0 ; i < KEY_SCHEDULE_BYTES ; i++) + key_sched [i] = 0 ; + round = 0 ; +} + +/******************************************************************************/ + +void AES::copy_n_bytes (byte * d, byte * s, byte nn) +{ + while (nn >= 4) + { + *d++ = *s++ ; // some unrolling + *d++ = *s++ ; + *d++ = *s++ ; + *d++ = *s++ ; + nn -= 4 ; + } + while (nn--) + *d++ = *s++ ; +} + +/******************************************************************************/ + +byte AES::encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) +{ + if (round) + { + byte s1 [N_BLOCK], r ; + copy_and_key (s1, plain, (byte*) (key_sched)) ; + + for (r = 1 ; r < round ; r++) + { + byte s2 [N_BLOCK] ; + mix_sub_columns (s2, s1) ; + copy_and_key (s1, s2, (byte*) (key_sched + r * N_BLOCK)) ; + } + shift_sub_rows (s1) ; + copy_and_key (cipher, s1, (byte*) (key_sched + r * N_BLOCK)) ; + } + else + return AES_FAILURE ; + return AES_SUCCESS ; +} + +/******************************************************************************/ + +byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) +{ + while (n_block--) + { + xor_block (iv, plain) ; + if (encrypt (iv, iv) != AES_SUCCESS) + return AES_FAILURE ; + copy_n_bytes (cipher, iv, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK ; + } + return AES_SUCCESS ; +} + +/******************************************************************************/ + +byte AES::cbc_encrypt (byte * plain, byte * cipher, int n_block) +{ + while (n_block--) + { + xor_block (iv, plain) ; + if (encrypt (iv, iv) != AES_SUCCESS) + return AES_FAILURE ; + copy_n_bytes (cipher, iv, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK ; + } + return AES_SUCCESS ; +} + +/******************************************************************************/ + +byte AES::decrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) +{ + if (round) + { + byte s1 [N_BLOCK] ; + copy_and_key (s1, plain, (byte*) (key_sched + round * N_BLOCK)) ; + inv_shift_sub_rows (s1) ; + + for (byte r = round ; --r ; ) + { + byte s2 [N_BLOCK] ; + copy_and_key (s2, s1, (byte*) (key_sched + r * N_BLOCK)) ; + inv_mix_sub_columns (s1, s2) ; + } + copy_and_key (cipher, s1, (byte*) (key_sched)) ; + } + else + return AES_FAILURE ; + return AES_SUCCESS ; +} + +/******************************************************************************/ + +byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) +{ + while (n_block--) + { + byte tmp [N_BLOCK] ; + copy_n_bytes (tmp, cipher, N_BLOCK) ; + if (decrypt (cipher, plain) != AES_SUCCESS) + return AES_FAILURE ; + xor_block (plain, iv) ; + copy_n_bytes (iv, tmp, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK; + } + return AES_SUCCESS ; +} + +/******************************************************************************/ + +byte AES::cbc_decrypt (byte * cipher, byte * plain, int n_block) +{ + while (n_block--) + { + byte tmp [N_BLOCK] ; + copy_n_bytes (tmp, cipher, N_BLOCK) ; + if (decrypt (cipher, plain) != AES_SUCCESS) + return AES_FAILURE ; + xor_block (plain, iv) ; + copy_n_bytes (iv, tmp, N_BLOCK) ; + plain += N_BLOCK ; + cipher += N_BLOCK; + } + return AES_SUCCESS ; +} + +/*****************************************************************************/ + +void AES::set_IV(unsigned long long int IVCl){ + memcpy(iv,&IVCl,8); + memcpy(iv+8,&IVCl,8); + IVC = IVCl; +} + +/******************************************************************************/ + +void AES::iv_inc(){ + IVC += 1; + memcpy(iv,&IVC,8); + memcpy(iv+8,&IVC,8); +} + +/******************************************************************************/ + +int AES::get_size(){ + return size; +} + +/******************************************************************************/ + +void AES::set_size(int sizel){ + size = sizel; +} + + +/******************************************************************************/ + +void AES::get_IV(byte *out){ + memcpy(out,&IVC,8); + memcpy(out+8,&IVC,8); +} + +/******************************************************************************/ + +void AES::calc_size_n_pad(int p_size){ + int s_of_p = p_size - 1; + if ( s_of_p % N_BLOCK == 0){ + size = s_of_p; + }else{ + size = s_of_p + (N_BLOCK-(s_of_p % N_BLOCK)); + } + pad = size - s_of_p; +} + +/******************************************************************************/ + +void AES::padPlaintext(void* in,byte* out) +{ + memcpy(out,in,size); + for (int i = size-pad; i < size; i++){; + out[i] = arr_pad[pad - 1]; + } +} + +/******************************************************************************/ + +bool AES::CheckPad(byte* in,int lsize){ + if (in[lsize-1] <= 0x0f){ + int lpad = (int)in[lsize-1]; + for (int i = lsize - 1; i >= lsize-lpad; i--){ + if (arr_pad[lpad - 1] != in[i]){ + return false; + } + } + }else{ + return true; + } +return true; +} + +/******************************************************************************/ + +void AES::printArray(byte output[],bool p_pad) +{ +uint8_t i,j; +uint8_t loops = size/N_BLOCK; +uint8_t outp = N_BLOCK; +for (j = 0; j < loops; j += 1){ + if (p_pad && (j == (loops - 1)) ) { outp = N_BLOCK - pad; } + for (i = 0; i < outp; i++) + { + printf_P(PSTR("%c"),output[j*N_BLOCK + i]); + } +} + printf_P(PSTR("\n")); +} + +/******************************************************************************/ + +void AES::printArray(byte output[],int sizel) +{ + for (int i = 0; i < sizel; i++) + { + printf_P(PSTR("%x"),output[i]); + } + printf_P(PSTR("\n")); +} + + +/******************************************************************************/ + +void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]){ + calc_size_n_pad(size_p); + byte plain_p[get_size()]; + padPlaintext(plain,plain_p); + int blocks = get_size() / N_BLOCK; + set_key (key, bits) ; + cbc_encrypt (plain_p, cipher, blocks, ivl); +} + +/******************************************************************************/ + +void AES::do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits){ + calc_size_n_pad(size_p); + byte plain_p[get_size()]; + padPlaintext(plain,plain_p); + int blocks = get_size() / N_BLOCK; + set_key (key, bits) ; + cbc_encrypt (plain_p, cipher, blocks); +} + +/******************************************************************************/ + +void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]){ + set_size(size_c); + int blocks = size_c / N_BLOCK; + set_key (key, bits); + cbc_decrypt (cipher,plain, blocks, ivl); +} + +/******************************************************************************/ + +void AES::do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits){ + set_size(size_c); + int blocks = size_c / N_BLOCK; + set_key (key, bits); + cbc_decrypt (cipher,plain, blocks); +} + + +/******************************************************************************/ + +#if defined(AES_LINUX) +double AES::millis(){ + gettimeofday(&tv, NULL); + return (tv.tv_sec + 0.000001 * tv.tv_usec); +} +#endif diff --git a/libraries/MySensors/drivers/AES/AES.h b/libraries/MySensors/drivers/AES/AES.h new file mode 100644 index 0000000..ec7b8a6 --- /dev/null +++ b/libraries/MySensors/drivers/AES/AES.h @@ -0,0 +1,415 @@ +#ifndef __AES_H__ +#define __AES_H__ + +#include "AES_config.h" +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state. + */ + + /* code was modified by george spanos + * 16/12/14 + */ + +class AES +{ + public: + +/* The following calls are for a precomputed key schedule + + NOTE: If the length_type used for the key length is an + unsigned 8-bit character, a key length of 256 bits must + be entered as a length in bytes (valid inputs are hence + 128, 192, 16, 24 and 32). +*/ + /** \fn AES() + * \brief AES constructor + * + * This function initialized an instance of AES. + */ + AES(); + + /** Set the cipher key for the pre-keyed version. + * @param key[] pointer to the key string. + * @param keylen Integer that indicates the length of the key. + * @note NOTE: If the length_type used for the key length is an unsigned 8-bit character, + * a key length of 256 bits must be entered as a length in bytes + * (valid inputs are hence 128, 192, 16, 24 and 32). + * + */ + byte set_key (byte key[], int keylen) ; + + /** clean up subkeys after use. + * + */ + void clean () ; // delete key schedule after use + + /** copying and xoring utilities. + * @param *AESt byte pointer of the AEStination array. + * @param *src byte pointer of the source array. + * @param n byte, indicating the sizeof the bytes to be copied. + * @note this is an alternative for memcpy(void *s1,const void *s2, site_t n), + * i have not updated the function in the implementation yet, but it is considered a future plan. + * + */ + void copy_n_bytes (byte * AESt, byte * src, byte n) ; + + /** Encrypt a single block of 16 bytes . + * @param plain[N_BLOCK] Array of the plaintext. + * @param cipher[N_BLOCK] Array of the ciphertext. + * @note The N_BLOCK is defined in AES_config.h as, + * @code #define N_ROW 4 + * #define N_COL 4 + * #define N_BLOCK (N_ROW * N_COL) + * @endcode + * Changed to that will change the Block_size. + * @Return 0 if SUCCESS or -1 if FAILURE + * + */ + byte encrypt (byte plain [N_BLOCK], byte cipher [N_BLOCK]) ; + + /** CBC encrypt a number of blocks (input and return an IV). + * + * @param *plain Pointer, points to the plaintex. + * @param *cipher Pointer, points to the ciphertext that will be created. + * @param n_block integer, indicated the number of blocks to be ciphered. + * @param iv[N_BLOCK] byte Array that holds the IV (initialization vector). + * @Return 0 if SUCCESS or -1 if FAILURE + * + */ + byte cbc_encrypt (byte * plain, byte * cipher, int n_block, byte iv [N_BLOCK]) ; + + /** CBC encrypt a number of blocks (input and return an IV). + * + * @param *plain Pointer, points to the plaintex. + * @param *cipher Pointer, points to the ciphertext that will be created. + * @param n_block integer, indicated the number of blocks to be ciphered. + * @Return 0 if SUCCESS or -1 if FAILURE + * + */ + byte cbc_encrypt (byte * plain, byte * cipher, int n_block) ; + + + /** Decrypt a single block of 16 bytes + * @param cipher[N_BLOCK] Array of the ciphertext. + * @param plain[N_BLOCK] Array of the plaintext. + * @note The N_BLOCK is defined in AES_config.h as, + * @code #define N_ROW 4 + * #define N_COL 4 + * #define N_BLOCK (N_ROW * N_COL) + * @endcode + * Changed to that will change the Block_size. + * @Return 0 if SUCCESS or -1 if FAILURE + * + */ + byte decrypt (byte cipher [N_BLOCK], byte plain [N_BLOCK]) ; + + /** CBC decrypt a number of blocks (input and return an IV) + * + * @param *cipher Pointer, points to the ciphertext that will be created. + * @param *plain Pointer, points to the plaintex. + * @param n_block integer, indicated the number of blocks to be ciphered. + * @param iv[N_BLOCK] byte Array that holds the IV (initialization vector). + * @Return 0 if SUCCESS or -1 if FAILURE + * + */ + byte cbc_decrypt (byte * cipher, byte * plain, int n_block, byte iv [N_BLOCK]) ; + + /** CBC decrypt a number of blocks (input and return an IV) + * + * @param *cipher Pointer, points to the ciphertext that will be created. + * @param *plain Pointer, points to the plaintex. + * @param n_block integer, indicated the number of blocks to be ciphered. + * @Return 0 if SUCCESS or -1 if FAILURE + * + */ + byte cbc_decrypt (byte * cipher, byte * plain, int n_block) ; + + /** Sets IV (initialization vector) and IVC (IV counter). + * This function changes the ivc and iv variables needed for AES. + * + * @param IVCl int or hex value of iv , ex. 0x0000000000000001 + * @note example: + * @code unsigned long long int my_iv = 01234567; @endcode + */ + void set_IV(unsigned long long int IVCl); + + /** increase the iv (initialization vector) and IVC (IV counter) by 1 + * + * This function increased the VI by one step in order to have a different IV each time + * + */ + void iv_inc(); + + /** Getter method for size + * + * This function return the size + * @return an integer, that is the size of the of the padded plaintext, + * thus, the size of the ciphertext. + */ + int get_size(); + + /** Setter method for size + * + * This function sets the size of the plaintext+pad + * + */ + void set_size(int sizel); + + /** Getter method for IV + * + * This function return the IV + * @param out byte pointer that gets the IV. + * @return none, the IV is writed to the out pointer. + */ + void get_IV(byte *out); + + /** Calculates the size of the plaintext and the padding. + * + * Calculates the size of theplaintext with the padding + * and the size of the padding needed. Moreover it stores them in their class variables. + * + * @param p_size the size of the byte array ex sizeof(plaintext) + */ + void calc_size_n_pad(int p_size); + + /** Pads the plaintext + * + * This function pads the plaintext and returns an char array with the + * plaintext and the padding in order for the plaintext to be compatible with + * 16bit size blocks required by AES + * + * @param in the string of the plaintext in a byte array + * @param out The string of the out array. + * @return no return, The padded plaintext is stored in the out pointer. + */ + void padPlaintext(void* in,byte* out); + + /** Check the if the padding is correct. + * + * This functions checks the padding of the plaintext. + * + * @param in the string of the plaintext in a byte array + * @param size the size of the string + * @return true if correct / false if not + */ + bool CheckPad(byte* in,int size); + + /** Prints the array given. + * + * This function prints the given array and pad, + * It is mainlly used for debugging purpuses or to output the string. + * + * @param output[] the string of the text in a byte array + * @param p_pad optional, used to print with out the padding characters + */ + void printArray(byte output[],bool p_pad = true); + + /** Prints the array given. + * + * This function prints the given array in Hexadecimal. + * + * @param output[] the string of the text in a byte array + * @param sizel the size of the array. + */ + void printArray(byte output[],int sizel); + + /** User friendly implementation of AES-CBC encryption. + * + * @param *plain pointer to the plaintext + * @param size_p size of the plaintext + * @param *cipher pointer to the ciphertext + * @param *key pointer to the key that will be used. + * @param bits bits of the encryption/decrpytion + * @param ivl[N_BLOCK] the initialization vector IV that will be used for encryption. + * @note The key will be stored in class variable. + */ + void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits, byte ivl [N_BLOCK]); + + /** User friendly implementation of AES-CBC encryption. + * + * @param *plain pointer to the plaintext + * @param size_p size of the plaintext + * @param *cipher pointer to the ciphertext + * @param *key pointer to the key that will be used. + * @param bits bits of the encryption/decrpytion + * @note The key will be stored in class variable. + */ + void do_aes_encrypt(byte *plain,int size_p,byte *cipher,byte *key, int bits); + + /** User friendly implementation of AES-CBC decryption. + * + * @param *cipher pointer to the ciphertext + * @param size_c size of the ciphertext + * @param *plain pointer to the plaintext + * @param *key pointer to the key that will be used. + * @param bits bits of the encryption/decrpytion + * @param ivl[N_BLOCK] the initialization vector IV that will be used for decryption. + * @note The key will be stored in class variable. + */ + void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits, byte ivl [N_BLOCK]); + + /** User friendly implementation of AES-CBC decryption. + * + * @param *cipher pointer to the ciphertext + * @param size_c size of the ciphertext + * @param *plain pointer to the plaintext + * @param *key pointer to the key that will be used. + * @param bits bits of the encryption/decrpytion + * @note The key will be stored in class variable. + */ + void do_aes_decrypt(byte *cipher,int size_c,byte *plain,byte *key, int bits); + + #if defined(AES_LINUX) + /** + * used in linux in order to retrieve the time in milliseconds. + * + * @return returns the milliseconds in a double format. + */ + double millis(); + #endif + private: + int round ;/**< holds the number of rounds to be used. */ + byte key_sched [KEY_SCHEDULE_BYTES] ;/**< holds the pre-computed key for the encryption/decrpytion. */ + unsigned long long int IVC;/**< holds the initialization vector counter in numerical format. */ + byte iv[16];/**< holds the initialization vector that will be used in the cipher. */ + int pad;/**< holds the size of the padding. */ + int size;/**< hold the size of the plaintext to be ciphered */ + #if defined(AES_LINUX) + timeval tv;/**< holds the time value on linux */ + byte arr_pad[15];/**< holds the hexadecimal padding values on linux */ + #else + byte arr_pad[15];// = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };/**< holds the hexadecimal padding values */ + #endif +} ; + + +#endif + +/** + * @example aes.ino + * For Arduino
+ * Updated: spaniakos 2015
+ * + * This is an example of how to use AES in CBC mode easily. + * The text and keys can be either in HEX or String format.
+ */ + + /** + * @example aes.cpp + * For Rasberry pi
+ * Updated: spaniakos 2015
+ * + * This is an example of how to use AES in CBC mode easily. + * The text and keys can be either in HEX or String format.
+ */ + + /** + * @example test_vectors.ino + * For Arduino
+ * Updated: spaniakos 2015
+ * + * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.
+ * plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. + */ + + /** + * @example test_vectors.cpp + * For Rasberry pi
+ * Updated: spaniakos 2015
+ * + * This is an example of monte carlo test vectors, in order to justify the effectiveness of the algorithm.
+ * plus is a classical approach to the AES encryption library with out the easy to use add-on modifications. + */ + +/** + * @mainpage AES library for Arduino and Raspberry pi. + * + * @section Goals design Goals + * + * This library is AESigned to be... + * @li Fast and efficient. + * @li Able to effectively encrypt and decrypt any size of string. + * @li Able to encrypt and decrypt using AES + * @li Able to encrypt and decrypt using AES-CBC + * @li Easy for the user to use in his programs. + * + * @section Acknowledgements Acknowledgements + * This is an AES library for the Arduino, based on tzikis's AES library, which you can find here:.
+ * Tzikis library was based on scottmac`s library, which you can find here:
+ * + * @section Installation Installation + *

Arduino

+ * Create a folder named _AES_ in the _libraries_ folder inside your Arduino sketch folder. If the + * libraries folder doesn't exist, create it. Then copy everything inside. (re)launch the Arduino IDE.
+ * You're done. Time for a mojito + * + *

Raspberry pi

+ * install

+ * + * sudo make install
+ * cd examples_Rpi
+ * make

+ * + * What to do after changes to the library

+ * sudo make clean
+ * sudo make install
+ * cd examples_Rpi
+ * make clean
+ * make

+ * What to do after changes to a sketch

+ * cd examples_Rpi
+ * make

+ * or
+ * make clean
+ * make


+ * How to start a sketch

+ * cd examples_Rpi
+ * sudo ./

+ * + * @section News News + * + * If issues are discovered with the documentation, please report them here + * @section Useful Useful References + * + * Please refer to: + * + * @li AES Class Documentation + * @li Download + * @li Source Code + * @li All spaniakos Documentation Main Page + * + * @section Board_Support Board Support + * + * Most standard Arduino based boards are supported: + * - Arduino + * - Intel Galileo support + * - Raspberry Pi Support + * + * - The library has not been tested to other boards, but it should suppport ATMega 328 based boards,Mega Boards,Arduino Due,ATTiny board + */ diff --git a/libraries/MySensors/drivers/AES/AES_config.h b/libraries/MySensors/drivers/AES/AES_config.h new file mode 100644 index 0000000..242c841 --- /dev/null +++ b/libraries/MySensors/drivers/AES/AES_config.h @@ -0,0 +1,44 @@ +/* code was modified by george spanos + * 16/12/14 + */ + +#ifndef __AES_CONFIG_H__ +#define __AES_CONFIG_H__ + +#if (defined(__linux) || defined(linux)) && !defined(__ARDUINO_X86__) + + #define AES_LINUX + + #include + #include + #include + #include + #include + #include +#else + #include +#endif + +#include +#include + +#if defined(__ARDUINO_X86__) || (defined (__linux) || defined (linux)) + #undef PROGMEM + #define PROGMEM __attribute__(( section(".progmem.data") )) + #define pgm_read_byte(p) (*(p)) + typedef unsigned char byte; + #define printf_P printf + #define PSTR(x) (x) +#else + #include +#endif + +#define N_ROW 4 +#define N_COL 4 +#define N_BLOCK (N_ROW * N_COL) +#define N_MAX_ROUNDS 14 +#define KEY_SCHEDULE_BYTES ((N_MAX_ROUNDS + 1) * N_BLOCK) +#define AES_SUCCESS (0) +#define AES_FAILURE (-1) + +#endif diff --git a/libraries/MySensors/drivers/AES/Doxyfile b/libraries/MySensors/drivers/AES/Doxyfile new file mode 100644 index 0000000..79cf3b7 --- /dev/null +++ b/libraries/MySensors/drivers/AES/Doxyfile @@ -0,0 +1,2372 @@ +# Doxyfile 1.8.6 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "AES Encryption Library for Arduino and Raspberry Pi" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Spaniakos - AES Encryption Library for Arduino and Raspberry Pi" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = "../Documentations/AES" + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = ino=c \ + pde=c + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = YES + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ./ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.as \ + *.js + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = examples \ + examples_RPi \ + examples_Rpi + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = YES + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more acurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 10 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = doxygen-custom.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /