diff --git a/Doxyfile b/Doxyfile index 2ea47a253..173499465 100644 --- a/Doxyfile +++ b/Doxyfile @@ -652,7 +652,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = src libs targets/stm32 +INPUT = src libs targets/stm32 targets/esp8266 # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -676,7 +676,7 @@ FILE_PATTERNS = # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. -RECURSIVE = 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 @@ -698,7 +698,7 @@ EXCLUDE_SYMLINKS = NO # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = *.md # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -1214,7 +1214,7 @@ SERVER_BASED_SEARCH = NO # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. -GENERATE_LATEX = YES +GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be diff --git a/libs/network/esp8266/jswrap_esp8266.c b/libs/network/esp8266/jswrap_esp8266.c index ae65fb413..fdc706a48 100644 --- a/libs/network/esp8266/jswrap_esp8266.c +++ b/libs/network/esp8266/jswrap_esp8266.c @@ -27,6 +27,7 @@ static void ipAddrToString(struct ip_addr addr, char *string); static char *nullTerminateString(char *target, char *source, int sourceLength); static void setupJsNetwork(); static void pingRecvCB(); +static char *wifiConnectStatusToString(uint8 status); static JsVar *jsScanCallback; static JsVar *jsWiFiEventCallback; @@ -65,22 +66,20 @@ static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; }*/ -/** - * \brief Connect the station to an access point. - * - `ssid` - The network id of the access point. - * - `password` - The password to use to connect to the access point. - */ /*JSON{ "type" : "staticmethod", "class" : "ESP8266WiFi", "name" : "connect", "generate" : "jswrap_ESP8266WiFi_connect", "params" : [ - ["ssid","JsVar","The network SSID"], + ["ssid","JsVar","The network id of the access point."], ["password","JsVar","The password to the access point"], ["gotIpCallback", "JsVar", "An optional callback invoked when we have an IP"] ] -}*/ +} + * + * Connect the station to an access point. + */ void jswrap_ESP8266WiFi_connect( JsVar *jsv_ssid, //!< The SSID of the access point to connect. JsVar *jsv_password, //!< The password for the access point. @@ -118,7 +117,9 @@ void jswrap_ESP8266WiFi_connect( if (gotIpCallback != NULL) { jsGotIpCallback = jsvLockAgainSafe(gotIpCallback); } - os_printf("jsGotIpCallback=%p\n", jsGotIpCallback); + + // Debug + // os_printf("jsGotIpCallback=%p\n", jsGotIpCallback); // Create strings from the JsVars for the ESP8266 API calls. char ssid[33]; @@ -128,8 +129,9 @@ void jswrap_ESP8266WiFi_connect( len = jsvGetString(jsv_password, password, sizeof(password)-1); password[len]='\0'; - os_printf("> - ssid=%s, password=%s\n", ssid, password); - // Set the WiFi mode of the ESP8266 + os_printf("> - ssid=%s, password=%s\n", ssid, password); + + // Set the WiFi mode of the ESP8266 wifi_set_opmode_current(STATION_MODE); struct station_config stationConfig; @@ -144,13 +146,49 @@ void jswrap_ESP8266WiFi_connect( // Set the WiFi configuration wifi_station_set_config(&stationConfig); + uint8 wifiConnectStatus = wifi_station_get_connect_status(); + os_printf(" - Current connect status: %s\n", wifiConnectStatusToString(wifiConnectStatus)); + + if (wifiConnectStatus == STATION_GOT_IP) { + // See issue #618. There are currently three schools of thought on what should happen + // when a connect is issued and we are already connected. + // + // Option #1 - Always perform a disconnect. + // Option #2 - Perform a disconnect if the SSID or PASSWORD are different from current + // Option #3 - Fail the connect if we are already connected. + // +#define ISSUE_618 1 + +#if ISSUE_618 == 1 + wifi_station_disconnect(); +#elif ISSUE_618 == 2 + struct station_config existingConfig; + wifi_station_get_config(&existingConfig); + if (os_strncpy((char *)existingConfig.ssid, (char *)stationConfig.ssid, 32) == 0 && + os_strncpy((char *)existingConfig.password, (char *)stationConfig.password, 64) == 0) { + if (jsGotIpCallback != NULL) { + JsVar *params[2]; + params[0] = jsvNewFromInteger(STATION_GOT_IP); + params[1] = jsvNewNull(); + jsiQueueEvents(NULL, jsGotIpCallback, params, 2); + } + return; + + } else { + wifi_station_disconnect(); + } +#elif ISSUE_618 == 3 + // Add a return code to the function and return an already connected error. +#endif + } + // Perform the network level connection. wifi_station_connect(); os_printf("< jswrap_ESP8266WiFi_connect\n"); } /** - * \brief Become an access point. + * Become an access point. * When we call this function we are instructing the ESP8266 to set itself up as an * access point to allow other WiFi stations to connect to it. In order to be an access * point, the ESP8266 needs to know the SSID it should use as well as the password used @@ -223,7 +261,7 @@ void jswrap_ESP8266WiFi_beAccessPoint( /** - * \brief Determine the list of access points available to us. + * Determine the list of access points available to us. */ /*JSON{ "type" : "staticmethod", @@ -261,7 +299,7 @@ void jswrap_ESP8266WiFi_getAccessPoints( /** - * \brief Disconnect the station from the access point. + * Disconnect the station from the access point. */ /*JSON{ "type" : "staticmethod", @@ -286,7 +324,7 @@ void jswrap_ESP8266WiFi_restart() { /** - * \brief Register a callback function that will be invoked when a WiFi event is detected. + * Register a callback function that will be invoked when a WiFi event is detected. */ /*JSON{ "type" : "staticmethod", @@ -326,7 +364,7 @@ void jswrap_ESP8266WiFi_onWiFiEvent( /** - * \brief Set whether or not the ESP8266 will perform an auto connect on startup. + * Set whether or not the ESP8266 will perform an auto connect on startup. * A value of true means it will while a value of false means it won't. */ /*JSON{ @@ -349,7 +387,6 @@ void jswrap_ESP8266WiFi_setAutoConnect( uint8 newValue = jsvGetBool(autoconnect); os_printf("New value: %d\n", newValue); - os_printf("jswrap_ESP8266WiFi_setAutoConnect -> Something breaks here :-(\n"); uart_rx_intr_disable(0); wifi_station_set_auto_connect(newValue); @@ -359,7 +396,7 @@ void jswrap_ESP8266WiFi_setAutoConnect( /** - * \brief Retrieve whether or not the ESP8266 will perform an auto connect on startup. + * Retrieve whether or not the ESP8266 will perform an auto connect on startup. * A value of 1 means it will while a value of zero means it won't. */ /*JSON{ @@ -376,7 +413,7 @@ JsVar *jswrap_ESP8266WiFi_getAutoConnect() { /** - * \brief Retrieve the reset information that is stored when event the ESP8266 resets. + * Retrieve the reset information that is stored when event the ESP8266 resets. * The result will be a JS object containing the details. */ /*JSON{ @@ -402,7 +439,7 @@ JsVar *jswrap_ESP8266WiFi_getRstInfo() { /** - * \brief Return an object that contains details about the state of the ESP8266. + * Return an object that contains details about the state of the ESP8266. * - `sdkVersion` - Version of the SDK. * - `cpuFrequency` - CPU operating frequency. * - `freeHeap` - Amount of free heap. @@ -429,7 +466,7 @@ JsVar *jswrap_ESP8266WiFi_getState() { } /** - * \brief Return the value of an integer representation (4 bytes) of IP address + * Return the value of an integer representation (4 bytes) of IP address * as a string. */ /*JSON{ @@ -455,7 +492,7 @@ JsVar *jswrap_ESP8266WiFi_getAddressAsString( /** - * \brief Retrieve the IP information about this network interface and return a JS + * Retrieve the IP information about this network interface and return a JS * object that contains its details. * The object will have the following properties defined upon it: * - `ip` - The IP address of the interface. @@ -483,7 +520,7 @@ JsVar *jswrap_ESP8266WiFi_getIPInfo() { /** - * \brief Query the station configuration and return a JS object that represents the + * Query the station configuration and return a JS object that represents the * current settings. * The object will have the following properties: * @@ -514,7 +551,7 @@ JsVar *jswrap_ESP8266WiFi_getStationConfig() { /** - * \brief Determine the list of connected stations and return them. + * Determine the list of connected stations and return them. */ /*JSON{ "type" : "staticmethod", @@ -542,7 +579,7 @@ JsVar *jswrap_ESP8266WiFi_getConnectedStations() { /** - * \brief Get the signal strength. + * Get the signal strength. */ /*JSON{ "type" : "staticmethod", @@ -559,7 +596,7 @@ JsVar *jswrap_ESP8266WiFi_getRSSI() { /** - * \brief Initialize the ESP8266 environment. + * Initialize the ESP8266 environment. */ /*JSON{ "type" : "staticmethod", @@ -693,7 +730,7 @@ void jswrap_ESP8266WiFi_socketEnd( /** - * \brief Perform a network ping request. + * Perform a network ping request. * The parameter can be either a String or a numeric IP address. */ /*JSON{ @@ -759,7 +796,7 @@ void jswrap_ESP8266WiFi_ping( /** - * \brief Dump the data in the socket. + * Dump the data in the socket. */ /*JSON{ "type" : "staticmethod", @@ -778,7 +815,7 @@ void jswrap_ESP8266WiFi_dumpSocket( } /** - * \brief Null terminate a string. + * Null terminate a string. */ static char *nullTerminateString(char *target, char *source, int sourceLength) { os_strncpy(target, source, sourceLength); @@ -797,7 +834,7 @@ static void setupJsNetwork() { /** - * \brief Handle receiving a response from a ping reply. + * Handle receiving a response from a ping reply. * If a callback function has been supplied we invoked that callback by queuing it for future * execution. A parameter is supplied to the callback which is a JavaScript object that contains: * - totalCount @@ -830,7 +867,7 @@ static void pingRecvCB(void *pingOpt, void *pingResponse) { /** - * \brief Callback function that is invoked at the culmination of a scan. + * Callback function that is invoked at the culmination of a scan. */ static void scanCB(void *arg, STATUS status) { /** @@ -897,7 +934,7 @@ static void scanCB(void *arg, STATUS status) { /** - * \brief Invoke the JavaScript callback to notify the program that an ESP8266 + * Invoke the JavaScript callback to notify the program that an ESP8266 * WiFi event has occurred. */ static void sendWifiEvent(uint32 eventType, JsVar *details) { @@ -925,7 +962,7 @@ static void sendWifiEvent(uint32 eventType, JsVar *details) { /** - * \brief ESP8266 WiFi Event handler. + * ESP8266 WiFi Event handler. * This function is called by the ESP8266 * environment when significant events happen related to the WiFi environment. * The event handler is registered with a call to wifi_set_event_handler_cb() @@ -993,7 +1030,7 @@ static void wifiEventHandler(System_Event_t *evt) { } /** - * \brief Write an IP address as a dotted decimal string. + * Write an IP address as a dotted decimal string. */ // Note: This may be a duplicate ... it appears that we may have an existing function // in network.c which does exactly this and more!! @@ -1001,3 +1038,29 @@ static void wifiEventHandler(System_Event_t *evt) { static void ipAddrToString(struct ip_addr addr, char *string) { os_sprintf(string, "%d.%d.%d.%d", ((char *)&addr)[0], ((char *)&addr)[1], ((char *)&addr)[2], ((char *)&addr)[3]); } + +/** + * Convert an ESP8266 WiFi connect status to a string. + * + * Convert the status (as returned by `wifi_station_get_connect_status()`) to a string + * representation. + * \return A string representation of a WiFi connect status. + */ +static char *wifiConnectStatusToString(uint8 status) { + switch(status) { + case STATION_IDLE: + return "STATION_IDLE"; + case STATION_CONNECTING: + return "STATION_CONNECTING"; + case STATION_WRONG_PASSWORD: + return "STATION_WRONG_PASSWORD"; + case STATION_NO_AP_FOUND: + return "STATION_NO_AP_FOUND"; + case STATION_CONNECT_FAIL: + return "STATION_CONNECT_FAIL"; + case STATION_GOT_IP: + return "STATION_GOT_IP"; + default: + return "Unknown connect status!!"; + } +} diff --git a/libs/network/esp8266/network_esp8266.c b/libs/network/esp8266/network_esp8266.c index 72ce01548..bb4d1fa35 100644 --- a/libs/network/esp8266/network_esp8266.c +++ b/libs/network/esp8266/network_esp8266.c @@ -1,1274 +1,1274 @@ -/* -5 * network_esp8266_board.c - - * - * Created on: Aug 29, 2015 - * Author: kolban - */ - -/** - * This file contains the implementation of the ESP8266_BOARD network interfaces at the TCP/IP - * level. - * - * Design notes - * ------------ - * We maintain an array of socketData structures. The number of such structures is defined in the - * MAX_SOCKETS define. The private variable that contains the array is called "socketArray". - * Each one of these array instances represents a possible socket structure that we can use. - * - * Each socket maintains state and the transitions are shown in a separate state diagram. In - * summary, the possible states are: - * - * * SOCKET_STATE_UNUSED - * * SOCKET_STATE_IDLE - * * SOCKET_STATE_CONNECTING - * * SOCKET_STATE_TRANSMITTING - * * SOCKET_STATE_CLOSING - * * SOCKET_STATE_HOST_RESOLVING - * * SOCKET_STATE_ERROR - * - * Each socket also maintains its creation purpose. There are three ways a socket - * can have been created: - * - * SOCKET_CREATED_SERVER - The socket was created as a server. - * SOCKET_CREATED_OUTBOUND - The socket was created by an out-bound. - * SOCKET_CREATED_INBOUND - The socket was created by an in-bound. - */ -// ESP8266 specific includes -#undef ESPSDK_1_3_0 -#include -#include -#include -#include -#include -#include - -#define _GCC_WRAP_STDINT_H -typedef long long int64_t; - -#include "network_esp8266.h" -#include "esp8266_board_utils.h" - -/** - * \brief The maximum number of concurrently open sockets we support. - * We should probably pair this with the ESP8266 concept of the maximum number of sockets - * that an ESP8266 instance can also support. - */ -#define MAX_SOCKETS (10) - -#define LOG os_printf - -static struct socketData *getSocketData(int s); - -/** - * \brief The next socketId to be used. - */ -static int g_nextSocketId = 0; - -static int getServerSocketByLocalPort(unsigned short port); -static void setSocketInError(int socketId, char *msg, int code); -static void dumpEspConn(struct espconn *pEspConn); -static struct socketData *allocateNewSocket(); -static void doClose(int socketId); -static void releaseSocket(int socketId); -static void resetSocketByData(struct socketData *pSocketData); -static void resetSocketById(int sckt); - -static void esp8266_callback_connectCB_inbound(void *arg); -static void esp8266_callback_connectCB_outbound(void *arg); -static void esp8266_callback_disconnectCB(void *arg); -static void esp8266_callback_sentCB(void *arg); -static void esp8266_callback_writeFinishedCB(void *arg); -static void esp8266_callback_recvCB(void *arg, char *pData, unsigned short len); -static void esp8266_callback_reconnectCB(void *arg, sint8 err); - -/** - * \brief A data structure that represents a memory buffer. - * A memory buffer is an object that represents a sized piece of memory. Given a - * memory buffer object, we know how big it is and can set or get data from it. - */ -struct memoryBuffer { - /** - * \brief The size of data associated with this buffer. - */ - size_t length; - - /** - * \brief A pointer to the memory associated with this buffer. This should be - * NULL if `length` is 0. - */ - uint8 *buf; -}; - -static uint8 *memoryBuffer_read(struct memoryBuffer *pMemoryBuffer, size_t readSize); -static uint8 *memoryBuffer_append(struct memoryBuffer *pMemoryBuffer, uint8 *pNewData, size_t length); -static void memoryBuffer_delete(struct memoryBuffer *pMemoryBuffer); -static int memoryBuffer_getSize(struct memoryBuffer *pMemoryBuffer); - -/** - * \brief The potential states for a socket. - * See the socket state diagram. - */ -enum SOCKET_STATE { - SOCKET_STATE_UNUSED, //!< The socket is unused - SOCKET_STATE_IDLE, //!< The socket is idle - SOCKET_STATE_CONNECTING, //!< The socket is connecting - SOCKET_STATE_TRANSMITTING, //!< The socket is transmitting - SOCKET_STATE_CLOSING, //!< The socket is closing - SOCKET_STATE_HOST_RESOLVING, //!< Resolving a a hostname - SOCKET_STATE_ERROR //!< The socket is in error -}; - -/** - * \brief How was the socket created. - */ -enum SOCKET_CREATION_TYPE { - SOCKET_CREATED_NONE, //!< The socket has not yet been created. - SOCKET_CREATED_SERVER, //!< The socket was created as a server. - SOCKET_CREATED_OUTBOUND, //!< The socket was created outbound. - SOCKET_CREATED_INBOUND //!< The socket was created inbound. -}; - -/** - * Here are some notes on the accepted list algorithms. - * - * tail - Where old entries are removed - * head - Where new entries are added - * - * When tail = head - the list is empty - * - * When a new entry is added: - * error: mod(head+1) == tail // List full - * *head = new entry - * head = mod(head+1) - * - * When an old entry is removed - * error: tail == head // List empty - * retrieved entry = *tail - * tail = mod(tail+1) - * - * - * 0 1 2 3 4 5 6 7 8 - * [ ][ ][ ][ ][ ][ ][ ][ ][ ] - */ - -/** - * \brief The maximum number of accepted sockets that can be remembered. - */ -#define MAX_ACCEPTED_SOCKETS (10) - -/** - * \brief The core socket structure. - * The structure is initialized by resetSocket. - */ -struct socketData { - int socketId; //!< The id of THIS socket. - enum SOCKET_STATE state; //!< What is the socket state? - enum SOCKET_CREATION_TYPE creationType; //!< How was the socket created? - bool isConnected; //!< Is this socket connected? - bool shouldClose; //!< Should this socket close when it can? - - struct espconn *pEspconn; //!< The ESPConn structure. - - struct memoryBuffer txMemoryBuffer; //!< Data to be transmitted. - uint8 *currentTx; //!< Data currently being transmitted. - uint8 *rxBuf; //!< Data received (inbound). - size_t rxBufLen; //!< The length of data in the buffer ready for consumption. - - char *errorMsg; //!< Error message. - int errorCode; //!< Error code. - - /** - * \brief A list of accepted sockets. - * This array contains the storage of a list of sockets that have been accepted by this - * server socket but have not yet been delivered to Espruino. A `head` and `tail` - * pair of indices are also associated. - */ - int acceptedSockets[MAX_ACCEPTED_SOCKETS]; - - /** - * \brief The head of the list of accepted sockets. - * The index into `acceptedSockets` where the next accepted socket will be placed. - */ - uint8 acceptedSocketsHead; - - /** - * \brief The tail of the list of accepted sockets. - * The index into `acceptedSockets` where the next accepted socket will be retrieved. - */ - uint8 acceptedSocketsTail; -}; - - -/** - * \brief An array of socket data structures. - */ -static struct socketData socketArray[MAX_SOCKETS]; - - -/** - * \brief Write the details of a socket to the debug log. - * The data associated with the socket is dumped to the debug log. - */ -void esp8266_dumpSocket( - int socketId //!< The ID of the socket data structure to be logged. - ) { - struct socketData *pSocketData = getSocketData(socketId); - LOG("Dump of socket=%d\n", socketId); - LOG(" - isConnected=%d", pSocketData->isConnected); - char *creationTypeMsg; - switch(pSocketData->creationType) { - case SOCKET_CREATED_NONE: - creationTypeMsg = "SOCKET_CREATED_NONE"; - break; - case SOCKET_CREATED_INBOUND: - creationTypeMsg = "SOCKET_CREATED_INBOUND"; - break; - case SOCKET_CREATED_OUTBOUND: - creationTypeMsg = "SOCKET_CREATED_OUTBOUND"; - break; - case SOCKET_CREATED_SERVER: - creationTypeMsg = "SOCKET_CREATED_SERVER"; - break; - } - LOG(", creationType=%s", creationTypeMsg); - LOG(", acceptedSockets=["); - int s=pSocketData->acceptedSocketsTail; - while(s != pSocketData->acceptedSocketsHead) { - LOG(" %d", pSocketData->acceptedSockets[s]); - s = (s+1)%MAX_ACCEPTED_SOCKETS; - } - LOG("]"); - LOG(", rxBufLen=%d", pSocketData->rxBufLen); - LOG(", tx length=%d", memoryBuffer_getSize(&(pSocketData->txMemoryBuffer))); - LOG(", currentTx=0x%d", (int)pSocketData->currentTx); - char *stateMsg; - switch(pSocketData->state) { - case SOCKET_STATE_CLOSING: - stateMsg = "SOCKET_STATE_CLOSING"; - break; - case SOCKET_STATE_CONNECTING: - stateMsg = "SOCKET_STATE_CONNECTING"; - break; - case SOCKET_STATE_ERROR: - stateMsg = "SOCKET_STATE_ERROR"; - break; - case SOCKET_STATE_IDLE: - stateMsg = "SOCKET_STATE_IDLE"; - break; - case SOCKET_STATE_TRANSMITTING: - stateMsg = "SOCKET_STATE_TRANSMITTING"; - break; - case SOCKET_STATE_HOST_RESOLVING: - stateMsg = "SOCKET_STATE_HOST_RESOLVING"; - break; - case SOCKET_STATE_UNUSED: - stateMsg = "SOCKET_STATE_UNUSED"; - break; - default: - stateMsg = "Unexpected state!!"; - break; - } - LOG(", state=%s", stateMsg); - LOG(", errorCode=%d", pSocketData->errorCode); - - // Print the errorMsg if it has anything to say - if (pSocketData->errorMsg != NULL && strlen(pSocketData->errorMsg) > 0) { - LOG(", errorMsg=\"%s\"", pSocketData->errorMsg); - } - - LOG("\n"); -} - - -/** - * \brief Dump a struct espconn (for debugging purposes). - */ -static void dumpEspConn( - struct espconn *pEspConn //!< - ) { - char ipString[20]; - LOG("Dump of espconn: 0x%x\n", (int)pEspConn); - if (pEspConn == NULL) { - return; - } - switch(pEspConn->type) { - case ESPCONN_TCP: - LOG(" - type = TCP\n"); - LOG(" - local address = %d.%d.%d.%d [%d]\n", - pEspConn->proto.tcp->local_ip[0], - pEspConn->proto.tcp->local_ip[1], - pEspConn->proto.tcp->local_ip[2], - pEspConn->proto.tcp->local_ip[3], - pEspConn->proto.tcp->local_port); - LOG(" - remote address = %d.%d.%d.%d [%d]\n", - pEspConn->proto.tcp->remote_ip[0], - pEspConn->proto.tcp->remote_ip[1], - pEspConn->proto.tcp->remote_ip[2], - pEspConn->proto.tcp->remote_ip[3], - pEspConn->proto.tcp->remote_port); - break; - case ESPCONN_UDP: - LOG(" - type = UDP\n"); - LOG(" - local_port = %d\n", pEspConn->proto.udp->local_port); - LOG(" - local_ip = %d.%d.%d.%d\n", - pEspConn->proto.tcp->local_ip[0], - pEspConn->proto.tcp->local_ip[1], - pEspConn->proto.tcp->local_ip[2], - pEspConn->proto.tcp->local_ip[3]); - LOG(" - remote_port = %d\n", pEspConn->proto.udp->remote_port); - LOG(" - remote_ip = %d.%d.%d.%d\n", - pEspConn->proto.tcp->remote_ip[0], - pEspConn->proto.tcp->remote_ip[1], - pEspConn->proto.tcp->remote_ip[2], - pEspConn->proto.tcp->remote_ip[3]); - break; - default: - LOG(" - type = Unknown!! 0x%x\n", pEspConn->type); - } - switch(pEspConn->state) { - case ESPCONN_NONE: - LOG(" - state=NONE"); - break; - case ESPCONN_WAIT: - LOG(" - state=WAIT"); - break; - case ESPCONN_LISTEN: - LOG(" - state=LISTEN"); - break; - case ESPCONN_CONNECT: - LOG(" - state=CONNECT"); - break; - case ESPCONN_WRITE: - LOG(" - state=WRITE"); - break; - case ESPCONN_READ: - LOG(" - state=READ"); - break; - case ESPCONN_CLOSE: - LOG(" - state=CLOSE"); - break; - default: - LOG(" - state=unknown!!"); - break; - } - LOG(", link_cnt=%d", pEspConn->link_cnt); - LOG(", reverse=0x%x\n", (unsigned int)pEspConn->reverse); -} - - -/** - * \brief Get the next new global socket id. - * \return A new socketId that is assured to be unique. - */ -static int getNextGlobalSocketId() { - int ret = g_nextSocketId; - g_nextSocketId++; - return ret; -} - - -/** - * \brief Allocate a new socket - * Look for the first free socket in the array of sockets and return the first one - * that is available. The socketId property is set to a unique and new socketId value - * that will not previously have been seen. - * \return The socketData structure for the returned socket. - */ -static struct socketData *allocateNewSocket() { - // Walk through each of the sockets in the array of possible sockets and stop - // at the first one that is flagged as not in use. For that socket, set its - // socketId to the next global socketId value. - int i; - for (i=0; isocketId == socketId) { - return pSocketData; - } - pSocketData++; - } - return NULL; -} - - -/** - * \brief Find the server socket that is bound to the given local port. - * \return The socket id of the socket listening on the given port or -1 if there is no - * server socket that matches. - */ -static int getServerSocketByLocalPort( - unsigned short port //!< The port number on which a server socket is listening. - ) { - // Loop through each of the sockets in the socket array looking for a socket - // that is inuse, a server and has a local_port of the passed in port number. - int socketArrayIndex; - struct socketData *pSocketData = socketArray; - for (socketArrayIndex=0; socketArrayIndexstate != SOCKET_STATE_UNUSED && - pSocketData->creationType == SOCKET_CREATED_SERVER && - pSocketData->pEspconn->proto.tcp->local_port == port) - { - return pSocketData->socketId; - } - pSocketData++; - } // End of for each socket - return -1; -} - - -/** - * \brief Reset the socket to its clean and unused state. - * The socket is found by its socket id. - */ -static void resetSocketById( - int sckt //!< The socket id to be reset. - ) { - struct socketData *pSocketData = getSocketData(sckt); - resetSocketByData(pSocketData); -} - -/** - * \brief Reset the socket to its clean and unused state. - * The socket is specified by its socket data pointer. - */ -static void resetSocketByData( - struct socketData *pSocketData //!< The data pointer to the socket. - ) { - assert(pSocketData != NULL); - - memoryBuffer_delete(&pSocketData->txMemoryBuffer); - - pSocketData->pEspconn = NULL; - pSocketData->state = SOCKET_STATE_UNUSED; - pSocketData->rxBuf = NULL; - pSocketData->rxBufLen = 0; - pSocketData->creationType = SOCKET_CREATED_NONE; - pSocketData->isConnected = false; - pSocketData->shouldClose = false; - pSocketData->errorMsg = ""; - pSocketData->errorCode = 0; - pSocketData->socketId = -1; - - pSocketData->acceptedSocketsHead = 0; // Set the head to 0 - pSocketData->acceptedSocketsTail = 0; // Set the tail to 9. - pSocketData->pEspconn = NULL; -} - - -/** - * \brief Release the socket and return it to the free pool. - */ -static void releaseSocket( - int socketId //!< The socket id of the socket to be released. - ) { - os_printf("> releaseSocket: %d\n", socketId); - esp8266_dumpSocket(socketId); - - struct socketData *pSocketData = getSocketData(socketId); - assert(pSocketData->state != SOCKET_STATE_UNUSED); - - if (memoryBuffer_getSize(&pSocketData->txMemoryBuffer) > 0) { - os_printf(" - Oh oh ... attempt to close socket while the TX memoryBuffer is not empty!\n"); - } - if (pSocketData->rxBuf != NULL || pSocketData->rxBufLen != 0) { - os_printf(" - Oh oh ... attempt to close socket while the rxBuffer is not empty!\n"); - } - - // If this socket is not an incoming socket that means that the espconn structure was created - // by us and we should release the storage we allocated. - if (pSocketData->creationType != SOCKET_CREATED_INBOUND) { - os_free(pSocketData->pEspconn->proto.tcp); - pSocketData->pEspconn->proto.tcp = NULL; - os_free(pSocketData->pEspconn); - pSocketData->pEspconn = NULL; - } - resetSocketByData(pSocketData); - os_printf("< releaseSocket\n"); -} - - -/** - * \brief Initialize the ESP8266_BOARD environment. - * Walk through each of the sockets and initialize each one. - */ -void netInit_esp8266_board() { - int socketArrayIndex; - struct socketData *pSocketData = socketArray; - for (socketArrayIndex=0; socketArrayIndexstate != SOCKET_STATE_CLOSING) { - int rc = espconn_disconnect(pSocketData->pEspconn); - pSocketData->state = SOCKET_STATE_CLOSING; - - if (rc != 0) { - os_printf("espconn_disconnect: rc=%d\n", rc); - setSocketInError(socketId, "espconn_disconnect", rc); - } - } - // Our existing state on entry was SOCKET_STATE_CLOSING which means that we got here - // because we were previously flagged as closing. - else { - releaseSocket(socketId); - } -} - - -/** - * \brief Set the given socket as being in error supplying a message and a code. - * The socket state is placed in `SOCKET_STATE_ERROR`. - */ -static void setSocketInError( - int socketId, //!< The socket id that is being flagged as in error. - char *msg, //!< A message to associate with the error. - int code //!< A low level error code. - ) { - struct socketData *pSocketData = getSocketData(socketId); - pSocketData->state = SOCKET_STATE_ERROR; - pSocketData->errorMsg = msg; - pSocketData->errorCode = code; -} - -/** - * \brief Callback function registered to the ESP8266 environment that is - * invoked when a new inbound connection has been formed. - * A new connection - * can occur when the ESP8266 makes a call out to a partner (in that - * case the ESP8266 is acting as a client) or a new connection can - * occur when a partner calls into a listening ESP8266. In that case - * the ESP8266 is acting as a server. - */ -static void esp8266_callback_connectCB_inbound( - void *arg //!< - ) { - os_printf(">> connectCB_inbound\n"); - struct espconn *pEspconn = (struct espconn *)arg; - assert(pEspconn != NULL); - - espconn_regist_disconcb(pEspconn, esp8266_callback_disconnectCB); - espconn_regist_reconcb(pEspconn, esp8266_callback_reconnectCB); - espconn_regist_sentcb(pEspconn, esp8266_callback_sentCB); - espconn_regist_recvcb(pEspconn, esp8266_callback_recvCB); - espconn_regist_write_finish(pEspconn, esp8266_callback_writeFinishedCB); - - dumpEspConn(pEspconn); - - int inboundSocket = getServerSocketByLocalPort(pEspconn->proto.tcp->local_port); - assert(inboundSocket != -1); - struct socketData *pSocketData = getSocketData(inboundSocket); - assert(pSocketData != NULL); - - esp8266_dumpSocket(pSocketData->socketId); - - os_printf("** new client has connected to us **\n"); - - if ((pSocketData->acceptedSocketsHead + 1) % MAX_ACCEPTED_SOCKETS == pSocketData->acceptedSocketsTail) { - os_printf("WARNING!! - Discarding inbound client because we have too many accepted clients.\n"); - os_printf("<< connectCB_inbound\n"); - return; - } - - struct socketData *pClientSocketData = allocateNewSocket(); - if (pClientSocketData == NULL) { - os_printf("!!! Ran out of sockets !!!\n"); - return; - } - assert(pClientSocketData != NULL); - pClientSocketData->pEspconn = pEspconn; - pClientSocketData->pEspconn->reverse = pClientSocketData; - pClientSocketData->creationType = SOCKET_CREATED_INBOUND; - pClientSocketData->isConnected = true; - pClientSocketData->state = SOCKET_STATE_IDLE; - - pSocketData->acceptedSockets[pSocketData->acceptedSocketsHead] = pClientSocketData->socketId; - pSocketData->acceptedSocketsHead = (pSocketData->acceptedSocketsHead + 1) % MAX_ACCEPTED_SOCKETS; - - os_printf("<< connectCB_inbound\n"); -} - -/** - * \brief Callback function registered to the ESP8266 environment that is - * invoked when a new outbound connection has been formed. - */ -static void esp8266_callback_connectCB_outbound( - void *arg //!< A pointer to a `struct espconn`. - ) { - os_printf(">> connectCB_outbound\n"); - struct espconn *pEspconn = (struct espconn *)arg; - assert(pEspconn != NULL); - - dumpEspConn(pEspconn); - - struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; - assert(pSocketData != NULL); - - esp8266_dumpSocket(pSocketData->socketId); - - // Flag the socket as connected to a partner. - pSocketData->isConnected = true; - - assert(pSocketData->state == SOCKET_STATE_CONNECTING); - if (pSocketData->shouldClose) { - doClose(pSocketData->socketId); - } else { - pSocketData->state = SOCKET_STATE_IDLE; - } - os_printf("<< connectCB_outbound\n"); -} - - -/** - * \brief Callback function registered to the ESP8266 environment that is - * Invoked when a previous connection has been disconnected. - */ -static void esp8266_callback_disconnectCB( - void *arg //!< A pointer to a `struct espconn`. - ) { - struct espconn *pEspconn = (struct espconn *)arg; - struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; - assert(pSocketData != NULL); - assert(pSocketData->state != SOCKET_STATE_UNUSED); - - os_printf(">> disconnectCB\n"); - dumpEspConn(pEspconn); - esp8266_dumpSocket(pSocketData->socketId); - - // If the socket state is SOCKET_STATE_CLOSING then that means we can release the socket. The reason - // for this is that the last thing the user did was request an explicit socket close. - if (pSocketData->state == SOCKET_STATE_CLOSING) { - releaseSocket(pSocketData->socketId); - } else { - pSocketData->state = SOCKET_STATE_CLOSING; - pSocketData->isConnected = false; - } - os_printf("<< disconnectCB\n"); -} - - -/** - * - */ -static void esp8266_callback_writeFinishedCB( - void *arg //!< A pointer to a `struct espconn`. - ) { - os_printf(">> writeFinishedCB\n"); - struct espconn *pEspconn = (struct espconn *)arg; - struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; - if (pSocketData->currentTx != NULL) { - os_free(pSocketData->currentTx); - pSocketData->currentTx = NULL; - } - os_printf("<< writeFinishedCB\n"); -} - - -/** - * \brief Error handler callback. - * Although this is called reconnect by Espressif, this is really an error handler - * routine. It will be called when an error is detected. - */ -static void esp8266_callback_reconnectCB( - void *arg, //!< A pointer to a `struct espconn`. - sint8 err //!< The error code. - ) { - os_printf(">> reconnectCB: Error code is: %d - %s\n", err, esp8266_errorToString(err)); - os_printf("<< reconnectCB"); -} - - -/** - * \brief Callback function registered to the ESP8266 environment that is - * invoked when a send operation has been completed. - */ -static void esp8266_callback_sentCB( - void *arg //!< A pointer to a `struct espconn`. - ) { - os_printf(">> sendCB\n"); - struct espconn *pEspconn = (struct espconn *)arg; - struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; - - assert(pSocketData != NULL); - assert(pSocketData->state == SOCKET_STATE_TRANSMITTING); - - // We have transmitted the data ... which means that the data that was in the transmission - // buffer can be released. - if (pSocketData->currentTx != NULL) { - os_free(pSocketData->currentTx); - pSocketData->currentTx = NULL; - } - - if (pSocketData->shouldClose) { - doClose(pSocketData->socketId); - } else { - pSocketData->state = SOCKET_STATE_IDLE; - } - os_printf("<< sendCB\n"); -} - - -/** - * \brief ESP8266 callback function that is invoked when new data has arrived over - * the TCP/IP connection. - */ -static void esp8266_callback_recvCB( - void *arg, //!< A pointer to a `struct espconn`. - char *pData, //!< A pointer to data received over the socket. - unsigned short len //!< The length of the data. - ) { - struct espconn *pEspconn = (struct espconn *)arg; - struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; - - assert(pSocketData != NULL); - assert(pSocketData->state != SOCKET_STATE_UNUSED); - - os_printf(">> recvCB for socket=%d, length=%d\n", pSocketData->socketId, len); - - // If we don't have any existing unconsumed data then malloc some storage and - // copy the received data into that storage. - if (pSocketData->rxBufLen == 0) { - pSocketData->rxBuf = (void *)os_malloc(len); - memcpy(pSocketData->rxBuf, pData, len); - pSocketData->rxBufLen = len; - } else { -// Allocate a new buffer big enough for the original data and the new data -// Copy the original data to the start of the new buffer ... -// Copy the new new data to the offset into the new buffer just after -// the original data. -// Release the original data. -// Update the socket data. - uint8 *pNewBuf = (uint8 *)os_malloc(len + pSocketData->rxBufLen); - memcpy(pNewBuf, pSocketData->rxBuf, pSocketData->rxBufLen); - memcpy(pNewBuf + pSocketData->rxBufLen, pData, len); - os_free(pSocketData->rxBuf); - pSocketData->rxBuf = pNewBuf; - pSocketData->rxBufLen += len; - } // End of new data allocated. - dumpEspConn(pEspconn); - os_printf("<< recvCB\n"); - -} - - -// ------------------------------------------------- - -/** - * \brief Define the implementation functions for the logical network functions. - */ -void netSetCallbacks_esp8266_board( - JsNetwork *net //!< The Network we are going to use. - ) { - net->idle = net_ESP8266_BOARD_idle; - net->checkError = net_ESP8266_BOARD_checkError; - net->createsocket = net_ESP8266_BOARD_createSocket; - net->closesocket = net_ESP8266_BOARD_closeSocket; - net->accept = net_ESP8266_BOARD_accept; - net->gethostbyname = net_ESP8266_BOARD_gethostbyname; - net->recv = net_ESP8266_BOARD_recv; - net->send = net_ESP8266_BOARD_send; -} - - -/** - * \brief Determine if there is a new client connection on the server socket. - * This function is called to poll to see if the serverSckt has a new - * accepted connection (socket) and, if it does, return it else return -1 to indicate - * that there was no new accepted socket. - */ -int net_ESP8266_BOARD_accept( - JsNetwork *net, //!< The Network we are going to use to create the socket. - int serverSckt //!< The socket that we are checking to see if there is a new client connection. - ) { - //os_printf("> net_ESP8266_BOARD_accept\n"); - struct socketData *pSocketData = getSocketData(serverSckt); - assert(pSocketData->state != SOCKET_STATE_UNUSED); - assert(pSocketData->creationType == SOCKET_CREATED_SERVER); - - // If the list is empty, return. - if (pSocketData->acceptedSocketsHead == pSocketData->acceptedSocketsTail) { - // Return -1 if there is no new client socket for this server. - return -1; - } - - // Return the 1st socket id that is in the list of accepted sockets. We also update the - // list to indicate that it has been read. - int acceptedSocketId = pSocketData->acceptedSockets[pSocketData->acceptedSocketsTail]; - pSocketData->acceptedSocketsTail = (pSocketData->acceptedSocketsTail + 1) % MAX_ACCEPTED_SOCKETS; - - os_printf("> net_ESP8266_BOARD_accept: Accepted a new socket, socketId=%d\n", acceptedSocketId); - return acceptedSocketId; -} - - -/** - * \brief Receive data from the network device. - * Returns the number of bytes received which may be 0 and -1 if there was an error. - */ -int net_ESP8266_BOARD_recv( - JsNetwork *net, //!< The Network we are going to use to create the socket. - int sckt, //!< The socket from which we are to receive data. - void *buf, //!< The storage buffer into which we will receive data. - size_t len //!< The length of the buffer. - ) { - struct socketData *pSocketData = getSocketData(sckt); - assert(pSocketData->state != SOCKET_STATE_UNUSED); - - // If there is no data in the receive buffer, then all we need do is return - // 0 bytes as the length of data moved. - if (pSocketData->rxBufLen == 0) { - if (pSocketData->state == SOCKET_STATE_CLOSING) { - return -1; - } - return 0; - } - - // If the receive buffer contains data and is it is able to fit in the buffer - // passed into us then we can copy all the data and the receive buffer will be clear. - if (pSocketData->rxBufLen <= len) { - memcpy(buf, pSocketData->rxBuf, pSocketData->rxBufLen); - int retLen = pSocketData->rxBufLen; - os_free(pSocketData->rxBuf); - pSocketData->rxBufLen = 0; - pSocketData->rxBuf = NULL; - return retLen; - } - - // If we are here, then we have more data in the receive buffer than is available - // to be returned in this request for data. So we have to copy the amount of data - // that is allowed to be returned and then strip that from the beginning of the - // receive buffer. - - // First we copy the data we are going to return. - memcpy(buf, pSocketData->rxBuf, len); - - // Next we allocate a new buffer and copy in the data we are not returning. - uint8 *pNewBuf = (uint8 *)os_malloc(pSocketData->rxBufLen-len); - memcpy(pNewBuf, pSocketData->rxBuf + len, pSocketData->rxBufLen-len); - - // Now we juggle pointers and release the original RX buffer now that we have a new - // one. It is likely that this algorithm can be significantly improved since there - // is a period of time where we might actuall have TWO copies of the data. - uint8 *pTemp = pSocketData->rxBuf; - pSocketData->rxBuf = pNewBuf; - pSocketData->rxBufLen = pSocketData->rxBufLen-len; - os_free(pTemp); - - return len; -} - - -/** - * \brief Send data to the partner. - * The return is the number of bytes actually transmitted which may also be - * 0 to indicate no bytes sent or -1 to indicate an error. For the ESP8266 implementation we - * will return 0 if the socket is not connected or we are in the `SOCKET_STATE_TRANSMITTING` - * state. - */ -int net_ESP8266_BOARD_send( - JsNetwork *net, //!< The Network we are going to use to create the socket. - int sckt, //!< The socket over which we will send data. - const void *buf, //!< The buffer containing the data to be sent. - size_t len //!< The length of data in the buffer to send. - ) { - os_printf("> net_ESP8266_BOARD_send: Request to send data to socket %d of size %d: ", sckt, len); - - struct socketData *pSocketData = getSocketData(sckt); - assert(pSocketData->state != SOCKET_STATE_UNUSED); - - // If we are not connected, then we can't currently send data. - if (pSocketData->isConnected == false) { - os_printf(" - Not connected\n"); - return 0; - } - - // If we are currently sending data, we can't send more. - if (pSocketData->state == SOCKET_STATE_TRANSMITTING) { - os_printf(" - Currently transmitting\n"); - return 0; - } - - // Log the content of the data we are sening. - esp8266_board_writeString(buf, len); - - os_printf("\n"); - - assert(pSocketData->state == SOCKET_STATE_IDLE); - - pSocketData->state = SOCKET_STATE_TRANSMITTING; - - // Copy the data that was passed to us to a private area. We do this because we must not - // assume that the data passed in will be available after this function returns. It may have - // been passed in on the stack. - assert(pSocketData->currentTx == NULL); - pSocketData->currentTx = (uint8_t *)os_malloc(len); - memcpy(pSocketData->currentTx, buf, len); - - // Send the data over the ESP8266 SDK. - int rc = espconn_send(pSocketData->pEspconn, pSocketData->currentTx, len); - if (rc < 0) { - setSocketInError(sckt, "espconn_send", rc); - os_free(pSocketData->currentTx); - pSocketData->currentTx = NULL; - return -1; - } - - esp8266_dumpSocket(sckt); - os_printf("< net_ESP8266_BOARD_send\n"); - return len; -} - - -/** - * \brief Perform idle processing. - * There is the possibility that we may wish to perform logic when we are idle. For the - * ESP8266 there is no specific idle network processing needed. - */ -void net_ESP8266_BOARD_idle( - JsNetwork *net //!< The Network we are part of. - ) { - // Don't echo here because it is called continuously - //os_printf("> net_ESP8266_BOARD_idle\n"); -} - - -/** - * \brief Check for errors. - * Returns true if there are NO errors. - */ -bool net_ESP8266_BOARD_checkError( - JsNetwork *net //!< The Network we are going to use to create the socket. - ) { - //os_printf("> net_ESP8266_BOARD_checkError\n"); - return true; -} - - -/** - * \brief Create a new socket. - * if `ipAddress == 0`, creates a server otherwise creates a client (and automatically connects). Returns >=0 on success. - */ -int net_ESP8266_BOARD_createSocket( - JsNetwork *net, //!< The Network we are going to use to create the socket. - uint32_t ipAddress, //!< The address of the partner of the socket or 0 if we are to be a server. - unsigned short port //!< The port number that the partner is listening upon. - ) { - os_printf("> net_ESP8266_BOARD_createSocket: host: %d.%d.%d.%d, port:%d \n", ((char *)(&ipAddress))[0], ((char *)(&ipAddress))[1], ((char *)(&ipAddress))[2], ((char *)(&ipAddress))[3], port); - - bool isServer = (ipAddress == 0); - - struct socketData *pSocketData = allocateNewSocket(); - if (pSocketData == NULL) { // No free socket - os_printf("< net_ESP8266_BOARD_createSocket: No free sockets\n"); - return -1; - } - - int newSocket = pSocketData->socketId; - pSocketData->pEspconn = (struct espconn *)os_malloc(sizeof(struct espconn)); - assert(pSocketData->pEspconn); - - struct espconn *pEspconn = pSocketData->pEspconn; - - pEspconn->type = ESPCONN_TCP; - pEspconn->state = ESPCONN_NONE; - pEspconn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp)); - pEspconn->reverse = pSocketData; - assert(pEspconn->proto.tcp != NULL); - os_memset(pEspconn->proto.tcp, 0, sizeof(esp_tcp)); - - // NOTE: We must not call these functions until AFTER we have allocated storage - // for the 'esp_tcp' structure. - espconn_regist_disconcb(pEspconn, esp8266_callback_disconnectCB); - espconn_regist_reconcb(pEspconn, esp8266_callback_reconnectCB); - espconn_regist_sentcb(pEspconn, esp8266_callback_sentCB); - espconn_regist_recvcb(pEspconn, esp8266_callback_recvCB); - espconn_regist_write_finish(pEspconn, esp8266_callback_writeFinishedCB); - - struct ip_info ipconfig; - wifi_get_ip_info(STATION_IF, &ipconfig); // Get the local IP address - os_memcpy(pEspconn->proto.tcp->local_ip, &ipconfig.ip, 4); - - // If we are not a server ... - if (isServer == false) { - pSocketData->state = SOCKET_STATE_CONNECTING; - pSocketData->creationType = SOCKET_CREATED_OUTBOUND; - pEspconn->proto.tcp->remote_port = port; - pEspconn->proto.tcp->local_port = espconn_port(); - - *(uint32 *)(pEspconn->proto.tcp->remote_ip) = ipAddress; - - // Ensure that we have flagged this socket as NOT connected - pSocketData->isConnected = false; - - espconn_regist_connectcb(pEspconn, esp8266_callback_connectCB_outbound); - - // Make a call to espconn_connect. - int rc = espconn_connect(pEspconn); - if (rc != 0) { - os_printf("Err: net_ESP8266_BOARD_createSocket -> espconn_connect returned: %d. Using local port: %d\n", rc, pEspconn->proto.tcp->local_port); - setSocketInError(newSocket, "espconn_connect", rc); - } - } - // If the ipAddress IS 0 ... then we are a server. - else - { - // We are going to set ourselves up as a server - pSocketData->state = SOCKET_STATE_IDLE; - pSocketData->creationType = SOCKET_CREATED_SERVER; - pEspconn->proto.tcp->local_port = port; - - espconn_regist_connectcb(pEspconn, esp8266_callback_connectCB_inbound); - - // Make a call to espconn_accept - int rc = espconn_accept(pEspconn); - if (rc != 0) { - os_printf("Err: net_ESP8266_BOARD_createSocket -> espconn_accept returned: %d. Using local port: %d\n", rc, pEspconn->proto.tcp->local_port); - setSocketInError(newSocket, "espconn_accept", rc); - } - } - - dumpEspConn(pEspconn); - os_printf("< net_ESP8266_BOARD_createSocket, socket=%d\n", newSocket); - return newSocket; -} - - -/** - * \brief Close a socket. - */ -void net_ESP8266_BOARD_closeSocket( - JsNetwork *net, //!< The Network we are going to use to create the socket. - int socketId //!< The socket to be closed. - ) { - os_printf("> net_ESP8266_BOARD_closeSocket, socket=%d\n", socketId); - - struct socketData *pSocketData = getSocketData(socketId); - - assert(pSocketData != NULL); - assert(pSocketData->state != SOCKET_STATE_UNUSED); // Shouldn't be closing an unused socket. - - dumpEspConn(pSocketData->pEspconn); - esp8266_dumpSocket(socketId); - - // How we close the socket is a function of what kind of socket it is. - if (pSocketData->creationType == SOCKET_CREATED_SERVER) { - int rc = espconn_delete(pSocketData->pEspconn); - if (rc != 0) { - os_printf("espconn_delete: rc=%d\n", rc); - } - } // End this is a server socket - else - { - if (pSocketData->state == SOCKET_STATE_IDLE || pSocketData->state == SOCKET_STATE_CLOSING) { - doClose(socketId); - } else { - pSocketData->shouldClose = true; - } - } // End this is a client socket -} - - -/** - * \brief Callback handler for espconn_gethostbyname. - * This is a function that will be called back by the ESP8266 when the resolution of - * a hostname has been completed. - */ -static void dnsFoundCallback(const char *hostName, ip_addr_t *ipAddr, void *arg) { - assert(arg != NULL); - - uint32_t *returnIp = (uint32_t *)arg; - - // ipAddr will be NULL if the IP address can not be resolved. - if (ipAddr == NULL) { - * returnIp = 0; - } else { - *returnIp = ipAddr->addr; - } -} - - -/** - * \brief Get an IP address from a name. - * Sets 'outIp' to 0 on failure and 0xFFFFFFFF on unknown. At some time later, the - * IP address will be properly updated. - */ -void net_ESP8266_BOARD_gethostbyname( - JsNetwork *net, //!< The Network we are going to use to create the socket. - char *hostName, //!< The string representing the hostname we wish to lookup. - uint32_t *outIp //!< The address into which the resolved IP address will be stored. - ) { - assert(hostName != NULL); - assert(outIp != NULL); - os_printf("> net_ESP8266_BOARD_gethostbyname: Resolving: %s\n", hostName); - int rc = espconn_gethostbyname((struct espconn *)outIp, hostName, (ip_addr_t *)outIp, dnsFoundCallback); - // A rc of ESPCONN_OK means that we have an IP and it was stored in outIp. - // A rc of ESPCONN_INPROGRESS means that we will get the IP on a callback. - if (rc == ESPCONN_INPROGRESS) { - *outIp = 0xFFFFFFFF; - } -} - - -// ---------------------------------------------------------------- - -/** - * The following section is all about a logical concept called a memoryBuffer. This is an - * abstract data type that contains data in memory. The operations we can perform upon it - * are: - - * o memoryBuffer_append - Append data to the end of the memory buffer. - * o memoryBuffer_read - Read a fixed number of bytes from the memory buffer. - * o memoryBuffer_delete - Delete the memory buffer. No further operations should be performed - * against it. - * o memoryBuffer_getSize - Get the size of data contained in the memory buffer. - */ - -/** - * \brief Delete all content of the memory buffer. - */ -static void memoryBuffer_delete( - struct memoryBuffer *pMemoryBuffer //!< - ) { - if (pMemoryBuffer->length > 0) { - os_free(pMemoryBuffer->buf); - pMemoryBuffer->buf = NULL; - pMemoryBuffer->length = 0; - } -} - - -/** - * \brief Append new data to the end of the existing memory buffer. - */ -static uint8 *memoryBuffer_append( - struct memoryBuffer *pMemoryBuffer, //!< - uint8 *pNewData, //!< - size_t length //!< - ) { - assert(pMemoryBuffer != NULL); - - if (length == 0) { - return pMemoryBuffer->buf; - } - - assert(pNewData != NULL); - - // Handle the memory buffer being empty. - if (pMemoryBuffer->length == 0) { - pMemoryBuffer->buf = (uint8 *)os_malloc(length); - if (pMemoryBuffer->buf == NULL) { // Out of memory - jsError("malloc failed at memoryBuffer_append trying to allocate %d", length); - } else { - memcpy(pMemoryBuffer->buf, pNewData, length); - pMemoryBuffer->length = length; - } - } else { - // The memory buffer was not empty, so we append data. - int newSize = pMemoryBuffer->length + length; - uint8 *resizedStorage = (uint8 *)os_realloc(pMemoryBuffer->buf, newSize); - if (resizedStorage != NULL) { - pMemoryBuffer->buf = resizedStorage; - memcpy(pMemoryBuffer->buf + length, pNewData, length); - pMemoryBuffer->length = newSize; - } - } - return pMemoryBuffer->buf; -} - - -/** - * \brief Return how much data is stored in the memory buffer. - */ -static int memoryBuffer_getSize( - struct memoryBuffer *pMemoryBuffer //!< - ) { - assert(pMemoryBuffer != NULL); - return pMemoryBuffer->length; -} - - -/** - * \brief Read data from the memory buffer of an exact size. - * The data that is returned - * should be released with an os_free() call. - */ -static uint8 *memoryBuffer_read( - struct memoryBuffer *pMemoryBuffer, //!< - size_t readSize //!< - ) { - assert(pMemoryBuffer != NULL); - assert((pMemoryBuffer->length > 0 && pMemoryBuffer->buf != NULL) || pMemoryBuffer->length == 0); - - // Check that we are NOT trying to read more data than we actually have available to us. - assert(readSize > pMemoryBuffer->length); - - // Handle the case where we are trying to read 0 bytes. - if (readSize == 0) { - return NULL; - } - - // If the size of data we are willing to read is EXACTLY the size of the buffer we - // have, then simply return a pointer to the buffer and we are done. - if (readSize == pMemoryBuffer->length) { - uint8 *pTemp = pMemoryBuffer->buf; - pMemoryBuffer->buf = NULL; - pMemoryBuffer->length = 0; - return pTemp; - } - - // We can assert that size < memory buffer length. - // - // Here we have determined that we wish to consume LESS data that we have available. - // That means we have to split our data into parts. - - // First we build the data that we will return and copy in the memory buffer data. - uint8 *pTemp = (uint8 *)os_malloc(readSize); - if (pTemp == NULL) { // Out of memory - jsError("malloc failed at memoryBuffer_append trying to allocate %d", readSize); - return NULL; - } - os_memcpy(pTemp, pMemoryBuffer->buf, readSize); - - // Now we create a memory buffer to hold the remaining data that was not - // returned. - int newSize = pMemoryBuffer->length - readSize; - uint8 *pTemp2 = (uint8 *)os_malloc(newSize); - os_memcpy(pTemp2, pMemoryBuffer->buf + readSize, newSize); - os_free(pMemoryBuffer->buf); - pMemoryBuffer->buf = pTemp2; - pMemoryBuffer->length = newSize; - return pTemp; -} +/* +5 * network_esp8266_board.c + + * + * Created on: Aug 29, 2015 + * Author: kolban + */ + +/** + * This file contains the implementation of the ESP8266_BOARD network interfaces at the TCP/IP + * level. + * + * Design notes + * ------------ + * We maintain an array of socketData structures. The number of such structures is defined in the + * MAX_SOCKETS define. The private variable that contains the array is called "socketArray". + * Each one of these array instances represents a possible socket structure that we can use. + * + * Each socket maintains state and the transitions are shown in a separate state diagram. In + * summary, the possible states are: + * + * * SOCKET_STATE_UNUSED + * * SOCKET_STATE_IDLE + * * SOCKET_STATE_CONNECTING + * * SOCKET_STATE_TRANSMITTING + * * SOCKET_STATE_CLOSING + * * SOCKET_STATE_HOST_RESOLVING + * * SOCKET_STATE_ERROR + * + * Each socket also maintains its creation purpose. There are three ways a socket + * can have been created: + * + * SOCKET_CREATED_SERVER - The socket was created as a server. + * SOCKET_CREATED_OUTBOUND - The socket was created by an out-bound. + * SOCKET_CREATED_INBOUND - The socket was created by an in-bound. + */ +// ESP8266 specific includes +#undef ESPSDK_1_3_0 +#include +#include +#include +#include +#include +#include + +#define _GCC_WRAP_STDINT_H +typedef long long int64_t; + +#include "network_esp8266.h" +#include "esp8266_board_utils.h" + +/** + * The maximum number of concurrently open sockets we support. + * We should probably pair this with the ESP8266 concept of the maximum number of sockets + * that an ESP8266 instance can also support. + */ +#define MAX_SOCKETS (10) + +#define LOG os_printf + +static struct socketData *getSocketData(int s); + +/** + * The next socketId to be used. + */ +static int g_nextSocketId = 0; + +static int getServerSocketByLocalPort(unsigned short port); +static void setSocketInError(int socketId, char *msg, int code); +static void dumpEspConn(struct espconn *pEspConn); +static struct socketData *allocateNewSocket(); +static void doClose(int socketId); +static void releaseSocket(int socketId); +static void resetSocketByData(struct socketData *pSocketData); +static void resetSocketById(int sckt); + +static void esp8266_callback_connectCB_inbound(void *arg); +static void esp8266_callback_connectCB_outbound(void *arg); +static void esp8266_callback_disconnectCB(void *arg); +static void esp8266_callback_sentCB(void *arg); +static void esp8266_callback_writeFinishedCB(void *arg); +static void esp8266_callback_recvCB(void *arg, char *pData, unsigned short len); +static void esp8266_callback_reconnectCB(void *arg, sint8 err); + +/** + * A data structure that represents a memory buffer. + * A memory buffer is an object that represents a sized piece of memory. Given a + * memory buffer object, we know how big it is and can set or get data from it. + */ +struct memoryBuffer { + /** + * The size of data associated with this buffer. + */ + size_t length; + + /** + * A pointer to the memory associated with this buffer. This should be + * NULL if `length` is 0. + */ + uint8 *buf; +}; + +static uint8 *memoryBuffer_read(struct memoryBuffer *pMemoryBuffer, size_t readSize); +static uint8 *memoryBuffer_append(struct memoryBuffer *pMemoryBuffer, uint8 *pNewData, size_t length); +static void memoryBuffer_delete(struct memoryBuffer *pMemoryBuffer); +static int memoryBuffer_getSize(struct memoryBuffer *pMemoryBuffer); + +/** + * The potential states for a socket. + * See the socket state diagram. + */ +enum SOCKET_STATE { + SOCKET_STATE_UNUSED, //!< The socket is unused + SOCKET_STATE_IDLE, //!< The socket is idle + SOCKET_STATE_CONNECTING, //!< The socket is connecting + SOCKET_STATE_TRANSMITTING, //!< The socket is transmitting + SOCKET_STATE_CLOSING, //!< The socket is closing + SOCKET_STATE_HOST_RESOLVING, //!< Resolving a a hostname + SOCKET_STATE_ERROR //!< The socket is in error +}; + +/** + * How was the socket created. + */ +enum SOCKET_CREATION_TYPE { + SOCKET_CREATED_NONE, //!< The socket has not yet been created. + SOCKET_CREATED_SERVER, //!< The socket was created as a server. + SOCKET_CREATED_OUTBOUND, //!< The socket was created outbound. + SOCKET_CREATED_INBOUND //!< The socket was created inbound. +}; + +/** + * Here are some notes on the accepted list algorithms. + * + * tail - Where old entries are removed + * head - Where new entries are added + * + * When tail = head - the list is empty + * + * When a new entry is added: + * error: mod(head+1) == tail // List full + * *head = new entry + * head = mod(head+1) + * + * When an old entry is removed + * error: tail == head // List empty + * retrieved entry = *tail + * tail = mod(tail+1) + * + * + * 0 1 2 3 4 5 6 7 8 + * [ ][ ][ ][ ][ ][ ][ ][ ][ ] + */ + +/** + * The maximum number of accepted sockets that can be remembered. + */ +#define MAX_ACCEPTED_SOCKETS (10) + +/** + * The core socket structure. + * The structure is initialized by resetSocket. + */ +struct socketData { + int socketId; //!< The id of THIS socket. + enum SOCKET_STATE state; //!< What is the socket state? + enum SOCKET_CREATION_TYPE creationType; //!< How was the socket created? + bool isConnected; //!< Is this socket connected? + bool shouldClose; //!< Should this socket close when it can? + + struct espconn *pEspconn; //!< The ESPConn structure. + + struct memoryBuffer txMemoryBuffer; //!< Data to be transmitted. + uint8 *currentTx; //!< Data currently being transmitted. + uint8 *rxBuf; //!< Data received (inbound). + size_t rxBufLen; //!< The length of data in the buffer ready for consumption. + + char *errorMsg; //!< Error message. + int errorCode; //!< Error code. + + /** + * A list of accepted sockets. + * This array contains the storage of a list of sockets that have been accepted by this + * server socket but have not yet been delivered to Espruino. A `head` and `tail` + * pair of indices are also associated. + */ + int acceptedSockets[MAX_ACCEPTED_SOCKETS]; + + /** + * The head of the list of accepted sockets. + * The index into `acceptedSockets` where the next accepted socket will be placed. + */ + uint8 acceptedSocketsHead; + + /** + * The tail of the list of accepted sockets. + * The index into `acceptedSockets` where the next accepted socket will be retrieved. + */ + uint8 acceptedSocketsTail; +}; + + +/** + * An array of socket data structures. + */ +static struct socketData socketArray[MAX_SOCKETS]; + + +/** + * Write the details of a socket to the debug log. + * The data associated with the socket is dumped to the debug log. + */ +void esp8266_dumpSocket( + int socketId //!< The ID of the socket data structure to be logged. + ) { + struct socketData *pSocketData = getSocketData(socketId); + LOG("Dump of socket=%d\n", socketId); + LOG(" - isConnected=%d", pSocketData->isConnected); + char *creationTypeMsg; + switch(pSocketData->creationType) { + case SOCKET_CREATED_NONE: + creationTypeMsg = "SOCKET_CREATED_NONE"; + break; + case SOCKET_CREATED_INBOUND: + creationTypeMsg = "SOCKET_CREATED_INBOUND"; + break; + case SOCKET_CREATED_OUTBOUND: + creationTypeMsg = "SOCKET_CREATED_OUTBOUND"; + break; + case SOCKET_CREATED_SERVER: + creationTypeMsg = "SOCKET_CREATED_SERVER"; + break; + } + LOG(", creationType=%s", creationTypeMsg); + LOG(", acceptedSockets=["); + int s=pSocketData->acceptedSocketsTail; + while(s != pSocketData->acceptedSocketsHead) { + LOG(" %d", pSocketData->acceptedSockets[s]); + s = (s+1)%MAX_ACCEPTED_SOCKETS; + } + LOG("]"); + LOG(", rxBufLen=%d", pSocketData->rxBufLen); + LOG(", tx length=%d", memoryBuffer_getSize(&(pSocketData->txMemoryBuffer))); + LOG(", currentTx=0x%d", (int)pSocketData->currentTx); + char *stateMsg; + switch(pSocketData->state) { + case SOCKET_STATE_CLOSING: + stateMsg = "SOCKET_STATE_CLOSING"; + break; + case SOCKET_STATE_CONNECTING: + stateMsg = "SOCKET_STATE_CONNECTING"; + break; + case SOCKET_STATE_ERROR: + stateMsg = "SOCKET_STATE_ERROR"; + break; + case SOCKET_STATE_IDLE: + stateMsg = "SOCKET_STATE_IDLE"; + break; + case SOCKET_STATE_TRANSMITTING: + stateMsg = "SOCKET_STATE_TRANSMITTING"; + break; + case SOCKET_STATE_HOST_RESOLVING: + stateMsg = "SOCKET_STATE_HOST_RESOLVING"; + break; + case SOCKET_STATE_UNUSED: + stateMsg = "SOCKET_STATE_UNUSED"; + break; + default: + stateMsg = "Unexpected state!!"; + break; + } + LOG(", state=%s", stateMsg); + LOG(", errorCode=%d", pSocketData->errorCode); + + // Print the errorMsg if it has anything to say + if (pSocketData->errorMsg != NULL && strlen(pSocketData->errorMsg) > 0) { + LOG(", errorMsg=\"%s\"", pSocketData->errorMsg); + } + + LOG("\n"); +} + + +/** + * Dump a struct espconn (for debugging purposes). + */ +static void dumpEspConn( + struct espconn *pEspConn //!< + ) { + char ipString[20]; + LOG("Dump of espconn: 0x%x\n", (int)pEspConn); + if (pEspConn == NULL) { + return; + } + switch(pEspConn->type) { + case ESPCONN_TCP: + LOG(" - type = TCP\n"); + LOG(" - local address = %d.%d.%d.%d [%d]\n", + pEspConn->proto.tcp->local_ip[0], + pEspConn->proto.tcp->local_ip[1], + pEspConn->proto.tcp->local_ip[2], + pEspConn->proto.tcp->local_ip[3], + pEspConn->proto.tcp->local_port); + LOG(" - remote address = %d.%d.%d.%d [%d]\n", + pEspConn->proto.tcp->remote_ip[0], + pEspConn->proto.tcp->remote_ip[1], + pEspConn->proto.tcp->remote_ip[2], + pEspConn->proto.tcp->remote_ip[3], + pEspConn->proto.tcp->remote_port); + break; + case ESPCONN_UDP: + LOG(" - type = UDP\n"); + LOG(" - local_port = %d\n", pEspConn->proto.udp->local_port); + LOG(" - local_ip = %d.%d.%d.%d\n", + pEspConn->proto.tcp->local_ip[0], + pEspConn->proto.tcp->local_ip[1], + pEspConn->proto.tcp->local_ip[2], + pEspConn->proto.tcp->local_ip[3]); + LOG(" - remote_port = %d\n", pEspConn->proto.udp->remote_port); + LOG(" - remote_ip = %d.%d.%d.%d\n", + pEspConn->proto.tcp->remote_ip[0], + pEspConn->proto.tcp->remote_ip[1], + pEspConn->proto.tcp->remote_ip[2], + pEspConn->proto.tcp->remote_ip[3]); + break; + default: + LOG(" - type = Unknown!! 0x%x\n", pEspConn->type); + } + switch(pEspConn->state) { + case ESPCONN_NONE: + LOG(" - state=NONE"); + break; + case ESPCONN_WAIT: + LOG(" - state=WAIT"); + break; + case ESPCONN_LISTEN: + LOG(" - state=LISTEN"); + break; + case ESPCONN_CONNECT: + LOG(" - state=CONNECT"); + break; + case ESPCONN_WRITE: + LOG(" - state=WRITE"); + break; + case ESPCONN_READ: + LOG(" - state=READ"); + break; + case ESPCONN_CLOSE: + LOG(" - state=CLOSE"); + break; + default: + LOG(" - state=unknown!!"); + break; + } + LOG(", link_cnt=%d", pEspConn->link_cnt); + LOG(", reverse=0x%x\n", (unsigned int)pEspConn->reverse); +} + + +/** + * Get the next new global socket id. + * \return A new socketId that is assured to be unique. + */ +static int getNextGlobalSocketId() { + int ret = g_nextSocketId; + g_nextSocketId++; + return ret; +} + + +/** + * Allocate a new socket + * Look for the first free socket in the array of sockets and return the first one + * that is available. The socketId property is set to a unique and new socketId value + * that will not previously have been seen. + * \return The socketData structure for the returned socket. + */ +static struct socketData *allocateNewSocket() { + // Walk through each of the sockets in the array of possible sockets and stop + // at the first one that is flagged as not in use. For that socket, set its + // socketId to the next global socketId value. + int i; + for (i=0; isocketId == socketId) { + return pSocketData; + } + pSocketData++; + } + return NULL; +} + + +/** + * Find the server socket that is bound to the given local port. + * \return The socket id of the socket listening on the given port or -1 if there is no + * server socket that matches. + */ +static int getServerSocketByLocalPort( + unsigned short port //!< The port number on which a server socket is listening. + ) { + // Loop through each of the sockets in the socket array looking for a socket + // that is inuse, a server and has a local_port of the passed in port number. + int socketArrayIndex; + struct socketData *pSocketData = socketArray; + for (socketArrayIndex=0; socketArrayIndexstate != SOCKET_STATE_UNUSED && + pSocketData->creationType == SOCKET_CREATED_SERVER && + pSocketData->pEspconn->proto.tcp->local_port == port) + { + return pSocketData->socketId; + } + pSocketData++; + } // End of for each socket + return -1; +} + + +/** + * Reset the socket to its clean and unused state. + * The socket is found by its socket id. + */ +static void resetSocketById( + int sckt //!< The socket id to be reset. + ) { + struct socketData *pSocketData = getSocketData(sckt); + resetSocketByData(pSocketData); +} + +/** + * Reset the socket to its clean and unused state. + * The socket is specified by its socket data pointer. + */ +static void resetSocketByData( + struct socketData *pSocketData //!< The data pointer to the socket. + ) { + assert(pSocketData != NULL); + + memoryBuffer_delete(&pSocketData->txMemoryBuffer); + + pSocketData->pEspconn = NULL; + pSocketData->state = SOCKET_STATE_UNUSED; + pSocketData->rxBuf = NULL; + pSocketData->rxBufLen = 0; + pSocketData->creationType = SOCKET_CREATED_NONE; + pSocketData->isConnected = false; + pSocketData->shouldClose = false; + pSocketData->errorMsg = ""; + pSocketData->errorCode = 0; + pSocketData->socketId = -1; + + pSocketData->acceptedSocketsHead = 0; // Set the head to 0 + pSocketData->acceptedSocketsTail = 0; // Set the tail to 9. + pSocketData->pEspconn = NULL; +} + + +/** + * Release the socket and return it to the free pool. + */ +static void releaseSocket( + int socketId //!< The socket id of the socket to be released. + ) { + os_printf("> releaseSocket: %d\n", socketId); + esp8266_dumpSocket(socketId); + + struct socketData *pSocketData = getSocketData(socketId); + assert(pSocketData->state != SOCKET_STATE_UNUSED); + + if (memoryBuffer_getSize(&pSocketData->txMemoryBuffer) > 0) { + os_printf(" - Oh oh ... attempt to close socket while the TX memoryBuffer is not empty!\n"); + } + if (pSocketData->rxBuf != NULL || pSocketData->rxBufLen != 0) { + os_printf(" - Oh oh ... attempt to close socket while the rxBuffer is not empty!\n"); + } + + // If this socket is not an incoming socket that means that the espconn structure was created + // by us and we should release the storage we allocated. + if (pSocketData->creationType != SOCKET_CREATED_INBOUND) { + os_free(pSocketData->pEspconn->proto.tcp); + pSocketData->pEspconn->proto.tcp = NULL; + os_free(pSocketData->pEspconn); + pSocketData->pEspconn = NULL; + } + resetSocketByData(pSocketData); + os_printf("< releaseSocket\n"); +} + + +/** + * Initialize the ESP8266_BOARD environment. + * Walk through each of the sockets and initialize each one. + */ +void netInit_esp8266_board() { + int socketArrayIndex; + struct socketData *pSocketData = socketArray; + for (socketArrayIndex=0; socketArrayIndexstate != SOCKET_STATE_CLOSING) { + int rc = espconn_disconnect(pSocketData->pEspconn); + pSocketData->state = SOCKET_STATE_CLOSING; + + if (rc != 0) { + os_printf("espconn_disconnect: rc=%d\n", rc); + setSocketInError(socketId, "espconn_disconnect", rc); + } + } + // Our existing state on entry was SOCKET_STATE_CLOSING which means that we got here + // because we were previously flagged as closing. + else { + releaseSocket(socketId); + } +} + + +/** + * Set the given socket as being in error supplying a message and a code. + * The socket state is placed in `SOCKET_STATE_ERROR`. + */ +static void setSocketInError( + int socketId, //!< The socket id that is being flagged as in error. + char *msg, //!< A message to associate with the error. + int code //!< A low level error code. + ) { + struct socketData *pSocketData = getSocketData(socketId); + pSocketData->state = SOCKET_STATE_ERROR; + pSocketData->errorMsg = msg; + pSocketData->errorCode = code; +} + +/** + * Callback function registered to the ESP8266 environment that is + * invoked when a new inbound connection has been formed. + * A new connection + * can occur when the ESP8266 makes a call out to a partner (in that + * case the ESP8266 is acting as a client) or a new connection can + * occur when a partner calls into a listening ESP8266. In that case + * the ESP8266 is acting as a server. + */ +static void esp8266_callback_connectCB_inbound( + void *arg //!< + ) { + os_printf(">> connectCB_inbound\n"); + struct espconn *pEspconn = (struct espconn *)arg; + assert(pEspconn != NULL); + + espconn_regist_disconcb(pEspconn, esp8266_callback_disconnectCB); + espconn_regist_reconcb(pEspconn, esp8266_callback_reconnectCB); + espconn_regist_sentcb(pEspconn, esp8266_callback_sentCB); + espconn_regist_recvcb(pEspconn, esp8266_callback_recvCB); + espconn_regist_write_finish(pEspconn, esp8266_callback_writeFinishedCB); + + dumpEspConn(pEspconn); + + int inboundSocket = getServerSocketByLocalPort(pEspconn->proto.tcp->local_port); + assert(inboundSocket != -1); + struct socketData *pSocketData = getSocketData(inboundSocket); + assert(pSocketData != NULL); + + esp8266_dumpSocket(pSocketData->socketId); + + os_printf("** new client has connected to us **\n"); + + if ((pSocketData->acceptedSocketsHead + 1) % MAX_ACCEPTED_SOCKETS == pSocketData->acceptedSocketsTail) { + os_printf("WARNING!! - Discarding inbound client because we have too many accepted clients.\n"); + os_printf("<< connectCB_inbound\n"); + return; + } + + struct socketData *pClientSocketData = allocateNewSocket(); + if (pClientSocketData == NULL) { + os_printf("!!! Ran out of sockets !!!\n"); + return; + } + assert(pClientSocketData != NULL); + pClientSocketData->pEspconn = pEspconn; + pClientSocketData->pEspconn->reverse = pClientSocketData; + pClientSocketData->creationType = SOCKET_CREATED_INBOUND; + pClientSocketData->isConnected = true; + pClientSocketData->state = SOCKET_STATE_IDLE; + + pSocketData->acceptedSockets[pSocketData->acceptedSocketsHead] = pClientSocketData->socketId; + pSocketData->acceptedSocketsHead = (pSocketData->acceptedSocketsHead + 1) % MAX_ACCEPTED_SOCKETS; + + os_printf("<< connectCB_inbound\n"); +} + +/** + * Callback function registered to the ESP8266 environment that is + * invoked when a new outbound connection has been formed. + */ +static void esp8266_callback_connectCB_outbound( + void *arg //!< A pointer to a `struct espconn`. + ) { + os_printf(">> connectCB_outbound\n"); + struct espconn *pEspconn = (struct espconn *)arg; + assert(pEspconn != NULL); + + dumpEspConn(pEspconn); + + struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; + assert(pSocketData != NULL); + + esp8266_dumpSocket(pSocketData->socketId); + + // Flag the socket as connected to a partner. + pSocketData->isConnected = true; + + assert(pSocketData->state == SOCKET_STATE_CONNECTING); + if (pSocketData->shouldClose) { + doClose(pSocketData->socketId); + } else { + pSocketData->state = SOCKET_STATE_IDLE; + } + os_printf("<< connectCB_outbound\n"); +} + + +/** + * Callback function registered to the ESP8266 environment that is + * Invoked when a previous connection has been disconnected. + */ +static void esp8266_callback_disconnectCB( + void *arg //!< A pointer to a `struct espconn`. + ) { + struct espconn *pEspconn = (struct espconn *)arg; + struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; + assert(pSocketData != NULL); + assert(pSocketData->state != SOCKET_STATE_UNUSED); + + os_printf(">> disconnectCB\n"); + dumpEspConn(pEspconn); + esp8266_dumpSocket(pSocketData->socketId); + + // If the socket state is SOCKET_STATE_CLOSING then that means we can release the socket. The reason + // for this is that the last thing the user did was request an explicit socket close. + if (pSocketData->state == SOCKET_STATE_CLOSING) { + releaseSocket(pSocketData->socketId); + } else { + pSocketData->state = SOCKET_STATE_CLOSING; + pSocketData->isConnected = false; + } + os_printf("<< disconnectCB\n"); +} + + +/** + * + */ +static void esp8266_callback_writeFinishedCB( + void *arg //!< A pointer to a `struct espconn`. + ) { + os_printf(">> writeFinishedCB\n"); + struct espconn *pEspconn = (struct espconn *)arg; + struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; + if (pSocketData->currentTx != NULL) { + os_free(pSocketData->currentTx); + pSocketData->currentTx = NULL; + } + os_printf("<< writeFinishedCB\n"); +} + + +/** + * Error handler callback. + * Although this is called reconnect by Espressif, this is really an error handler + * routine. It will be called when an error is detected. + */ +static void esp8266_callback_reconnectCB( + void *arg, //!< A pointer to a `struct espconn`. + sint8 err //!< The error code. + ) { + os_printf(">> reconnectCB: Error code is: %d - %s\n", err, esp8266_errorToString(err)); + os_printf("<< reconnectCB"); +} + + +/** + * Callback function registered to the ESP8266 environment that is + * invoked when a send operation has been completed. + */ +static void esp8266_callback_sentCB( + void *arg //!< A pointer to a `struct espconn`. + ) { + os_printf(">> sendCB\n"); + struct espconn *pEspconn = (struct espconn *)arg; + struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; + + assert(pSocketData != NULL); + assert(pSocketData->state == SOCKET_STATE_TRANSMITTING); + + // We have transmitted the data ... which means that the data that was in the transmission + // buffer can be released. + if (pSocketData->currentTx != NULL) { + os_free(pSocketData->currentTx); + pSocketData->currentTx = NULL; + } + + if (pSocketData->shouldClose) { + doClose(pSocketData->socketId); + } else { + pSocketData->state = SOCKET_STATE_IDLE; + } + os_printf("<< sendCB\n"); +} + + +/** + * ESP8266 callback function that is invoked when new data has arrived over + * the TCP/IP connection. + */ +static void esp8266_callback_recvCB( + void *arg, //!< A pointer to a `struct espconn`. + char *pData, //!< A pointer to data received over the socket. + unsigned short len //!< The length of the data. + ) { + struct espconn *pEspconn = (struct espconn *)arg; + struct socketData *pSocketData = (struct socketData *)pEspconn->reverse; + + assert(pSocketData != NULL); + assert(pSocketData->state != SOCKET_STATE_UNUSED); + + os_printf(">> recvCB for socket=%d, length=%d\n", pSocketData->socketId, len); + + // If we don't have any existing unconsumed data then malloc some storage and + // copy the received data into that storage. + if (pSocketData->rxBufLen == 0) { + pSocketData->rxBuf = (void *)os_malloc(len); + memcpy(pSocketData->rxBuf, pData, len); + pSocketData->rxBufLen = len; + } else { +// Allocate a new buffer big enough for the original data and the new data +// Copy the original data to the start of the new buffer ... +// Copy the new new data to the offset into the new buffer just after +// the original data. +// Release the original data. +// Update the socket data. + uint8 *pNewBuf = (uint8 *)os_malloc(len + pSocketData->rxBufLen); + memcpy(pNewBuf, pSocketData->rxBuf, pSocketData->rxBufLen); + memcpy(pNewBuf + pSocketData->rxBufLen, pData, len); + os_free(pSocketData->rxBuf); + pSocketData->rxBuf = pNewBuf; + pSocketData->rxBufLen += len; + } // End of new data allocated. + dumpEspConn(pEspconn); + os_printf("<< recvCB\n"); + +} + + +// ------------------------------------------------- + +/** + * Define the implementation functions for the logical network functions. + */ +void netSetCallbacks_esp8266_board( + JsNetwork *net //!< The Network we are going to use. + ) { + net->idle = net_ESP8266_BOARD_idle; + net->checkError = net_ESP8266_BOARD_checkError; + net->createsocket = net_ESP8266_BOARD_createSocket; + net->closesocket = net_ESP8266_BOARD_closeSocket; + net->accept = net_ESP8266_BOARD_accept; + net->gethostbyname = net_ESP8266_BOARD_gethostbyname; + net->recv = net_ESP8266_BOARD_recv; + net->send = net_ESP8266_BOARD_send; +} + + +/** + * Determine if there is a new client connection on the server socket. + * This function is called to poll to see if the serverSckt has a new + * accepted connection (socket) and, if it does, return it else return -1 to indicate + * that there was no new accepted socket. + */ +int net_ESP8266_BOARD_accept( + JsNetwork *net, //!< The Network we are going to use to create the socket. + int serverSckt //!< The socket that we are checking to see if there is a new client connection. + ) { + //os_printf("> net_ESP8266_BOARD_accept\n"); + struct socketData *pSocketData = getSocketData(serverSckt); + assert(pSocketData->state != SOCKET_STATE_UNUSED); + assert(pSocketData->creationType == SOCKET_CREATED_SERVER); + + // If the list is empty, return. + if (pSocketData->acceptedSocketsHead == pSocketData->acceptedSocketsTail) { + // Return -1 if there is no new client socket for this server. + return -1; + } + + // Return the 1st socket id that is in the list of accepted sockets. We also update the + // list to indicate that it has been read. + int acceptedSocketId = pSocketData->acceptedSockets[pSocketData->acceptedSocketsTail]; + pSocketData->acceptedSocketsTail = (pSocketData->acceptedSocketsTail + 1) % MAX_ACCEPTED_SOCKETS; + + os_printf("> net_ESP8266_BOARD_accept: Accepted a new socket, socketId=%d\n", acceptedSocketId); + return acceptedSocketId; +} + + +/** + * Receive data from the network device. + * Returns the number of bytes received which may be 0 and -1 if there was an error. + */ +int net_ESP8266_BOARD_recv( + JsNetwork *net, //!< The Network we are going to use to create the socket. + int sckt, //!< The socket from which we are to receive data. + void *buf, //!< The storage buffer into which we will receive data. + size_t len //!< The length of the buffer. + ) { + struct socketData *pSocketData = getSocketData(sckt); + assert(pSocketData->state != SOCKET_STATE_UNUSED); + + // If there is no data in the receive buffer, then all we need do is return + // 0 bytes as the length of data moved. + if (pSocketData->rxBufLen == 0) { + if (pSocketData->state == SOCKET_STATE_CLOSING) { + return -1; + } + return 0; + } + + // If the receive buffer contains data and is it is able to fit in the buffer + // passed into us then we can copy all the data and the receive buffer will be clear. + if (pSocketData->rxBufLen <= len) { + memcpy(buf, pSocketData->rxBuf, pSocketData->rxBufLen); + int retLen = pSocketData->rxBufLen; + os_free(pSocketData->rxBuf); + pSocketData->rxBufLen = 0; + pSocketData->rxBuf = NULL; + return retLen; + } + + // If we are here, then we have more data in the receive buffer than is available + // to be returned in this request for data. So we have to copy the amount of data + // that is allowed to be returned and then strip that from the beginning of the + // receive buffer. + + // First we copy the data we are going to return. + memcpy(buf, pSocketData->rxBuf, len); + + // Next we allocate a new buffer and copy in the data we are not returning. + uint8 *pNewBuf = (uint8 *)os_malloc(pSocketData->rxBufLen-len); + memcpy(pNewBuf, pSocketData->rxBuf + len, pSocketData->rxBufLen-len); + + // Now we juggle pointers and release the original RX buffer now that we have a new + // one. It is likely that this algorithm can be significantly improved since there + // is a period of time where we might actuall have TWO copies of the data. + uint8 *pTemp = pSocketData->rxBuf; + pSocketData->rxBuf = pNewBuf; + pSocketData->rxBufLen = pSocketData->rxBufLen-len; + os_free(pTemp); + + return len; +} + + +/** + * Send data to the partner. + * The return is the number of bytes actually transmitted which may also be + * 0 to indicate no bytes sent or -1 to indicate an error. For the ESP8266 implementation we + * will return 0 if the socket is not connected or we are in the `SOCKET_STATE_TRANSMITTING` + * state. + */ +int net_ESP8266_BOARD_send( + JsNetwork *net, //!< The Network we are going to use to create the socket. + int sckt, //!< The socket over which we will send data. + const void *buf, //!< The buffer containing the data to be sent. + size_t len //!< The length of data in the buffer to send. + ) { + os_printf("> net_ESP8266_BOARD_send: Request to send data to socket %d of size %d: ", sckt, len); + + struct socketData *pSocketData = getSocketData(sckt); + assert(pSocketData->state != SOCKET_STATE_UNUSED); + + // If we are not connected, then we can't currently send data. + if (pSocketData->isConnected == false) { + os_printf(" - Not connected\n"); + return 0; + } + + // If we are currently sending data, we can't send more. + if (pSocketData->state == SOCKET_STATE_TRANSMITTING) { + os_printf(" - Currently transmitting\n"); + return 0; + } + + // Log the content of the data we are sening. + esp8266_board_writeString(buf, len); + + os_printf("\n"); + + assert(pSocketData->state == SOCKET_STATE_IDLE); + + pSocketData->state = SOCKET_STATE_TRANSMITTING; + + // Copy the data that was passed to us to a private area. We do this because we must not + // assume that the data passed in will be available after this function returns. It may have + // been passed in on the stack. + assert(pSocketData->currentTx == NULL); + pSocketData->currentTx = (uint8_t *)os_malloc(len); + memcpy(pSocketData->currentTx, buf, len); + + // Send the data over the ESP8266 SDK. + int rc = espconn_send(pSocketData->pEspconn, pSocketData->currentTx, len); + if (rc < 0) { + setSocketInError(sckt, "espconn_send", rc); + os_free(pSocketData->currentTx); + pSocketData->currentTx = NULL; + return -1; + } + + esp8266_dumpSocket(sckt); + os_printf("< net_ESP8266_BOARD_send\n"); + return len; +} + + +/** + * Perform idle processing. + * There is the possibility that we may wish to perform logic when we are idle. For the + * ESP8266 there is no specific idle network processing needed. + */ +void net_ESP8266_BOARD_idle( + JsNetwork *net //!< The Network we are part of. + ) { + // Don't echo here because it is called continuously + //os_printf("> net_ESP8266_BOARD_idle\n"); +} + + +/** + * Check for errors. + * Returns true if there are NO errors. + */ +bool net_ESP8266_BOARD_checkError( + JsNetwork *net //!< The Network we are going to use to create the socket. + ) { + //os_printf("> net_ESP8266_BOARD_checkError\n"); + return true; +} + + +/** + * Create a new socket. + * if `ipAddress == 0`, creates a server otherwise creates a client (and automatically connects). Returns >=0 on success. + */ +int net_ESP8266_BOARD_createSocket( + JsNetwork *net, //!< The Network we are going to use to create the socket. + uint32_t ipAddress, //!< The address of the partner of the socket or 0 if we are to be a server. + unsigned short port //!< The port number that the partner is listening upon. + ) { + os_printf("> net_ESP8266_BOARD_createSocket: host: %d.%d.%d.%d, port:%d \n", ((char *)(&ipAddress))[0], ((char *)(&ipAddress))[1], ((char *)(&ipAddress))[2], ((char *)(&ipAddress))[3], port); + + bool isServer = (ipAddress == 0); + + struct socketData *pSocketData = allocateNewSocket(); + if (pSocketData == NULL) { // No free socket + os_printf("< net_ESP8266_BOARD_createSocket: No free sockets\n"); + return -1; + } + + int newSocket = pSocketData->socketId; + pSocketData->pEspconn = (struct espconn *)os_malloc(sizeof(struct espconn)); + assert(pSocketData->pEspconn); + + struct espconn *pEspconn = pSocketData->pEspconn; + + pEspconn->type = ESPCONN_TCP; + pEspconn->state = ESPCONN_NONE; + pEspconn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp)); + pEspconn->reverse = pSocketData; + assert(pEspconn->proto.tcp != NULL); + os_memset(pEspconn->proto.tcp, 0, sizeof(esp_tcp)); + + // NOTE: We must not call these functions until AFTER we have allocated storage + // for the 'esp_tcp' structure. + espconn_regist_disconcb(pEspconn, esp8266_callback_disconnectCB); + espconn_regist_reconcb(pEspconn, esp8266_callback_reconnectCB); + espconn_regist_sentcb(pEspconn, esp8266_callback_sentCB); + espconn_regist_recvcb(pEspconn, esp8266_callback_recvCB); + espconn_regist_write_finish(pEspconn, esp8266_callback_writeFinishedCB); + + struct ip_info ipconfig; + wifi_get_ip_info(STATION_IF, &ipconfig); // Get the local IP address + os_memcpy(pEspconn->proto.tcp->local_ip, &ipconfig.ip, 4); + + // If we are not a server ... + if (isServer == false) { + pSocketData->state = SOCKET_STATE_CONNECTING; + pSocketData->creationType = SOCKET_CREATED_OUTBOUND; + pEspconn->proto.tcp->remote_port = port; + pEspconn->proto.tcp->local_port = espconn_port(); + + *(uint32 *)(pEspconn->proto.tcp->remote_ip) = ipAddress; + + // Ensure that we have flagged this socket as NOT connected + pSocketData->isConnected = false; + + espconn_regist_connectcb(pEspconn, esp8266_callback_connectCB_outbound); + + // Make a call to espconn_connect. + int rc = espconn_connect(pEspconn); + if (rc != 0) { + os_printf("Err: net_ESP8266_BOARD_createSocket -> espconn_connect returned: %d. Using local port: %d\n", rc, pEspconn->proto.tcp->local_port); + setSocketInError(newSocket, "espconn_connect", rc); + } + } + // If the ipAddress IS 0 ... then we are a server. + else + { + // We are going to set ourselves up as a server + pSocketData->state = SOCKET_STATE_IDLE; + pSocketData->creationType = SOCKET_CREATED_SERVER; + pEspconn->proto.tcp->local_port = port; + + espconn_regist_connectcb(pEspconn, esp8266_callback_connectCB_inbound); + + // Make a call to espconn_accept + int rc = espconn_accept(pEspconn); + if (rc != 0) { + os_printf("Err: net_ESP8266_BOARD_createSocket -> espconn_accept returned: %d. Using local port: %d\n", rc, pEspconn->proto.tcp->local_port); + setSocketInError(newSocket, "espconn_accept", rc); + } + } + + dumpEspConn(pEspconn); + os_printf("< net_ESP8266_BOARD_createSocket, socket=%d\n", newSocket); + return newSocket; +} + + +/** + * Close a socket. + */ +void net_ESP8266_BOARD_closeSocket( + JsNetwork *net, //!< The Network we are going to use to create the socket. + int socketId //!< The socket to be closed. + ) { + os_printf("> net_ESP8266_BOARD_closeSocket, socket=%d\n", socketId); + + struct socketData *pSocketData = getSocketData(socketId); + + assert(pSocketData != NULL); + assert(pSocketData->state != SOCKET_STATE_UNUSED); // Shouldn't be closing an unused socket. + + dumpEspConn(pSocketData->pEspconn); + esp8266_dumpSocket(socketId); + + // How we close the socket is a function of what kind of socket it is. + if (pSocketData->creationType == SOCKET_CREATED_SERVER) { + int rc = espconn_delete(pSocketData->pEspconn); + if (rc != 0) { + os_printf("espconn_delete: rc=%d\n", rc); + } + } // End this is a server socket + else + { + if (pSocketData->state == SOCKET_STATE_IDLE || pSocketData->state == SOCKET_STATE_CLOSING) { + doClose(socketId); + } else { + pSocketData->shouldClose = true; + } + } // End this is a client socket +} + + +/** + * Callback handler for espconn_gethostbyname. + * This is a function that will be called back by the ESP8266 when the resolution of + * a hostname has been completed. + */ +static void dnsFoundCallback(const char *hostName, ip_addr_t *ipAddr, void *arg) { + assert(arg != NULL); + + uint32_t *returnIp = (uint32_t *)arg; + + // ipAddr will be NULL if the IP address can not be resolved. + if (ipAddr == NULL) { + * returnIp = 0; + } else { + *returnIp = ipAddr->addr; + } +} + + +/** + * Get an IP address from a name. + * Sets 'outIp' to 0 on failure and 0xFFFFFFFF on unknown. At some time later, the + * IP address will be properly updated. + */ +void net_ESP8266_BOARD_gethostbyname( + JsNetwork *net, //!< The Network we are going to use to create the socket. + char *hostName, //!< The string representing the hostname we wish to lookup. + uint32_t *outIp //!< The address into which the resolved IP address will be stored. + ) { + assert(hostName != NULL); + assert(outIp != NULL); + os_printf("> net_ESP8266_BOARD_gethostbyname: Resolving: %s\n", hostName); + int rc = espconn_gethostbyname((struct espconn *)outIp, hostName, (ip_addr_t *)outIp, dnsFoundCallback); + // A rc of ESPCONN_OK means that we have an IP and it was stored in outIp. + // A rc of ESPCONN_INPROGRESS means that we will get the IP on a callback. + if (rc == ESPCONN_INPROGRESS) { + *outIp = 0xFFFFFFFF; + } +} + + +// ---------------------------------------------------------------- + +/** + * The following section is all about a logical concept called a memoryBuffer. This is an + * abstract data type that contains data in memory. The operations we can perform upon it + * are: + + * o memoryBuffer_append - Append data to the end of the memory buffer. + * o memoryBuffer_read - Read a fixed number of bytes from the memory buffer. + * o memoryBuffer_delete - Delete the memory buffer. No further operations should be performed + * against it. + * o memoryBuffer_getSize - Get the size of data contained in the memory buffer. + */ + +/** + * Delete all content of the memory buffer. + */ +static void memoryBuffer_delete( + struct memoryBuffer *pMemoryBuffer //!< + ) { + if (pMemoryBuffer->length > 0) { + os_free(pMemoryBuffer->buf); + pMemoryBuffer->buf = NULL; + pMemoryBuffer->length = 0; + } +} + + +/** + * Append new data to the end of the existing memory buffer. + */ +static uint8 *memoryBuffer_append( + struct memoryBuffer *pMemoryBuffer, //!< + uint8 *pNewData, //!< + size_t length //!< + ) { + assert(pMemoryBuffer != NULL); + + if (length == 0) { + return pMemoryBuffer->buf; + } + + assert(pNewData != NULL); + + // Handle the memory buffer being empty. + if (pMemoryBuffer->length == 0) { + pMemoryBuffer->buf = (uint8 *)os_malloc(length); + if (pMemoryBuffer->buf == NULL) { // Out of memory + jsError("malloc failed at memoryBuffer_append trying to allocate %d", length); + } else { + memcpy(pMemoryBuffer->buf, pNewData, length); + pMemoryBuffer->length = length; + } + } else { + // The memory buffer was not empty, so we append data. + int newSize = pMemoryBuffer->length + length; + uint8 *resizedStorage = (uint8 *)os_realloc(pMemoryBuffer->buf, newSize); + if (resizedStorage != NULL) { + pMemoryBuffer->buf = resizedStorage; + memcpy(pMemoryBuffer->buf + length, pNewData, length); + pMemoryBuffer->length = newSize; + } + } + return pMemoryBuffer->buf; +} + + +/** + * Return how much data is stored in the memory buffer. + */ +static int memoryBuffer_getSize( + struct memoryBuffer *pMemoryBuffer //!< + ) { + assert(pMemoryBuffer != NULL); + return pMemoryBuffer->length; +} + + +/** + * Read data from the memory buffer of an exact size. + * The data that is returned + * should be released with an os_free() call. + */ +static uint8 *memoryBuffer_read( + struct memoryBuffer *pMemoryBuffer, //!< + size_t readSize //!< + ) { + assert(pMemoryBuffer != NULL); + assert((pMemoryBuffer->length > 0 && pMemoryBuffer->buf != NULL) || pMemoryBuffer->length == 0); + + // Check that we are NOT trying to read more data than we actually have available to us. + assert(readSize > pMemoryBuffer->length); + + // Handle the case where we are trying to read 0 bytes. + if (readSize == 0) { + return NULL; + } + + // If the size of data we are willing to read is EXACTLY the size of the buffer we + // have, then simply return a pointer to the buffer and we are done. + if (readSize == pMemoryBuffer->length) { + uint8 *pTemp = pMemoryBuffer->buf; + pMemoryBuffer->buf = NULL; + pMemoryBuffer->length = 0; + return pTemp; + } + + // We can assert that size < memory buffer length. + // + // Here we have determined that we wish to consume LESS data that we have available. + // That means we have to split our data into parts. + + // First we build the data that we will return and copy in the memory buffer data. + uint8 *pTemp = (uint8 *)os_malloc(readSize); + if (pTemp == NULL) { // Out of memory + jsError("malloc failed at memoryBuffer_append trying to allocate %d", readSize); + return NULL; + } + os_memcpy(pTemp, pMemoryBuffer->buf, readSize); + + // Now we create a memory buffer to hold the remaining data that was not + // returned. + int newSize = pMemoryBuffer->length - readSize; + uint8 *pTemp2 = (uint8 *)os_malloc(newSize); + os_memcpy(pTemp2, pMemoryBuffer->buf + readSize, newSize); + os_free(pMemoryBuffer->buf); + pMemoryBuffer->buf = pTemp2; + pMemoryBuffer->length = newSize; + return pTemp; +} diff --git a/libs/network/network.c b/libs/network/network.c index 5e700fde1..c51de50e0 100644 --- a/libs/network/network.c +++ b/libs/network/network.c @@ -117,7 +117,7 @@ unsigned long networkFlipIPAddress(unsigned long addr) { } /** - * \brief Get the IP address of a hostname. + * Get the IP address of a hostname. * Retrieve the IP address of a hostname and return it in the address of the * ip address passed in. If the hostname is as dotted decimal string, we will * decode that immediately otherwise we will use the network adapter's `gethostbyname` diff --git a/src/jsdevices.c b/src/jsdevices.c index 7a24c6ebf..d71c59777 100644 --- a/src/jsdevices.c +++ b/src/jsdevices.c @@ -32,7 +32,7 @@ JshEventCallbackCallback jshEventCallbacks[EV_EXTI_MAX+1-EV_EXTI0]; // DATA TRANSMIT BUFFER /** - * \brief A single character to be transmitted. + * A single character to be transmitted. */ typedef struct { IOEventFlags flags; //!< Where this data should be transmitted @@ -40,7 +40,7 @@ typedef struct { } PACKED_FLAGS TxBufferItem; /** - * \brief An array of items to transmit. + * An array of items to transmit. */ volatile TxBufferItem txBuffer[TXBUFFERMASK+1]; @@ -67,7 +67,7 @@ volatile unsigned char ioHead=0, ioTail=0; /** - * \brief Initialize all the devices. + * Initialize all the devices. */ void jshInitDevices() { // called from jshInit int i; @@ -83,7 +83,7 @@ void jshInitDevices() { // called from jshInit // ---------------------------------------------------------------------------- /** - * \brief Queue a character for transmission. + * Queue a character for transmission. */ void jshTransmit( IOEventFlags device, //!< The device to be used for transmission. @@ -140,7 +140,7 @@ IOEventFlags jshGetDeviceToTransmit() { } /** - * \brief Try and get a character for transmission. + * Try and get a character for transmission. * \return The next byte to transmit or -1 if there is none. */ int jshGetCharToTransmit( @@ -187,7 +187,7 @@ void jshTransmitFlush() { } /** - * \brief Discard all the data waiting for transmission. + * Discard all the data waiting for transmission. */ void jshTransmitClearDevice( IOEventFlags device //!< The device to be cleared. @@ -210,7 +210,7 @@ void jshTransmitMove(IOEventFlags from, IOEventFlags to) { } /** - * \brief Determine if we have data to be transmitted. + * Determine if we have data to be transmitted. * \return True if we have data to transmit and false otherwise. */ bool jshHasTransmitData() { @@ -218,7 +218,7 @@ bool jshHasTransmitData() { } /** - * \brief flag that the buffer has overflowed. + * flag that the buffer has overflowed. */ void jshIOEventOverflowed() { // Error here - just set flag so we don't dump a load of data out @@ -227,7 +227,7 @@ void jshIOEventOverflowed() { /** - * \brief Send a character to the specified device. + * Send a character to the specified device. */ void jshPushIOCharEvent( IOEventFlags channel, // !< The device to target for output. @@ -340,7 +340,7 @@ bool jshPopIOEventOfType(IOEventFlags eventType, IOEvent *result) { } /** - * \brief Determine if we have I/O events to process. + * Determine if we have I/O events to process. * \return True if there are I/O events to be processed. */ bool jshHasEvents() { @@ -369,7 +369,7 @@ bool jshHasEventSpaceForChars(int n) { // DEVICES /** - * \brief Get a string representation of a device. + * Get a string representation of a device. * \return A string representation of a device. */ const char *jshGetDeviceString( @@ -417,7 +417,7 @@ const char *jshGetDeviceString( } /** - * \brief Get a device identity from a string. + * Get a device identity from a string. * \return A device identity. */ IOEventFlags jshFromDeviceString( diff --git a/src/jsinteractive.c b/src/jsinteractive.c index ad7eb9b0f..5e1e290ae 100644 --- a/src/jsinteractive.c +++ b/src/jsinteractive.c @@ -71,7 +71,7 @@ void jsiDebuggerLine(JsVar *line); // ---------------------------------------------------------------------------- /** - * \brief Get the device from the class variable. + * Get the device from the class variable. */ IOEventFlags jsiGetDeviceFromClass(JsVar *class) { // Devices have their Object data set up to something special @@ -124,7 +124,7 @@ static NO_INLINE void jsiAppendToInputLine(const char *str) { } /** - * \brief Change the console to a new location. + * Change the console to a new location. */ void jsiSetConsoleDevice( IOEventFlags device //!< The device to use as a console. @@ -157,7 +157,7 @@ void jsiSetConsoleDevice( } /** - * \brief Retrieve the device being used as the console. + * Retrieve the device being used as the console. */ IOEventFlags jsiGetConsoleDevice() { // The `consoleDevice` is the global used to hold the current console. This function @@ -166,7 +166,7 @@ IOEventFlags jsiGetConsoleDevice() { } /** - * \brief Send a character to the console. + * Send a character to the console. */ NO_INLINE void jsiConsolePrintChar(char data) { jshTransmit(consoleDevice, (unsigned char)data); @@ -183,7 +183,7 @@ NO_INLINE void jsiConsolePrint(const char *str) { } /** - * \brief Perform a printf to the console. + * Perform a printf to the console. * Execute a printf command to the current JS console. */ void jsiConsolePrintf(const char *fmt, ...) { @@ -228,7 +228,7 @@ void jsiConsolePrintStringVarWithNewLineChar(JsVar *v, size_t fromCharacter, cha } /** - * \brief Print the contents of a string var - directly. + * Print the contents of a string var - directly. */ void jsiConsolePrintStringVar(JsVar *v) { jsiConsolePrintStringVarWithNewLineChar(v,0,0); @@ -357,7 +357,7 @@ void jsiConsolePrintPosition(struct JsLex *lex, size_t tokenPos) { } /** - * \brief Clear the input line of data. + * Clear the input line of data. */ void jsiClearInputLine() { jsiConsoleRemoveInputLine(); @@ -368,7 +368,7 @@ void jsiClearInputLine() { } /** - * \brief ??? What does this do ???. + * ??? What does this do ???. */ void jsiSetBusy( JsiBusyDevice device, //!< ??? @@ -386,7 +386,7 @@ void jsiSetBusy( } /** - * \brief Set the status of a pin as a function of whether we are asleep. + * Set the status of a pin as a function of whether we are asleep. * When called, if a pin is set for a sleep indicator, we set the pin to be true * if the sleep type is awake and false otherwise. */ diff --git a/src/jspin.c b/src/jspin.c index d874862bf..d0a6f0f01 100644 --- a/src/jspin.c +++ b/src/jspin.c @@ -25,7 +25,7 @@ #endif /** - * \brief Validate that the pin is a good pin. + * Validate that the pin is a good pin. * \return True if the pin is valid. */ bool jshIsPinValid(Pin pin) { @@ -34,7 +34,7 @@ bool jshIsPinValid(Pin pin) { } /** - * \brief Get a pin value from an encoded strin. + * Get a pin value from an encoded strin. * \return A pin value. */ Pin jshGetPinFromString(const char *s) { @@ -223,7 +223,7 @@ void jshSetPinStateIsManual(Pin pin, bool manual) { // ---------------------------------------------------------------------------- /** - * \brief Get the value of a pin. + * Get the value of a pin. * \return The value of the pin. */ bool jshPinInput( @@ -243,7 +243,7 @@ bool jshPinInput( /** - * \brief Set the value of a pin. + * Set the value of a pin. */ void jshPinOutput( Pin pin, //!< The pin to set. diff --git a/src/jsspi.c b/src/jsspi.c index 80692e10b..2b4e87a98 100644 --- a/src/jsspi.c +++ b/src/jsspi.c @@ -15,7 +15,7 @@ #include "jsinteractive.h" /** - * \brief Dump the internal SPI Info data structure to the console. + * Dump the internal SPI Info data structure to the console. * This is an internal debugging function. */ void jsspiDumpSPIInfo(JshSPIInfo *inf) { @@ -31,7 +31,7 @@ int jsspiHardwareFunc(int data, spi_sender_data *info) { /** - * \brief Send a single byte through SPI. + * Send a single byte through SPI. * \return The received byte. */ int jsspiFastSoftwareFunc( @@ -56,7 +56,7 @@ int jsspiFastSoftwareFunc( /** - * \brief Send a single byte through SPI. + * Send a single byte through SPI. * \return The received byte. */ int jsspiSoftwareFunc( @@ -105,7 +105,7 @@ int jsspiSoftwareFunc( /** - * \brief Populate a JshSPIInfo structure from a JS Object. + * Populate a JshSPIInfo structure from a JS Object. * The object properties that are examined are: * * `sck` - The pin to use for the clock. * * `miso` - The pin to use for Master In/Slave Out. @@ -149,7 +149,7 @@ void jsspiPopulateSPIInfo( } /** - * \brief Select the SPI send function. + * Select the SPI send function. * Get the correct SPI send function (and the data to send to it). We do this * by examining the device and determining if it is hardware, software fast * or software regular. diff --git a/src/jsutils.c b/src/jsutils.c index d6cadaf30..b21de1a9f 100644 --- a/src/jsutils.c +++ b/src/jsutils.c @@ -156,7 +156,7 @@ long long stringToIntWithRadix(const char *s, int forceRadix, bool *hasError) { } /** - * \brief Convert hex, binary, octal or decimal string into an int. + * Convert hex, binary, octal or decimal string into an int. */ long long stringToInt(const char *s) { return stringToIntWithRadix(s,0,0); @@ -327,7 +327,7 @@ void srand(unsigned int seed) { /** - * \brief Convert a string to a JS float variable where the string is of a specific radix. + * Convert a string to a JS float variable where the string is of a specific radix. * \return A JS float variable. */ JsVarFloat stringToFloatWithRadix( @@ -413,7 +413,7 @@ JsVarFloat stringToFloatWithRadix( /** - * \brief convert a string to a floating point JS variable. + * convert a string to a floating point JS variable. * \return a JS float variable. */ JsVarFloat stringToFloat( @@ -512,7 +512,7 @@ JsVarFloat wrapAround(JsVarFloat val, JsVarFloat size) { } /** - * \brief Espruino-special printf with a callback. + * Espruino-special printf with a callback. * * The supported format specifiers are: * * `%d` = int diff --git a/src/jsvariterator.c b/src/jsvariterator.c index 2b59daf0b..d76ebc5ff 100644 --- a/src/jsvariterator.c +++ b/src/jsvariterator.c @@ -14,7 +14,7 @@ #include "jsvariterator.h" /** - * \brief Iterate over the contents of the content of a variable, calling callback for each. + * Iterate over the contents of the content of a variable, calling callback for each. * Contents may be: * * numeric -> output * * a string -> output each character @@ -94,7 +94,7 @@ bool jsvIterateCallback( /** - * \brief An iterable callback that counts how many times it was called. + * An iterable callback that counts how many times it was called. * This is a function that can be supplied to `jsvIterateCallback`. */ static void jsvIterateCallbackCountCb( @@ -108,7 +108,7 @@ static void jsvIterateCallbackCountCb( /** - * \brief Determine how many items are in this variable that will be iterated over. + * Determine how many items are in this variable that will be iterated over. * \return The number of iterations we will call for this variable. */ int jsvIterateCallbackCount(JsVar *var) { diff --git a/src/jswrap_io.c b/src/jswrap_io.c index 0033621a3..f04024f66 100644 --- a/src/jswrap_io.c +++ b/src/jswrap_io.c @@ -254,7 +254,7 @@ example `digitalWrite([A1,A1,A0,A0],0b0101)` would pulse A0 followed by A1. */ /** - * \brief Set the output of a GPIO. + * Set the output of a GPIO. */ void jswrap_io_digitalWrite( JsVar *pinVar, //!< A pin or pins. @@ -299,7 +299,7 @@ the last array element is the least significant bit, for example if `A0=A1=1` an */ /** - * \brief Read the value of a GPIO pin. + * Read the value of a GPIO pin. */ JsVarInt jswrap_io_digitalRead(JsVar *pinVar) { // Hadnle the case where it is an array of pins. @@ -351,7 +351,7 @@ Set the mode of the given pin. */ /** - * \brief Set the mode of a pin. + * Set the mode of a pin. */ void jswrap_io_pinMode( Pin pin, //!< The pin to set. diff --git a/src/jswrap_pin.c b/src/jswrap_pin.c index 177173417..dc8458995 100644 --- a/src/jswrap_pin.c +++ b/src/jswrap_pin.c @@ -40,7 +40,7 @@ You can call the methods on Pin, or you can use Wiring-style functions such as d Creates a pin from the given argument (or returns undefined if no argument) */ /** - * \brief Create an instance of a Pin class. + * Create an instance of a Pin class. */ JsVar *jswrap_pin_constructor(JsVar *val) { Pin pin = jshGetPinFromVar(val); @@ -189,7 +189,7 @@ Get information about this pin and its capabilities. Of the form: Will return undefined if pin is not valid. */ /** - * \brief + * */ JsVar *jswrap_pin_getInfo( JsVar *parent //!< The class instance representing the pin. diff --git a/src/jswrap_spi_i2c.c b/src/jswrap_spi_i2c.c index 0894334e0..76b057ac7 100644 --- a/src/jswrap_spi_i2c.c +++ b/src/jswrap_spi_i2c.c @@ -163,7 +163,7 @@ typedef struct { /** - * \brief Send a single byte to the SPI device, used ad callback. + * Send a single byte to the SPI device, used ad callback. */ void jswrap_spi_send_cb( int c, //!< The byte to send through SPI. @@ -181,7 +181,7 @@ void jswrap_spi_send_cb( /** - * \brief Send data through SPI. + * Send data through SPI. * The data can be in a variety of formats including: * * `numeric` - A single byte is transmitted. * * `string` - Each character in the string is transmitted. diff --git a/targets/esp8266/esp8266_board_utils.c b/targets/esp8266/esp8266_board_utils.c index 06720046a..abe42051c 100644 --- a/targets/esp8266/esp8266_board_utils.c +++ b/targets/esp8266/esp8266_board_utils.c @@ -13,7 +13,7 @@ typedef long long int64_t; #include "jsutils.h" /** - * \brief Convert an ESP8266 error code to a string. + * Convert an ESP8266 error code to a string. * Given an ESP8266 network error code, return a string representation * of the meaning of that code. * \return A string representation of an error code. @@ -51,7 +51,7 @@ const char *esp8266_errorToString( /** - * \brief Write a buffer of data to the console. + * Write a buffer of data to the console. * The buffer is pointed to by the buffer * parameter and will be written for the length parameter. This is useful because * unlike a string, the data does not have to be NULL terminated. diff --git a/targets/esp8266/jshardware.c b/targets/esp8266/jshardware.c index d2e6fb5ed..19b94d92e 100644 --- a/targets/esp8266/jshardware.c +++ b/targets/esp8266/jshardware.c @@ -76,14 +76,14 @@ void jshInit() { } // End of jshInit /** - * \brief Reset the hardware to a power-on state + * Reset the hardware to a power-on state. */ void jshReset() { - system_restart(); + //system_restart(); } // End of jshReset /** - * \brief Handle whatever needs to be done in the idle loop when there's nothing to do + * Handle whatever needs to be done in the idle loop when there's nothing to do. * * Nothing is needed on the esp8266. The watchdog timer is taken care of by the SDK. */ @@ -127,7 +127,7 @@ bool jshSleep(JsSysTime timeUntilWake) { void jshDelayMicroseconds(int microsec) { // Keep things simple and make the user responsible if they sleep for too long... if (microsec > 0) { - os_printf("Delay %ldus\n", microsec); + os_printf("Delay %d us\n", microsec); os_delay_us(microsec); } #if 0 @@ -215,7 +215,7 @@ static uint8_t pinFunction(JshPinState state) { /** - * \brief Convert a pin state to a string representation. + * Convert a pin state to a string representation. */ static char *pinStateToString(JshPinState state) { switch(state) { @@ -251,7 +251,7 @@ static char *pinStateToString(JshPinState state) { } /** - * \brief Set the state of the specific pin. + * Set the state of the specific pin. * * The possible states are: * @@ -321,7 +321,7 @@ void jshPinSetState(Pin pin, //!< The pin to have its state changed. /** - * \brief Return the current state of the selected pin. + * Return the current state of the selected pin. * \return The current state of the selected pin. */ JshPinState jshPinGetState(Pin pin) { @@ -332,7 +332,7 @@ JshPinState jshPinGetState(Pin pin) { //===== GPIO and PIN stuff ===== /** - * \brief Set the value of the corresponding pin. + * Set the value of the corresponding pin. */ void jshPinSetValue(Pin pin, //!< The pin to have its value changed. bool value //!< The new value of the pin. @@ -344,7 +344,7 @@ void jshPinSetValue(Pin pin, //!< The pin to have its value changed. /** - * \brief Get the value of the corresponding pin. + * Get the value of the corresponding pin. * \return The current value of the pin. */ bool jshPinGetValue(Pin pin //!< The pin to have its value read. @@ -356,7 +356,7 @@ bool jshPinGetValue(Pin pin //!< The pin to have its value read. /** - * \brief + * */ JsVarFloat jshPinAnalog(Pin pin) { os_printf("> ESP8266: jshPinAnalog: %d\n", pin); @@ -365,7 +365,7 @@ JsVarFloat jshPinAnalog(Pin pin) { /** - * \brief + * */ int jshPinAnalogFast(Pin pin) { os_printf("> ESP8266: jshPinAnalogFast: %d\n", pin); @@ -374,7 +374,7 @@ int jshPinAnalogFast(Pin pin) { /** - * \brief + * */ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) { // if freq<=0, the default is used os_printf("ESP8266: jshPinAnalogOutput: %d, %d, %d\n", pin, (int)value, (int)freq); @@ -384,7 +384,7 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, Js /** - * \brief + * */ void jshSetOutputValue(JshPinFunction func, int value) { os_printf("ESP8266: jshSetOutputValue %d %d\n", func, value); @@ -392,7 +392,7 @@ void jshSetOutputValue(JshPinFunction func, int value) { /** - * \brief + * */ void jshEnableWatchDog(JsVarFloat timeout) { os_printf("ESP8266: jshEnableWatchDog %0.3f\n", timeout); @@ -400,7 +400,7 @@ void jshEnableWatchDog(JsVarFloat timeout) { /** - * \brief + * */ bool jshGetWatchedPinState(IOEventFlags device) { os_printf("ESP8266: jshGetWatchedPinState %d", device); @@ -409,7 +409,7 @@ bool jshGetWatchedPinState(IOEventFlags device) { /** - * \brief Set the value of the pin to be the value supplied and then wait for + * Set the value of the pin to be the value supplied and then wait for * a given period and set the pin value again to be the opposite. */ void jshPinPulse(Pin pin, //!< The pin to be pulsed. @@ -427,7 +427,7 @@ void jshPinPulse(Pin pin, //!< The pin to be pulsed. /** - * \brief + * */ bool jshCanWatch(Pin pin) { return false; @@ -435,7 +435,7 @@ bool jshCanWatch(Pin pin) { /** - * \brief + * */ IOEventFlags jshPinWatch( Pin pin, //!< Unknown @@ -449,7 +449,7 @@ IOEventFlags jshPinWatch( /** - * \brief + * */ JshPinFunction jshGetCurrentPinFunction(Pin pin) { //os_printf("jshGetCurrentPinFunction %d\n", pin); @@ -457,7 +457,7 @@ JshPinFunction jshGetCurrentPinFunction(Pin pin) { } /** - * \brief + * */ bool jshIsEventForPin(IOEvent *event, Pin pin) { return IOEVENTFLAGS_GETTYPE(event->flags) == pinToEVEXTI(pin); @@ -466,7 +466,7 @@ bool jshIsEventForPin(IOEvent *event, Pin pin) { //===== USART and Serial ===== /** - * \brief + * */ void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) { } @@ -477,8 +477,8 @@ bool jshIsUSBSERIALConnected() { } // End of jshIsUSBSERIALConnected /** - * \brief * Kick a device into action (if required). + * * For instance we may need * to set up interrupts. In this ESP8266 implementation, we transmit all the * data that can be found associated with the device. @@ -493,7 +493,8 @@ void jshUSARTKick( //===== SPI ===== /** - * \brief Unknown + * Unknown + * * */ void jshSPISetup( @@ -516,7 +517,7 @@ int jshSPISend( /** - \brief * Send 16 bit data through the given SPI device. + * Send 16 bit data through the given SPI device. */ void jshSPISend16( IOEventFlags device, //!< Unknown @@ -529,7 +530,7 @@ void jshSPISend16( /** - * \brief Set whether to send 16 bits or 8 over SPI. + * Set whether to send 16 bits or 8 over SPI. */ void jshSPISet16( IOEventFlags device, //!< Unknown @@ -540,7 +541,7 @@ void jshSPISet16( /** - * \brief Wait until SPI send is finished. + * Wait until SPI send is finished. */ void jshSPIWait( IOEventFlags device //!< Unknown @@ -630,7 +631,7 @@ static void saveTime() { (uint32_t)(rtcTimeStamp.timeStamp >> 32); system_rtc_mem_write(RTC_TIME_ADDR, &rtcTimeStamp, sizeof(rtcTimeStamp)); os_printf("RTC write: %lu %lu 0x%08x\n", (uint32_t)(rtcTimeStamp.timeStamp/1000000), - rtcTimeStamp.hwTimeStamp, rtcTimeStamp.cksum); + rtcTimeStamp.hwTimeStamp, (int)rtcTimeStamp.cksum); } /** @@ -641,13 +642,6 @@ JsSysTime jshGetSystemTime() { // in us } // End of jshGetSystemTime - -bool jshFlashContainsCode() { - os_printf("ESP8266: jshFlashContainsCode\n"); - return false; -} - - /** * Set the current time in microseconds. */ @@ -703,8 +697,8 @@ static void systemTimeInit(void) { uint32_t cksum = rtcTimeStamp.cksum ^ rtcTimeStamp.hwTimeStamp ^ (uint32_t)(rtcTimeStamp.timeStamp & 0xffffffff) ^ (uint32_t)(rtcTimeStamp.timeStamp >> 32); - os_printf("RTC read: %lu %lu 0x%08x (0x%08x)\n", (uint32_t)(rtcTimeStamp.timeStamp/1000000), - rtcTimeStamp.hwTimeStamp, rtcTimeStamp.cksum, cksum); + os_printf("RTC read: %d %d 0x%08x (0x%08x)\n", (int)(rtcTimeStamp.timeStamp/1000000), + (int)rtcTimeStamp.hwTimeStamp, (unsigned int)rtcTimeStamp.cksum, (unsigned int)cksum); if (reason < 1 || reason > 4 || cksum != 0xdeadbeef) { // we lost track of time, start at zero os_printf("RTC: cannot restore time\n"); @@ -754,7 +748,7 @@ void jshUtilTimerDisable() { } void jshUtilTimerStart(JsSysTime period) { - os_printf("UStimer arm %lluus\n"); + os_printf("UStimer arm\n"); os_timer_arm_us(&utilTimer, (uint32_t)period, 0); } @@ -826,7 +820,7 @@ unsigned int jshGetRandomNumber() { //===== Read-write flash ===== /** - * \brief Read data from flash memory into the buffer. + * Read data from flash memory into the buffer. * * This reads from flash using memory-mapped reads. Only works for the first 1MB and * requires 4-byte aligned reads. @@ -856,7 +850,7 @@ void jshFlashRead( /** - * \brief Write data to flash memory from the buffer. + * Write data to flash memory from the buffer. * * This is called from jswrap_flash_write and ... which guarantee that addr is 4-byte aligned * and len is a multiple of 4. @@ -883,7 +877,7 @@ void jshFlashWrite( /** - * \brief Return start address and size of the flash page the given address resides in. + * Return start address and size of the flash page the given address resides in. * Returns false if no page. */ bool jshFlashGetPage( @@ -901,7 +895,7 @@ bool jshFlashGetPage( /** - * \brief Erase the flash page containing the address. + * Erase the flash page containing the address. */ void jshFlashErasePage( uint32_t addr //!< diff --git a/targets/esp8266/user_main.c b/targets/esp8266/user_main.c index 84b775c79..2ab983ae7 100644 --- a/targets/esp8266/user_main.c +++ b/targets/esp8266/user_main.c @@ -47,7 +47,7 @@ static os_timer_t mainLoopSuspendTimer; #if 0 /** - * \brief A callback function to be invoked when a line has been entered on the telnet client. + * A callback function to be invoked when a line has been entered on the telnet client. * Here we want to pass that line to the JS parser for processing. */ static void telnetLineCB(char *line) { @@ -79,7 +79,7 @@ static char *flash_maps[] = { }; /** - * \brief Dump the ESP8266 restart information. + * Dump the ESP8266 restart information. * This is purely for debugging. * When an ESP8266 crashes, before it ends, it records its exception information. * This function retrieves that data and logs it. @@ -102,7 +102,7 @@ static void dumpRestart() { /** - * \brief Queue a task for the main loop. + * Queue a task for the main loop. */ static void queueTaskMainLoop() { system_os_post(TASK_APP_QUEUE, TASK_APP_MAINLOOP, 0); @@ -110,7 +110,7 @@ static void queueTaskMainLoop() { /** - * \brief Suspend processing the main loop for a period of time. + * Suspend processing the main loop for a period of time. */ void suspendMainLoop( uint32 interval //!< suspension interval in milliseconds @@ -121,7 +121,7 @@ void suspendMainLoop( /** - * \brief Enable main loop processing. + * Enable main loop processing. */ static void enableMainLoop() { suspendMainLoopFlag = false; @@ -129,7 +129,7 @@ static void enableMainLoop() { } /** - * \brief Idle callback from the SDK, triggers an idle loop iteration + * Idle callback from the SDK, triggers an idle loop iteration */ static void idle(void) { // The idle callback comes form the SDK's ets_run function just before it puts the @@ -143,7 +143,7 @@ static void idle(void) { /** - * \brief The event handler for ESP8266 tasks as created by system_os_post() on the TASK_APP_QUEUE. + * The event handler for ESP8266 tasks as created by system_os_post() on the TASK_APP_QUEUE. */ static void eventHandler( os_event_t *pEvent //!< @@ -178,7 +178,7 @@ static void eventHandler( static uint32 lastTime = 0; /** - * \brief Perform the main loop processing. + * Perform the main loop processing. * This is where work is performed * as often as possible. */ @@ -244,7 +244,7 @@ void user_rf_pre_init() { /** - * \brief The main entry point in an ESP8266 application. + * The main entry point in an ESP8266 application. * It is where the logic of ESP8266 starts. */ void user_init() {