Jelajahi Sumber

add eth tester for W5500 module

MX 1 tahun lalu
melakukan
4f722fd09f
100 mengubah file dengan 32730 tambahan dan 0 penghapusan
  1. 6 0
      .gitignore
  2. 21 0
      README.md
  3. 57 0
      application.fam
  4. TEMPAT SAMPAH
      docs/FlipperZeroPinout.jpg
  5. TEMPAT SAMPAH
      docs/w5500-lite-assembled-top.jpg
  6. TEMPAT SAMPAH
      docs/w5500-lite-pinout.png
  7. 301 0
      eth_save_process.c
  8. 31 0
      eth_save_process.h
  9. 212 0
      eth_troubleshooter_app.c
  10. 49 0
      eth_troubleshooter_app.h
  11. 422 0
      eth_view_process.c
  12. 59 0
      eth_view_process.h
  13. 582 0
      eth_worker.c
  14. 78 0
      eth_worker.h
  15. 8 0
      eth_worker_dhcp.c
  16. 31 0
      eth_worker_i.h
  17. 11 0
      eth_worker_ping.c
  18. TEMPAT SAMPAH
      images/ethernet_icon_10x10px.png
  19. TEMPAT SAMPAH
      images/exit_128x64px.png
  20. TEMPAT SAMPAH
      images/init_100x19px.png
  21. TEMPAT SAMPAH
      images/main_128x64px.png
  22. TEMPAT SAMPAH
      images/screenshot-ping.png
  23. TEMPAT SAMPAH
      images/screenshot_dhcp.png
  24. TEMPAT SAMPAH
      images/screenshot_init.png
  25. TEMPAT SAMPAH
      images/screenshot_static.png
  26. 22 0
      lib/ioLibrary_Driver/.gitattributes
  27. 1940 0
      lib/ioLibrary_Driver/.gitignore
  28. 225 0
      lib/ioLibrary_Driver/Application/loopback/loopback.c
  29. 38 0
      lib/ioLibrary_Driver/Application/loopback/loopback.h
  30. 113 0
      lib/ioLibrary_Driver/Application/multicast/multicast.c
  31. 28 0
      lib/ioLibrary_Driver/Application/multicast/multicast.h
  32. TEMPAT SAMPAH
      lib/ioLibrary_Driver/Ethernet/Socket_APIs_V3.0.3.chm
  33. 386 0
      lib/ioLibrary_Driver/Ethernet/W5100/w5100.c
  34. 1865 0
      lib/ioLibrary_Driver/Ethernet/W5100/w5100.h
  35. 514 0
      lib/ioLibrary_Driver/Ethernet/W5100S/w5100s.c
  36. 3323 0
      lib/ioLibrary_Driver/Ethernet/W5100S/w5100s.h
  37. 353 0
      lib/ioLibrary_Driver/Ethernet/W5200/w5200.c
  38. 2110 0
      lib/ioLibrary_Driver/Ethernet/W5200/w5200.h
  39. 225 0
      lib/ioLibrary_Driver/Ethernet/W5300/w5300.c
  40. 2336 0
      lib/ioLibrary_Driver/Ethernet/W5300/w5300.h
  41. 267 0
      lib/ioLibrary_Driver/Ethernet/W5500/w5500.c
  42. 2165 0
      lib/ioLibrary_Driver/Ethernet/W5500/w5500.h
  43. 931 0
      lib/ioLibrary_Driver/Ethernet/socket.c
  44. 489 0
      lib/ioLibrary_Driver/Ethernet/socket.h
  45. 842 0
      lib/ioLibrary_Driver/Ethernet/wizchip_conf.c
  46. 661 0
      lib/ioLibrary_Driver/Ethernet/wizchip_conf.h
  47. 991 0
      lib/ioLibrary_Driver/Internet/DHCP/dhcp.c
  48. 159 0
      lib/ioLibrary_Driver/Internet/DHCP/dhcp.h
  49. 564 0
      lib/ioLibrary_Driver/Internet/DNS/dns.c
  50. 109 0
      lib/ioLibrary_Driver/Internet/DNS/dns.h
  51. 584 0
      lib/ioLibrary_Driver/Internet/FTPClient/ftpc.c
  52. 130 0
      lib/ioLibrary_Driver/Internet/FTPClient/ftpc.h
  53. 75 0
      lib/ioLibrary_Driver/Internet/FTPClient/stdio_private.h
  54. 983 0
      lib/ioLibrary_Driver/Internet/FTPServer/ftpd.c
  55. 154 0
      lib/ioLibrary_Driver/Internet/FTPServer/ftpd.h
  56. 74 0
      lib/ioLibrary_Driver/Internet/FTPServer/stdio_private.h
  57. 298 0
      lib/ioLibrary_Driver/Internet/ICMP/ping.c
  58. 38 0
      lib/ioLibrary_Driver/Internet/ICMP/ping.h
  59. 582 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTClient.c
  60. 182 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTClient.h
  61. 136 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTConnect.h
  62. 214 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTConnectClient.c
  63. 148 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTConnectServer.c
  64. 107 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTDeserializePublish.c
  65. 255 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTFormat.c
  66. 37 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTFormat.h
  67. 410 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTPacket.c
  68. 133 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTPacket.h
  69. 38 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTPublish.h
  70. 169 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSerializePublish.c
  71. 39 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSubscribe.h
  72. 137 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSubscribeClient.c
  73. 112 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSubscribeServer.c
  74. 38 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTUnsubscribe.h
  75. 106 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeClient.c
  76. 102 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeServer.c
  77. 78 0
      lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/StackTrace.h
  78. 182 0
      lib/ioLibrary_Driver/Internet/MQTT/mqtt_interface.c
  79. 271 0
      lib/ioLibrary_Driver/Internet/MQTT/mqtt_interface.h
  80. 927 0
      lib/ioLibrary_Driver/Internet/SNMP/snmp.c
  81. 122 0
      lib/ioLibrary_Driver/Internet/SNMP/snmp.h
  82. 147 0
      lib/ioLibrary_Driver/Internet/SNMP/snmp_custom.c
  83. 41 0
      lib/ioLibrary_Driver/Internet/SNMP/snmp_custom.h
  84. 45 0
      lib/ioLibrary_Driver/Internet/SNMP/tools/OID_Converter/Readme.txt
  85. 33 0
      lib/ioLibrary_Driver/Internet/SNMP/tools/net-snmp-5.7(win32-bin)/snmptrapd.conf
  86. 450 0
      lib/ioLibrary_Driver/Internet/SNTP/sntp.c
  87. 76 0
      lib/ioLibrary_Driver/Internet/SNTP/sntp.h
  88. 158 0
      lib/ioLibrary_Driver/Internet/TFTP/netutil.c
  89. 27 0
      lib/ioLibrary_Driver/Internet/TFTP/netutil.h
  90. 660 0
      lib/ioLibrary_Driver/Internet/TFTP/tftp.c
  91. 101 0
      lib/ioLibrary_Driver/Internet/TFTP/tftp.h
  92. 402 0
      lib/ioLibrary_Driver/Internet/httpServer/httpParser.c
  93. 158 0
      lib/ioLibrary_Driver/Internet/httpServer/httpParser.h
  94. 749 0
      lib/ioLibrary_Driver/Internet/httpServer/httpServer.c
  95. 111 0
      lib/ioLibrary_Driver/Internet/httpServer/httpServer.h
  96. 75 0
      lib/ioLibrary_Driver/Internet/httpServer/httpUtil.c
  97. 32 0
      lib/ioLibrary_Driver/Internet/httpServer/httpUtil.h
  98. 58 0
      lib/ioLibrary_Driver/README.md
  99. TEMPAT SAMPAH
      lib/ioLibrary_Driver/iolibrary.chm
  100. 22 0
      lib/ioLibrary_Driver/license.txt

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+dist/*
+.vscode
+.clang-format
+.editorconfig
+.env
+.ufbt

+ 21 - 0
README.md

@@ -0,0 +1,21 @@
+# Flipper Zero Ethernet Troubleshooter
+
+This is a small helper that lets you connect your Flipper via RJ45 to your network
+You can then set the interface-mac and test if you can get an IP via DHCP and the ping addresses.
+
+## Prerequisites
+
+To get started you will need a specific module called the W5500 Lite with a chiop from WHIZnet Co., Ltd.
+You can find those modules on AliExpress etc. [Find Module here](https://www.google.com/search?q=WS5500+Ethernet)
+The second thing you will need is a proto-board for the Flipper Zero, which you can get [here](https://shop.flipperzero.one/products/proto-boards).
+
+## Assembly
+
+If you got those things, you can get started.
+You will need to solder the board yourself, but don't worry. It's not that complicated.
+First we will need to know the pinout of the W5500-Lite-Module.
+![w5500 pinout](docs/w5500-lite-pinout.png)
+here is the Flipper-Pinout to see where you will have to connect everything:
+![flipper pinout](docs/FlipperZeroPinout.jpg)
+and if you have correctly soldered you will end up with something like:
+![w5500 assebled board](docs/w5500-lite-assembled-top.jpg)

+ 57 - 0
application.fam

@@ -0,0 +1,57 @@
+App(
+    appid="eth_troubleshooter",
+    name="[W5500] Ethernet",
+    apptype=FlipperAppType.EXTERNAL,
+    entry_point="eth_troubleshooter_app",
+    cdefines=["ETH_TROUBLESHOOTER"],
+    requires=[
+        "gui",
+        "power",
+    ],
+    stack_size=5 * 1024,
+    order=90,
+    fap_icon="images/ethernet_icon_10x10px.png",
+    fap_category="GPIO",
+    fap_icon_assets="images",
+    fap_private_libs=[
+        Lib(
+            cflags=[
+                "-Wunused-parameter",
+                "-Wunused-function",
+                "-Wredundant-decls",
+                "-Wunused-parameter",
+            ],
+            name="ioLibrary_Driver",
+            fap_include_paths=[
+                "Ethernet/W5500",
+                "Ethernet",
+                "Internet/DHCP",
+                "Internet/DNS",
+                # "Internet/FTPClient",
+                # "Internet/FTPServer",
+                # "Internet/httpServer",
+                "Internet/ICMP",
+                # "Internet/MQTT",
+                # "Internet/MQTT/MQTTPacket/src",
+                # "Internet/SNMP",
+                # "Internet/SNTP",
+                # "Internet/TFTP",
+            ],
+            sources=[
+                "Ethernet/W5500/*.c",
+                "Ethernet/*.c",
+                "Internet/DHCP/*.c",
+                "Internet/DNS/*.c",
+                # "Internet/FTPClient/*.c",
+                # "Internet/FTPServer/*.c",
+                # "Internet/httpServer/*.c",
+                "Internet/ICMP/*.c",
+                # "Internet/MQTT/*.c",
+                # "Internet/MQTT/MQTTPacket/src/*.c",
+                # "Internet/SNMP/*.c",
+                # "Internet/SNTP/*.c",
+                # "Internet/TFTP/*.c",
+            ],
+        ),
+    ],
+)

TEMPAT SAMPAH
docs/FlipperZeroPinout.jpg


TEMPAT SAMPAH
docs/w5500-lite-assembled-top.jpg


TEMPAT SAMPAH
docs/w5500-lite-pinout.png


+ 301 - 0
eth_save_process.c

@@ -0,0 +1,301 @@
+#include "eth_save_process.h"
+
+#include <furi.h>
+#include <furi_hal.h>
+#include <storage/storage.h>
+#include <locale/locale.h>
+
+#define TAG "EthSave"
+
+#define STORAGE_FILE_BUF_LEN 50
+
+// fuction spizzhena from archive_favorites.c
+static bool storage_read_line(File* file, FuriString* str_result) {
+    furi_string_reset(str_result);
+    uint8_t buffer[STORAGE_FILE_BUF_LEN];
+    bool result = false;
+
+    do {
+        uint16_t read_count = storage_file_read(file, buffer, STORAGE_FILE_BUF_LEN);
+        if(storage_file_get_error(file) != FSE_OK) {
+            return false;
+        }
+
+        for(uint16_t i = 0; i < read_count; i++) {
+            if(buffer[i] == '\n') {
+                uint32_t position = storage_file_tell(file);
+                if(storage_file_get_error(file) != FSE_OK) {
+                    return false;
+                }
+
+                position = position - read_count + i + 1;
+
+                storage_file_seek(file, position, true);
+                if(storage_file_get_error(file) != FSE_OK) {
+                    return false;
+                }
+
+                result = true;
+                break;
+            } else {
+                furi_string_push_back(str_result, buffer[i]);
+            }
+        }
+
+        if(result || read_count == 0) {
+            break;
+        }
+    } while(true);
+
+    return result;
+}
+
+static bool storage_printf(File* file, const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    FuriString* fstring = furi_string_alloc_vprintf(format, args);
+    va_end(args);
+    if(storage_file_write(file, furi_string_get_cstr(fstring), furi_string_size(fstring)) &&
+       storage_file_write(file, "\n", 1)) {
+        furi_string_free(fstring);
+        return true;
+    }
+    furi_string_free(fstring);
+    return false;
+}
+
+static bool storage_write_config(File* file, const EthernetSaveConfig* cfg) {
+    storage_file_seek(file, 0, true);
+    storage_file_truncate(file);
+
+    bool result = true;
+    result = result ? storage_printf(
+                          file,
+                          "mac: %02X-%02X-%02X-%02X-%02X-%02X",
+                          cfg->mac[0],
+                          cfg->mac[1],
+                          cfg->mac[2],
+                          cfg->mac[3],
+                          cfg->mac[4],
+                          cfg->mac[5]) :
+                      result;
+    result = result ?
+                 storage_printf(
+                     file, "ip: %d.%d.%d.%d", cfg->ip[0], cfg->ip[1], cfg->ip[2], cfg->ip[3]) :
+                 result;
+    result =
+        result ?
+            storage_printf(
+                file, "mask: %d.%d.%d.%d", cfg->mask[0], cfg->mask[1], cfg->mask[2], cfg->mask[3]) :
+            result;
+    result = result ? storage_printf(
+                          file,
+                          "gateway: %d.%d.%d.%d",
+                          cfg->gateway[0],
+                          cfg->gateway[1],
+                          cfg->gateway[2],
+                          cfg->gateway[3]) :
+                      result;
+    result =
+        result ?
+            storage_printf(
+                file, "dns: %d.%d.%d.%d", cfg->dns[0], cfg->dns[1], cfg->dns[2], cfg->dns[3]) :
+            result;
+    result = result ? storage_printf(
+                          file,
+                          "ping_ip: %d.%d.%d.%d",
+                          cfg->ping_ip[0],
+                          cfg->ping_ip[1],
+                          cfg->ping_ip[2],
+                          cfg->ping_ip[3]) :
+                      result;
+    return result;
+}
+
+static void read_02X(const char* str, uint8_t* byte) {
+    uint8_t b[2] = {str[0], str[1]};
+
+    for(int i = 0; i < 2; ++i) {
+        if('0' <= b[i] && b[i] <= '9') {
+            b[i] -= '0';
+        } else if('A' <= b[i] && b[i] <= 'F') {
+            b[i] -= 'A' - 0x0A;
+        } else {
+            b[i] = 0;
+        }
+    }
+
+    *byte = b[1] + (b[0] << 4);
+}
+
+static void read_ip(const char* str, uint8_t* ip) {
+    uint8_t ip_i = 0;
+    uint8_t i = 0;
+    uint16_t tmp = 0;
+    for(;;) {
+        if('0' <= str[i] && str[i] <= '9') {
+            tmp = tmp * 10 + str[i] - '0';
+        } else if(str[i] == '.' || str[i] != '\n' || str[i] != '\0') {
+            if(tmp <= 0xFF && ip_i < 4) {
+                ip[ip_i] = tmp;
+                ip_i += 1;
+                tmp = 0;
+            } else {
+                break;
+            }
+            if(str[i] != '\n' && ip_i == 4) {
+                return;
+            }
+        } else {
+            break;
+        }
+        i += 1;
+    }
+    FURI_LOG_E(TAG, "cannot parse as ip string [%s]", str);
+    ip[0] = ip[1] = ip[2] = ip[3] = 0;
+    return;
+}
+
+static void set_default_config(EthernetSaveConfig* cfg) {
+    const uint8_t def_mac[6] = ETHERNET_SAVE_DEFAULT_MAC;
+    const uint8_t def_ip[4] = ETHERNET_SAVE_DEFAULT_IP;
+    const uint8_t def_mask[4] = ETHERNET_SAVE_DEFAULT_MASK;
+    const uint8_t def_gateway[4] = ETHERNET_SAVE_DEFAULT_GATEWAY;
+    const uint8_t def_dns[4] = ETHERNET_SAVE_DEFAULT_DNS;
+    const uint8_t def_ping_ip[4] = ETHERNET_SAVE_DEFAULT_PING_IP;
+
+    memcpy(cfg->mac, def_mac, 6);
+    memcpy(cfg->ip, def_ip, 4);
+    memcpy(cfg->mask, def_mask, 4);
+    memcpy(cfg->gateway, def_gateway, 4);
+    memcpy(cfg->dns, def_dns, 4);
+    memcpy(cfg->ping_ip, def_ping_ip, 4);
+}
+
+bool storage_read_config(File* file, EthernetSaveConfig* cfg) {
+    FuriString* fstring = furi_string_alloc();
+
+    while(storage_read_line(file, fstring)) {
+        const char* str = furi_string_get_cstr(fstring);
+        if(!strncmp(str, "mac: ", 5)) {
+            read_02X(str + strlen("mac: "), &cfg->mac[0]);
+            read_02X(str + strlen("mac: XX-"), &cfg->mac[1]);
+            read_02X(str + strlen("mac: XX-XX-"), &cfg->mac[2]);
+            read_02X(str + strlen("mac: XX-XX-XX-"), &cfg->mac[3]);
+            read_02X(str + strlen("mac: XX-XX-XX-XX-"), &cfg->mac[4]);
+            read_02X(str + strlen("mac: XX-XX-XX-XX-XX-"), &cfg->mac[5]);
+        } else if(!strncmp(str, "ip: ", 4)) {
+            read_ip(str + strlen("ip: "), cfg->ip);
+        } else if(!strncmp(str, "mask: ", 6)) {
+            read_ip(str + strlen("mask: "), cfg->mask);
+        } else if(!strncmp(str, "gateway: ", 9)) {
+            read_ip(str + strlen("gateway: "), cfg->gateway);
+        } else if(!strncmp(str, "dns: ", 5)) {
+            read_ip(str + strlen("dns: "), cfg->dns);
+        } else if(!strncmp(str, "ping_ip: ", 9)) {
+            read_ip(str + strlen("ping_ip: "), cfg->ping_ip);
+        }
+    }
+
+    furi_string_free(fstring);
+    return true;
+}
+
+void ethernet_save_process_write(const EthernetSaveConfig* config) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+
+    File* file = storage_file_alloc(storage);
+
+    if(!storage_file_open(file, APP_DATA_PATH("config.txt"), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
+        FURI_LOG_E(TAG, "Failed to open file");
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return;
+    }
+
+    if(!storage_write_config(file, config)) {
+        FURI_LOG_E(TAG, "Failed to write cpnfig to file");
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return;
+    }
+    storage_file_close(file);
+    storage_file_free(file);
+    furi_record_close(RECORD_STORAGE);
+}
+
+void ethernet_save_process_read(EthernetSaveConfig* config) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+
+    File* file = storage_file_alloc(storage);
+
+    if(!storage_file_open(file, APP_DATA_PATH("config.txt"), FSAM_READ, FSOM_OPEN_EXISTING)) {
+        FURI_LOG_E(TAG, "Failed to open file or file not exists");
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return;
+    }
+    if(!storage_read_config(file, config)) {
+        FURI_LOG_E(TAG, "Failed to read config from file");
+        storage_file_close(file);
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return;
+    }
+    storage_file_close(file);
+
+    storage_file_free(file);
+
+    furi_record_close(RECORD_STORAGE);
+}
+
+EthernetSaveConfig* ethernet_save_process_malloc() {
+    EthernetSaveConfig* config = malloc(sizeof(EthernetSaveConfig));
+
+    set_default_config(config);
+
+    ethernet_save_process_read(config);
+
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+
+    FURI_LOG_E(TAG, "ethernet_save_process_malloc");
+
+    File* file = storage_file_alloc(storage);
+
+    if(!storage_file_open(file, APP_DATA_PATH("log.txt"), FSAM_WRITE, FSOM_OPEN_APPEND)) {
+        FURI_LOG_E(TAG, "Failed to open file or file not exists");
+        storage_file_free(file);
+        furi_record_close(RECORD_STORAGE);
+        return NULL;
+    }
+
+    config->log_file = file;
+
+    return config;
+}
+
+void ethernet_save_process_print(EthernetSaveConfig* config, const char* str) {
+    furi_assert(config);
+    DateTime datetime = {0};
+    furi_hal_rtc_get_datetime(&datetime);
+    storage_printf(
+        config->log_file,
+        "%4d.%02d.%02d-%02d:%2d:%02d || %s",
+        datetime.year,
+        datetime.month,
+        datetime.day,
+        datetime.hour,
+        datetime.minute,
+        datetime.second,
+        str);
+}
+
+void ethernet_save_process_free(EthernetSaveConfig* config) {
+    FURI_LOG_E(TAG, "ethernet_save_process_free");
+    ethernet_save_process_write(config);
+    storage_file_close(config->log_file);
+    storage_file_free(config->log_file);
+    furi_record_close(RECORD_STORAGE);
+    free(config);
+}

+ 31 - 0
eth_save_process.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include <stdint.h>
+#include <storage/storage.h>
+
+typedef struct EthernetSaveConfig {
+    uint8_t mac[6];
+    uint8_t ip[4];
+    uint8_t mask[4];
+    uint8_t gateway[4];
+    uint8_t dns[4];
+    uint8_t ping_ip[4];
+    File* log_file;
+} EthernetSaveConfig;
+
+#define ETHERNET_SAVE_DEFAULT_MAC \
+    { 0x10, 0x08, 0xDC, 0x47, 0x47, 0x54 }
+#define ETHERNET_SAVE_DEFAULT_IP \
+    { 192, 168, 0, 101 }
+#define ETHERNET_SAVE_DEFAULT_MASK \
+    { 255, 255, 255, 0 }
+#define ETHERNET_SAVE_DEFAULT_GATEWAY \
+    { 192, 168, 0, 1 }
+#define ETHERNET_SAVE_DEFAULT_DNS \
+    { 192, 168, 0, 1 }
+#define ETHERNET_SAVE_DEFAULT_PING_IP \
+    { 8, 8, 8, 8 }
+
+EthernetSaveConfig* ethernet_save_process_malloc();
+void ethernet_save_process_free(EthernetSaveConfig* config);
+void ethernet_save_process_print(EthernetSaveConfig* config, const char* str);

+ 212 - 0
eth_troubleshooter_app.c

@@ -0,0 +1,212 @@
+
+#include "eth_troubleshooter_app.h"
+
+#include <furi.h>
+#include <furi_hal_power.h>
+#include <gui/gui.h>
+#include <gui/elements.h>
+#include <input/input.h>
+#include <notification/notification_messages.h>
+
+#include "eth_worker.h"
+#include "eth_worker_i.h"
+#include "eth_view_process.h"
+
+#define TAG "EthTroubleshooterApp"
+
+static void draw_process_selector(Canvas* canvas, DrawProcess selector, CursorPosition cursor) {
+    uint8_t y = 0;
+    if(selector == PROCESS_INIT) y = 11;
+    if(selector == PROCESS_DHCP) y = 22;
+    if(selector == PROCESS_STATIC) y = 34;
+    if(selector == PROCESS_PING) y = 44;
+    if(selector == PROCESS_RESET) y = 55;
+
+    if(cursor == CURSOR_INSIDE_PROCESS) {
+        canvas_invert_color(canvas);
+        canvas_draw_line(canvas, 25, y + 1, 25, y + 7);
+        canvas_invert_color(canvas);
+        canvas_draw_line(canvas, 0, y + 1, 0, y + 7);
+        canvas_draw_line(canvas, 1, y, 25, y);
+        canvas_draw_line(canvas, 1, y + 8, 25, y + 8);
+    } else {
+        canvas_draw_line(canvas, 0, y + 1, 0, y + 7);
+        canvas_draw_line(canvas, 23, y + 1, 23, y + 7);
+        canvas_draw_line(canvas, 1, y, 22, y);
+        canvas_draw_line(canvas, 1, y + 8, 22, y + 8);
+    }
+
+    if(cursor == CURSOR_CLICK_PROCESS) {
+        canvas_draw_box(canvas, 1, y, 22, 9);
+    }
+}
+
+static void draw_battery_cunsumption(Canvas* canvas, double cons) {
+    FuriString* string = furi_string_alloc_set("aaaaaaaa");
+    if(cons >= 0) {
+        furi_string_printf(string, "--");
+    } else if(cons < -1) {
+        furi_string_printf(string, "%1.1fk", -cons);
+    } else {
+        furi_string_printf(string, "%3.f", -(cons * 1000));
+    }
+
+    canvas_draw_str(canvas, 112, 7, furi_string_get_cstr(string));
+    furi_string_free(string);
+}
+
+static void eth_troubleshooter_app_draw_callback(Canvas* canvas, void* ctx) {
+    furi_assert(ctx);
+    EthTroubleshooterApp* app = ctx;
+
+    canvas_clear(canvas);
+
+    DrawProcess process = app->draw_process;
+    CursorPosition cursor = app->cursor_position;
+    float consumption = app->info.current_gauge;
+
+    canvas_set_font(canvas, FontSecondary);
+
+    if(cursor == CURSOR_EXIT_ICON) {
+        canvas_draw_icon(canvas, 0, 0, &I_exit_128x64px);
+    } else {
+        canvas_draw_icon(canvas, 0, 0, &I_main_128x64px);
+        draw_process_selector(canvas, process, cursor);
+        draw_battery_cunsumption(canvas, (double)consumption);
+        ethernet_view_process_draw(app->eth_worker->active_process, canvas);
+        if(furi_hal_power_is_otg_enabled()) {
+            canvas_draw_str(canvas, 22, 6, "+");
+        } else {
+            canvas_draw_str(canvas, 22, 6, "-");
+        }
+    }
+}
+
+static void eth_troubleshooter_battery_info_update_model(void* ctx) {
+    furi_assert(ctx);
+    EthTroubleshooterApp* app = ctx;
+    power_get_info(app->power, &app->info);
+}
+
+static void eth_troubleshooter_app_input_callback(InputEvent* input_event, void* ctx) {
+    furi_assert(ctx);
+
+    FuriMessageQueue* event_queue = ctx;
+    furi_message_queue_put(event_queue, input_event, FuriWaitForever);
+}
+
+EthTroubleshooterApp* eth_troubleshooter_app_alloc() {
+    EthTroubleshooterApp* app = malloc(sizeof(EthTroubleshooterApp));
+
+    app->view_port = view_port_alloc();
+    app->event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
+    app->eth_worker = eth_worker_alloc();
+
+    view_port_draw_callback_set(app->view_port, eth_troubleshooter_app_draw_callback, app);
+    view_port_input_callback_set(app->view_port, eth_troubleshooter_app_input_callback, app->event_queue);
+
+    app->gui = furi_record_open(RECORD_GUI);
+    gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
+
+    app->notifications = furi_record_open(RECORD_NOTIFICATION);
+
+    app->power = furi_record_open(RECORD_POWER);
+
+    return app;
+}
+
+void eth_troubleshooter_app_free(EthTroubleshooterApp* app) {
+    furi_assert(app);
+
+    view_port_enabled_set(app->view_port, false);
+    gui_remove_view_port(app->gui, app->view_port);
+    view_port_free(app->view_port);
+
+    furi_message_queue_free(app->event_queue);
+    eth_worker_free(app->eth_worker);
+
+    furi_record_close(RECORD_GUI);
+    furi_record_close(RECORD_NOTIFICATION);
+    furi_record_close(RECORD_POWER);
+}
+
+void eth_troubleshooter_app_key_handler(EthTroubleshooterApp* app, InputKey key) {
+    if(app->cursor_position == CURSOR_CHOOSE_PROCESS) {
+        if(key == InputKeyUp || key == InputKeyDown) {
+            app->draw_process =
+                (app->draw_process + PROCESS_RESET + (key == InputKeyDown ? 2 : 0)) %
+                (PROCESS_RESET + 1);
+            eth_worker_set_active_process(app->eth_worker, (EthWorkerProcess)app->draw_process);
+        } else if(key == InputKeyOk) {
+            ethernet_view_process_move(app->eth_worker->active_process, 0);
+            app->cursor_position = CURSOR_CLICK_PROCESS;
+            view_port_update(app->view_port);
+            furi_delay_ms(150);
+            eth_run(app->eth_worker, (EthWorkerProcess)app->draw_process);
+            app->cursor_position = CURSOR_CHOOSE_PROCESS;
+        } else if(key == InputKeyRight) {
+            eth_worker_set_active_process(app->eth_worker, (EthWorkerProcess)app->draw_process);
+            app->cursor_position = CURSOR_INSIDE_PROCESS;
+        } else if(key == InputKeyBack) {
+            app->cursor_position = CURSOR_EXIT_ICON;
+        }
+    } else if(app->cursor_position == CURSOR_INSIDE_PROCESS) {
+        if(app->eth_worker->active_process->editing) {
+            ethernet_view_process_keyevent(app->eth_worker->active_process, key);
+        } else if(key == InputKeyLeft) {
+            app->eth_worker->active_process->editing = 0;
+            app->cursor_position = CURSOR_CHOOSE_PROCESS;
+        } else if(key == InputKeyBack) {
+            ethernet_view_process_move(app->eth_worker->active_process, 0);
+            app->eth_worker->active_process->editing = 0;
+            app->cursor_position = CURSOR_CHOOSE_PROCESS;
+        } else if(key == InputKeyUp) {
+            ethernet_view_process_move(app->eth_worker->active_process, -1);
+        } else if(key == InputKeyDown) {
+            ethernet_view_process_move(app->eth_worker->active_process, 1);
+        } else if(key == InputKeyOk || key == InputKeyRight) {
+            app->eth_worker->active_process->editing = 1;
+        }
+    } else if(app->cursor_position == CURSOR_EXIT_ICON) {
+        if(key == InputKeyBack) {
+            app->cursor_position = CURSOR_EXIT;
+        } else if(key == InputKeyOk) {
+            app->cursor_position = CURSOR_CHOOSE_PROCESS;
+        }
+    }
+}
+
+int32_t eth_troubleshooter_app(void* p) {
+    UNUSED(p);
+    EthTroubleshooterApp* app = eth_troubleshooter_app_alloc();
+
+    InputEvent event;
+    uint8_t long_press = 0;
+    InputKey long_press_key = 0;
+
+    while(1) {
+        eth_troubleshooter_battery_info_update_model(app);
+        if(furi_message_queue_get(app->event_queue, &event, 200) == FuriStatusOk) {
+            if(event.type == InputTypePress) {
+                eth_troubleshooter_app_key_handler(app, event.key);
+            } else if(event.type == InputTypeLong) {
+                long_press = 1;
+                long_press_key = event.key;
+            } else if(event.type == InputTypeRelease) {
+                long_press = 0;
+                long_press_key = 0;
+            }
+        }
+        if(long_press && long_press_key != InputKeyBack) {
+            eth_troubleshooter_app_key_handler(app, long_press_key);
+        }
+        if(app->cursor_position == CURSOR_EXIT) {
+            eth_run(app->eth_worker, EthWorkerProcessExit);
+            break;
+        }
+        view_port_update(app->view_port);
+    }
+
+    eth_troubleshooter_app_free(app);
+    return 0;
+}

+ 49 - 0
eth_troubleshooter_app.h

@@ -0,0 +1,49 @@
+#pragma once
+
+#include <furi.h>
+#include <gui/gui.h>
+#include <notification/notification_messages.h>
+#include <power/power_service/power.h>
+
+#include "eth_worker.h"
+#include "eth_troubleshooter_icons.h"
+
+typedef enum {
+    DRAW_ALL,
+    DRAW_ONLY_TEXT,
+    DRAW_ONLY_PICTURES,
+    TOTAL_DRAW_MODES = 3,
+} DrawMode;
+
+typedef enum {
+    PROCESS_INIT,
+    PROCESS_DHCP,
+    PROCESS_STATIC,
+    PROCESS_PING,
+    PROCESS_RESET,
+} DrawProcess;
+
+typedef enum {
+    CURSOR_CHOOSE_PROCESS,
+    CURSOR_CLICK_PROCESS,
+    CURSOR_INSIDE_PROCESS,
+    CURSOR_EXIT_ICON,
+    CURSOR_EXIT,
+} CursorPosition;
+
+struct EthTroubleshooterApp {
+    Gui* gui;
+    ViewPort* view_port;
+    FuriMessageQueue* event_queue;
+    NotificationApp* notifications;
+    EthWorker* eth_worker;
+
+    Power* power;
+    PowerInfo info;
+
+    DrawMode draw_mode;
+    DrawProcess draw_process;
+    CursorPosition cursor_position;
+};
+
+typedef struct EthTroubleshooterApp EthTroubleshooterApp;

+ 422 - 0
eth_view_process.c

@@ -0,0 +1,422 @@
+#include "eth_view_process.h"
+
+#include "eth_worker.h"
+#include "eth_worker_i.h"
+#include "eth_troubleshooter_icons.h"
+
+#include <u8g2.h>
+
+#include <furi_hal.h>
+#include <gui/gui.h>
+#include <gui/canvas.h>
+#include <string.h>
+
+#define TAG "EthView"
+
+EthViewProcess* ethernet_view_process_malloc(EthWorkerProcess type, EthernetSaveConfig* config) {
+    EthViewProcess* evp = malloc(sizeof(EthViewProcess));
+    evp->type = type;
+    evp->autofill = 1;
+    evp->carriage = 0;
+    evp->position = 0;
+    evp->x = 27;
+    evp->y = 6;
+    evp->strings_cnt = 10;
+
+    if(type == EthWorkerProcessInit) {
+        evp->y += 22;
+        EthViewDrawInit* init = malloc(sizeof(EthViewDrawInit));
+        memset(init, 0, sizeof(EthViewDrawInit));
+        init->mac = (uint8_t*)config->mac;
+        evp->draw_struct = init;
+    } else if(type == EthWorkerProcessStatic) {
+        evp->y += 22;
+        EthViewDrawStatic* stat = malloc(sizeof(EthViewDrawStatic));
+        memset(stat, 0, sizeof(EthViewDrawStatic));
+        stat->ip = config->ip;
+        stat->mask = config->mask;
+        stat->gateway = config->gateway;
+        stat->dns = config->dns;
+        evp->draw_struct = stat;
+        evp->strings_cnt = 20;
+    } else if(type == EthWorkerProcessDHCP) {
+        evp->strings_cnt = 20;
+    } else if(type == EthWorkerProcessPing) {
+        evp->y += 11;
+        EthViewDrawPing* ping = malloc(sizeof(EthViewDrawPing));
+        memset(ping, 0, sizeof(EthViewDrawPing));
+        ping->ip = config->ping_ip;
+        evp->draw_struct = ping;
+        evp->strings_cnt = 20;
+    }
+
+    evp->fifo = malloc(sizeof(EthViewProcessLine) * evp->strings_cnt);
+    return evp;
+}
+
+void ethernet_view_process_free(EthViewProcess* evp) {
+    free(evp->fifo);
+    if(evp->type == EthWorkerProcessInit || evp->type == EthWorkerProcessStatic ||
+       evp->type == EthWorkerProcessPing) {
+        free(evp->draw_struct);
+    }
+    free(evp);
+}
+
+static void draw_hex_digit(Canvas* canvas, uint8_t x, uint8_t y, uint8_t digit) {
+    char digit_str[] = "0";
+    if(digit < 0xA) {
+        digit_str[0] += digit;
+    } else if(digit < 0x10) {
+        digit_str[0] = 'A';
+        digit_str[0] += digit - 0xA;
+    } else {
+        return;
+    }
+
+    canvas_draw_str(canvas, x, y, digit_str);
+}
+
+static void draw_dec_number(Canvas* canvas, uint8_t x, uint8_t y, uint8_t num) {
+    char num_str[] = "0";
+    {
+        num_str[0] = '0' + num % 10;
+        canvas_draw_str(canvas, x + 6 + 6, y, num_str);
+    }
+    if(num >= 10) {
+        num_str[0] = '0' + num / 10 - (num / 100) * 10;
+        canvas_draw_str(canvas, x + 6, y, num_str);
+    }
+    if(num >= 100) {
+        num_str[0] = '0' + num / 100;
+        canvas_draw_str(canvas, x, y, num_str);
+    }
+}
+
+static void draw_static_mode(Canvas* canvas, uint8_t mode) {
+    const uint8_t s1 = 13;
+    const uint8_t s2 = 31;
+    const uint8_t s3 = 19;
+    const uint8_t s4 = 21;
+    const uint8_t s = 35;
+    const uint8_t h = 7;
+    const uint8_t y = 10;
+    const uint8_t y1 = 15;
+
+    if(mode == EthViewDrawStaticModeIp) {
+        canvas_invert_color(canvas);
+        canvas_draw_box(canvas, s, y, s1, h);
+        canvas_invert_color(canvas);
+        canvas_draw_str(canvas, 38, y1, "ip");
+    }
+    if(mode == EthViewDrawStaticModeMask) {
+        canvas_invert_color(canvas);
+        canvas_draw_box(canvas, s + s1, y, s2, h);
+        canvas_invert_color(canvas);
+        canvas_draw_str(canvas, 53, y1, "mask");
+    }
+    if(mode == EthViewDrawStaticModeGateway) {
+        canvas_invert_color(canvas);
+        canvas_draw_box(canvas, s + s1 + s2, y, s3, h);
+        canvas_invert_color(canvas);
+        canvas_draw_str(canvas, 82, y1, "gw");
+    }
+    if(mode == EthViewDrawStaticModeDNS) {
+        canvas_invert_color(canvas);
+        canvas_draw_box(canvas, s + s1 + s2 + s3, y, s4, h);
+        canvas_invert_color(canvas);
+        canvas_draw_str(canvas, 102, y1, "dns");
+    }
+}
+
+static uint8_t* draw_static_get_current_adress(EthViewDrawStatic* evds) {
+    furi_assert(evds);
+    if(evds->current_mode == EthViewDrawStaticModeIp) return evds->ip;
+    if(evds->current_mode == EthViewDrawStaticModeMask) return evds->mask;
+    if(evds->current_mode == EthViewDrawStaticModeGateway) return evds->gateway;
+    if(evds->current_mode == EthViewDrawStaticModeDNS) return evds->dns;
+    return evds->ip;
+}
+
+void ethernet_view_process_draw(EthViewProcess* process, Canvas* canvas) {
+    furi_assert(canvas);
+    furi_assert(process);
+    canvas_set_font(canvas, FontSecondary);
+
+    const uint8_t x = process->x;
+    const uint8_t y = process->y;
+    const uint8_t str_height = 11;
+    const uint8_t str_count = (64 - y) / str_height;
+    uint8_t carriage = process->carriage;
+    uint8_t position = process->position;
+
+    if(process->autofill) {
+        position = (carriage + process->strings_cnt - str_count) % process->strings_cnt;
+        process->position = position;
+    }
+
+    for(uint8_t i = 0; i < str_count; ++i) {
+        uint8_t y1 = y + (i + 1) * str_height;
+        canvas_draw_str(canvas, x, y1, process->fifo[(position + i) % process->strings_cnt].data);
+    }
+
+    if(process->type == EthWorkerProcessInit) {
+        uint8_t editing = process->editing;
+        canvas_draw_icon(canvas, 27, 10, &I_init_100x19px);
+        uint8_t octet = ((EthViewDrawInit*)process->draw_struct)->current_octet;
+        uint8_t* mac = ((EthViewDrawInit*)process->draw_struct)->mac;
+        for(uint8_t i = 0; i < 6; ++i) {
+            uint8_t x1 = 29 + i * 17;
+            uint8_t x2 = x1 + 6;
+            draw_hex_digit(canvas, x1, 25, (mac[i] & 0xF0) >> 4);
+            draw_hex_digit(canvas, x2, 25, (mac[i] & 0x0F));
+            if(editing && (octet / 2 == i)) {
+                uint8_t x = octet & 1 ? x2 : x1;
+                canvas_draw_line(canvas, x, 26, x + 4, 26);
+                canvas_draw_line(canvas, x, 27, x + 4, 27);
+            }
+        }
+    } else if(process->type == EthWorkerProcessStatic) {
+        canvas_draw_frame(canvas, 31, 18, 21, 13);
+        canvas_draw_frame(canvas, 55, 18, 21, 13);
+        canvas_draw_frame(canvas, 79, 18, 21, 13);
+        canvas_draw_frame(canvas, 103, 18, 21, 13);
+        canvas_draw_box(canvas, 29, 10, 97, 7);
+        uint8_t mode = ((EthViewDrawStatic*)process->draw_struct)->current_mode;
+        uint8_t current_digit = ((EthViewDrawStatic*)process->draw_struct)->current_digit;
+        uint8_t* adress = draw_static_get_current_adress((EthViewDrawStatic*)process->draw_struct);
+        uint8_t editing = ((EthViewDrawStatic*)process->draw_struct)->editing;
+        for(uint8_t i = 0; i < 4; ++i) {
+            if(i == mode && process->editing) {
+                draw_static_mode(canvas, mode);
+            } else {
+                canvas_invert_color(canvas);
+                draw_static_mode(canvas, i);
+                canvas_invert_color(canvas);
+            }
+        }
+        for(uint8_t i = 0; i < 4; ++i) {
+            uint8_t x = 33 + i * 24;
+            draw_dec_number(canvas, x, 27, adress[i]);
+            if(editing && (current_digit / 3 == i)) {
+                uint8_t x1 = x + 6 * (current_digit % 3);
+                canvas_draw_line(canvas, x1, 28, x1 + 4, 28);
+                canvas_draw_line(canvas, x1, 29, x1 + 4, 29);
+            }
+        }
+    } else if(process->type == EthWorkerProcessPing) {
+        canvas_draw_frame(canvas, 35, 8, 21, 13);
+        canvas_draw_frame(canvas, 59, 8, 21, 13);
+        canvas_draw_frame(canvas, 83, 8, 21, 13);
+        canvas_draw_frame(canvas, 107, 8, 21, 13);
+        uint8_t current_digit = ((EthViewDrawPing*)process->draw_struct)->current_digit;
+        uint8_t* adress = ((EthViewDrawPing*)process->draw_struct)->ip;
+        for(uint8_t i = 0; i < 4; ++i) {
+            uint8_t x = 37 + i * 24;
+            draw_dec_number(canvas, x, 17, adress[i]);
+            if(process->editing && (current_digit / 3 == i)) {
+                uint8_t x1 = x + 6 * (current_digit % 3);
+                canvas_draw_line(canvas, x1, 18, x1 + 4, 18);
+                canvas_draw_line(canvas, x1, 19, x1 + 4, 19);
+            }
+        }
+    } else if(process->type == EthWorkerProcessReset) {
+        process->editing = 0;
+    }
+}
+
+static void mac_change_hex_digit(uint8_t* mac, uint8_t octet, int8_t diff) {
+    uint8_t digit = (octet & 1) ? (mac[octet / 2] & 0x0F) : (mac[octet / 2] >> 4);
+    digit = (digit + diff) & 0xF;
+    if(octet & 1) {
+        mac[octet / 2] = (mac[octet / 2] & 0xF0) | digit;
+    } else {
+        mac[octet / 2] = (digit << 4) | (mac[octet / 2] & 0x0F);
+    }
+}
+
+static void adress_change_dec_digit(uint8_t* ip, uint8_t digit, int8_t diff) {
+    {
+        uint8_t k = 0;
+        k = (digit % 3 == 0) ? 100 : k;
+        k = (digit % 3 == 1) ? 10 : k;
+        k = (digit % 3 == 2) ? 1 : k;
+        diff *= k;
+    }
+    {
+        int16_t ip1 = ip[digit / 3];
+        if(diff > 0 && ((0x100 - ip1) > diff)) ip1 += diff;
+        if(diff < 0 && (ip1 + diff >= 0)) ip1 += diff;
+        ip[digit / 3] = ip1;
+    }
+}
+
+void ethernet_view_process_keyevent(EthViewProcess* process, InputKey key) {
+    furi_assert(process);
+    if(process->type == EthWorkerProcessInit) {
+        uint8_t octet = ((EthViewDrawInit*)process->draw_struct)->current_octet;
+        uint8_t* mac = ((EthViewDrawInit*)process->draw_struct)->mac;
+        if(key == InputKeyLeft) {
+            if(octet > 0) octet -= 1;
+        } else if(key == InputKeyRight) {
+            if(octet < 11) octet += 1;
+        } else if(key == InputKeyUp) {
+            mac_change_hex_digit(mac, octet, 1);
+        } else if(key == InputKeyDown) {
+            mac_change_hex_digit(mac, octet, -1);
+        } else if(key == InputKeyOk || key == InputKeyBack) {
+            process->editing = 0;
+        }
+        ((EthViewDrawInit*)process->draw_struct)->current_octet = octet;
+    } else if(process->type == EthWorkerProcessDHCP) {
+        process->editing = 0;
+        if(key == InputKeyUp || key == InputKeyDown) {
+            ethernet_view_process_move(process, (key == InputKeyDown) ? 1 : -1);
+        }
+    } else if(process->type == EthWorkerProcessStatic) {
+        uint8_t digit = ((EthViewDrawStatic*)process->draw_struct)->current_digit;
+        uint8_t mode = ((EthViewDrawStatic*)process->draw_struct)->current_mode;
+        uint8_t* adress = draw_static_get_current_adress((EthViewDrawStatic*)process->draw_struct);
+        uint8_t editing = ((EthViewDrawStatic*)process->draw_struct)->editing;
+        if(editing) {
+            if(key == InputKeyLeft) {
+                if(digit > 0) {
+                    digit -= 1;
+                } else {
+                    ((EthViewDrawStatic*)process->draw_struct)->editing = 0;
+                }
+            } else if(key == InputKeyRight) {
+                if(digit < 11) digit += 1;
+            } else if(key == InputKeyUp) {
+                adress_change_dec_digit(adress, digit, 1);
+            } else if(key == InputKeyDown) {
+                adress_change_dec_digit(adress, digit, -1);
+            } else if(key == InputKeyOk || key == InputKeyBack) {
+                ((EthViewDrawStatic*)process->draw_struct)->editing = 0;
+            }
+        } else {
+            if(key == InputKeyLeft) {
+                if(mode > 0) {
+                    mode -= 1;
+                } else {
+                    process->editing = 0;
+                }
+            } else if(key == InputKeyRight) {
+                if(mode < 3) {
+                    mode += 1;
+                }
+            } else if(key == InputKeyUp || key == InputKeyDown) {
+                ethernet_view_process_move(process, (key == InputKeyDown) ? 1 : -1);
+            } else if(key == InputKeyOk) {
+                ((EthViewDrawStatic*)process->draw_struct)->editing = 1;
+            } else if(key == InputKeyBack) {
+                mode = 0;
+                process->editing = 0;
+            }
+        }
+        ((EthViewDrawStatic*)process->draw_struct)->current_mode = mode;
+        ((EthViewDrawStatic*)process->draw_struct)->current_digit = digit;
+    } else if(process->type == EthWorkerProcessPing) {
+        uint8_t digit = ((EthViewDrawPing*)process->draw_struct)->current_digit;
+        uint8_t* adress = ((EthViewDrawPing*)process->draw_struct)->ip;
+        if(key == InputKeyLeft) {
+            if(digit > 0) {
+                digit -= 1;
+            } else {
+                process->editing = 0;
+            }
+        } else if(key == InputKeyRight) {
+            if(digit < 11) digit += 1;
+        } else if(key == InputKeyUp) {
+            adress_change_dec_digit(adress, digit, 1);
+        } else if(key == InputKeyDown) {
+            adress_change_dec_digit(adress, digit, -1);
+        } else if(key == InputKeyOk || key == InputKeyBack) {
+            process->editing = 0;
+        }
+        ((EthViewDrawPing*)process->draw_struct)->current_digit = digit;
+    } else {
+        if(key == InputKeyBack || key == InputKeyLeft) {
+            process->editing = 0;
+        }
+    }
+}
+
+void ethernet_view_process_move(EthViewProcess* process, int8_t shift) {
+    furi_assert(process);
+    uint8_t position = process->position;
+    if(shift <= -process->strings_cnt) {
+        position = 0;
+    } else if(shift >= process->strings_cnt) {
+        position = process->carriage - 1;
+    } else {
+        position = (position + (process->strings_cnt + shift)) % process->strings_cnt;
+    }
+    process->position = position;
+    process->autofill = !shift;
+}
+
+void ethernet_view_process_autofill(EthViewProcess* process, uint8_t state) {
+    furi_assert(process);
+    process->autofill = state;
+}
+
+static uint16_t get_string_with_width(const char* str, uint16_t width) {
+    u8g2_t canvas_memory;
+    Canvas* canvas = (Canvas*)&canvas_memory; // grazniy hack
+    canvas_set_font(canvas, FontSecondary);
+
+    uint8_t end = 0;
+    char copy[SCREEN_SYMBOLS_WIDTH + 1] = {0};
+
+    for(;;) {
+        if(str[end] == '\n') {
+            break;
+        }
+        if(str[end] == '\0') {
+            break;
+        }
+        if(end == SCREEN_SYMBOLS_WIDTH) {
+            break;
+        }
+        copy[end] = str[end];
+        if(canvas_string_width(canvas, copy) > width) {
+            end -= 1;
+            break;
+        }
+        end += 1;
+    }
+
+    return end;
+}
+
+void evp_printf(EthViewProcess* process, const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    FuriString* fstring = furi_string_alloc_vprintf(format, args);
+    va_end(args);
+    ethernet_view_process_print(process, furi_string_get_cstr(fstring));
+    furi_string_free(fstring);
+}
+
+void ethernet_view_process_print(EthViewProcess* process, const char* str) {
+    furi_assert(process);
+
+    uint16_t max_width = 126 - process->x;
+    uint16_t ptr = 0;
+    uint16_t len = strlen(str);
+
+    while(ptr < len) {
+        if(str[ptr] == '\n') ptr += 1;
+        uint16_t start = ptr;
+        ptr += get_string_with_width(str + ptr, max_width);
+        uint8_t carriage = process->carriage;
+        uint8_t carriage1 = (carriage + 1) % process->strings_cnt;
+        uint8_t carriage2 = (carriage + 2) % process->strings_cnt;
+        memset(process->fifo[carriage].data, 0, SCREEN_SYMBOLS_WIDTH);
+        memset(process->fifo[carriage1].data, 0, SCREEN_SYMBOLS_WIDTH);
+        memset(process->fifo[carriage2].data, 0, SCREEN_SYMBOLS_WIDTH);
+        memcpy(process->fifo[carriage].data, str + start, ptr - start);
+        process->carriage = carriage1;
+    }
+}

+ 59 - 0
eth_view_process.h

@@ -0,0 +1,59 @@
+#pragma once
+
+#include "eth_worker.h"
+#include "eth_save_process.h"
+#include <gui/gui.h>
+
+#define SCREEN_SYMBOLS_WIDTH 30
+
+EthViewProcess* ethernet_view_process_malloc(EthWorkerProcess type, EthernetSaveConfig* config);
+void ethernet_view_process_free(EthViewProcess* evp);
+
+void ethernet_view_process_draw(EthViewProcess* process, Canvas* canvas);
+void ethernet_view_process_keyevent(EthViewProcess* process, InputKey key);
+void ethernet_view_process_print(EthViewProcess* process, const char* str);
+void ethernet_view_process_move(EthViewProcess* process, int8_t shift);
+void evp_printf(EthViewProcess* process, const char* format, ...);
+
+typedef struct EthViewProcessLine {
+    char data[SCREEN_SYMBOLS_WIDTH];
+} EthViewProcessLine;
+
+struct EthViewProcess {
+    EthViewProcessLine* fifo;
+    EthWorkerProcess type;
+    uint8_t strings_cnt;
+    uint8_t carriage;
+    uint8_t position;
+    uint8_t autofill;
+    uint8_t editing;
+    uint8_t x;
+    uint8_t y;
+    void* draw_struct;
+};
+
+typedef struct EthViewDrawInit {
+    uint8_t* mac;
+    uint8_t current_octet;
+} EthViewDrawInit;
+
+typedef enum {
+    EthViewDrawStaticModeIp,
+    EthViewDrawStaticModeMask,
+    EthViewDrawStaticModeGateway,
+    EthViewDrawStaticModeDNS
+} EthViewDrawStaticMode;
+typedef struct EthViewDrawStatic {
+    EthViewDrawStaticMode current_mode;
+    uint8_t* ip;
+    uint8_t* mask;
+    uint8_t* gateway;
+    uint8_t* dns;
+    uint8_t current_digit;
+    uint8_t editing;
+} EthViewDrawStatic;
+
+typedef struct EthViewDrawPing {
+    uint8_t current_digit;
+    uint8_t* ip;
+} EthViewDrawPing;

+ 582 - 0
eth_worker.c

@@ -0,0 +1,582 @@
+#include "eth_worker_i.h"
+#include "eth_worker.h"
+#include "eth_save_process.h"
+
+#include <furi_hal.h>
+#include "dhcp.h"
+#include "socket.h"
+#include <wizchip_conf.h>
+
+#define TAG "EthWorker"
+
+static EthWorker* static_worker = NULL;
+
+EthWorker* eth_worker_alloc() {
+    EthWorker* worker = malloc(sizeof(EthWorker));
+
+    worker->config = ethernet_save_process_malloc();
+    furi_assert(worker->config);
+
+    worker->init_process = ethernet_view_process_malloc(EthWorkerProcessInit, worker->config);
+    worker->dhcp_process = ethernet_view_process_malloc(EthWorkerProcessDHCP, worker->config);
+    worker->stat_process = ethernet_view_process_malloc(EthWorkerProcessStatic, worker->config);
+    worker->ping_process = ethernet_view_process_malloc(EthWorkerProcessPing, worker->config);
+    worker->reset_process = ethernet_view_process_malloc(EthWorkerProcessReset, worker->config);
+    worker->active_process = worker->init_process;
+
+    static_worker = worker;
+
+    worker->state = worker->next_state = EthWorkerStateNotAllocated;
+
+    worker->timer = furi_timer_alloc(dhcp_timer_callback, FuriTimerTypePeriodic, NULL);
+    furi_timer_start(worker->timer, 1000);
+
+    eth_log(EthWorkerProcessReset, "Finik Ethernet [START]");
+
+    return worker;
+}
+
+void eth_worker_free(EthWorker* worker) {
+    eth_log(EthWorkerProcessReset, "Finik Ethernet [STOP]");
+
+    eth_run(worker, EthWorkerProcessExit);
+
+    static_worker = NULL;
+    furi_assert(worker);
+
+    ethernet_view_process_free(worker->init_process);
+    ethernet_view_process_free(worker->dhcp_process);
+    ethernet_view_process_free(worker->stat_process);
+    ethernet_view_process_free(worker->ping_process);
+    ethernet_view_process_free(worker->reset_process);
+    ethernet_save_process_free(worker->config);
+
+    furi_timer_stop(worker->timer);
+    furi_timer_free(worker->timer);
+
+    free(worker);
+}
+
+void eth_worker_change_state(EthWorker* worker, EthWorkerState state) {
+    furi_assert(worker);
+    worker->state = state;
+}
+
+void eth_worker_set_active_process(EthWorker* worker, EthWorkerProcess state) {
+    furi_assert(worker);
+    switch(state) {
+    case EthWorkerProcessInit:
+        worker->active_process = worker->init_process;
+        break;
+    case EthWorkerProcessDHCP:
+        worker->active_process = worker->dhcp_process;
+        break;
+    case EthWorkerProcessStatic:
+        worker->active_process = worker->stat_process;
+        break;
+    case EthWorkerProcessPing:
+        worker->active_process = worker->ping_process;
+        break;
+    case EthWorkerProcessReset:
+        worker->active_process = worker->reset_process;
+        break;
+    default:
+        break;
+    }
+}
+
+void eth_worker_log(EthWorker* worker, const char* str) {
+    furi_assert(worker);
+    ethernet_save_process_print(worker->config, str);
+}
+
+static EthViewProcess* get_process(EthWorker* worker, EthWorkerProcess process) {
+    furi_assert(worker);
+    switch(process) {
+    case EthWorkerProcessInit:
+        return worker->init_process;
+    case EthWorkerProcessDHCP:
+        return worker->dhcp_process;
+    case EthWorkerProcessStatic:
+        return worker->stat_process;
+    case EthWorkerProcessPing:
+        return worker->ping_process;
+    case EthWorkerProcessReset:
+        return worker->reset_process;
+    case EthWorkerProcessActive:
+        return worker->active_process;
+    default:
+        return NULL;
+    }
+}
+
+void eth_log(EthWorkerProcess process, const char* format, ...) {
+    furi_assert(static_worker);
+    va_list args;
+    va_start(args, format);
+    FuriString* fstring = furi_string_alloc_vprintf(format, args);
+    const char* string = furi_string_get_cstr(fstring);
+    va_end(args);
+
+    FURI_LOG_I(TAG, "%s", string);
+    ethernet_save_process_print(static_worker->config, string);
+    ethernet_view_process_print(get_process(static_worker, process), string);
+    if(process != EthWorkerProcessReset) {
+        ethernet_view_process_print(get_process(static_worker, EthWorkerProcessReset), string);
+    }
+    furi_string_free(fstring);
+}
+
+void eth_printf(const char* format, ...) {
+    furi_assert(static_worker);
+    va_list args;
+    va_start(args, format);
+    FuriString* fstring = furi_string_alloc_vprintf(format, args);
+    const char* string = furi_string_get_cstr(fstring);
+    va_end(args);
+
+    FURI_LOG_I(TAG, "%s", string);
+    //ehternet_save_process_print(static_worker->config, string);
+    furi_string_free(fstring);
+}
+
+static void eth_set_force_state(EthWorkerState state) {
+    EthWorker* worker = static_worker;
+    furi_assert(worker);
+    worker->next_state = EthWorkerStateDefaultNext;
+    if(worker->state == EthWorkerStateNotAllocated) {
+        return;
+    }
+    worker->state = state;
+}
+
+void eth_set_state() {
+}
+
+void eth_set_next_state(EthWorkerState state) {
+    EthWorker* worker = static_worker;
+    furi_assert(worker);
+    if(state == EthWorkerStateReset || state == EthWorkerStateStop) {
+        eth_set_force_state(state);
+        return;
+    }
+    if(worker->state == EthWorkerStateNotInited) {
+        if(state == EthWorkerStateInit) {
+            worker->next_state = state;
+        }
+    }
+    if(worker->state == EthWorkerStateInited) {
+        if(state == EthWorkerStateDHCP || state == EthWorkerStateStaticIp) {
+            worker->next_state = state;
+        }
+    }
+    if(worker->state == EthWorkerStateOnline) {
+        if(state == EthWorkerStatePing) {
+            worker->next_state = state;
+        }
+    }
+}
+
+void eth_run(EthWorker* worker, EthWorkerProcess process) {
+    furi_assert(worker);
+    switch(process) {
+    case EthWorkerProcessInit:
+        if(worker->state == EthWorkerStateNotAllocated) {
+            worker->thread = furi_thread_alloc();
+            furi_thread_set_name(worker->thread, "EthWorker");
+            furi_thread_set_stack_size(worker->thread, 8192);
+            furi_thread_set_callback(worker->thread, eth_worker_task);
+            furi_thread_set_context(worker->thread, worker);
+            worker->state = EthWorkerStateNotInited;
+            furi_thread_start(worker->thread);
+        }
+        eth_set_next_state(EthWorkerStateInit);
+        break;
+    case EthWorkerProcessDHCP:
+        eth_set_next_state(EthWorkerStateDHCP);
+        break;
+    case EthWorkerProcessStatic:
+        eth_set_next_state(EthWorkerStateStaticIp);
+        break;
+    case EthWorkerProcessPing:
+        eth_set_next_state(EthWorkerStatePing);
+        break;
+    case EthWorkerProcessReset:
+        eth_set_next_state(EthWorkerStateReset);
+        eth_log(EthWorkerProcessInit, "reset module");
+        eth_log(EthWorkerProcessDHCP, "reset module");
+        eth_log(EthWorkerProcessStatic, "reset module");
+        eth_log(EthWorkerProcessPing, "reset module");
+        eth_log(EthWorkerProcessReset, "reset module");
+        break;
+    case EthWorkerProcessExit:
+        if(worker->state != EthWorkerStateNotAllocated) {
+            eth_set_force_state(EthWorkerStateStop);
+            furi_thread_join(worker->thread);
+            furi_thread_free(worker->thread);
+            worker->state = EthWorkerStateNotAllocated;
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+/************************** Ethernet Worker Thread *****************************/
+
+static uint8_t ip_assigned = 0;
+static GpioPin cspin = {.port = GPIOA, .pin = LL_GPIO_PIN_4};
+static GpioPin resetpin = {.port = GPIOC, .pin = LL_GPIO_PIN_3};
+
+static void W5500_Select(void) {
+    furi_hal_gpio_write(&cspin, false);
+}
+
+static void W5500_Unselect(void) {
+    furi_hal_gpio_write(&cspin, true);
+}
+
+static void Callback_IPAssigned(void) {
+    eth_log(
+        EthWorkerProcessDHCP, "Callback: IP assigned! Leased time: %d sec", getDHCPLeasetime());
+    ip_assigned = 1;
+}
+
+static void Callback_IPConflict(void) {
+    eth_log(EthWorkerProcessDHCP, "Callback: IP conflict!");
+}
+
+static void W5500_ReadBuff(uint8_t* buff, uint16_t len) {
+    furi_hal_spi_bus_rx(&furi_hal_spi_bus_handle_external, buff, len, 1000);
+}
+
+static void W5500_WriteBuff(uint8_t* buff, uint16_t len) {
+    furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_external, buff, len, 1000);
+}
+
+static uint8_t W5500_ReadByte(void) {
+    uint8_t byte;
+    W5500_ReadBuff(&byte, sizeof(byte));
+    return byte;
+}
+
+static void W5500_WriteByte(uint8_t byte) {
+    W5500_WriteBuff(&byte, sizeof(byte));
+}
+
+static wiz_NetInfo gWIZNETINFO;
+void update_WIZNETINFO(uint8_t is_dhcp) {
+    furi_assert(static_worker);
+    memcpy(gWIZNETINFO.mac, static_worker->config->mac, 6);
+    if(is_dhcp) {
+        memset(gWIZNETINFO.ip, 0, 4);
+        memset(gWIZNETINFO.sn, 0, 4);
+        memset(gWIZNETINFO.gw, 0, 4);
+        memset(gWIZNETINFO.dns, 0, 4);
+        gWIZNETINFO.dhcp = NETINFO_DHCP;
+    } else {
+        memcpy(gWIZNETINFO.ip, static_worker->config->ip, 4);
+        memcpy(gWIZNETINFO.sn, static_worker->config->mask, 4);
+        memcpy(gWIZNETINFO.gw, static_worker->config->gateway, 4);
+        memcpy(gWIZNETINFO.dns, static_worker->config->dns, 4);
+        gWIZNETINFO.dhcp = NETINFO_STATIC;
+    }
+}
+
+int check_phylink(EthWorker* worker, EthWorkerState state, EthWorkerProcess proc, int timeout) {
+    uint32_t start_time = furi_get_tick();
+    uint32_t last_log_time = start_time;
+    eth_log(proc, "phy link check 0");
+    for(;;) {
+        if(furi_get_tick() > start_time + timeout) {
+            eth_log(proc, "phy link timeout");
+            break;
+        }
+        if(worker->state != state) {
+            eth_log(proc, "state changed");
+            break;
+        }
+        uint8_t link = PHY_LINK_OFF;
+        if(ctlwizchip(CW_GET_PHYLINK, (void*)&link) == -1) {
+            eth_log(proc, "Unknown PHY link status");
+            break;
+        }
+        if(link != PHY_LINK_OFF) {
+            eth_log(proc, "phy link on");
+            return 1;
+        }
+        furi_delay_ms(20);
+        if(furi_get_tick() > last_log_time + 1000) {
+            eth_log(proc, "phy link check %d", (last_log_time - start_time) / 1000);
+            last_log_time = furi_get_tick();
+        }
+    }
+    return 0;
+}
+
+#define DHCP_SOCKET 0
+uint8_t ping_auto(uint8_t s, uint8_t* addr);
+
+static void load_net_parameters(const EthernetSaveConfig* cfg) {
+    gWIZNETINFO.gw[0] = cfg->gateway[0];
+    gWIZNETINFO.gw[1] = cfg->gateway[1];
+    gWIZNETINFO.gw[2] = cfg->gateway[2];
+    gWIZNETINFO.gw[3] = cfg->gateway[3];
+
+    gWIZNETINFO.sn[0] = cfg->mask[0];
+    gWIZNETINFO.sn[1] = cfg->mask[1];
+    gWIZNETINFO.sn[2] = cfg->mask[2];
+    gWIZNETINFO.sn[3] = cfg->mask[3];
+
+    gWIZNETINFO.mac[0] = cfg->mac[0];
+    gWIZNETINFO.mac[1] = cfg->mac[1];
+    gWIZNETINFO.mac[2] = cfg->mac[2];
+    gWIZNETINFO.mac[3] = cfg->mac[3];
+    gWIZNETINFO.mac[4] = cfg->mac[4];
+    gWIZNETINFO.mac[5] = cfg->mac[5];
+
+    gWIZNETINFO.ip[0] = cfg->ip[0];
+    gWIZNETINFO.ip[1] = cfg->ip[1];
+    gWIZNETINFO.ip[2] = cfg->ip[2];
+    gWIZNETINFO.ip[3] = cfg->ip[3];
+
+    gWIZNETINFO.dns[0] = cfg->dns[0];
+    gWIZNETINFO.dns[1] = cfg->dns[1];
+    gWIZNETINFO.dns[2] = cfg->dns[2];
+    gWIZNETINFO.dns[3] = cfg->dns[3];
+
+    gWIZNETINFO.dhcp = NETINFO_STATIC;
+}
+
+int32_t eth_worker_task(void* context) {
+    furi_assert(context);
+    EthWorker* worker = (EthWorker*)context;
+    furi_hal_power_insomnia_enter();
+
+    furi_hal_spi_acquire(&furi_hal_spi_bus_handle_external);
+    uint8_t W5500FifoSize[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};
+    uint8_t dhcp_buffer[2048];
+
+    reg_wizchip_spi_cbfunc(W5500_ReadByte, W5500_WriteByte);
+    reg_wizchip_spiburst_cbfunc(W5500_ReadBuff, W5500_WriteBuff);
+    reg_wizchip_cs_cbfunc(W5500_Select, W5500_Unselect);
+
+    furi_hal_gpio_write(&resetpin, true);
+    furi_hal_gpio_write(&cspin, true);
+    furi_hal_gpio_init(&resetpin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedVeryHigh);
+    furi_hal_gpio_init(&cspin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedVeryHigh);
+
+    while(worker->state != EthWorkerStateStop) {
+        if(worker->state == EthWorkerStateNotInited) {
+            if(worker->next_state == EthWorkerStateInit) {
+                worker->state = worker->next_state;
+            }
+        } else if(worker->state == EthWorkerStateInited) {
+            if(worker->next_state == EthWorkerStateDHCP ||
+               worker->next_state == EthWorkerStateStaticIp) {
+                worker->state = worker->next_state;
+            }
+        } else if(worker->state == EthWorkerStateOnline) {
+            if(worker->next_state == EthWorkerStatePing) {
+                worker->state = worker->next_state;
+            }
+        } else if(worker->state == EthWorkerStateReset) {
+            worker->state = EthWorkerStateNotInited;
+        }
+
+        if(worker->state == EthWorkerStateInit) {
+            furi_hal_power_enable_otg();
+            furi_delay_ms(300);
+            furi_hal_gpio_write(&resetpin, false);
+            furi_delay_ms(50);
+            furi_hal_gpio_write(&resetpin, true);
+            if(ctlwizchip(CW_INIT_WIZCHIP, (void*)W5500FifoSize) == -1) {
+                eth_log(EthWorkerProcessInit, "[error] W5500 init fail");
+                eth_set_force_state(EthWorkerStateNotInited);
+                continue;
+            }
+            eth_log(EthWorkerProcessInit, "W5500 inited");
+            furi_delay_ms(50);
+            update_WIZNETINFO(false);
+            wizchip_setnetinfo(&gWIZNETINFO);
+            wiz_NetInfo readed_net_info;
+            wizchip_getnetinfo(&readed_net_info);
+            if(memcmp(&readed_net_info, &gWIZNETINFO, sizeof(wiz_NetInfo))) {
+                eth_log(EthWorkerProcessInit, "[error] module not detected");
+                eth_set_force_state(EthWorkerStateNotInited);
+                continue;
+            }
+            setSHAR(gWIZNETINFO.mac);
+            wiz_PhyConf conf;
+            wizphy_getphyconf(&conf);
+            eth_log(
+                EthWorkerProcessInit,
+                "conf %d %d %d %d",
+                conf.by,
+                conf.mode,
+                conf.speed,
+                conf.duplex);
+            eth_log(EthWorkerProcessInit, "net info setted");
+            eth_log(
+                EthWorkerProcessInit,
+                "mac: %02X-%02X-%02X-%02X-%02X-%02X",
+                gWIZNETINFO.mac[0],
+                gWIZNETINFO.mac[1],
+                gWIZNETINFO.mac[2],
+                gWIZNETINFO.mac[3],
+                gWIZNETINFO.mac[4],
+                gWIZNETINFO.mac[5]);
+            eth_set_force_state(EthWorkerStateInited);
+        } else if(worker->state == EthWorkerStateDHCP) {
+            if(!check_phylink(worker, EthWorkerStateDHCP, EthWorkerProcessDHCP, 5000)) {
+                worker->state = EthWorkerStateInited;
+                continue;
+            }
+            reg_dhcp_cbfunc(Callback_IPAssigned, Callback_IPAssigned, Callback_IPConflict);
+            DHCP_init(DHCP_SOCKET, dhcp_buffer);
+            {
+                // DHCP_run();
+                // eth_log(EthWorkerProcessDHCP, "DHCP Send Discover");
+                // furi_delay_ms(1000);
+                // DHCP_stop();
+            }
+            uint8_t next_cycle = 1;
+            uint16_t divider = 0;
+            while(next_cycle && worker->state == EthWorkerStateDHCP) {
+                uint8_t dhcp_ret = DHCP_run();
+                switch(dhcp_ret) {
+                case DHCP_IP_ASSIGN:
+                case DHCP_IP_CHANGED:
+                case DHCP_IP_LEASED:
+                    getIPfromDHCP(gWIZNETINFO.ip);
+                    getGWfromDHCP(gWIZNETINFO.gw);
+                    getSNfromDHCP(gWIZNETINFO.sn);
+                    getDNSfromDHCP(gWIZNETINFO.dns);
+                    gWIZNETINFO.dhcp = NETINFO_DHCP;
+                    ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);
+                    eth_log(
+                        EthWorkerProcessDHCP, "DHCP IP Leased Time : %ld Sec", getDHCPLeasetime());
+                    break;
+                case DHCP_FAILED:
+                    eth_log(EthWorkerProcessDHCP, "DHCP Failed");
+                    break;
+                }
+                furi_delay_ms(10);
+                if(divider++ % 100 == 0) {
+                    eth_log(EthWorkerProcessDHCP, "DHCP process %d", divider / 100);
+                    if(divider > 2000) {
+                        DHCP_stop();
+                        eth_log(EthWorkerProcessDHCP, "DHCP Stop by timer");
+                        eth_set_force_state(EthWorkerStateInited);
+                        break;
+                    }
+                }
+                next_cycle = (dhcp_ret == DHCP_RUNNING);
+            }
+            if(worker->state != EthWorkerStateDHCP) {
+                continue;
+            }
+            eth_log(
+                EthWorkerProcessDHCP,
+                "IP address:\n %d.%d.%d.%d",
+                gWIZNETINFO.ip[0],
+                gWIZNETINFO.ip[1],
+                gWIZNETINFO.ip[2],
+                gWIZNETINFO.ip[3]);
+            eth_log(
+                EthWorkerProcessDHCP,
+                "SM Mask:\n %d.%d.%d.%d",
+                gWIZNETINFO.sn[0],
+                gWIZNETINFO.sn[1],
+                gWIZNETINFO.sn[2],
+                gWIZNETINFO.sn[3]);
+            eth_log(
+                EthWorkerProcessDHCP,
+                "Gate way:\n %d.%d.%d.%d",
+                gWIZNETINFO.gw[0],
+                gWIZNETINFO.gw[1],
+                gWIZNETINFO.gw[2],
+                gWIZNETINFO.gw[3]);
+            eth_log(
+                EthWorkerProcessDHCP,
+                "DNS Server:\n %d.%d.%d.%d",
+                gWIZNETINFO.dns[0],
+                gWIZNETINFO.dns[1],
+                gWIZNETINFO.dns[2],
+                gWIZNETINFO.dns[3]);
+            eth_set_force_state(EthWorkerStateOnline);
+        } else if(worker->state == EthWorkerStateStaticIp) {
+            if(!check_phylink(worker, EthWorkerStateStaticIp, EthWorkerProcessStatic, 5000)) {
+                worker->state = EthWorkerStateInited;
+                continue;
+            }
+            eth_log(EthWorkerProcessStatic, "set static ip");
+            load_net_parameters(worker->config);
+            eth_log(
+                EthWorkerProcessStatic,
+                "IP address:\n %d.%d.%d.%d",
+                gWIZNETINFO.ip[0],
+                gWIZNETINFO.ip[1],
+                gWIZNETINFO.ip[2],
+                gWIZNETINFO.ip[3]);
+            eth_log(
+                EthWorkerProcessStatic,
+                "SM Mask:\n %d.%d.%d.%d",
+                gWIZNETINFO.sn[0],
+                gWIZNETINFO.sn[1],
+                gWIZNETINFO.sn[2],
+                gWIZNETINFO.sn[3]);
+            eth_log(
+                EthWorkerProcessStatic,
+                "Gate way:\n %d.%d.%d.%d",
+                gWIZNETINFO.gw[0],
+                gWIZNETINFO.gw[1],
+                gWIZNETINFO.gw[2],
+                gWIZNETINFO.gw[3]);
+            eth_log(
+                EthWorkerProcessStatic,
+                "DNS Server:\n %d.%d.%d.%d",
+                gWIZNETINFO.dns[0],
+                gWIZNETINFO.dns[1],
+                gWIZNETINFO.dns[2],
+                gWIZNETINFO.dns[3]);
+            ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);
+            eth_set_force_state(EthWorkerStateOnline);
+        } else if(worker->state == EthWorkerStatePing) {
+            uint8_t* adress = worker->config->ping_ip;
+            eth_log(
+                EthWorkerProcessPing,
+                "ping %d.%d.%d.%d",
+                adress[0],
+                adress[1],
+                adress[2],
+                adress[3]);
+            const uint8_t tryes = 4;
+            uint8_t try = 0;
+            while(try < tryes && worker->state == EthWorkerStatePing) {
+                try++;
+                uint32_t start_time = furi_get_tick();
+                uint8_t res = ping_auto_interface(adress);
+                uint32_t res_time = furi_get_tick();
+                if(res == 3) {
+                    eth_log(EthWorkerProcessPing, "%d success %d ms", try, res_time - start_time);
+                } else {
+                    eth_log(
+                        EthWorkerProcessPing, "%d error %d, %d", try, res, res_time - start_time);
+                    break;
+                }
+            }
+            if(worker->state != EthWorkerStatePing) {
+                break;
+            }
+            eth_set_force_state(EthWorkerStateOnline);
+        }
+        furi_delay_ms(5);
+    }
+
+    furi_hal_spi_release(&furi_hal_spi_bus_handle_external);
+    furi_hal_power_disable_otg();
+    furi_hal_power_insomnia_exit();
+
+    return 0;
+}

+ 78 - 0
eth_worker.h

@@ -0,0 +1,78 @@
+#pragma once
+
+#include <stdint.h>
+
+typedef struct EthWorker EthWorker;
+typedef struct EthViewProcess EthViewProcess;
+
+typedef enum {
+    EthWorkerStateNotAllocated = 0,
+    EthWorkerStateNotInited,
+    EthWorkerStateDefaultNext,
+    EthWorkerStateInited,
+    EthWorkerStateInit,
+    EthWorkerStateModulePowerOn,
+    EthWorkerStateModuleConnect,
+    EthWorkerStateMACInit,
+    EthWorkerStateStaticIp,
+    EthWorkerStateDHCP,
+    EthWorkerStateOnline,
+    EthWorkerStatePing,
+    EthWorkerStateStop,
+    EthWorkerStateReset,
+} EthWorkerState;
+
+typedef enum {
+    EthWorkerProcessInit,
+    EthWorkerProcessDHCP,
+    EthWorkerProcessStatic,
+    EthWorkerProcessPing,
+    EthWorkerProcessReset,
+    EthWorkerProcessActive,
+    EthWorkerProcessExit,
+} EthWorkerProcess;
+
+typedef enum {
+    EthWorkerSubstateInProcess = 0,
+    EthWorkerSubStateSuccess,
+    EthWorkerSubStateError,
+} EthWorkerSubState;
+
+typedef enum {
+    EthCustomEventUpdate = 0,
+    EthCustomEventModuleInit,
+    EthCustomEventModuleError,
+    EthCustomEventModulePowerOn,
+    EthCustomEventModuleConnect,
+    EthCustomEventMACInit,
+    EthCustomEventStaticIp,
+    EthCustomEventDHCP,
+    EthCustomEventPing,
+    EthCustomEventTCP2UART,
+    EthCustomEventTCP2CLI,
+    EthCustomEventSaved,
+} EthCustomEvent;
+
+typedef void (*EthWorkerCallback)(EthCustomEvent event, void* context);
+
+EthWorker* eth_worker_alloc();
+
+EthWorkerState eth_worker_get_state(EthWorker* eth_worker);
+void eth_worker_set_active_process(EthWorker* eth_worker, EthWorkerProcess state);
+
+void eth_worker_free(EthWorker* eth_worker);
+
+void eth_worker_start(
+    EthWorker* eth_worker,
+    EthWorkerState state,
+    EthWorkerCallback callback,
+    void* context);
+
+void eth_worker_stop(EthWorker* eth_worker);
+void eth_worker_dhcp(EthWorker* eth_worker);
+void eth_worker_w5500(EthWorker* eth_worker);
+void eth_worker_init_process(EthWorker* eth_worker);
+
+#define PING_SOCKET 1
+uint8_t ping_auto_interface(uint8_t* adress);
+void dhcp_timer_callback(void* context);

+ 8 - 0
eth_worker_dhcp.c

@@ -0,0 +1,8 @@
+#include "eth_worker.h"
+#include <furi_hal.h>
+#include <dhcp.h>
+
+void dhcp_timer_callback(void* context) {
+    UNUSED(context);
+    DHCP_time_handler();
+}

+ 31 - 0
eth_worker_i.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include <furi.h>
+#include "eth_worker.h"
+#include "eth_view_process.h"
+#include "eth_save_process.h"
+
+struct EthWorker {
+    FuriThread* thread;
+    void* context;
+    EthernetSaveConfig* config;
+    EthViewProcess* init_process;
+    EthViewProcess* dhcp_process;
+    EthViewProcess* stat_process;
+    EthViewProcess* ping_process;
+    EthViewProcess* reset_process;
+    EthViewProcess* active_process;
+
+    EthWorkerState state;
+    EthWorkerState next_state;
+    EthWorkerSubState sub_state;
+    EthWorkerCallback callback;
+    FuriTimer* timer;
+};
+
+void eth_worker_change_state(EthWorker* eth_worker, EthWorkerState state);
+void eth_worker_log(EthWorker* eth_worker, const char* str);
+void eth_run(EthWorker* worker, EthWorkerProcess process);
+void eth_log(EthWorkerProcess process, const char* format, ...);
+
+int32_t eth_worker_task(void* context);

+ 11 - 0
eth_worker_ping.c

@@ -0,0 +1,11 @@
+#include "eth_worker.h"
+#include <furi_hal.h>
+#include <ping.h>
+
+void ping_wait_ms(int ms) {
+    furi_delay_ms(ms);
+}
+
+uint8_t ping_auto_interface(uint8_t* adress) {
+    return ping_auto(PING_SOCKET, adress);
+}

TEMPAT SAMPAH
images/ethernet_icon_10x10px.png


TEMPAT SAMPAH
images/exit_128x64px.png


TEMPAT SAMPAH
images/init_100x19px.png


TEMPAT SAMPAH
images/main_128x64px.png


TEMPAT SAMPAH
images/screenshot-ping.png


TEMPAT SAMPAH
images/screenshot_dhcp.png


TEMPAT SAMPAH
images/screenshot_init.png


TEMPAT SAMPAH
images/screenshot_static.png


+ 22 - 0
lib/ioLibrary_Driver/.gitattributes

@@ -0,0 +1,22 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+
+# Custom for Visual Studio
+*.cs     diff=csharp
+*.sln    merge=union
+*.csproj merge=union
+*.vbproj merge=union
+*.fsproj merge=union
+*.dbproj merge=union
+
+# Standard to msysgit
+*.doc	 diff=astextplain
+*.DOC	 diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot  diff=astextplain
+*.DOT  diff=astextplain
+*.pdf  diff=astextplain
+*.PDF	 diff=astextplain
+*.rtf	 diff=astextplain
+*.RTF	 diff=astextplain

+ 1940 - 0
lib/ioLibrary_Driver/.gitignore

@@ -0,0 +1,1940 @@
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# =========================
+# Operating System Files
+# =========================
+
+# OSX
+# =========================
+
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+man/man3/wizchip_conf.h.3
+man/man3/wizchip_conf.c.3
+man/man3/wiz_PhyConf_t.3
+man/man3/wiz_NetTimeout_t.3
+man/man3/wiz_NetInfo_t.3
+man/man3/w5500.jpg.3
+man/man3/w5500.h.3
+man/man3/w5500.c.3
+man/man3/w5300.h.3
+man/man3/w5300.c.3
+man/man3/w5200_w5500.jpg.3
+man/man3/w5200.h.3
+man/man3/ftpc.h.3
+man/man3/ftpc.c.3
+man/man3/ftpc.3
+man/man3/extra_functions.3
+man/man3/doxygen_log.txt.3
+man/man3/dns.h.3
+man/man3/dns.c.3
+man/man3/dhdr.3
+man/man3/dhcp.h.3
+man/man3/dhcp.c.3
+man/man3/dataEntryType.3
+man/man3/_un_l2cval.3
+man/man3/_st_http_socket.3
+man/man3/_st_http_request.3
+man/man3/_ntpformat.3
+man/man3/_httpServer_webContent.3
+man/man3/W5100.3
+man/man3/Timer.3
+man/man3/StackTrace.h.3
+man/man3/Special_function_W5100S.3
+man/man3/Socket_register_group_W5300.3
+man/man3/Socket_register_group_W5200.3
+man/man3/Socket_register_group_W5100S.3
+man/man3/Socket_register_group_W5100.3
+man/man3/Socket_register_group.3
+man/man3/Socket_register_access_function_W5300.3
+man/man3/Socket_register_access_function_W5200.3
+man/man3/Socket_register_access_function_W5100S.3
+man/man3/Socket_register_access_function_W5100.3
+man/man3/Socket_register_access_function.3
+man/man3/Readme.txt.3
+man/man3/RIP_MSG.3
+man/man3/README.md.3
+man/man3/Network.3
+man/man3/MessageData.3
+man/man3/Main_page.txt.3
+man/man3/MQTTUnsubscribeServer.c.3
+man/man3/MQTTUnsubscribeClient.c.3
+man/man3/MQTTUnsubscribe.h.3
+man/man3/MQTTTransport.3
+man/man3/MQTTSubscribeServer.c.3
+man/man3/MQTTSubscribeClient.c.3
+man/man3/MQTTSubscribe.h.3
+man/man3/MQTTString.3
+man/man3/MQTTSerializePublish.c.3
+man/man3/MQTTPublish.h.3
+man/man3/MQTTPacket_willOptions.3
+man/man3/MQTTPacket_connectData.3
+man/man3/MQTTPacket.h.3
+man/man3/MQTTPacket.c.3
+man/man3/MQTTMessage.3
+man/man3/MQTTLenString.3
+man/man3/MQTTHeader.3
+man/man3/MQTTFormat.h.3
+man/man3/MQTTFormat.c.3
+man/man3/MQTTDeserializePublish.c.3
+man/man3/MQTTConnectServer.c.3
+man/man3/MQTTConnectFlags.3
+man/man3/MQTTConnectClient.c.3
+man/man3/MQTTConnect.h.3
+man/man3/MQTTConnackFlags.3
+man/man3/MQTTClient_MessageHandlers.3
+man/man3/MQTTClient.h.3
+man/man3/MQTTClient.c.3
+man/man3/MQTTClient.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_img_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_image_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_httpServer_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_TFTP_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_SNTP_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_SNMP_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_MQTT_MQTTPacket_src_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_MQTT_MQTTPacket_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_MQTT_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_FTPServer_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_FTPClient_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_DNS_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_DHCP_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Internet_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Ethernet_W5500_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Ethernet_W5300_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Ethernet_W5200_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Ethernet_W5100_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Ethernet_W5100S_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Ethernet_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Application_loopback_.3
+man/man3/D__workspace_CoIDE WorkSpace_ioLibrary_Driver_Application_.3
+man/man3/DATA_TYPE.3
+man/man3/Common_register_group_W5300.3
+man/man3/Common_register_group_W5200.3
+man/man3/Common_register_group_W5100S.3
+man/man3/Common_register_group_W5100.3
+man/man3/Common_register_group.3
+man/man3/Common_register_access_function_W5300.3
+man/man3/Common_register_access_function_W5200.3
+man/man3/Common_register_access_function_W5100S.3
+man/man3/Common_register_access_function_W5100.3
+man/man3/Common_register_access_function.3
+man/man3/Command.3
+man/man3/Berkeley_SOCKET.jpg.3
+man/man3/Basic_IO_function_W5300.3
+man/man3/Basic_IO_function_W5200.3
+man/man3/Basic_IO_function_W5100S.3
+man/man3/Basic_IO_function_W5100.3
+man/man3/Basic_IO_function.3
+latex/wizchip__conf_8h__incl.pdf
+latex/wizchip__conf_8h__incl.md5
+latex/wizchip__conf_8h__dep__incl.pdf
+latex/wizchip__conf_8h__dep__incl.md5
+latex/wizchip__conf_8h.tex
+latex/wizchip__conf_8c__incl.pdf
+latex/wizchip__conf_8c__incl.md5
+latex/wizchip__conf_8c.tex
+latex/w5500_8jpg.tex
+latex/w5500_8h__incl.pdf
+latex/w5500_8h__incl.md5
+latex/w5500_8h__dep__incl.pdf
+latex/w5500_8h__dep__incl.md5
+latex/w5500_8h.tex
+latex/w5500_8c__incl.pdf
+latex/w5500_8c__incl.md5
+latex/w5500_8c.tex
+latex/w5300_8h__incl.pdf
+latex/w5300_8h__incl.md5
+latex/w5300_8h.tex
+latex/w5300_8c__incl.pdf
+latex/w5300_8c__incl.md5
+latex/w5300_8c.tex
+latex/w5200__w5500_8jpg.tex
+latex/w5200_8h__incl.pdf
+latex/w5200_8h__incl.md5
+latex/w5200_8h__dep__incl.pdf
+latex/w5200_8h__dep__incl.md5
+latex/w5200_8h.tex
+latex/w5200_8c__incl.pdf
+latex/w5200_8c__incl.md5
+latex/w5200_8c.tex
+latex/w5100s_8h__incl.pdf
+latex/w5100s_8h__incl.md5
+latex/w5100s_8h__dep__incl.pdf
+latex/w5100s_8h__dep__incl.md5
+latex/w5100s_8h.tex
+latex/w5100s_8c__incl.pdf
+latex/w5100s_8c__incl.md5
+latex/w5100s_8c.tex
+latex/w5100_8h__incl.pdf
+latex/w5100_8h__incl.md5
+latex/w5100_8h__dep__incl.pdf
+latex/w5100_8h__dep__incl.md5
+latex/w5100_8h.tex
+latex/w5100_8c__incl.pdf
+latex/w5100_8c__incl.md5
+latex/w5100_8c.tex
+latex/union_m_q_t_t_header.tex
+latex/union_m_q_t_t_connect_flags.tex
+latex/union_m_q_t_t_connack_flags.tex
+latex/union__un__l2cval.tex
+latex/union_____w_i_z_c_h_i_p_1_1___i_f.tex
+latex/todo.tex
+latex/tftp_8h__incl.pdf
+latex/tftp_8h__incl.md5
+latex/tftp_8h__dep__incl.pdf
+latex/tftp_8h__dep__incl.md5
+latex/tftp_8h.tex
+latex/tftp_8c__incl.pdf
+latex/tftp_8c__incl.md5
+latex/tftp_8c.tex
+latex/structwiz___phy_conf__t.tex
+latex/structwiz___net_timeout__t.tex
+latex/structwiz___net_info__t.tex
+latex/structtlv_struct_type.tex
+latex/structtftp__option.tex
+latex/structtftp__error.tex
+latex/structtftp__data.tex
+latex/structmessage_struct.tex
+latex/structftpd.tex
+latex/structftpc.tex
+latex/structdhdr.tex
+latex/structdata_entry_type.tex
+latex/struct_timer.tex
+latex/struct_r_i_p___m_s_g.tex
+latex/struct_network.tex
+latex/struct_message_data__coll__graph.pdf
+latex/struct_message_data__coll__graph.md5
+latex/struct_message_data.tex
+latex/struct_m_q_t_t_transport.tex
+latex/struct_m_q_t_t_string__coll__graph.pdf
+latex/struct_m_q_t_t_string__coll__graph.md5
+latex/struct_m_q_t_t_string.tex
+latex/struct_m_q_t_t_packet__will_options__coll__graph.pdf
+latex/struct_m_q_t_t_packet__will_options__coll__graph.md5
+latex/struct_m_q_t_t_packet__will_options.tex
+latex/struct_m_q_t_t_packet__connect_data__coll__graph.pdf
+latex/struct_m_q_t_t_packet__connect_data__coll__graph.md5
+latex/struct_m_q_t_t_packet__connect_data.tex
+latex/struct_m_q_t_t_message.tex
+latex/struct_m_q_t_t_len_string.tex
+latex/struct_m_q_t_t_client__coll__graph.pdf
+latex/struct_m_q_t_t_client__coll__graph.md5
+latex/struct_m_q_t_t_client_1_1_message_handlers.tex
+latex/struct_m_q_t_t_client.tex
+latex/struct_command.tex
+latex/struct__st__http__socket.tex
+latex/struct__st__http__request.tex
+latex/struct__ntpformat.tex
+latex/struct__http_server__web_content.tex
+latex/struct__datetime.tex
+latex/struct____file.tex
+latex/struct_____w_i_z_c_h_i_p__coll__graph.pdf
+latex/struct_____w_i_z_c_h_i_p__coll__graph.md5
+latex/struct_____w_i_z_c_h_i_p_1_1___c_s.tex
+latex/struct_____w_i_z_c_h_i_p_1_1___c_r_i_s.tex
+latex/struct_____w_i_z_c_h_i_p.tex
+latex/socket_8h__incl.pdf
+latex/socket_8h__incl.md5
+latex/socket_8h__dep__incl.pdf
+latex/socket_8h__dep__incl.md5
+latex/socket_8h.tex
+latex/socket_8c__incl.pdf
+latex/socket_8c__incl.md5
+latex/socket_8c.tex
+latex/sntp_8h__incl.pdf
+latex/sntp_8h__incl.md5
+latex/sntp_8h__dep__incl.pdf
+latex/sntp_8h__dep__incl.md5
+latex/sntp_8h.tex
+latex/sntp_8c__incl.pdf
+latex/sntp_8c__incl.md5
+latex/sntp_8c.tex
+latex/snmp__custom_8h__incl.pdf
+latex/snmp__custom_8h__incl.md5
+latex/snmp__custom_8h__dep__incl.pdf
+latex/snmp__custom_8h__dep__incl.md5
+latex/snmp__custom_8h.tex
+latex/snmp__custom_8c__incl.pdf
+latex/snmp__custom_8c__incl.md5
+latex/snmp__custom_8c.tex
+latex/snmp_8h__dep__incl.pdf
+latex/snmp_8h__dep__incl.md5
+latex/snmp_8h.tex
+latex/snmp_8c__incl.pdf
+latex/snmp_8c__incl.md5
+latex/snmp_8c.tex
+latex/refman.tex
+latex/netutil_8h__incl.pdf
+latex/netutil_8h__incl.md5
+latex/netutil_8h__dep__incl.pdf
+latex/netutil_8h__dep__incl.md5
+latex/netutil_8h.tex
+latex/netutil_8c__incl.pdf
+latex/netutil_8c__incl.md5
+latex/netutil_8c.tex
+latex/mqtt__interface_8h__dep__incl.pdf
+latex/mqtt__interface_8h__dep__incl.md5
+latex/mqtt__interface_8h.tex
+latex/mqtt__interface_8c__incl.pdf
+latex/mqtt__interface_8c__incl.md5
+latex/mqtt__interface_8c.tex
+latex/modules.tex
+latex/md__r_e_a_d_m_e.tex
+latex/make.bat
+latex/loopback_8h__incl.pdf
+latex/loopback_8h__incl.md5
+latex/loopback_8h__dep__incl.pdf
+latex/loopback_8h__dep__incl.md5
+latex/loopback_8h.tex
+latex/loopback_8c__incl.pdf
+latex/loopback_8c__incl.md5
+latex/loopback_8c.tex.tmp
+latex/loopback_8c.tex
+latex/license_8txt.tex
+latex/index.tex
+latex/http_util_8h__incl.pdf
+latex/http_util_8h__incl.md5
+latex/http_util_8h__dep__incl.pdf
+latex/http_util_8h__dep__incl.md5
+latex/http_util_8h.tex
+latex/http_util_8c__incl.pdf
+latex/http_util_8c__incl.md5
+latex/http_util_8c.tex
+latex/http_server_8h__incl.pdf
+latex/http_server_8h__incl.md5
+latex/http_server_8h__dep__incl.pdf
+latex/http_server_8h__dep__incl.md5
+latex/http_server_8h.tex
+latex/http_server_8c__incl.pdf
+latex/http_server_8c__incl.md5
+latex/http_server_8c.tex
+latex/http_parser_8h__incl.pdf
+latex/http_parser_8h__incl.md5
+latex/http_parser_8h__dep__incl.pdf
+latex/http_parser_8h__dep__incl.md5
+latex/http_parser_8h.tex
+latex/http_parser_8c__incl.pdf
+latex/http_parser_8c__incl.md5
+latex/http_parser_8c.tex
+latex/group__snmp__module.tex
+latex/group__extra__functions.tex
+latex/group___w_i_znet__socket___a_p_is.tex
+latex/group___w_i_z_c_h_i_p__register___w5300.tex
+latex/group___w_i_z_c_h_i_p__register___w5300.pdf
+latex/group___w_i_z_c_h_i_p__register___w5300.md5
+latex/group___w_i_z_c_h_i_p__register___w5200.tex
+latex/group___w_i_z_c_h_i_p__register___w5200.pdf
+latex/group___w_i_z_c_h_i_p__register___w5200.md5
+latex/group___w_i_z_c_h_i_p__register___w5100_s.tex
+latex/group___w_i_z_c_h_i_p__register___w5100_s.pdf
+latex/group___w_i_z_c_h_i_p__register___w5100_s.md5
+latex/group___w_i_z_c_h_i_p__register___w5100.tex
+latex/group___w_i_z_c_h_i_p__register___w5100.pdf
+latex/group___w_i_z_c_h_i_p__register___w5100.md5
+latex/group___w_i_z_c_h_i_p__register.tex
+latex/group___w_i_z_c_h_i_p__register.pdf
+latex/group___w_i_z_c_h_i_p__register.md5
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5300.tex
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5300.pdf
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5300.md5
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5200.tex
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5200.pdf
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5200.md5
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5100_s.tex
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5100_s.pdf
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5100_s.md5
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5100.tex
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5100.pdf
+latex/group___w_i_z_c_h_i_p___i_o___functions___w5100.md5
+latex/group___w_i_z_c_h_i_p___i_o___functions.tex
+latex/group___w_i_z_c_h_i_p___i_o___functions.pdf
+latex/group___w_i_z_c_h_i_p___i_o___functions.md5
+latex/group___w5500.tex
+latex/group___w5500.pdf
+latex/group___w5500.md5
+latex/group___w5300.tex
+latex/group___w5300.pdf
+latex/group___w5300.md5
+latex/group___w5200.tex
+latex/group___w5200.pdf
+latex/group___w5200.md5
+latex/group___w5100_s.tex
+latex/group___w5100_s.pdf
+latex/group___w5100_s.md5
+latex/group___w5100.tex
+latex/group___w5100.pdf
+latex/group___w5100.md5
+latex/group___special__function___w5100_s.tex
+latex/group___special__function___w5100_s.pdf
+latex/group___special__function___w5100_s.md5
+latex/group___socket__register__group___w5300.tex
+latex/group___socket__register__group___w5300.pdf
+latex/group___socket__register__group___w5300.md5
+latex/group___socket__register__group___w5200.tex
+latex/group___socket__register__group___w5200.pdf
+latex/group___socket__register__group___w5200.md5
+latex/group___socket__register__group___w5100_s.tex
+latex/group___socket__register__group___w5100_s.pdf
+latex/group___socket__register__group___w5100_s.md5
+latex/group___socket__register__group___w5100.tex
+latex/group___socket__register__group___w5100.pdf
+latex/group___socket__register__group___w5100.md5
+latex/group___socket__register__group.tex
+latex/group___socket__register__group.pdf
+latex/group___socket__register__group.md5
+latex/group___socket__register__access__function___w5300.tex
+latex/group___socket__register__access__function___w5300.pdf
+latex/group___socket__register__access__function___w5300.md5
+latex/group___socket__register__access__function___w5200.tex
+latex/group___socket__register__access__function___w5200.pdf
+latex/group___socket__register__access__function___w5200.md5
+latex/group___socket__register__access__function___w5100_s.tex
+latex/group___socket__register__access__function___w5100_s.pdf
+latex/group___socket__register__access__function___w5100_s.md5
+latex/group___socket__register__access__function___w5100.tex
+latex/group___socket__register__access__function___w5100.pdf
+latex/group___socket__register__access__function___w5100.md5
+latex/group___socket__register__access__function.tex
+latex/group___socket__register__access__function.pdf
+latex/group___socket__register__access__function.md5
+latex/group___d_a_t_a___t_y_p_e.tex
+latex/group___common__register__group___w5300.tex
+latex/group___common__register__group___w5300.pdf
+latex/group___common__register__group___w5300.md5
+latex/group___common__register__group___w5200.tex
+latex/group___common__register__group___w5200.pdf
+latex/group___common__register__group___w5200.md5
+latex/group___common__register__group___w5100_s.tex
+latex/group___common__register__group___w5100_s.pdf
+latex/group___common__register__group___w5100_s.md5
+latex/group___common__register__group___w5100.tex
+latex/group___common__register__group___w5100.pdf
+latex/group___common__register__group___w5100.md5
+latex/group___common__register__group.tex
+latex/group___common__register__group.pdf
+latex/group___common__register__group.md5
+latex/group___common__register__access__function___w5300.tex
+latex/group___common__register__access__function___w5300.pdf
+latex/group___common__register__access__function___w5300.md5
+latex/group___common__register__access__function___w5200.tex
+latex/group___common__register__access__function___w5200.pdf
+latex/group___common__register__access__function___w5200.md5
+latex/group___common__register__access__function___w5100_s.tex
+latex/group___common__register__access__function___w5100_s.pdf
+latex/group___common__register__access__function___w5100_s.md5
+latex/group___common__register__access__function___w5100.tex
+latex/group___common__register__access__function___w5100.pdf
+latex/group___common__register__access__function___w5100.md5
+latex/group___common__register__access__function.tex
+latex/group___common__register__access__function.pdf
+latex/group___common__register__access__function.md5
+latex/group___basic___i_o__function___w5300.tex
+latex/group___basic___i_o__function___w5300.pdf
+latex/group___basic___i_o__function___w5300.md5
+latex/group___basic___i_o__function___w5200.tex
+latex/group___basic___i_o__function___w5200.pdf
+latex/group___basic___i_o__function___w5200.md5
+latex/group___basic___i_o__function___w5100_s.tex
+latex/group___basic___i_o__function___w5100_s.pdf
+latex/group___basic___i_o__function___w5100_s.md5
+latex/group___basic___i_o__function___w5100.tex
+latex/group___basic___i_o__function___w5100.pdf
+latex/group___basic___i_o__function___w5100.md5
+latex/group___basic___i_o__function.tex
+latex/group___basic___i_o__function.pdf
+latex/group___basic___i_o__function.md5
+latex/ftpd_8h__incl.pdf
+latex/ftpd_8h__incl.md5
+latex/ftpd_8h__dep__incl.pdf
+latex/ftpd_8h__dep__incl.md5
+latex/ftpd_8h.tex
+latex/ftpd_8c__incl.pdf
+latex/ftpd_8c__incl.md5
+latex/ftpd_8c.tex
+latex/ftpc_8h__incl.pdf
+latex/ftpc_8h__incl.md5
+latex/ftpc_8h__dep__incl.pdf
+latex/ftpc_8h__dep__incl.md5
+latex/ftpc_8h.tex
+latex/ftpc_8c__incl.pdf
+latex/ftpc_8c__incl.md5
+latex/ftpc_8c.tex
+latex/files.tex
+latex/doxygen__log_8txt.tex
+latex/doxygen.sty
+latex/dns_8h__incl.pdf
+latex/dns_8h__incl.md5
+latex/dns_8h__dep__incl.pdf
+latex/dns_8h__dep__incl.md5
+latex/dns_8h.tex
+latex/dns_8c__incl.pdf
+latex/dns_8c__incl.md5
+latex/dns_8c.tex
+latex/dir_fe682d1d76c251404f71241aa833642c_dep.pdf
+latex/dir_fe682d1d76c251404f71241aa833642c_dep.md5
+latex/dir_fe682d1d76c251404f71241aa833642c.tex
+latex/dir_fca0adf6655fb1759a15e5776097c124_dep.pdf
+latex/dir_fca0adf6655fb1759a15e5776097c124_dep.md5
+latex/dir_fca0adf6655fb1759a15e5776097c124.tex
+latex/dir_f841453af36a2df9a2123f87589fe4f8_dep.pdf
+latex/dir_f841453af36a2df9a2123f87589fe4f8_dep.md5
+latex/dir_f841453af36a2df9a2123f87589fe4f8.tex
+latex/dir_f10a527ab5b3936e2edf95a019a13ec7_dep.pdf
+latex/dir_f10a527ab5b3936e2edf95a019a13ec7_dep.md5
+latex/dir_f10a527ab5b3936e2edf95a019a13ec7.tex
+latex/dir_eb1463819d84903762eb6f59cc0c4383_dep.pdf
+latex/dir_eb1463819d84903762eb6f59cc0c4383_dep.md5
+latex/dir_eb1463819d84903762eb6f59cc0c4383.tex
+latex/dir_e5121bff4754a4ad570fa548a998f0c5_dep.pdf
+latex/dir_e5121bff4754a4ad570fa548a998f0c5_dep.md5
+latex/dir_e5121bff4754a4ad570fa548a998f0c5.tex
+latex/dir_b88037d6581d528000057b4eaec3e673_dep.pdf
+latex/dir_b88037d6581d528000057b4eaec3e673_dep.md5
+latex/dir_b88037d6581d528000057b4eaec3e673.tex
+latex/dir_a5a06f90a751e77147778694c516f622_dep.pdf
+latex/dir_a5a06f90a751e77147778694c516f622_dep.md5
+latex/dir_a5a06f90a751e77147778694c516f622.tex
+latex/dir_a483286db9c12f74c7364bdaa9e78c36_dep.pdf
+latex/dir_a483286db9c12f74c7364bdaa9e78c36_dep.md5
+latex/dir_a483286db9c12f74c7364bdaa9e78c36.tex
+latex/dir_a138ed074e64356ad02dbb8d94382c4f_dep.pdf
+latex/dir_a138ed074e64356ad02dbb8d94382c4f_dep.md5
+latex/dir_a138ed074e64356ad02dbb8d94382c4f.tex
+latex/dir_97b8cbb23222306012bd2d84398746c9_dep.pdf
+latex/dir_97b8cbb23222306012bd2d84398746c9_dep.md5
+latex/dir_97b8cbb23222306012bd2d84398746c9.tex
+latex/dir_6e6e4d5e89221ed61dd87b2954f72a78_dep.pdf
+latex/dir_6e6e4d5e89221ed61dd87b2954f72a78_dep.md5
+latex/dir_6e6e4d5e89221ed61dd87b2954f72a78.tex
+latex/dir_6de1940466803d61d2f9d1259cb01031.tex
+latex/dir_5a912e51f6f9520965e8671f07512599_dep.pdf
+latex/dir_5a912e51f6f9520965e8671f07512599_dep.md5
+latex/dir_5a912e51f6f9520965e8671f07512599.tex
+latex/dir_4c7002aef9ece892c0aedd728ed93eff.tex
+latex/dir_498fbcdef69ea105b96b8673d051b2e3_dep.pdf
+latex/dir_498fbcdef69ea105b96b8673d051b2e3_dep.md5
+latex/dir_498fbcdef69ea105b96b8673d051b2e3.tex
+latex/dir_46819ec1095f3903911c103f5ebbb29f_dep.pdf
+latex/dir_46819ec1095f3903911c103f5ebbb29f_dep.md5
+latex/dir_46819ec1095f3903911c103f5ebbb29f.tex
+latex/dir_4396dcc0e095a5bc10b1affe087807cf_dep.pdf
+latex/dir_4396dcc0e095a5bc10b1affe087807cf_dep.md5
+latex/dir_4396dcc0e095a5bc10b1affe087807cf.tex
+latex/dir_337e147d8ae2958ef29ccaa8e2f968db_dep.pdf
+latex/dir_337e147d8ae2958ef29ccaa8e2f968db_dep.md5
+latex/dir_337e147d8ae2958ef29ccaa8e2f968db.tex
+latex/dir_2c7bb40a7e5a6685f00216dd2909cd99_dep.pdf
+latex/dir_2c7bb40a7e5a6685f00216dd2909cd99_dep.md5
+latex/dir_2c7bb40a7e5a6685f00216dd2909cd99.tex
+latex/dir_2c1dd796c287ab9a5cf44281d8a3cbeb.tex
+latex/dir_072fcb7a67163ce1d8f22ad4144c7e08.tex
+latex/dhcp_8h__dep__incl.pdf
+latex/dhcp_8h__dep__incl.md5
+latex/dhcp_8h.tex
+latex/dhcp_8c__incl.pdf
+latex/dhcp_8c__incl.md5
+latex/dhcp_8c.tex
+latex/annotated.tex
+latex/_w_i_znet___s_o_c_k_e_t_8jpg.tex
+latex/_stack_trace_8h__incl.pdf
+latex/_stack_trace_8h__incl.md5
+latex/_stack_trace_8h__dep__incl.pdf
+latex/_stack_trace_8h__dep__incl.md5
+latex/_stack_trace_8h.tex
+latex/_readme_8txt.tex
+latex/_r_e_a_d_m_e_8md.tex
+latex/_main__page_8txt.tex
+latex/_m_q_t_t_unsubscribe_server_8c__incl.pdf
+latex/_m_q_t_t_unsubscribe_server_8c__incl.md5
+latex/_m_q_t_t_unsubscribe_server_8c.tex
+latex/_m_q_t_t_unsubscribe_client_8c__incl.pdf
+latex/_m_q_t_t_unsubscribe_client_8c__incl.md5
+latex/_m_q_t_t_unsubscribe_client_8c.tex
+latex/_m_q_t_t_unsubscribe_8h__dep__incl.pdf
+latex/_m_q_t_t_unsubscribe_8h__dep__incl.md5
+latex/_m_q_t_t_unsubscribe_8h.tex
+latex/_m_q_t_t_subscribe_server_8c__incl.pdf
+latex/_m_q_t_t_subscribe_server_8c__incl.md5
+latex/_m_q_t_t_subscribe_server_8c.tex
+latex/_m_q_t_t_subscribe_client_8c__incl.pdf
+latex/_m_q_t_t_subscribe_client_8c__incl.md5
+latex/_m_q_t_t_subscribe_client_8c.tex
+latex/_m_q_t_t_subscribe_8h__dep__incl.pdf
+latex/_m_q_t_t_subscribe_8h__dep__incl.md5
+latex/_m_q_t_t_subscribe_8h.tex
+latex/_m_q_t_t_serialize_publish_8c__incl.pdf
+latex/_m_q_t_t_serialize_publish_8c__incl.md5
+latex/_m_q_t_t_serialize_publish_8c.tex
+latex/_m_q_t_t_publish_8h__dep__incl.pdf
+latex/_m_q_t_t_publish_8h__dep__incl.md5
+latex/_m_q_t_t_publish_8h.tex
+latex/_m_q_t_t_packet_8h__incl.pdf
+latex/_m_q_t_t_packet_8h__incl.md5
+latex/_m_q_t_t_packet_8h__dep__incl.pdf
+latex/_m_q_t_t_packet_8h__dep__incl.md5
+latex/_m_q_t_t_packet_8h.tex
+latex/_m_q_t_t_packet_8c__incl.pdf
+latex/_m_q_t_t_packet_8c__incl.md5
+latex/_m_q_t_t_packet_8c.tex
+latex/_m_q_t_t_format_8h__incl.pdf
+latex/_m_q_t_t_format_8h__incl.md5
+latex/_m_q_t_t_format_8h__dep__incl.pdf
+latex/_m_q_t_t_format_8h__dep__incl.md5
+latex/_m_q_t_t_format_8h.tex
+latex/_m_q_t_t_format_8c__incl.pdf
+latex/_m_q_t_t_format_8c__incl.md5
+latex/_m_q_t_t_format_8c.tex
+latex/_m_q_t_t_deserialize_publish_8c__incl.pdf
+latex/_m_q_t_t_deserialize_publish_8c__incl.md5
+latex/_m_q_t_t_deserialize_publish_8c.tex
+latex/_m_q_t_t_connect_server_8c__incl.pdf
+latex/_m_q_t_t_connect_server_8c__incl.md5
+latex/_m_q_t_t_connect_server_8c.tex
+latex/_m_q_t_t_connect_client_8c__incl.pdf
+latex/_m_q_t_t_connect_client_8c__incl.md5
+latex/_m_q_t_t_connect_client_8c.tex
+latex/_m_q_t_t_connect_8h__dep__incl.pdf
+latex/_m_q_t_t_connect_8h__dep__incl.md5
+latex/_m_q_t_t_connect_8h.tex
+latex/_m_q_t_t_client_8h__incl.pdf
+latex/_m_q_t_t_client_8h__incl.md5
+latex/_m_q_t_t_client_8h__dep__incl.pdf
+latex/_m_q_t_t_client_8h__dep__incl.md5
+latex/_m_q_t_t_client_8h.tex
+latex/_m_q_t_t_client_8c__incl.pdf
+latex/_m_q_t_t_client_8c__incl.md5
+latex/_m_q_t_t_client_8c.tex
+latex/_f_t_p_server_2stdio__private_8h__incl.pdf
+latex/_f_t_p_server_2stdio__private_8h__incl.md5
+latex/_f_t_p_server_2stdio__private_8h__dep__incl.pdf
+latex/_f_t_p_server_2stdio__private_8h__dep__incl.md5
+latex/_f_t_p_server_2stdio__private_8h.tex
+latex/_f_t_p_client_2stdio__private_8h__incl.pdf
+latex/_f_t_p_client_2stdio__private_8h__incl.md5
+latex/_f_t_p_client_2stdio__private_8h__dep__incl.pdf
+latex/_f_t_p_client_2stdio__private_8h__dep__incl.md5
+latex/_f_t_p_client_2stdio__private_8h.tex
+latex/_berkeley___s_o_c_k_e_t_8jpg.tex
+latex/Makefile
+image/w5500.jpg
+image/w5200_w5500.jpg
+image/WIZnet_SOCKET.jpg
+image/Berkeley_SOCKET.jpg
+html/wizchip__conf_8h_source.html
+html/wizchip__conf_8h__incl.png
+html/wizchip__conf_8h__incl.md5
+html/wizchip__conf_8h__incl.map
+html/wizchip__conf_8h__dep__incl.png
+html/wizchip__conf_8h__dep__incl.md5
+html/wizchip__conf_8h__dep__incl.map
+html/wizchip__conf_8h.html
+html/wizchip__conf_8c_source.html
+html/wizchip__conf_8c__incl.png
+html/wizchip__conf_8c__incl.md5
+html/wizchip__conf_8c__incl.map
+html/wizchip__conf_8c.html
+html/w5500_8jpg_source.html
+html/w5500_8jpg.html
+html/w5500_8h_source.html
+html/w5500_8h__incl.png
+html/w5500_8h__incl.md5
+html/w5500_8h__incl.map
+html/w5500_8h__dep__incl.png
+html/w5500_8h__dep__incl.md5
+html/w5500_8h__dep__incl.map
+html/w5500_8h.html
+html/w5500_8c_source.html
+html/w5500_8c__incl.png
+html/w5500_8c__incl.md5
+html/w5500_8c__incl.map
+html/w5500_8c.html
+html/w5300_8h_source.html
+html/w5300_8h__incl.png
+html/w5300_8h__incl.md5
+html/w5300_8h__incl.map
+html/w5300_8h.html
+html/w5300_8c_source.html
+html/w5300_8c__incl.png
+html/w5300_8c__incl.md5
+html/w5300_8c__incl.map
+html/w5300_8c.html
+html/w5200_w5500.jpg
+html/w5200__w5500_8jpg_source.html
+html/w5200__w5500_8jpg.html
+html/w5200_8h_source.html
+html/w5200_8h__incl.png
+html/w5200_8h__incl.md5
+html/w5200_8h__incl.map
+html/w5200_8h__dep__incl.png
+html/w5200_8h__dep__incl.md5
+html/w5200_8h__dep__incl.map
+html/w5200_8h.html
+html/w5200_8c_source.html
+html/w5200_8c__incl.png
+html/w5200_8c__incl.md5
+html/w5200_8c__incl.map
+html/w5200_8c.html
+html/w5100s_8h_source.html
+html/w5100s_8h__incl.png
+html/w5100s_8h__incl.md5
+html/w5100s_8h__incl.map
+html/w5100s_8h__dep__incl.png
+html/w5100s_8h__dep__incl.md5
+html/w5100s_8h__dep__incl.map
+html/w5100s_8h.html
+html/w5100s_8c_source.html
+html/w5100s_8c__incl.png
+html/w5100s_8c__incl.md5
+html/w5100s_8c__incl.map
+html/w5100s_8c.html
+html/w5100_8h_source.html
+html/w5100_8h__incl.png
+html/w5100_8h__incl.md5
+html/w5100_8h__incl.map
+html/w5100_8h__dep__incl.png
+html/w5100_8h__dep__incl.md5
+html/w5100_8h__dep__incl.map
+html/w5100_8h.html
+html/w5100_8c_source.html
+html/w5100_8c__incl.png
+html/w5100_8c__incl.md5
+html/w5100_8c__incl.map
+html/w5100_8c.html
+html/union_m_q_t_t_header.html
+html/union_m_q_t_t_connect_flags.html
+html/union_m_q_t_t_connack_flags.html
+html/union__un__l2cval.html
+html/union_____w_i_z_c_h_i_p_1_1___i_f.html
+html/todo.html
+html/tftp_8h_source.html
+html/tftp_8h__incl.png
+html/tftp_8h__incl.md5
+html/tftp_8h__incl.map
+html/tftp_8h__dep__incl.png
+html/tftp_8h__dep__incl.md5
+html/tftp_8h__dep__incl.map
+html/tftp_8h.html
+html/tftp_8c_source.html
+html/tftp_8c__incl.png
+html/tftp_8c__incl.md5
+html/tftp_8c__incl.map
+html/tftp_8c.html
+html/tabs.css
+html/tab_s.png
+html/tab_h.png
+html/tab_b.png
+html/tab_a.png
+html/sync_on.png
+html/sync_off.png
+html/structwiz___phy_conf__t.html
+html/structwiz___net_timeout__t.html
+html/structwiz___net_info__t.html
+html/structtlv_struct_type.html
+html/structtftp__option.html
+html/structtftp__error.html
+html/structtftp__data.html
+html/structmessage_struct.html
+html/structftpd.html
+html/structftpc.html
+html/structdhdr.html
+html/structdata_entry_type.html
+html/struct_timer.html
+html/struct_r_i_p___m_s_g.html
+html/struct_network.html
+html/struct_message_data__coll__graph.png
+html/struct_message_data__coll__graph.md5
+html/struct_message_data__coll__graph.map
+html/struct_message_data.html
+html/struct_m_q_t_t_transport.html
+html/struct_m_q_t_t_string__coll__graph.png
+html/struct_m_q_t_t_string__coll__graph.md5
+html/struct_m_q_t_t_string__coll__graph.map
+html/struct_m_q_t_t_string.html
+html/struct_m_q_t_t_packet__will_options__coll__graph.png
+html/struct_m_q_t_t_packet__will_options__coll__graph.md5
+html/struct_m_q_t_t_packet__will_options__coll__graph.map
+html/struct_m_q_t_t_packet__will_options.html
+html/struct_m_q_t_t_packet__connect_data__coll__graph.png
+html/struct_m_q_t_t_packet__connect_data__coll__graph.md5
+html/struct_m_q_t_t_packet__connect_data__coll__graph.map
+html/struct_m_q_t_t_packet__connect_data.html
+html/struct_m_q_t_t_message.html
+html/struct_m_q_t_t_len_string.html
+html/struct_m_q_t_t_client__coll__graph.png
+html/struct_m_q_t_t_client__coll__graph.md5
+html/struct_m_q_t_t_client__coll__graph.map
+html/struct_m_q_t_t_client_1_1_message_handlers.html
+html/struct_m_q_t_t_client.html
+html/struct_command.html
+html/struct__st__http__socket.html
+html/struct__st__http__request.html
+html/struct__ntpformat.html
+html/struct__http_server__web_content.html
+html/struct__datetime.html
+html/struct____file.html
+html/struct_____w_i_z_c_h_i_p__coll__graph.png
+html/struct_____w_i_z_c_h_i_p__coll__graph.md5
+html/struct_____w_i_z_c_h_i_p__coll__graph.map
+html/struct_____w_i_z_c_h_i_p_1_1___c_s.html
+html/struct_____w_i_z_c_h_i_p_1_1___c_r_i_s.html
+html/struct_____w_i_z_c_h_i_p.html
+html/splitbar.png
+html/socket_8h_source.html
+html/socket_8h__incl.png
+html/socket_8h__incl.md5
+html/socket_8h__incl.map
+html/socket_8h__dep__incl.png
+html/socket_8h__dep__incl.md5
+html/socket_8h__dep__incl.map
+html/socket_8h.html
+html/socket_8c_source.html
+html/socket_8c__incl.png
+html/socket_8c__incl.md5
+html/socket_8c__incl.map
+html/socket_8c.html
+html/sntp_8h_source.html
+html/sntp_8h__incl.png
+html/sntp_8h__incl.md5
+html/sntp_8h__incl.map
+html/sntp_8h__dep__incl.png
+html/sntp_8h__dep__incl.md5
+html/sntp_8h__dep__incl.map
+html/sntp_8h.html
+html/sntp_8c_source.html
+html/sntp_8c__incl.png
+html/sntp_8c__incl.md5
+html/sntp_8c__incl.map
+html/sntp_8c.html
+html/snmp__custom_8h_source.html
+html/snmp__custom_8h__incl.png
+html/snmp__custom_8h__incl.md5
+html/snmp__custom_8h__incl.map
+html/snmp__custom_8h__dep__incl.png
+html/snmp__custom_8h__dep__incl.md5
+html/snmp__custom_8h__dep__incl.map
+html/snmp__custom_8h.html
+html/snmp__custom_8c_source.html
+html/snmp__custom_8c__incl.png
+html/snmp__custom_8c__incl.md5
+html/snmp__custom_8c__incl.map
+html/snmp__custom_8c.html
+html/snmp_8h_source.html
+html/snmp_8h__dep__incl.png
+html/snmp_8h__dep__incl.md5
+html/snmp_8h__dep__incl.map
+html/snmp_8h.html
+html/snmp_8c_source.html
+html/snmp_8c__incl.png
+html/snmp_8c__incl.md5
+html/snmp_8c__incl.map
+html/snmp_8c.html
+html/search/variables_f.js
+html/search/variables_f.html
+html/search/variables_e.js
+html/search/variables_e.html
+html/search/variables_d.js
+html/search/variables_d.html
+html/search/variables_c.js
+html/search/variables_c.html
+html/search/variables_b.js
+html/search/variables_b.html
+html/search/variables_a.js
+html/search/variables_a.html
+html/search/variables_9.js
+html/search/variables_9.html
+html/search/variables_8.js
+html/search/variables_8.html
+html/search/variables_7.js
+html/search/variables_7.html
+html/search/variables_6.js
+html/search/variables_6.html
+html/search/variables_5.js
+html/search/variables_5.html
+html/search/variables_4.js
+html/search/variables_4.html
+html/search/variables_3.js
+html/search/variables_3.html
+html/search/variables_2.js
+html/search/variables_2.html
+html/search/variables_18.js
+html/search/variables_18.html
+html/search/variables_17.js
+html/search/variables_17.html
+html/search/variables_16.js
+html/search/variables_16.html
+html/search/variables_15.js
+html/search/variables_15.html
+html/search/variables_14.js
+html/search/variables_14.html
+html/search/variables_13.js
+html/search/variables_13.html
+html/search/variables_12.js
+html/search/variables_12.html
+html/search/variables_11.js
+html/search/variables_11.html
+html/search/variables_10.js
+html/search/variables_10.html
+html/search/variables_1.js
+html/search/variables_1.html
+html/search/variables_0.js
+html/search/variables_0.html
+html/search/typedefs_9.js
+html/search/typedefs_9.html
+html/search/typedefs_8.js
+html/search/typedefs_8.html
+html/search/typedefs_7.js
+html/search/typedefs_7.html
+html/search/typedefs_6.js
+html/search/typedefs_6.html
+html/search/typedefs_5.js
+html/search/typedefs_5.html
+html/search/typedefs_4.js
+html/search/typedefs_4.html
+html/search/typedefs_3.js
+html/search/typedefs_3.html
+html/search/typedefs_2.js
+html/search/typedefs_2.html
+html/search/typedefs_1.js
+html/search/typedefs_1.html
+html/search/typedefs_0.js
+html/search/typedefs_0.html
+html/search/searchdata.js
+html/search/search_r.png
+html/search/search_m.png
+html/search/search_l.png
+html/search/search.js
+html/search/search.css
+html/search/pages_2.js
+html/search/pages_2.html
+html/search/pages_1.js
+html/search/pages_1.html
+html/search/pages_0.js
+html/search/pages_0.html
+html/search/nomatches.html
+html/search/mag_sel.png
+html/search/groups_6.js
+html/search/groups_6.html
+html/search/groups_5.js
+html/search/groups_5.html
+html/search/groups_4.js
+html/search/groups_4.html
+html/search/groups_3.js
+html/search/groups_3.html
+html/search/groups_2.js
+html/search/groups_2.html
+html/search/groups_1.js
+html/search/groups_1.html
+html/search/groups_0.js
+html/search/groups_0.html
+html/search/functions_f.js
+html/search/functions_f.html
+html/search/functions_e.js
+html/search/functions_e.html
+html/search/functions_d.js
+html/search/functions_d.html
+html/search/functions_c.js
+html/search/functions_c.html
+html/search/functions_b.js
+html/search/functions_b.html
+html/search/functions_a.js
+html/search/functions_a.html
+html/search/functions_9.js
+html/search/functions_9.html
+html/search/functions_8.js
+html/search/functions_8.html
+html/search/functions_7.js
+html/search/functions_7.html
+html/search/functions_6.js
+html/search/functions_6.html
+html/search/functions_5.js
+html/search/functions_5.html
+html/search/functions_4.js
+html/search/functions_4.html
+html/search/functions_3.js
+html/search/functions_3.html
+html/search/functions_2.js
+html/search/functions_2.html
+html/search/functions_11.js
+html/search/functions_11.html
+html/search/functions_10.js
+html/search/functions_10.html
+html/search/functions_1.js
+html/search/functions_1.html
+html/search/functions_0.js
+html/search/functions_0.html
+html/search/files_a.js
+html/search/files_a.html
+html/search/files_9.js
+html/search/files_9.html
+html/search/files_8.js
+html/search/files_8.html
+html/search/files_7.js
+html/search/files_7.html
+html/search/files_6.js
+html/search/files_6.html
+html/search/files_5.js
+html/search/files_5.html
+html/search/files_4.js
+html/search/files_4.html
+html/search/files_3.js
+html/search/files_3.html
+html/search/files_2.js
+html/search/files_2.html
+html/search/files_1.js
+html/search/files_1.html
+html/search/files_0.js
+html/search/files_0.html
+html/search/enumvalues_f.js
+html/search/enumvalues_f.html
+html/search/enumvalues_e.js
+html/search/enumvalues_e.html
+html/search/enumvalues_d.js
+html/search/enumvalues_d.html
+html/search/enumvalues_c.js
+html/search/enumvalues_c.html
+html/search/enumvalues_b.js
+html/search/enumvalues_b.html
+html/search/enumvalues_a.js
+html/search/enumvalues_a.html
+html/search/enumvalues_9.js
+html/search/enumvalues_9.html
+html/search/enumvalues_8.js
+html/search/enumvalues_8.html
+html/search/enumvalues_7.js
+html/search/enumvalues_7.html
+html/search/enumvalues_6.js
+html/search/enumvalues_6.html
+html/search/enumvalues_5.js
+html/search/enumvalues_5.html
+html/search/enumvalues_4.js
+html/search/enumvalues_4.html
+html/search/enumvalues_3.js
+html/search/enumvalues_3.html
+html/search/enumvalues_2.js
+html/search/enumvalues_2.html
+html/search/enumvalues_12.js
+html/search/enumvalues_12.html
+html/search/enumvalues_11.js
+html/search/enumvalues_11.html
+html/search/enumvalues_10.js
+html/search/enumvalues_10.html
+html/search/enumvalues_1.js
+html/search/enumvalues_1.html
+html/search/enumvalues_0.js
+html/search/enumvalues_0.html
+html/search/enums_9.js
+html/search/enums_9.html
+html/search/enums_8.js
+html/search/enums_8.html
+html/search/enums_7.js
+html/search/enums_7.html
+html/search/enums_6.js
+html/search/enums_6.html
+html/search/enums_5.js
+html/search/enums_5.html
+html/search/enums_4.js
+html/search/enums_4.html
+html/search/enums_3.js
+html/search/enums_3.html
+html/search/enums_2.js
+html/search/enums_2.html
+html/search/enums_1.js
+html/search/enums_1.html
+html/search/enums_0.js
+html/search/enums_0.html
+html/search/defines_f.js
+html/search/defines_f.html
+html/search/defines_e.js
+html/search/defines_e.html
+html/search/defines_d.js
+html/search/defines_d.html
+html/search/defines_c.js
+html/search/defines_c.html
+html/search/defines_b.js
+html/search/defines_b.html
+html/search/defines_a.js
+html/search/defines_a.html
+html/search/defines_9.js
+html/search/defines_9.html
+html/search/defines_8.js
+html/search/defines_8.html
+html/search/defines_7.js
+html/search/defines_7.html
+html/search/defines_6.js
+html/search/defines_6.html
+html/search/defines_5.js
+html/search/defines_5.html
+html/search/defines_4.js
+html/search/defines_4.html
+html/search/defines_3.js
+html/search/defines_3.html
+html/search/defines_2.js
+html/search/defines_2.html
+html/search/defines_15.js
+html/search/defines_15.html
+html/search/defines_14.js
+html/search/defines_14.html
+html/search/defines_13.js
+html/search/defines_13.html
+html/search/defines_12.js
+html/search/defines_12.html
+html/search/defines_11.js
+html/search/defines_11.html
+html/search/defines_10.js
+html/search/defines_10.html
+html/search/defines_1.js
+html/search/defines_1.html
+html/search/defines_0.js
+html/search/defines_0.html
+html/search/close.png
+html/search/classes_8.js
+html/search/classes_8.html
+html/search/classes_7.js
+html/search/classes_7.html
+html/search/classes_6.js
+html/search/classes_6.html
+html/search/classes_5.js
+html/search/classes_5.html
+html/search/classes_4.js
+html/search/classes_4.html
+html/search/classes_3.js
+html/search/classes_3.html
+html/search/classes_2.js
+html/search/classes_2.html
+html/search/classes_1.js
+html/search/classes_1.html
+html/search/classes_0.js
+html/search/classes_0.html
+html/search/all_f.js
+html/search/all_f.html
+html/search/all_e.js
+html/search/all_e.html
+html/search/all_d.js
+html/search/all_d.html
+html/search/all_c.js
+html/search/all_c.html
+html/search/all_b.js
+html/search/all_b.html
+html/search/all_a.js
+html/search/all_a.html
+html/search/all_9.js
+html/search/all_9.html
+html/search/all_8.js
+html/search/all_8.html
+html/search/all_7.js
+html/search/all_7.html
+html/search/all_6.js
+html/search/all_6.html
+html/search/all_5.js
+html/search/all_5.html
+html/search/all_4.js
+html/search/all_4.html
+html/search/all_3.js
+html/search/all_3.html
+html/search/all_2.js
+html/search/all_2.html
+html/search/all_1a.js
+html/search/all_1a.html
+html/search/all_19.js
+html/search/all_19.html
+html/search/all_18.js
+html/search/all_18.html
+html/search/all_17.js
+html/search/all_17.html
+html/search/all_16.js
+html/search/all_16.html
+html/search/all_15.js
+html/search/all_15.html
+html/search/all_14.js
+html/search/all_14.html
+html/search/all_13.js
+html/search/all_13.html
+html/search/all_12.js
+html/search/all_12.html
+html/search/all_11.js
+html/search/all_11.html
+html/search/all_10.js
+html/search/all_10.html
+html/search/all_1.js
+html/search/all_1.html
+html/search/all_0.js
+html/search/all_0.html
+html/pages.html
+html/open.png
+html/netutil_8h_source.html
+html/netutil_8h__incl.png
+html/netutil_8h__incl.md5
+html/netutil_8h__incl.map
+html/netutil_8h__dep__incl.png
+html/netutil_8h__dep__incl.md5
+html/netutil_8h__dep__incl.map
+html/netutil_8h.html
+html/netutil_8c_source.html
+html/netutil_8c__incl.png
+html/netutil_8c__incl.md5
+html/netutil_8c__incl.map
+html/netutil_8c.html
+html/nav_h.png
+html/nav_g.png
+html/nav_f.png
+html/mqtt__interface_8h_source.html
+html/mqtt__interface_8h__dep__incl.png
+html/mqtt__interface_8h__dep__incl.md5
+html/mqtt__interface_8h__dep__incl.map
+html/mqtt__interface_8h.html
+html/mqtt__interface_8c_source.html
+html/mqtt__interface_8c__incl.png
+html/mqtt__interface_8c__incl.md5
+html/mqtt__interface_8c__incl.map
+html/mqtt__interface_8c.html
+html/modules.html
+html/menudata.js
+html/menu.js
+html/md__r_e_a_d_m_e.html
+html/loopback_8h_source.html
+html/loopback_8h__incl.png
+html/loopback_8h__incl.md5
+html/loopback_8h__incl.map
+html/loopback_8h__dep__incl.png
+html/loopback_8h__dep__incl.md5
+html/loopback_8h__dep__incl.map
+html/loopback_8h.html
+html/loopback_8c_source.html
+html/loopback_8c__incl.png
+html/loopback_8c__incl.md5
+html/loopback_8c__incl.map
+html/loopback_8c.html
+html/license_8txt.html
+html/jquery.js
+html/index.html
+html/http_util_8h_source.html
+html/http_util_8h__incl.png
+html/http_util_8h__incl.md5
+html/http_util_8h__incl.map
+html/http_util_8h__dep__incl.png
+html/http_util_8h__dep__incl.md5
+html/http_util_8h__dep__incl.map
+html/http_util_8h.html
+html/http_util_8c_source.html
+html/http_util_8c__incl.png
+html/http_util_8c__incl.md5
+html/http_util_8c__incl.map
+html/http_util_8c.html
+html/http_server_8h_source.html
+html/http_server_8h__incl.png
+html/http_server_8h__incl.md5
+html/http_server_8h__incl.map
+html/http_server_8h__dep__incl.png
+html/http_server_8h__dep__incl.md5
+html/http_server_8h__dep__incl.map
+html/http_server_8h.html
+html/http_server_8c_source.html
+html/http_server_8c__incl.png
+html/http_server_8c__incl.md5
+html/http_server_8c__incl.map
+html/http_server_8c.html
+html/http_parser_8h_source.html
+html/http_parser_8h__incl.png
+html/http_parser_8h__incl.md5
+html/http_parser_8h__incl.map
+html/http_parser_8h__dep__incl.png
+html/http_parser_8h__dep__incl.md5
+html/http_parser_8h__dep__incl.map
+html/http_parser_8h.html
+html/http_parser_8c_source.html
+html/http_parser_8c__incl.png
+html/http_parser_8c__incl.md5
+html/http_parser_8c__incl.map
+html/http_parser_8c.html
+html/group__snmp__module.html
+html/group__extra__functions.html
+html/group___w_i_znet__socket___a_p_is.html
+html/group___w_i_z_c_h_i_p__register___w5300.png
+html/group___w_i_z_c_h_i_p__register___w5300.md5
+html/group___w_i_z_c_h_i_p__register___w5300.map
+html/group___w_i_z_c_h_i_p__register___w5300.html
+html/group___w_i_z_c_h_i_p__register___w5200.png
+html/group___w_i_z_c_h_i_p__register___w5200.md5
+html/group___w_i_z_c_h_i_p__register___w5200.map
+html/group___w_i_z_c_h_i_p__register___w5200.html
+html/group___w_i_z_c_h_i_p__register___w5100_s.png
+html/group___w_i_z_c_h_i_p__register___w5100_s.md5
+html/group___w_i_z_c_h_i_p__register___w5100_s.map
+html/group___w_i_z_c_h_i_p__register___w5100_s.html
+html/group___w_i_z_c_h_i_p__register___w5100.png
+html/group___w_i_z_c_h_i_p__register___w5100.md5
+html/group___w_i_z_c_h_i_p__register___w5100.map
+html/group___w_i_z_c_h_i_p__register___w5100.html
+html/group___w_i_z_c_h_i_p__register.png
+html/group___w_i_z_c_h_i_p__register.md5
+html/group___w_i_z_c_h_i_p__register.map
+html/group___w_i_z_c_h_i_p__register.html
+html/group___w_i_z_c_h_i_p___i_o___functions___w5300.png
+html/group___w_i_z_c_h_i_p___i_o___functions___w5300.md5
+html/group___w_i_z_c_h_i_p___i_o___functions___w5300.map
+html/group___w_i_z_c_h_i_p___i_o___functions___w5300.html
+html/group___w_i_z_c_h_i_p___i_o___functions___w5200.png
+html/group___w_i_z_c_h_i_p___i_o___functions___w5200.md5
+html/group___w_i_z_c_h_i_p___i_o___functions___w5200.map
+html/group___w_i_z_c_h_i_p___i_o___functions___w5200.html
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100_s.png
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100_s.md5
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100_s.map
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100_s.html
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100.png
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100.md5
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100.map
+html/group___w_i_z_c_h_i_p___i_o___functions___w5100.html
+html/group___w_i_z_c_h_i_p___i_o___functions.png
+html/group___w_i_z_c_h_i_p___i_o___functions.md5
+html/group___w_i_z_c_h_i_p___i_o___functions.map
+html/group___w_i_z_c_h_i_p___i_o___functions.html
+html/group___w5500.png
+html/group___w5500.md5
+html/group___w5500.map
+html/group___w5500.html
+html/group___w5300.png
+html/group___w5300.md5
+html/group___w5300.map
+html/group___w5300.html
+html/group___w5200.png
+html/group___w5200.md5
+html/group___w5200.map
+html/group___w5200.html
+html/group___w5100_s.png
+html/group___w5100_s.md5
+html/group___w5100_s.map
+html/group___w5100_s.html
+html/group___w5100.png
+html/group___w5100.md5
+html/group___w5100.map
+html/group___w5100.html
+html/group___special__function___w5100_s.png
+html/group___special__function___w5100_s.md5
+html/group___special__function___w5100_s.map
+html/group___special__function___w5100_s.html
+html/group___socket__register__group___w5300.png
+html/group___socket__register__group___w5300.md5
+html/group___socket__register__group___w5300.map
+html/group___socket__register__group___w5300.html
+html/group___socket__register__group___w5200.png
+html/group___socket__register__group___w5200.md5
+html/group___socket__register__group___w5200.map
+html/group___socket__register__group___w5200.html
+html/group___socket__register__group___w5100_s.png
+html/group___socket__register__group___w5100_s.md5
+html/group___socket__register__group___w5100_s.map
+html/group___socket__register__group___w5100_s.html
+html/group___socket__register__group___w5100.png
+html/group___socket__register__group___w5100.md5
+html/group___socket__register__group___w5100.map
+html/group___socket__register__group___w5100.html
+html/group___socket__register__group.png
+html/group___socket__register__group.md5
+html/group___socket__register__group.map
+html/group___socket__register__group.html
+html/group___socket__register__access__function___w5300.png
+html/group___socket__register__access__function___w5300.md5
+html/group___socket__register__access__function___w5300.map
+html/group___socket__register__access__function___w5300.html
+html/group___socket__register__access__function___w5200.png
+html/group___socket__register__access__function___w5200.md5
+html/group___socket__register__access__function___w5200.map
+html/group___socket__register__access__function___w5200.html
+html/group___socket__register__access__function___w5100_s.png
+html/group___socket__register__access__function___w5100_s.md5
+html/group___socket__register__access__function___w5100_s.map
+html/group___socket__register__access__function___w5100_s.html
+html/group___socket__register__access__function___w5100.png
+html/group___socket__register__access__function___w5100.md5
+html/group___socket__register__access__function___w5100.map
+html/group___socket__register__access__function___w5100.html
+html/group___socket__register__access__function.png
+html/group___socket__register__access__function.md5
+html/group___socket__register__access__function.map
+html/group___socket__register__access__function.html
+html/group___d_a_t_a___t_y_p_e.html
+html/group___common__register__group___w5300.png
+html/group___common__register__group___w5300.md5
+html/group___common__register__group___w5300.map
+html/group___common__register__group___w5300.html
+html/group___common__register__group___w5200.png
+html/group___common__register__group___w5200.md5
+html/group___common__register__group___w5200.map
+html/group___common__register__group___w5200.html
+html/group___common__register__group___w5100_s.png
+html/group___common__register__group___w5100_s.md5
+html/group___common__register__group___w5100_s.map
+html/group___common__register__group___w5100_s.html
+html/group___common__register__group___w5100.png
+html/group___common__register__group___w5100.md5
+html/group___common__register__group___w5100.map
+html/group___common__register__group___w5100.html
+html/group___common__register__group.png
+html/group___common__register__group.md5
+html/group___common__register__group.map
+html/group___common__register__group.html
+html/group___common__register__access__function___w5300.png
+html/group___common__register__access__function___w5300.md5
+html/group___common__register__access__function___w5300.map
+html/group___common__register__access__function___w5300.html
+html/group___common__register__access__function___w5200.png
+html/group___common__register__access__function___w5200.md5
+html/group___common__register__access__function___w5200.map
+html/group___common__register__access__function___w5200.html
+html/group___common__register__access__function___w5100_s.png
+html/group___common__register__access__function___w5100_s.md5
+html/group___common__register__access__function___w5100_s.map
+html/group___common__register__access__function___w5100_s.html
+html/group___common__register__access__function___w5100.png
+html/group___common__register__access__function___w5100.md5
+html/group___common__register__access__function___w5100.map
+html/group___common__register__access__function___w5100.html
+html/group___common__register__access__function.png
+html/group___common__register__access__function.md5
+html/group___common__register__access__function.map
+html/group___common__register__access__function.html
+html/group___basic___i_o__function___w5300.png
+html/group___basic___i_o__function___w5300.md5
+html/group___basic___i_o__function___w5300.map
+html/group___basic___i_o__function___w5300.html
+html/group___basic___i_o__function___w5200.png
+html/group___basic___i_o__function___w5200.md5
+html/group___basic___i_o__function___w5200.map
+html/group___basic___i_o__function___w5200.html
+html/group___basic___i_o__function___w5100_s.png
+html/group___basic___i_o__function___w5100_s.md5
+html/group___basic___i_o__function___w5100_s.map
+html/group___basic___i_o__function___w5100_s.html
+html/group___basic___i_o__function___w5100.png
+html/group___basic___i_o__function___w5100.md5
+html/group___basic___i_o__function___w5100.map
+html/group___basic___i_o__function___w5100.html
+html/group___basic___i_o__function.png
+html/group___basic___i_o__function.md5
+html/group___basic___i_o__function.map
+html/group___basic___i_o__function.html
+html/graph_legend.png
+html/graph_legend.md5
+html/graph_legend.html
+html/globals_x.html
+html/globals_w.html
+html/globals_vars.html
+html/globals_v.html
+html/globals_u.html
+html/globals_type.html
+html/globals_t.html
+html/globals_s.html
+html/globals_r.html
+html/globals_q.html
+html/globals_p.html
+html/globals_o.html
+html/globals_n.html
+html/globals_m.html
+html/globals_l.html
+html/globals_k.html
+html/globals_i.html
+html/globals_h.html
+html/globals_g.html
+html/globals_func_w.html
+html/globals_func_u.html
+html/globals_func_t.html
+html/globals_func_s.html
+html/globals_func_r.html
+html/globals_func_p.html
+html/globals_func_n.html
+html/globals_func_m.html
+html/globals_func_l.html
+html/globals_func_k.html
+html/globals_func_i.html
+html/globals_func_h.html
+html/globals_func_g.html
+html/globals_func_f.html
+html/globals_func_d.html
+html/globals_func_c.html
+html/globals_func_b.html
+html/globals_func.html
+html/globals_f.html
+html/globals_eval_x.html
+html/globals_eval_v.html
+html/globals_eval_u.html
+html/globals_eval_t.html
+html/globals_eval_s.html
+html/globals_eval_r.html
+html/globals_eval_q.html
+html/globals_eval_p.html
+html/globals_eval_n.html
+html/globals_eval_m.html
+html/globals_eval_l.html
+html/globals_eval_i.html
+html/globals_eval_h.html
+html/globals_eval_f.html
+html/globals_eval_e.html
+html/globals_eval_d.html
+html/globals_eval_c.html
+html/globals_eval_b.html
+html/globals_eval.html
+html/globals_enum.html
+html/globals_e.html
+html/globals_defs_w.html
+html/globals_defs_v.html
+html/globals_defs_u.html
+html/globals_defs_t.html
+html/globals_defs_s.html
+html/globals_defs_r.html
+html/globals_defs_q.html
+html/globals_defs_p.html
+html/globals_defs_o.html
+html/globals_defs_n.html
+html/globals_defs_m.html
+html/globals_defs_l.html
+html/globals_defs_i.html
+html/globals_defs_h.html
+html/globals_defs_g.html
+html/globals_defs_f.html
+html/globals_defs_e.html
+html/globals_defs_d.html
+html/globals_defs_c.html
+html/globals_defs_b.html
+html/globals_defs_a.html
+html/globals_defs.html
+html/globals_d.html
+html/globals_c.html
+html/globals_b.html
+html/globals_a.html
+html/globals.html
+html/functions_y.html
+html/functions_x.html
+html/functions_w.html
+html/functions_vars_y.html
+html/functions_vars_x.html
+html/functions_vars_w.html
+html/functions_vars_v.html
+html/functions_vars_u.html
+html/functions_vars_t.html
+html/functions_vars_s.html
+html/functions_vars_r.html
+html/functions_vars_q.html
+html/functions_vars_p.html
+html/functions_vars_o.html
+html/functions_vars_n.html
+html/functions_vars_m.html
+html/functions_vars_l.html
+html/functions_vars_k.html
+html/functions_vars_i.html
+html/functions_vars_h.html
+html/functions_vars_g.html
+html/functions_vars_f.html
+html/functions_vars_e.html
+html/functions_vars_d.html
+html/functions_vars_c.html
+html/functions_vars_b.html
+html/functions_vars_a.html
+html/functions_vars.html
+html/functions_v.html
+html/functions_u.html
+html/functions_t.html
+html/functions_s.html
+html/functions_r.html
+html/functions_q.html
+html/functions_p.html
+html/functions_o.html
+html/functions_n.html
+html/functions_m.html
+html/functions_l.html
+html/functions_k.html
+html/functions_i.html
+html/functions_h.html
+html/functions_g.html
+html/functions_f.html
+html/functions_e.html
+html/functions_d.html
+html/functions_c.html
+html/functions_b.html
+html/functions_a.html
+html/functions.html
+html/ftpd_8h_source.html
+html/ftpd_8h__incl.png
+html/ftpd_8h__incl.md5
+html/ftpd_8h__incl.map
+html/ftpd_8h__dep__incl.png
+html/ftpd_8h__dep__incl.md5
+html/ftpd_8h__dep__incl.map
+html/ftpd_8h.html
+html/ftpd_8c_source.html
+html/ftpd_8c__incl.png
+html/ftpd_8c__incl.md5
+html/ftpd_8c__incl.map
+html/ftpd_8c.html
+html/ftpc_8h_source.html
+html/ftpc_8h__incl.png
+html/ftpc_8h__incl.md5
+html/ftpc_8h__incl.map
+html/ftpc_8h__dep__incl.png
+html/ftpc_8h__dep__incl.md5
+html/ftpc_8h__dep__incl.map
+html/ftpc_8h.html
+html/ftpc_8c_source.html
+html/ftpc_8c__incl.png
+html/ftpc_8c__incl.md5
+html/ftpc_8c__incl.map
+html/ftpc_8c.html
+html/folderopen.png
+html/folderclosed.png
+html/files.html
+html/dynsections.js
+html/doxygen__log_8txt.html
+html/doxygen.png
+html/doxygen.css
+html/doc.png
+html/dns_8h_source.html
+html/dns_8h__incl.png
+html/dns_8h__incl.md5
+html/dns_8h__incl.map
+html/dns_8h__dep__incl.png
+html/dns_8h__dep__incl.md5
+html/dns_8h__dep__incl.map
+html/dns_8h.html
+html/dns_8c_source.html
+html/dns_8c__incl.png
+html/dns_8c__incl.md5
+html/dns_8c__incl.map
+html/dns_8c.html
+html/dir_fe682d1d76c251404f71241aa833642c_dep.png
+html/dir_fe682d1d76c251404f71241aa833642c_dep.md5
+html/dir_fe682d1d76c251404f71241aa833642c_dep.map
+html/dir_fe682d1d76c251404f71241aa833642c.html
+html/dir_fca0adf6655fb1759a15e5776097c124_dep.png
+html/dir_fca0adf6655fb1759a15e5776097c124_dep.md5
+html/dir_fca0adf6655fb1759a15e5776097c124_dep.map
+html/dir_fca0adf6655fb1759a15e5776097c124.html
+html/dir_f841453af36a2df9a2123f87589fe4f8_dep.png
+html/dir_f841453af36a2df9a2123f87589fe4f8_dep.md5
+html/dir_f841453af36a2df9a2123f87589fe4f8_dep.map
+html/dir_f841453af36a2df9a2123f87589fe4f8.html
+html/dir_f10a527ab5b3936e2edf95a019a13ec7_dep.png
+html/dir_f10a527ab5b3936e2edf95a019a13ec7_dep.md5
+html/dir_f10a527ab5b3936e2edf95a019a13ec7_dep.map
+html/dir_f10a527ab5b3936e2edf95a019a13ec7.html
+html/dir_eb1463819d84903762eb6f59cc0c4383_dep.png
+html/dir_eb1463819d84903762eb6f59cc0c4383_dep.md5
+html/dir_eb1463819d84903762eb6f59cc0c4383_dep.map
+html/dir_eb1463819d84903762eb6f59cc0c4383.html
+html/dir_e5121bff4754a4ad570fa548a998f0c5_dep.png
+html/dir_e5121bff4754a4ad570fa548a998f0c5_dep.md5
+html/dir_e5121bff4754a4ad570fa548a998f0c5_dep.map
+html/dir_e5121bff4754a4ad570fa548a998f0c5.html
+html/dir_b88037d6581d528000057b4eaec3e673_dep.png
+html/dir_b88037d6581d528000057b4eaec3e673_dep.md5
+html/dir_b88037d6581d528000057b4eaec3e673_dep.map
+html/dir_b88037d6581d528000057b4eaec3e673.html
+html/dir_a5a06f90a751e77147778694c516f622_dep.png
+html/dir_a5a06f90a751e77147778694c516f622_dep.md5
+html/dir_a5a06f90a751e77147778694c516f622_dep.map
+html/dir_a5a06f90a751e77147778694c516f622.html
+html/dir_a483286db9c12f74c7364bdaa9e78c36_dep.png
+html/dir_a483286db9c12f74c7364bdaa9e78c36_dep.md5
+html/dir_a483286db9c12f74c7364bdaa9e78c36_dep.map
+html/dir_a483286db9c12f74c7364bdaa9e78c36.html
+html/dir_a138ed074e64356ad02dbb8d94382c4f_dep.png
+html/dir_a138ed074e64356ad02dbb8d94382c4f_dep.md5
+html/dir_a138ed074e64356ad02dbb8d94382c4f_dep.map
+html/dir_a138ed074e64356ad02dbb8d94382c4f.html
+html/dir_97b8cbb23222306012bd2d84398746c9_dep.png
+html/dir_97b8cbb23222306012bd2d84398746c9_dep.md5
+html/dir_97b8cbb23222306012bd2d84398746c9_dep.map
+html/dir_97b8cbb23222306012bd2d84398746c9.html
+html/dir_6e6e4d5e89221ed61dd87b2954f72a78_dep.png
+html/dir_6e6e4d5e89221ed61dd87b2954f72a78_dep.md5
+html/dir_6e6e4d5e89221ed61dd87b2954f72a78_dep.map
+html/dir_6e6e4d5e89221ed61dd87b2954f72a78.html
+html/dir_6de1940466803d61d2f9d1259cb01031.html
+html/dir_5a912e51f6f9520965e8671f07512599_dep.png
+html/dir_5a912e51f6f9520965e8671f07512599_dep.md5
+html/dir_5a912e51f6f9520965e8671f07512599_dep.map
+html/dir_5a912e51f6f9520965e8671f07512599.html
+html/dir_4c7002aef9ece892c0aedd728ed93eff.html
+html/dir_498fbcdef69ea105b96b8673d051b2e3_dep.png
+html/dir_498fbcdef69ea105b96b8673d051b2e3_dep.md5
+html/dir_498fbcdef69ea105b96b8673d051b2e3_dep.map
+html/dir_498fbcdef69ea105b96b8673d051b2e3.html
+html/dir_46819ec1095f3903911c103f5ebbb29f_dep.png
+html/dir_46819ec1095f3903911c103f5ebbb29f_dep.md5
+html/dir_46819ec1095f3903911c103f5ebbb29f_dep.map
+html/dir_46819ec1095f3903911c103f5ebbb29f.html
+html/dir_4396dcc0e095a5bc10b1affe087807cf_dep.png
+html/dir_4396dcc0e095a5bc10b1affe087807cf_dep.md5
+html/dir_4396dcc0e095a5bc10b1affe087807cf_dep.map
+html/dir_4396dcc0e095a5bc10b1affe087807cf.html
+html/dir_337e147d8ae2958ef29ccaa8e2f968db_dep.png
+html/dir_337e147d8ae2958ef29ccaa8e2f968db_dep.md5
+html/dir_337e147d8ae2958ef29ccaa8e2f968db_dep.map
+html/dir_337e147d8ae2958ef29ccaa8e2f968db.html
+html/dir_2c7bb40a7e5a6685f00216dd2909cd99_dep.png
+html/dir_2c7bb40a7e5a6685f00216dd2909cd99_dep.md5
+html/dir_2c7bb40a7e5a6685f00216dd2909cd99_dep.map
+html/dir_2c7bb40a7e5a6685f00216dd2909cd99.html
+html/dir_2c1dd796c287ab9a5cf44281d8a3cbeb.html
+html/dir_072fcb7a67163ce1d8f22ad4144c7e08.html
+html/dir_000020_000002.html
+html/dir_000019_000002.html
+html/dir_000018_000002.html
+html/dir_000017_000002.html
+html/dir_000015_000016.html
+html/dir_000015_000002.html
+html/dir_000014_000015.html
+html/dir_000014_000002.html
+html/dir_000013_000002.html
+html/dir_000012_000002.html
+html/dir_000011_000002.html
+html/dir_000010_000002.html
+html/dir_000009_000002.html
+html/dir_000002_000007.html
+html/dir_000002_000004.html
+html/dir_000001_000002.html
+html/dhcp_8h_source.html
+html/dhcp_8h__dep__incl.png
+html/dhcp_8h__dep__incl.md5
+html/dhcp_8h__dep__incl.map
+html/dhcp_8h.html
+html/dhcp_8c_source.html
+html/dhcp_8c__incl.png
+html/dhcp_8c__incl.md5
+html/dhcp_8c__incl.map
+html/dhcp_8c.html
+html/closed.png
+html/classes.html
+html/bdwn.png
+html/bc_s.png
+html/annotated.html
+html/_w_i_znet___s_o_c_k_e_t_8jpg_source.html
+html/_w_i_znet___s_o_c_k_e_t_8jpg.html
+html/_stack_trace_8h_source.html
+html/_stack_trace_8h__incl.png
+html/_stack_trace_8h__incl.md5
+html/_stack_trace_8h__incl.map
+html/_stack_trace_8h__dep__incl.png
+html/_stack_trace_8h__dep__incl.md5
+html/_stack_trace_8h__dep__incl.map
+html/_stack_trace_8h.html
+html/_readme_8txt.html
+html/_r_e_a_d_m_e_8md_source.html
+html/_r_e_a_d_m_e_8md.html
+html/_main__page_8txt.html
+html/_m_q_t_t_unsubscribe_server_8c_source.html
+html/_m_q_t_t_unsubscribe_server_8c__incl.png
+html/_m_q_t_t_unsubscribe_server_8c__incl.md5
+html/_m_q_t_t_unsubscribe_server_8c__incl.map
+html/_m_q_t_t_unsubscribe_server_8c.html
+html/_m_q_t_t_unsubscribe_client_8c_source.html
+html/_m_q_t_t_unsubscribe_client_8c__incl.png
+html/_m_q_t_t_unsubscribe_client_8c__incl.md5
+html/_m_q_t_t_unsubscribe_client_8c__incl.map
+html/_m_q_t_t_unsubscribe_client_8c.html
+html/_m_q_t_t_unsubscribe_8h_source.html
+html/_m_q_t_t_unsubscribe_8h__dep__incl.png
+html/_m_q_t_t_unsubscribe_8h__dep__incl.md5
+html/_m_q_t_t_unsubscribe_8h__dep__incl.map
+html/_m_q_t_t_unsubscribe_8h.html
+html/_m_q_t_t_subscribe_server_8c_source.html
+html/_m_q_t_t_subscribe_server_8c__incl.png
+html/_m_q_t_t_subscribe_server_8c__incl.md5
+html/_m_q_t_t_subscribe_server_8c__incl.map
+html/_m_q_t_t_subscribe_server_8c.html
+html/_m_q_t_t_subscribe_client_8c_source.html
+html/_m_q_t_t_subscribe_client_8c__incl.png
+html/_m_q_t_t_subscribe_client_8c__incl.md5
+html/_m_q_t_t_subscribe_client_8c__incl.map
+html/_m_q_t_t_subscribe_client_8c.html
+html/_m_q_t_t_subscribe_8h_source.html
+html/_m_q_t_t_subscribe_8h__dep__incl.png
+html/_m_q_t_t_subscribe_8h__dep__incl.md5
+html/_m_q_t_t_subscribe_8h__dep__incl.map
+html/_m_q_t_t_subscribe_8h.html
+html/_m_q_t_t_serialize_publish_8c_source.html
+html/_m_q_t_t_serialize_publish_8c__incl.png
+html/_m_q_t_t_serialize_publish_8c__incl.md5
+html/_m_q_t_t_serialize_publish_8c__incl.map
+html/_m_q_t_t_serialize_publish_8c.html
+html/_m_q_t_t_publish_8h_source.html
+html/_m_q_t_t_publish_8h__dep__incl.png
+html/_m_q_t_t_publish_8h__dep__incl.md5
+html/_m_q_t_t_publish_8h__dep__incl.map
+html/_m_q_t_t_publish_8h.html
+html/_m_q_t_t_packet_8h_source.html
+html/_m_q_t_t_packet_8h__incl.png
+html/_m_q_t_t_packet_8h__incl.md5
+html/_m_q_t_t_packet_8h__incl.map
+html/_m_q_t_t_packet_8h__dep__incl.png
+html/_m_q_t_t_packet_8h__dep__incl.md5
+html/_m_q_t_t_packet_8h__dep__incl.map
+html/_m_q_t_t_packet_8h.html
+html/_m_q_t_t_packet_8c_source.html
+html/_m_q_t_t_packet_8c__incl.png
+html/_m_q_t_t_packet_8c__incl.md5
+html/_m_q_t_t_packet_8c__incl.map
+html/_m_q_t_t_packet_8c.html
+html/_m_q_t_t_format_8h_source.html
+html/_m_q_t_t_format_8h__incl.png
+html/_m_q_t_t_format_8h__incl.md5
+html/_m_q_t_t_format_8h__incl.map
+html/_m_q_t_t_format_8h__dep__incl.png
+html/_m_q_t_t_format_8h__dep__incl.md5
+html/_m_q_t_t_format_8h__dep__incl.map
+html/_m_q_t_t_format_8h.html
+html/_m_q_t_t_format_8c_source.html
+html/_m_q_t_t_format_8c__incl.png
+html/_m_q_t_t_format_8c__incl.md5
+html/_m_q_t_t_format_8c__incl.map
+html/_m_q_t_t_format_8c.html
+html/_m_q_t_t_deserialize_publish_8c_source.html
+html/_m_q_t_t_deserialize_publish_8c__incl.png
+html/_m_q_t_t_deserialize_publish_8c__incl.md5
+html/_m_q_t_t_deserialize_publish_8c__incl.map
+html/_m_q_t_t_deserialize_publish_8c.html
+html/_m_q_t_t_connect_server_8c_source.html
+html/_m_q_t_t_connect_server_8c__incl.png
+html/_m_q_t_t_connect_server_8c__incl.md5
+html/_m_q_t_t_connect_server_8c__incl.map
+html/_m_q_t_t_connect_server_8c.html
+html/_m_q_t_t_connect_client_8c_source.html
+html/_m_q_t_t_connect_client_8c__incl.png
+html/_m_q_t_t_connect_client_8c__incl.md5
+html/_m_q_t_t_connect_client_8c__incl.map
+html/_m_q_t_t_connect_client_8c.html
+html/_m_q_t_t_connect_8h_source.html
+html/_m_q_t_t_connect_8h__dep__incl.png
+html/_m_q_t_t_connect_8h__dep__incl.md5
+html/_m_q_t_t_connect_8h__dep__incl.map
+html/_m_q_t_t_connect_8h.html
+html/_m_q_t_t_client_8h_source.html
+html/_m_q_t_t_client_8h__incl.png
+html/_m_q_t_t_client_8h__incl.md5
+html/_m_q_t_t_client_8h__incl.map
+html/_m_q_t_t_client_8h__dep__incl.png
+html/_m_q_t_t_client_8h__dep__incl.md5
+html/_m_q_t_t_client_8h__dep__incl.map
+html/_m_q_t_t_client_8h.html
+html/_m_q_t_t_client_8c_source.html
+html/_m_q_t_t_client_8c__incl.png
+html/_m_q_t_t_client_8c__incl.md5
+html/_m_q_t_t_client_8c__incl.map
+html/_m_q_t_t_client_8c.html
+html/_f_t_p_server_2stdio__private_8h_source.html
+html/_f_t_p_server_2stdio__private_8h__incl.png
+html/_f_t_p_server_2stdio__private_8h__incl.md5
+html/_f_t_p_server_2stdio__private_8h__incl.map
+html/_f_t_p_server_2stdio__private_8h__dep__incl.png
+html/_f_t_p_server_2stdio__private_8h__dep__incl.md5
+html/_f_t_p_server_2stdio__private_8h__dep__incl.map
+html/_f_t_p_server_2stdio__private_8h.html
+html/_f_t_p_client_2stdio__private_8h_source.html
+html/_f_t_p_client_2stdio__private_8h__incl.png
+html/_f_t_p_client_2stdio__private_8h__incl.md5
+html/_f_t_p_client_2stdio__private_8h__incl.map
+html/_f_t_p_client_2stdio__private_8h__dep__incl.png
+html/_f_t_p_client_2stdio__private_8h__dep__incl.md5
+html/_f_t_p_client_2stdio__private_8h__dep__incl.map
+html/_f_t_p_client_2stdio__private_8h.html
+html/_berkeley___s_o_c_k_e_t_8jpg_source.html
+html/_berkeley___s_o_c_k_e_t_8jpg.html
+html/WIZnet_SOCKET.jpg
+html/Berkeley_SOCKET.jpg
+Main_page.txt
+Doxyfile
+man/man3/sntp.c.3
+man/man3/snmp_module.3
+man/man3/snmp_custom.h.3
+man/man3/snmp_custom.c.3
+man/man3/snmp.h.3
+man/man3/snmp.c.3
+man/man3/netutil.h.3
+man/man3/netutil.c.3
+man/man3/mqtt_interface.h.3
+man/man3/mqtt_interface.c.3
+man/man3/messageStruct.3
+man/man3/md__r_e_a_d_m_e.3
+man/man3/loopback.h.3
+man/man3/loopback.c.3
+man/man3/license.txt.3
+man/man3/httpUtil.h.3
+man/man3/_datetime.3
+man/man3/__file.3
+man/man3/__WIZCHIP__IF.3
+man/man3/__WIZCHIP__CS.3
+man/man3/__WIZCHIP__CRIS.3
+man/man3/__WIZCHIP.3
+man/man3/WIZnet_socket_APIs.3
+man/man3/WIZnet_SOCKET.jpg.3
+man/man3/WIZCHIP_register.3
+man/man3/WIZCHIP_IO_Functions_W5300.3
+man/man3/WIZCHIP_IO_Functions_W5200.3
+man/man3/WIZCHIP_IO_Functions_W5100S.3
+man/man3/W5500.3
+man/man3/W5300.3
+man/man3/W5100S.3
+man/man3/w5200.c.3
+man/man3/w5100s.h.3
+man/man3/w5100s.c.3
+man/man3/w5100.h.3
+man/man3/w5100.c.3
+man/man3/todo.3
+man/man3/tlvStructType.3
+man/man3/tftp_option.3
+man/man3/tftp_error.3
+man/man3/tftp_data.3
+man/man3/tftp.h.3
+man/man3/tftp.c.3
+man/man3/stdio_private.h.3
+man/man3/socket.h.3
+man/man3/socket.c.3
+man/man3/sntp.h.3
+man/man3/httpUtil.c.3
+man/man3/httpServer.h.3
+man/man3/httpServer.c.3
+man/man3/httpParser.h.3
+man/man3/httpParser.c.3
+man/man3/ftpd.h.3
+man/man3/ftpd.c.3
+man/man3/ftpd.3
+man/man3/WIZCHIP_register_W5300.3
+man/man3/WIZCHIP_register_W5200.3
+man/man3/WIZCHIP_register_W5100S.3
+man/man3/WIZCHIP_register_W5100.3
+man/man3/WIZCHIP_IO_Functions_W5100.3
+man/man3/WIZCHIP_IO_Functions.3
+man/man3/W5200.3

+ 225 - 0
lib/ioLibrary_Driver/Application/loopback/loopback.c

@@ -0,0 +1,225 @@
+#include <stdio.h>
+#include "loopback.h"
+#include "socket.h"
+#include "wizchip_conf.h"
+
+#if LOOPBACK_MODE == LOOPBACK_MAIN_NOBLCOK
+
+int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
+{
+   int32_t ret;
+   uint16_t size = 0, sentsize=0;
+
+#ifdef _LOOPBACK_DEBUG_
+   uint8_t destip[4];
+   uint16_t destport;
+#endif
+
+   switch(getSn_SR(sn))
+   {
+      case SOCK_ESTABLISHED :
+         if(getSn_IR(sn) & Sn_IR_CON)
+         {
+#ifdef _LOOPBACK_DEBUG_
+			getSn_DIPR(sn, destip);
+			destport = getSn_DPORT(sn);
+
+			printf("%d:Connected - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
+#endif
+			setSn_IR(sn,Sn_IR_CON);
+         }
+		 if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
+         {
+			if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
+			ret = recv(sn, buf, size);
+
+			if(ret <= 0) return ret;      // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.
+			size = (uint16_t) ret;
+			sentsize = 0;
+
+			while(size != sentsize)
+			{
+				ret = send(sn, buf+sentsize, size-sentsize);
+				if(ret < 0)
+				{
+					close(sn);
+					return ret;
+				}
+				sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
+			}
+         }
+         break;
+      case SOCK_CLOSE_WAIT :
+#ifdef _LOOPBACK_DEBUG_
+         //printf("%d:CloseWait\r\n",sn);
+#endif
+         if((ret = disconnect(sn)) != SOCK_OK) return ret;
+#ifdef _LOOPBACK_DEBUG_
+         printf("%d:Socket Closed\r\n", sn);
+#endif
+         break;
+      case SOCK_INIT :
+#ifdef _LOOPBACK_DEBUG_
+    	 printf("%d:Listen, TCP server loopback, port [%d]\r\n", sn, port);
+#endif
+         if( (ret = listen(sn)) != SOCK_OK) return ret;
+         break;
+      case SOCK_CLOSED:
+#ifdef _LOOPBACK_DEBUG_
+         //printf("%d:TCP server loopback start\r\n",sn);
+#endif
+         if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
+#ifdef _LOOPBACK_DEBUG_
+         //printf("%d:Socket opened\r\n",sn);
+#endif
+         break;
+      default:
+         break;
+   }
+   return 1;
+}
+
+
+int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport)
+{
+   int32_t ret; // return value for SOCK_ERRORs
+   uint16_t size = 0, sentsize=0;
+
+   // Destination (TCP Server) IP info (will be connected)
+   // >> loopback_tcpc() function parameter
+   // >> Ex)
+   //	uint8_t destip[4] = 	{192, 168, 0, 214};
+   //	uint16_t destport = 	5000;
+
+   // Port number for TCP client (will be increased)
+   static uint16_t any_port = 	50000;
+
+   // Socket Status Transitions
+   // Check the W5500 Socket n status register (Sn_SR, The 'Sn_SR' controlled by Sn_CR command or Packet send/recv status)
+   switch(getSn_SR(sn))
+   {
+      case SOCK_ESTABLISHED :
+         if(getSn_IR(sn) & Sn_IR_CON)	// Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
+         {
+#ifdef _LOOPBACK_DEBUG_
+			printf("%d:Connected to - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
+#endif
+			setSn_IR(sn, Sn_IR_CON);  // this interrupt should be write the bit cleared to '1'
+         }
+
+         //////////////////////////////////////////////////////////////////////////////////////////////
+         // Data Transaction Parts; Handle the [data receive and send] process
+         //////////////////////////////////////////////////////////////////////////////////////////////
+		 if((size = getSn_RX_RSR(sn)) > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length
+         {
+			if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array)
+			ret = recv(sn, buf, size); // Data Receive process (H/W Rx socket buffer -> User's buffer)
+
+			if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end
+			size = (uint16_t) ret;
+			sentsize = 0;
+
+			// Data sentsize control
+			while(size != sentsize)
+			{
+				ret = send(sn, buf+sentsize, size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
+				if(ret < 0) // Send Error occurred (sent data length < 0)
+				{
+					close(sn); // socket close
+					return ret;
+				}
+				sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
+			}
+         }
+		 //////////////////////////////////////////////////////////////////////////////////////////////
+         break;
+
+      case SOCK_CLOSE_WAIT :
+#ifdef _LOOPBACK_DEBUG_
+         //printf("%d:CloseWait\r\n",sn);
+#endif
+         if((ret=disconnect(sn)) != SOCK_OK) return ret;
+#ifdef _LOOPBACK_DEBUG_
+         printf("%d:Socket Closed\r\n", sn);
+#endif
+         break;
+
+      case SOCK_INIT :
+#ifdef _LOOPBACK_DEBUG_
+    	 printf("%d:Try to connect to the %d.%d.%d.%d : %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport);
+#endif
+    	 if( (ret = connect(sn, destip, destport)) != SOCK_OK) return ret;	//	Try to TCP connect to the TCP server (destination)
+         break;
+
+      case SOCK_CLOSED:
+    	  close(sn);
+    	  if((ret=socket(sn, Sn_MR_TCP, any_port++, 0x00)) != sn){
+         if(any_port == 0xffff) any_port = 50000;
+         return ret; // TCP socket open with 'any_port' port number
+        } 
+#ifdef _LOOPBACK_DEBUG_
+    	 //printf("%d:TCP client loopback start\r\n",sn);
+         //printf("%d:Socket opened\r\n",sn);
+#endif
+         break;
+      default:
+         break;
+   }
+   return 1;
+}
+
+
+int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port)
+{
+   int32_t  ret;
+   uint16_t size, sentsize;
+   uint8_t  destip[4];
+   uint16_t destport;
+
+   switch(getSn_SR(sn))
+   {
+      case SOCK_UDP :
+         if((size = getSn_RX_RSR(sn)) > 0)
+         {
+            if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
+            ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
+            if(ret <= 0)
+            {
+#ifdef _LOOPBACK_DEBUG_
+               printf("%d: recvfrom error. %ld\r\n",sn,ret);
+#endif
+               return ret;
+            }
+            size = (uint16_t) ret;
+            sentsize = 0;
+            while(sentsize != size)
+            {
+               ret = sendto(sn, buf+sentsize, size-sentsize, destip, destport);
+               if(ret < 0)
+               {
+#ifdef _LOOPBACK_DEBUG_
+                  printf("%d: sendto error. %ld\r\n",sn,ret);
+#endif
+                  return ret;
+               }
+               sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
+            }
+         }
+         break;
+      case SOCK_CLOSED:
+#ifdef _LOOPBACK_DEBUG_
+         //printf("%d:UDP loopback start\r\n",sn);
+#endif
+         if((ret = socket(sn, Sn_MR_UDP, port, 0x00)) != sn)
+            return ret;
+#ifdef _LOOPBACK_DEBUG_
+         printf("%d:Opened, UDP loopback, port [%d]\r\n", sn, port);
+#endif
+         break;
+      default :
+         break;
+   }
+   return 1;
+}
+
+#endif

+ 38 - 0
lib/ioLibrary_Driver/Application/loopback/loopback.h

@@ -0,0 +1,38 @@
+#ifndef _LOOPBACK_H_
+#define _LOOPBACK_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* Loopback test debug message printout enable */
+#define	_LOOPBACK_DEBUG_
+
+/* DATA_BUF_SIZE define for Loopback example */
+#ifndef DATA_BUF_SIZE
+	#define DATA_BUF_SIZE			2048
+#endif
+
+/************************/
+/* Select LOOPBACK_MODE */
+/************************/
+#define LOOPBACK_MAIN_NOBLOCK    0
+#define LOOPBACK_MODE   LOOPBACK_MAIN_NOBLOCK
+
+
+/* TCP server Loopback test example */
+int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port);
+
+/* TCP client Loopback test example */
+int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport);
+
+/* UDP Loopback test example */
+int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 113 - 0
lib/ioLibrary_Driver/Application/multicast/multicast.c

@@ -0,0 +1,113 @@
+#include "multicast.h"
+#include <stdio.h>
+#include "socket.h"
+#include "wizchip_conf.h"
+
+
+int32_t multicast_loopback(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port)
+{
+   int32_t  ret;
+   uint16_t size, sentsize;
+   uint8_t destip[4];
+   uint16_t destport, port=3000;
+
+   switch(getSn_SR(sn))
+   {
+      case SOCK_UDP :
+         if((size = getSn_RX_RSR(sn)) > 0)
+         {
+            if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
+            ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
+            if(ret <= 0)
+            {
+#ifdef _MULTICAST_DEBUG_
+               printf("%d: recvfrom error. %ld\r\n",sn,ret);
+#endif
+               return ret;
+            }
+            size = (uint16_t) ret;
+            sentsize = 0;
+            while(sentsize != size)
+            {
+               ret = sendto(sn, buf+sentsize, size-sentsize, destip, destport);
+               if(ret < 0)
+               {
+#ifdef _MULTICAST_DEBUG_
+                  printf("%d: sendto error. %ld\r\n",sn,ret);
+#endif
+                  return ret;
+               }
+               sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
+            }
+         }
+
+         break;
+      case SOCK_CLOSED:
+#ifdef _MULTICAST_DEBUG_
+         printf("%d:Multicast Loopback start\r\n",sn);
+#endif
+         setSn_DIPR(0, multicast_ip);
+         setSn_DPORT(0, multicast_port);
+         if((ret = socket(sn, Sn_MR_UDP, port, Sn_MR_MULTI)) != sn)
+            return ret;
+#ifdef _MULTICAST_DEBUG_
+         printf("%d:Opened, UDP Multicast Socket\r\n", sn);
+         printf("%d:Multicast Group IP - %d.%d.%d.%d\r\n", sn, multicast_ip[0], multicast_ip[1], multicast_ip[2], multicast_ip[3]);
+         printf("%d:Multicast Group Port - %d\r\n", sn, multicast_port);
+#endif
+         break;
+      default :
+         break;
+   }
+   return 1;
+}
+
+int32_t multicast_recv(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port)
+{
+   int32_t  ret;
+   uint16_t size, port=3000;
+   uint8_t destip[4];
+   uint16_t destport;
+
+   switch(getSn_SR(sn))
+   {
+      case SOCK_UDP :
+         if((size = getSn_RX_RSR(sn)) > 0)
+         {
+            if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
+            ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
+            if(ret <= 0)
+            {
+#ifdef _MULTICAST_DEBUG_
+               printf("%d: recvfrom error. %ld\r\n",sn,ret);
+#endif
+               return ret;
+            }
+            size = (uint16_t) ret;
+#ifdef _MULTICAST_DEBUG_
+            printf("\r\nrecv size : %d\r\n", size);
+            for(int i=0; i<size; i++)
+            	printf("%c", buf[i]);
+            printf("\r\n");
+#endif
+         }
+         break;
+      case SOCK_CLOSED:
+#ifdef _MULTICAST_DEBUG_
+         printf("%d:Multicast Recv start\r\n",sn);
+#endif
+         setSn_DIPR(sn, multicast_ip);
+         setSn_DPORT(sn, multicast_port);
+         if((ret = socket(sn, Sn_MR_UDP, port, Sn_MR_MULTI)) != sn)
+            return ret;
+#ifdef _MULTICAST_DEBUG_
+         printf("%d:Opened, UDP Multicast Socket\r\n", sn);
+         printf("%d:Multicast Group IP - %d.%d.%d.%d\r\n", sn, multicast_ip[0], multicast_ip[1], multicast_ip[2], multicast_ip[3]);
+         printf("%d:Multicast Group Port - %d\r\n", sn, multicast_port);
+#endif
+         break;
+      default :
+         break;
+   }
+   return 1;
+}

+ 28 - 0
lib/ioLibrary_Driver/Application/multicast/multicast.h

@@ -0,0 +1,28 @@
+#ifndef _MULTICAST_H_
+#define _MULTICAST_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/* Multicast test debug message printout enable */
+#define _MULTICAST_DEBUG_
+
+#ifndef DATA_BUF_SIZE
+	#define DATA_BUF_SIZE			2048
+#endif
+
+/* UDP Multicast Loopback test example */
+int32_t multicast_loopback(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port);
+
+/* UDP Multicast Recv test example */
+int32_t multicast_recv(uint8_t sn, uint8_t* buf, uint8_t* multicast_ip, uint16_t multicast_port);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

TEMPAT SAMPAH
lib/ioLibrary_Driver/Ethernet/Socket_APIs_V3.0.3.chm


+ 386 - 0
lib/ioLibrary_Driver/Ethernet/W5100/w5100.c

@@ -0,0 +1,386 @@
+//*****************************************************************************
+//
+//! \file w5100.c
+//! \brief W5100 HAL Interface.
+//! \version 1.0.0
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! 
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include "w5100.h"
+
+#if   (_WIZCHIP_ == 5100)
+/**
+@brief  This function writes the data into W5100 registers.
+*/
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
+{
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+   WIZCHIP.IF.SPI._write_byte(0xF0);
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >>  0);
+   WIZCHIP.IF.SPI._write_byte(wb);    // Data write (write 1byte data)
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
+   //M20150601 : Rename the function for integrating with ioLibrary
+   //WIZCHIP.IF.BUS._write_byte(AddrSel,wb);
+   WIZCHIP.IF.BUS._write_data(AddrSel,wb);
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+
+   //add indirect bus 
+   //M20150601 : Rename the function for integrating with ioLibrary
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));	
+   //WIZCHIP.IF.BUS._write_byte(IDM_DR,wb);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));	
+   WIZCHIP.IF.BUS._write_data(IDM_DR,wb);
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+/**
+@brief  This function reads the value from W5100 registers.
+*/
+uint8_t  WIZCHIP_READ(uint32_t AddrSel)
+{
+   uint8_t ret;
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+   WIZCHIP.IF.SPI._write_byte(0x0F);
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >>  0);
+   ret = WIZCHIP.IF.SPI._read_byte(); 
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
+   //M20150601 : Rename the function for integrating with ioLibrary
+   //ret = WIZCHIP.IF.BUS._read_byte(AddrSel);
+   ret = WIZCHIP.IF.BUS._read_data(AddrSel);   
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+
+   //add indirect bus
+   //M20150601 : Rename the function for integrating with ioLibrary
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));	
+   //ret = WIZCHIP.IF.BUS._read_byte(IDM_DR);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));	
+   ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
+
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"   
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+   return ret;
+}
+
+
+/**
+@brief  This function writes into W5100 memory(Buffer)
+*/ 
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint16_t i = 0;
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();   //M20150601 : Moved here.
+
+#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+  for(i = 0; i < len; i++)
+  {
+     //M20160715 : Depricated "M20150601 : Remove _select() to top-side"
+     //            CS should be controlled every SPI frames
+     WIZCHIP.CS._select();
+     WIZCHIP.IF.SPI._write_byte(0xF0);
+     WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >>  8);
+     WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >>  0);
+     WIZCHIP.IF.SPI._write_byte(pBuf[i]);    // Data write (write 1byte data)
+     //M20160715 : Depricated "M20150601 : Remove _select() to top-side"
+	  WIZCHIP.CS._deselect();
+  }
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
+   for(i = 0; i < len; i++)
+   //M20150601 : Rename the function for integrating with ioLibrary  
+   //  WIZCHIP.IF.BUS._write_byte(AddrSel+i,pBuf[i]);  
+       WIZCHIP.IF.BUS._write_data(AddrSel+i,pBuf[i]);  
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+   //M20150601 : Rename the function for integrating with ioLibrary  
+   /*
+   WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI);     
+   WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
+   for(i = 0 ; i < len; i++)
+      WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]);
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);   
+   */
+   setMR(getMR()|MR_AI);     
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
+   for(i = 0 ; i < len; i++)
+      WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]);
+   setMR(getMR() & ~MR_AI);   
+
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!!"
+#endif
+   
+   WIZCHIP.CS._deselect();  //M20150601 : Moved here.
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+/**
+@brief  This function reads into W5100 memory(Buffer)
+*/ 
+
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint16_t i = 0;
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();   //M20150601 : Moved here.
+   
+   #if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+   for(i = 0; i < len; i++)
+   {
+     //M20160715 : Depricated "M20150601 : Remove _select() to top-side"
+     //            CS should be controlled every SPI frames
+     WIZCHIP.CS._select();
+      WIZCHIP.IF.SPI._write_byte(0x0F);
+      WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >>  8);
+      WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >>  0);
+      pBuf[i] = WIZCHIP.IF.SPI._read_byte(); 
+     //M20160715 : Depricated "M20150601 : Remove _select() to top-side"
+	  WIZCHIP.CS._deselect();
+   }
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
+   for(i = 0 ; i < len; i++)
+   //M20150601 : Rename the function for integrating with ioLibrary  
+   // pBuf[i]	= WIZCHIP.IF.BUS._read_byte(AddrSel+i);
+      pBuf[i]	= WIZCHIP.IF.BUS._read_data(AddrSel+i);
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+   //M20150601 : Rename the function for integrating with ioLibrary  
+   /*
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI);    
+   WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));	
+   for(i = 0 ; i < len; i++)
+      pBuf[i]	= WIZCHIP.IF.BUS._read_byte(IDM_DR);
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); 
+   */
+   setMR(getMR() | MR_AI);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));	
+   for(i = 0 ; i < len; i++)
+      pBuf[i]	= WIZCHIP.IF.BUS._read_data(IDM_DR);
+   setMR(getMR() & ~MR_AI); 
+   
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!!"
+#endif
+
+   WIZCHIP.CS._deselect();    //M20150601 : Moved Here.
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+///////////////////////////////////
+// Socket N regsiter IO function //
+///////////////////////////////////
+
+uint16_t getSn_TX_FSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_TX_FSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+
+uint16_t getSn_RX_RSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_RX_RSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+uint32_t getSn_RxBASE(uint8_t sn)
+{
+   int8_t  i;
+#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
+   uint32_t rxbase = _W5100_IO_BASE_ + _WIZCHIP_IO_RXBUF_;
+#else   
+   uint32_t rxbase = _WIZCHIP_IO_RXBUF_;
+#endif   
+   for(i = 0; i < sn; i++)
+      rxbase += getSn_RxMAX(i);
+
+   return rxbase;
+}
+
+uint32_t getSn_TxBASE(uint8_t sn)
+{
+   int8_t  i;
+#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
+   uint32_t txbase = _W5100_IO_BASE_ + _WIZCHIP_IO_TXBUF_;
+#else   
+   uint32_t txbase = _WIZCHIP_IO_TXBUF_;
+#endif   
+   for(i = 0; i < sn; i++)
+      txbase += getSn_TxMAX(i);
+   return txbase;
+}
+
+/**
+@brief  This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip.
+
+This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
+register. User should read upper byte first and lower byte later to get proper value.
+And this function is being used for copy the data form application buffer to Transmite
+buffer of the chip. It calculate the actual physical address where one has to write
+the data in transmite buffer. Here also take care of the condition while it exceed
+the Tx memory uper-bound of socket.
+
+*/
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+  uint16_t ptr;
+  uint16_t size;
+  uint16_t dst_mask;
+  uint16_t dst_ptr;
+
+  ptr = getSn_TX_WR(sn);
+
+  dst_mask = ptr & getSn_TxMASK(sn);
+  dst_ptr = getSn_TxBASE(sn) + dst_mask;
+  
+  if (dst_mask + len > getSn_TxMAX(sn)) 
+  {
+    size = getSn_TxMAX(sn) - dst_mask;
+    WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
+    wizdata += size;
+    size = len - size;
+    dst_ptr = getSn_TxBASE(sn);
+    WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
+  } 
+  else
+  {
+    WIZCHIP_WRITE_BUF(dst_ptr, wizdata, len);
+  }
+
+  ptr += len;
+
+  setSn_TX_WR(sn, ptr);  
+}
+
+
+/**
+@brief  This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer.
+
+This function read the Rx read pointer register
+and after copy the data from receive buffer update the Rx write pointer register.
+User should read upper byte first and lower byte later to get proper value.
+It calculate the actual physical address where one has to read
+the data from Receive buffer. Here also take care of the condition while it exceed
+the Rx memory uper-bound of socket.
+*/
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+  uint16_t ptr;
+  uint16_t size;
+  uint16_t src_mask;
+  uint16_t src_ptr;
+
+  ptr = getSn_RX_RD(sn);
+  
+  src_mask = (uint32_t)ptr & getSn_RxMASK(sn);
+  src_ptr = (getSn_RxBASE(sn) + src_mask);
+
+  
+  if( (src_mask + len) > getSn_RxMAX(sn) ) 
+  {
+    size = getSn_RxMAX(sn) - src_mask;
+    WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
+    wizdata += size;
+    size = len - size;
+	src_ptr = getSn_RxBASE(sn);
+    WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, size);
+  } 
+  else
+  {
+    WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, len);
+  }
+    
+  ptr += len;
+  
+  setSn_RX_RD(sn, ptr);
+}
+
+void wiz_recv_ignore(uint8_t sn, uint16_t len)
+{
+  uint16_t ptr;
+
+  ptr = getSn_RX_RD(sn);
+  
+  ptr += len;
+  setSn_RX_RD(sn,ptr);
+}
+
+#endif

+ 1865 - 0
lib/ioLibrary_Driver/Ethernet/W5100/w5100.h

@@ -0,0 +1,1865 @@
+//* ****************************************************************************
+//! \file w5100.h
+//! \brief W5100 HAL Header File.
+//! \version 1.0.0
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#ifndef	_W5100_H_
+#define	_W5100_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "wizchip_conf.h"
+
+/// \cond DOXY_APPLY_CODE
+#if   (_WIZCHIP_ == 5100)
+/// \endcond
+
+#define _WIZCHIP_SN_BASE_  (0x0400)
+#define _WIZCHIP_SN_SIZE_  (0x0100)
+#define _WIZCHIP_IO_TXBUF_ (0x4000) /* Internal Tx buffer address of the iinchip */
+#define _WIZCHIP_IO_RXBUF_ (0x6000) /* Internal Rx buffer address of the iinchip */
+
+
+#define WIZCHIP_CREG_BLOCK      	      0x00   ///< Common register block
+#define WIZCHIP_SREG_BLOCK(N)    	   (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block
+
+#define WIZCHIP_OFFSET_INC(ADDR, N)    (ADDR + N) ///< Increase offset address
+
+#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
+   #define _W5100_IO_BASE_     _WIZCHIP_IO_BASE_
+#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_)
+	#define IDM_OR             ((_WIZCHIP_IO_BASE  + 0x0000))
+	#define IDM_AR0            ((_WIZCHIP_IO_BASE_ + 0x0001))
+	#define IDM_AR1            ((_WIZCHIP_IO_BASE_ + 0x0002))
+	#define IDM_DR             ((_WIZCHIP_IO_BASE_ + 0x0003))
+	#define _W5100_IO_BASE_    0x0000
+#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define _W5100_IO_BASE_    0x0000
+#endif
+
+///////////////////////////////////////
+// Definition For Legacy Chip Driver //
+///////////////////////////////////////
+#define IINCHIP_READ(ADDR)                WIZCHIP_READ(ADDR)               ///< The defined for legacy chip driver
+#define IINCHIP_WRITE(ADDR,VAL)           WIZCHIP_WRITE(ADDR,VAL)          ///< The defined for legacy chip driver
+#define IINCHIP_READ_BUF(ADDR,BUF,LEN)    WIZCHIP_READ_BUF(ADDR,BUF,LEN)   ///< The defined for legacy chip driver
+#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN)   WIZCHIP_WRITE(ADDR,BUF,LEN)      ///< The defined for legacy chip driver
+
+
+//-----------    defgroup --------------------------------
+
+/**
+ * @defgroup W5100 W5100
+ * @brief WHIZCHIP register defines and I/O functions of @b W5100.
+ *
+ * - @ref WIZCHIP_register_W5100 : @ref Common_register_group_W5100 and @ref Socket_register_group_W5100
+ * - @ref WIZCHIP_IO_Functions_W5100 : @ref Basic_IO_function_W5100, @ref Common_register_access_function_W5100 and @ref Socket_register_group_W5100
+ */
+ 
+ /**
+ * @defgroup WIZCHIP_register_W5100 WIZCHIP register
+ * @ingroup W5100
+ * @brief WIZCHIP register defines register group of <b> W5100 </b>.
+ *
+ * - \ref Common_register_group_W5100 : Common register group W5100
+ * - \ref Socket_register_group_W5100 : \c SOCKET n register group W5100
+ */
+ 
+
+/**
+ * @defgroup WIZCHIP_IO_Functions_W5100 WIZCHIP I/O functions
+ * @ingroup W5100 
+ * @brief This supports the basic I/O functions for \ref WIZCHIP_register_W5100.
+ *
+ * - <b> Basic I/O function </b> \n
+ *   WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n
+ *
+ * - \ref Common_register_group_W5100 <b>access functions</b> \n
+ * 	-# @b Mode \n
+ *    getMR(), setMR()
+ * 	-# @b Interrupt \n
+ *    getIR(), setIR(), getIMR(), setIMR(), 
+ * 	-# <b> Network Information </b> \n
+ *    getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
+ * 	-# @b Retransmission \n
+ *    getRCR(), setRCR(), getRTR(), setRTR()
+ * 	-# @b PPPoE \n
+ *    getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC()
+ *
+ * - \ref Socket_register_group_W5100 <b>access functions</b> \n
+ *   -# <b> SOCKET control</b> \n
+ *      getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IR(), setSn_IR()
+ *   -# <b> SOCKET information</b> \n
+ *      getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
+ *      getSn_MSSR(), setSn_MSSR()
+ *   -# <b> SOCKET communication </b> \n
+ *      getSn_RXMEM_SIZE(), setSn_RXMEM_SIZE(), getSn_TXMEM_SIZE(), setSn_TXMEM_SIZE() \n
+ *      getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
+ *      getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
+ *      getSn_TX_FSR(), getSn_RX_RSR()
+ *   -# <b> IP header field </b> \n
+ *      getSn_FRAG(), setSn_FRAG(),  getSn_TOS(), setSn_TOS() \n
+ *      getSn_TTL(), setSn_TTL()
+ */
+ 
+/**
+ * @defgroup Common_register_group_W5100 Common register
+ * @ingroup WIZCHIP_register_W5100
+ * @brief Common register group\n
+ * It set the basic for the networking\n
+ * It set the configuration such as interrupt, network information, ICMP, etc.
+ * @details
+ * @sa MR : Mode register.
+ * @sa GAR, SUBR, SHAR, SIPR
+ * @sa IR, Sn_IR, _IMR_  : Interrupt.
+ * @sa _RTR_, _RCR_ : Data retransmission.
+ * @sa PTIMER, PMAGIC : PPPoE.
+ */
+
+
+ /**
+ * @defgroup Socket_register_group_W5100 Socket register
+ * @ingroup WIZCHIP_register_W5100
+ * @brief Socket register group\n
+ * Socket register configures and control SOCKETn which is necessary to data communication.
+ * @details
+ * @sa Sn_MR, Sn_CR, Sn_IR : SOCKETn Control
+ * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
+ * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_FRAG : Internet protocol.
+ * @sa Sn_RXMEM_SIZE, Sn_TXMEM_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
+ */
+ 
+ /**
+ * @defgroup Basic_IO_function_W5100 Basic I/O function
+ * @ingroup WIZCHIP_IO_Functions_W5100
+ * @brief These are basic input/output functions to read values from register or write values to register.
+ */
+
+/**
+ * @defgroup Common_register_access_function_W5100 Common register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5100
+ * @brief These are functions to access <b>common registers</b>.
+ */
+ 
+/**
+ * @defgroup Socket_register_access_function_W5100 Socket register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5100
+ * @brief These are functions to access <b>socket registers</b>.
+ */
+ 
+ //-----------------------------------------------------------------------------------
+
+//----------------------------- W5100 Common Registers IOMAP -----------------------------
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Mode Register address(R/W)\n
+ * \ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
+ * @details Each bit of \ref MR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>AI</td> <td>IND</td> </tr>
+ * </table>
+ * - \ref MR_RST		 	   : Reset
+ * - \ref MR_PB         	: Ping block
+ * - \ref MR_PPPOE      	: PPPoE mode
+ * - \ref MR_AI         	: Address Auto-Increment in Indirect Bus Interface
+ * - \ref MR_IND         	: Indirect Bus Interface mode
+ */
+#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
+   #define MR					(_WIZCHIP_IO_BASE_ + (0x0000))  // Mode
+#else
+   #define MR					(_W5100_IO_BASE_ + (0x0000))  // Mode
+#endif   
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Gateway IP Register address(R/W)
+ * @details \ref GAR configures the default gateway address.
+ */
+#define GAR     			(_W5100_IO_BASE_ + (0x0001))  // GW Address
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Subnet mask Register address(R/W)
+ * @details \ref SUBR configures the subnet mask address.
+ */
+#define SUBR    			(_W5100_IO_BASE_ + (0x0005)) // SN Mask Address
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Source MAC Register address(R/W)
+ * @details \ref SHAR configures the source hardware address.
+ */
+#define SHAR    			(_W5100_IO_BASE_ + (0x0009)) // Source Hardware Address
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Source IP Register address(R/W)
+ * @details \ref SIPR configures the source IP address.
+ */
+#define SIPR    			(_W5100_IO_BASE_ + (0x000F)) // Source IP Address
+
+// Reserved					(_W5100_IO_BASE_ + (0x0013))
+// Reserved					(_W5100_IO_BASE_ + (0x0014))
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Interrupt Register(R/W)
+ * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host.
+ * If \ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
+ * Each bit of \ref IR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>CONFLICT</td> <td>UNREACH</td> <td>PPPoE</td> <td>Reserved</td> <td>S3_INT</td> <td>S2_INT</td> <td>S1_INT</td> <td>S0_INT</td> </tr>
+ * </table>
+ * - \ref IR_CONFLICT : IP conflict
+ * - \ref IR_UNREACH  : Destination unreachable
+ * - \ref IR_PPPoE	 : PPPoE connection close
+ * - \ref IR_SOCK(3)  : SOCKET 3 Interrupt
+ * - \ref IR_SOCK(2)  : SOCKET 2 Interrupt
+ * - \ref IR_SOCK(1)  : SOCKET 1 Interrupt
+ * - \ref IR_SOCK(0)  : SOCKET 0 Interrupt 
+ */
+#define IR					(_W5100_IO_BASE_ + (0x0015)) // Interrupt
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Socket Interrupt Mask Register(R/W)
+ * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR.
+ * When a bit of \ref _IMR_ is and the corresponding bit of \ref IR is set, Interrupt will be issued.
+ */
+#define _IMR_    			(_W5100_IO_BASE_ + (0x0016)) // Socket Interrupt Mask
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Timeout register address( 1 is 100us )(R/W)
+ * @details \ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of \ref _RTR_ is x07D0or 000
+ * And so the default timeout period is 200ms(100us X 2000). During the time configured by \ref _RTR_, W5100 waits for the peer response
+ * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
+ * If the peer does not respond within the \ref _RTR_ time, W5100 retransmits the packet or issues timeout.
+ */
+#define _RTR_     			(_W5100_IO_BASE_ + (0x0017)) // Retry Time
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief Retry count register(R/W)
+ * @details \ref _RCR_ configures the number of time of retransmission.
+ * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (\ref Sn_IR_TIMEOUT = '1').
+ */
+#define _RCR_      		(_W5100_IO_BASE_ + (0x0019)) // Retry Count
+#define RMSR				(_W5100_IO_BASE_ + (0x001A)) // Receicve Memory Size
+#define TMSR				(_W5100_IO_BASE_ + (0x001B)) // Trnasmit Memory Size
+
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief PPP LCP Request Timer register  in PPPoE mode(R)
+ * @details \ref PATR notifies authentication method that has been agreed at the connection with
+ * PPPoE Server. W5100 supports two types of Authentication method - PAP and CHAP.
+ */
+#define PATR            (_W5100_IO_BASE_ + (0x001C))
+
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief PPP LCP Request Timer register  in PPPoE mode(R)
+ * @details \ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
+ */
+#define PTIMER  			(_W5100_IO_BASE_ + (0x0028)) // PPP LCP RequestTimer
+
+/**
+ * @ingroup Common_register_group_W5100
+ * @brief PPP LCP Magic number register  in PPPoE mode(R)
+ * @details \ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
+ */
+#define PMAGIC   			(_W5100_IO_BASE_ + (0x0029)) // PPP LCP Magic number
+
+#define UIPR0				(_W5100_IO_BASE_ + (0x002A))
+#define UPORT0          (_W5100_IO_BASE  + (0x002E))
+
+
+
+//----------------------------- W5100 Socket Registers -----------------------------
+
+//--------------------------- For Backward Compatibility ---------------------------
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief socket Mode register(R/W)
+ * @details \ref Sn_MR configures the option or protocol type of Socket n.\n\n
+ * Each bit of \ref Sn_MR defined as the following.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>MULTI</td> <td>MF</td> <td>ND/MC</td> <td>Reserved</td> <td>Protocol[3]</td> <td>Protocol[2]</td> <td>Protocol[1]</td> <td>Protocol[0]</td> </tr>
+ * </table>
+ * - \ref Sn_MR_MULTI	: Support UDP Multicasting
+ * - \ref Sn_MR_MF	   : Support MACRAW
+ * - \ref Sn_MR_ND		: No Delayed Ack(TCP) flag
+ * - \ref Sn_MR_MC   	: IGMP version used <b>in UDP mulitcasting</b>
+ * - <b>Protocol</b>
+ * <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ * </table>
+ * - <b>In case of Socket 0</b>
+ *  <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>1</td> <td>PPPoE</td>   </tr>
+ * </table> 
+ *	 - \ref Sn_MR_MACRAW	: MAC LAYER RAW SOCK \n
+ *  - \ref Sn_MR_UDP		: UDP
+ *  - \ref Sn_MR_TCP		: TCP
+ *  - \ref Sn_MR_CLOSE	: Unused socket
+ *  @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR(sn)			(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0000)) // socket Mode register
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Socket command register(R/W)
+ * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
+ * After W5100 accepts the command, the \ref Sn_CR register is automatically cleared to 0x00.
+ * Even though \ref Sn_CR is cleared to 0x00, the command is still being processed.\n
+ * To check whether the command is completed or not, please check the \ref Sn_IR or \ref Sn_SR.
+ * - \ref Sn_CR_OPEN 		: Initialize or open socket.
+ * - \ref Sn_CR_LISTEN 		: Wait connection request in TCP mode(<b>Server mode</b>)
+ * - \ref Sn_CR_CONNECT 	: Send connection request in TCP mode(<b>Client mode</b>)
+ * - \ref Sn_CR_DISCON 		: Send closing request in TCP mode.
+ * - \ref Sn_CR_CLOSE   	: Close socket.
+ * - \ref Sn_CR_SEND    	: Update TX buffer pointer and send data.
+ * - \ref Sn_CR_SEND_MAC	: Send data with MAC address, so without ARP process.
+ * - \ref Sn_CR_SEND_KEEP 	: Send keep alive message.
+ * - \ref Sn_CR_RECV		: Update RX buffer pointer and receive data.
+ * - <b>In case of S0_MR(P3:P0) = S0_MR_PPPoE</b>
+ *  <table>
+ * 		<tr>   <td><b>Value</b></td> <td><b>Symbol</b></td> <td><b>Description</b></td></tr>
+ * 		<tr>   <td>0x23</td> <td>PCON</td> <td>PPPoE connection begins by transmitting PPPoE discovery packet</td>  </tr>
+ * 		<tr>   <td>0x24</td> <td>PDISCON</td> <td>Closes PPPoE connection</td>  </tr>
+ * 		<tr>   <td>0x25</td> <td>PCR</td> <td>In each phase, it transmits REQ message.</td> </tr>
+ * 		<tr>   <td>0x26</td> <td>PCN</td> <td>In each phase, it transmits NAK message.</td> </tr>
+ * 		<tr>   <td>0x27</td> <td>PCJ</td> <td>In each phase, it transmits REJECT message.</td> </tr>
+ * </table> 
+ */
+#define Sn_CR(sn)			(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0001)) // channel Sn_CR register
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Socket interrupt register(R)
+ * @details \ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
+ * When an interrupt occurs and the corresponding bit \ref IR_SOCK(N) in \ref _IMR_ are set, \ref IR_SOCK(N) in \ref IR becomes '1'.\n
+ * In order to clear the \ref Sn_IR bit, the host should write the bit to \n
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>PRECV</td> <td>PFAIL</td> <td>PNEXT</td> <td>SEND_OK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr>
+ * </table>
+ * - \ref Sn_IR_PRECV : <b>PPP Receive Interrupt</b>
+ * - \ref Sn_IR_PFAIL : <b>PPP Fail Interrupt</b>
+ * - \ref Sn_IR_PNEXT : <b>PPP Next Phase Interrupt</b>
+ * - \ref Sn_IR_SENDOK : <b>SEND_OK Interrupt</b>
+ * - \ref Sn_IR_TIMEOUT : <b>TIMEOUT Interrupt</b>
+ * - \ref Sn_IR_RECV : <b>RECV Interrupt</b>
+ * - \ref Sn_IR_DISCON : <b>DISCON Interrupt</b>
+ * - \ref Sn_IR_CON : <b>CON Interrupt</b>
+ */
+#define Sn_IR(sn)			(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0002)) // channel interrupt register
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Socket status register(R)
+ * @details \ref Sn_SR indicates the status of Socket n.\n
+ * The status of Socket n is changed by \ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
+ * @par Normal status
+ * - \ref SOCK_CLOSED 		: Closed
+ * - \ref SOCK_INIT   		: Initiate state
+ * - \ref SOCK_LISTEN    	: Listen state
+ * - \ref SOCK_ESTABLISHED 	: Success to connect
+ * - \ref SOCK_CLOSE_WAIT   : Closing state
+ * - \ref SOCK_UDP   		: UDP socket
+ * - \ref SOCK_MACRAW  		: MAC raw mode socket
+ *@par Temporary status during changing the status of Socket n.
+ * - \ref SOCK_SYNSENT   	: This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
+ * - \ref SOCK_SYNRECV    	: It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
+ * - \ref SOCK_FIN_WAIT		: Connection state
+ * - \ref SOCK_CLOSING		: Closing state
+ * - \ref SOCK_TIME_WAIT	: Closing state
+ * - \ref SOCK_LAST_ACK 	: Closing state
+ */
+#define Sn_SR(sn)			(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0003)) // channel status register
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief source port register(R/W)
+ * @details \ref Sn_PORT configures the source port number of Socket n.
+ * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered.
+*/
+#define Sn_PORT(sn)		(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0004)) // source port register
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Peer MAC register address(R/W)
+ * @details \ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
+ * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
+ */
+#define Sn_DHAR(sn)     (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0006)) // Peer MAC register address
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Peer IP register address(R/W)
+ * @details \ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP client mode, it configures an IP address of TCP server before CONNECT command.
+ * In TCP server mode, it indicates an IP address of TCP client after successfully establishing connection.
+ * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
+ */
+#define Sn_DIPR(sn)		(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x000C)) // Peer IP register address
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Peer port register address(R/W)
+ * @details \ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP clientmode, it configures the listen port number of TCP server before CONNECT command.
+ * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
+ * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
+ */
+#define Sn_DPORT(sn)    (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0010)) // Peer port register address
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
+ * @details \ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
+ */
+#define Sn_MSSR(sn)	   (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0012)) // Maximum Segment Size(Sn_MSSR0) register address
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief IP Protocol(PROTO) Register(R/W)
+ * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is
+ * valid only in IPRAW mode, and ignored in other modes.
+ */
+#define Sn_PROTO(sn)	   (_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0014)) // Protocol of IP Header field register in IP raw mode
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief IP Type of Service(TOS) Register(R/W)
+ * @details \ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TOS(sn)			(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + 0x0015) // IP Type of Service(TOS) Register 
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief IP Time to live(TTL) Register(R/W)
+ * @details \ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TTL(sn)		(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0016)) // IP Time to live(TTL) Register 
+
+// Reserved					(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0017))
+// Reserved					(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0018))
+// Reserved					(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0019))
+// Reserved					(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001A))
+// Reserved					(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001B))
+// Reserved					(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001C))
+// Reserved					(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001D))
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Transmit free memory size register(R)
+ * @details \ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by \ref Sn_TXMEM_SIZE.
+ * Data bigger than \ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
+ * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
+ * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
+ * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
+ */
+#define Sn_TX_FSR(sn)	(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0020)) // Transmit free memory size register
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Transmit memory read pointer register address(R)
+ * @details \ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.
+ * After its initialization, it is auto-increased by SEND command.
+ * SEND command transmits the saved data from the current \ref Sn_TX_RD to the \ref Sn_TX_WR in the Socket n TX Buffer.
+ * After transmitting the saved data, the SEND command increases the \ref Sn_TX_RD as same as the \ref Sn_TX_WR.
+ * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_TX_RD(sn)		(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0022)) // Transmit memory read pointer register address
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Transmit memory write pointer register address(R/W)
+ * @details \ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.\n
+ * It should be read or be updated like as follows.\n
+ * 1. Read the starting address for saving the transmitting data.\n
+ * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
+ * 3. After saving the transmitting data, update \ref Sn_TX_WR to the increased value as many as transmitting data size.
+ * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
+ * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
+ */
+#define Sn_TX_WR(sn)		(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0024)) // Transmit memory write pointer register address
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Received data size register(R)
+ * @details \ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
+ * \ref Sn_RX_RSR does not exceed the \ref Sn_RXMEM_SIZE and is calculated as the difference between
+ * Socket n RX Write Pointer (\ref Sn_RX_WR)and Socket n RX Read Pointer (\ref Sn_RX_RD)
+ */
+#define Sn_RX_RSR(sn)	(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0026)) // Received data size register
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Read point of Receive memory(R/W)
+ * @details \ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
+ * 1. Read the starting save address of the received data.\n
+ * 2. Read data from the starting address of Socket n RX Buffer.\n
+ * 3. After reading the received data, Update \ref Sn_RX_RD to the increased value as many as the reading size.
+ * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
+ * update with the lower 16bits value ignored the carry bit.\n
+ * 4. Order RECV command is for notifying the updated \ref Sn_RX_RD to W5100.
+ */
+#define Sn_RX_RD(sn)		(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0028)) // Read point of Receive memory
+
+/**
+ * @ingroup Socket_register_group_W5100
+ * @brief Write point of Receive memory(R)
+ * @details \ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
+ * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_RX_WR(sn)		(_W5100_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002A)) // Write point of Receive memory
+
+
+//----------------------------- W5100 Register values  -----------------------------
+
+/* MODE register values */
+/**
+ * @brief Reset
+ * @details If this bit is  All internal registers will be initialized. It will be automatically cleared as after S/W reset.
+ */
+#define MR_RST				0x80 ///< reset 
+
+
+/**
+ * @brief Ping block
+ * @details 0 : Disable Ping block\n
+ * 1 : Enable Ping block\n
+ * If the bit is  it blocks the response to a ping request.
+ */
+#define MR_PB				0x10 ///< ping block 
+
+/**
+ * @brief Enable PPPoE
+ * @details 0 : DisablePPPoE mode\n
+ * 1 : EnablePPPoE mode\n
+ * If you use ADSL, this bit should be '1'.
+ */
+#define MR_PPPOE			0x08 ///< enable pppoe 
+
+/**
+ * @brief Address Auto-Increment in Indirect Bus Interface
+ * @details 0 : Disable auto-increment \n
+ * 1 : Enable auto-incremente \n
+ * At the Indirect Bus Interface mode, if this bit is set as ��1��, the address will
+ * be automatically increased by 1 whenever read and write are performed.
+ */
+#define MR_AI				0x02 ///< auto-increment in indirect mode 
+
+/**
+ * @brief Indirect Bus Interface mode
+ * @details 0 : Disable Indirect bus Interface mode \n
+ * 1 : Enable Indirect bus Interface mode \n
+ * If this bit is set as ��1��, Indirect Bus Interface mode is set.
+ */
+#define MR_IND				0x01 ///< enable indirect mode 
+
+/* IR register values */
+/**
+ * @brief Check IP conflict.
+ * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
+ */
+#define IR_CONFLICT			0x80 ///< check ip confict 
+
+/**
+ * @brief Get the destination unreachable message in UDP sending.
+ * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as 
+ * When this bit is  Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR.
+ */
+#define IR_UNREACH			0x40 ///< check destination unreachable
+
+/**
+ * @brief Get the PPPoE close message.
+ * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
+ */
+#define IR_PPPoE			0x20 ///< get the PPPoE close message 
+
+#define IR_SOCK(sn)		(0x01 << sn)	///< check socket interrupt
+
+
+// Sn_MR values 
+/* Sn_MR Default values */
+/**
+ * @brief Unused socket
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_CLOSE			0x00 ///< unused socket 
+
+/**
+ * @brief TCP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_TCP			0x01 ///< TCP 
+
+/**
+ * @brief UDP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_UDP       0x02 ///< UDP 
+#define Sn_MR_IPRAW     0x03 ///< IP LAYER RAW SOCK 
+
+/**
+ * @brief MAC LAYER RAW SOCK
+ * @details This configures the protocol mode of Socket n.
+ * @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR_MACRAW		0x04 ///< MAC LAYER RAW SOCK 
+
+/**
+ * @brief PPPoE
+ * @details This configures the protocol mode of Socket n.
+ * @note PPPoE mode should be only used in Socket 0.
+ */
+#define Sn_MR_PPPoE			0x05 ///< PPPoE
+
+/**
+ * @brief No Delayed Ack(TCP), Multicast flag
+ * @details 0 : Disable No Delayed ACK option\n
+ * 1 : Enable No Delayed ACK option\n
+ * This bit is applied only during TCP mode (P[3:0] = 001).\n
+ * When this bit is  It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
+ * When this bit is  It sends the ACK packet after waiting for the timeout time configured by \ref _RTR_.
+ */
+#define Sn_MR_ND			0x20 ///< No Delayed Ack(TCP) flag 
+
+/**
+ * @brief Support UDP Multicasting
+ * @details 0 : using IGMP version 2\n
+ * 1 : using IGMP version 1\n
+ * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = '1')
+ * It configures the version for IGMP messages (Join/Leave/Report).
+ */
+#define Sn_MR_MC			Sn_MR_ND ///< Select IGMP version 1(0) or 2(1) 
+
+/**
+ * @brief MAC filter enable in @ref Sn_MR_MACRAW mode
+ * @details 0 : disable MAC Filtering\n
+ * 1 : enable MAC Filtering\n
+ * This bit is applied only during MACRAW mode(P[3:0] = 100.\n
+ * When set as  W5100 can only receive broadcasting packet or packet sent to itself.
+ * When this bit is  W5100 can receive all packets on Ethernet.
+ * If user wants to implement Hybrid TCP/IP stack,
+ * it is recommended that this bit is set as for reducing host overhead to process the all received packets.
+ */
+#define Sn_MR_MF			0x40 ///< Use MAC filter
+#define Sn_MR_MFEN      Sn_MR_MF
+
+
+/* Sn_MR Default values */
+/**
+ * @brief Support UDP Multicasting
+ * @details 0 : disable Multicasting\n
+ * 1 : enable Multicasting\n
+ * This bit is applied only during UDP mode(P[3:0] = 010).\n
+ * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
+ * before Socket n is opened by OPEN command of \ref Sn_CR.
+ */
+#define Sn_MR_MULTI			0x80 ///< support multicating 
+
+/* Sn_CR values */
+/**
+ * @brief Initialize or open socket
+ * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
+ * The table below shows the value of \ref Sn_SR corresponding to \ref Sn_MR.\n
+ * <table>
+ *   <tr>  <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td>            		 </tr>
+ *   <tr>  <td>Sn_MR_CLOSE  (000)</td> <td>--</td>         	   		 </tr>
+ *   <tr>  <td>Sn_MR_TCP  (001)</td> <td>SOCK_INIT (0x13)</td>  		 </tr>
+ *   <tr>  <td>Sn_MR_UDP  (010)</td>  <td>SOCK_UDP (0x22)</td>  		 </tr>
+ *   <tr>  <td>S0_MR_IPRAW  (011)</td>  <td>SOCK_IPRAW (0x32)</td>  </tr>
+ *   <tr>  <td>S0_MR_MACRAW  (100)</td>  <td>SOCK_MACRAW (0x42)</td>  </tr>
+ *   <tr>  <td>S0_MR_PPPoE  (101)</td>  <td>SOCK_PPPoE (0x5F)</td>  </tr>
+ * </table>
+ */
+#define Sn_CR_OPEN			0x01 ///< initialize or open socket 
+
+/**
+ * @brief Wait connection request in TCP mode(Server mode)
+ * @details This is valid only in TCP mode (Sn_MR(P3:P0) = \ref Sn_MR_TCP).//
+ * In this mode, Socket n operates as a 'TCP server' and waits for connection-request (SYN packet) from any 'TCP client'.//
+ * The \ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.//
+ * When a 'TCP client' connection request is successfully established,
+ * the \ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes 
+ * But when a 'TCP client' connection request is failed, Sn_IR(3) becomes and the status of \ref Sn_SR changes to SOCK_CLOSED.
+ */
+#define Sn_CR_LISTEN		0x02 ///< wait connection request in tcp mode(Server mode) 
+
+/**
+ * @brief Send connection request in TCP mode(Client mode)
+ * @details  To connect, a connect-request (SYN packet) is sent to <b>TCP server</b>configured by \ref Sn_DIPR & Sn_DPORT(destination address & port).
+ * If the connect-request is successful, the \ref Sn_SR is changed to \ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
+ * The connect-request fails in the following three cases.\n
+ * 1. When a @b ARPTO occurs (\ref Sn_IR[3] = '1') because destination hardware address is not acquired through the ARP-process.\n
+ * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) ='1')\n
+ * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, \ref Sn_SR is changed to \ref SOCK_CLOSED.
+ * @note This is valid only in TCP mode and operates when Socket n acts as <b>TCP client</b>
+ */
+#define Sn_CR_CONNECT		0x04 ///< send connection request in tcp mode(Client mode) 
+
+/**
+ * @brief Send closing request in TCP mode
+ * @details Regardless of <b>TCP server</b>or <b>TCP client</b> the DISCON command processes the disconnect-process (<b>Active close</b>or <b>Passive close</b>.\n
+ * @par Active close
+ * it transmits disconnect-request(FIN packet) to the connected peer\n
+ * @par Passive close
+ * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
+ * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), \ref Sn_SR is changed to \ref SOCK_CLOSED.\n
+ * Otherwise, TCPTO occurs (Sn_IR(3)='1') and then \ref Sn_SR is changed to \ref SOCK_CLOSED.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_DISCON		0x08 ///< send closing reqeuset in tcp mode 
+
+/**
+ * @brief Close socket
+ * @details Sn_SR is changed to \ref SOCK_CLOSED.
+ */
+#define Sn_CR_CLOSE         0x10
+
+/**
+ * @brief Update TX buffer pointer and send data
+ * @details SEND transmits all the data in the Socket n TX buffer.\n
+ * For more details, please refer to Socket n TX Free Size Register (\ref Sn_TX_FSR), Socket n,
+ * TX Write Pointer Register(\ref Sn_TX_WR), and Socket n TX Read Pointer Register(\ref Sn_TX_RD).
+ */
+#define Sn_CR_SEND          0x20
+
+/**
+ * @brief Send data with MAC address, so without ARP process
+ * @details The basic operation is same as SEND.\n
+ * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
+ * But SEND_MAC transmits data without the automatic ARP-process.\n
+ * In this case, the destination hardware address is acquired from \ref Sn_DHAR configured by host, instead of APR-process.
+ * @note Valid only in UDP mode.
+ */
+#define Sn_CR_SEND_MAC      0x21
+
+/**
+ * @brief Send keep alive message
+ * @details It checks the connection status by sending 1byte keep-alive packet.\n
+ * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_SEND_KEEP     0x22
+
+/**
+ * @brief Update RX buffer pointer and receive data
+ * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (\ref Sn_RX_RD).\n
+ * For more details, refer to Socket n RX Received Size Register (\ref Sn_RX_RSR), Socket n RX Write Pointer Register (\ref Sn_RX_WR),
+ * and Socket n RX Read Pointer Register (\ref Sn_RX_RD).
+ */
+#define Sn_CR_RECV          0x40
+
+/**
+ * @brief PPPoE connection
+ * @details PPPoE connection begins by transmitting PPPoE discovery packet
+ */
+#define Sn_CR_PCON			0x23
+
+/**
+ * @brief Closes PPPoE connection
+ * @details Closes PPPoE connection
+ */		 
+#define Sn_CR_PDISCON		0x24		 
+
+/**
+ * @brief REQ message transmission
+ * @details In each phase, it transmits REQ message.
+ */
+#define Sn_CR_PCR			0x25		 
+
+/**
+ * @brief NAK massage transmission
+ * @details In each phase, it transmits NAK message.
+ */
+#define Sn_CR_PCN			0x26		
+
+/**
+ * @brief REJECT message transmission
+ * @details In each phase, it transmits REJECT message.
+ */
+#define Sn_CR_PCJ			0x27		
+
+/* Sn_IR values */
+/**
+ * @brief PPP Receive Interrupt
+ * @details PPP Receive Interrupts when the option which is not supported is received.
+ */
+#define Sn_IR_PRECV			0x80	
+
+/**
+ * @brief PPP Fail Interrupt
+ * @details PPP Fail Interrupts when PAP Authentication is failed.
+ */	
+#define Sn_IR_PFAIL			0x40		
+
+/**
+ * @brief PPP Next Phase Interrupt
+ * @details PPP Next Phase Interrupts when the phase is changed during ADSL connection process.
+ */
+#define Sn_IR_PNEXT			0x20		
+
+/**
+ * @brief SEND_OK Interrupt
+ * @details This is issued when SEND command is completed.
+ */
+#define Sn_IR_SENDOK		0x10 ///< complete sending 
+
+/**
+ * @brief TIMEOUT Interrupt
+ * @details This is issued when ARPTO or TCPTO occurs.
+ */
+#define Sn_IR_TIMEOUT		0x08 ///< assert timeout 
+
+/**
+ * @brief RECV Interrupt
+ * @details This is issued whenever data is received from a peer.
+ */
+#define Sn_IR_RECV          0x04
+
+/**
+ * @brief DISCON Interrupt
+ * @details This is issued when FIN or FIN/ACK packet is received from a peer.
+ */
+#define Sn_IR_DISCON        0x02
+
+/**
+ * @brief CON Interrupt
+ * @details This is issued one time when the connection with peer is successful and then \ref Sn_SR is changed to \ref SOCK_ESTABLISHED.
+ */
+#define Sn_IR_CON           0x01
+
+/* Sn_SR values */
+/**
+ * @brief Closed
+ * @details This indicates that Socket n is released.\n
+ * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to \ref SOCK_CLOSED regardless of previous status.
+ */
+#define SOCK_CLOSED			0x00 ///< closed 
+
+/**
+ * @brief Initiate state
+ * @details This indicates Socket n is opened with TCP mode.\n
+ * It is changed to \ref SOCK_INIT when Sn_MR(P[3:0]) = 001)and OPEN command is ordered.\n
+ * After \ref SOCK_INIT, user can use LISTEN /CONNECT command.
+ */
+#define SOCK_INIT 			0x13 ///< init state 
+
+/**
+ * @brief Listen state
+ * @details This indicates Socket n is operating as <b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer (<b>TCP client</b>).\n
+ * It will change to \ref SOCK_ESTABLISHED when the connection-request is successfully accepted.\n
+ * Otherwise it will change to \ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = '1').
+ */
+#define SOCK_LISTEN         0x14
+
+/**
+ * @brief Connection state
+ * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
+ * It is temporarily shown when \ref Sn_SR is changed from \ref SOCK_INIT to \ref SOCK_ESTABLISHED by CONNECT command.\n
+ * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to \ref SOCK_ESTABLISHED.\n
+ * Otherwise, it changes to \ref SOCK_CLOSED after TCPTO (\ref Sn_IR[TIMEOUT] = '1') is occurred.
+ */
+#define SOCK_SYNSENT        0x15
+
+/**
+ * @brief Connection state
+ * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
+ * If socket n sends the response (SYN/ACK  packet) to the peer successfully,  it changes to \ref SOCK_ESTABLISHED. \n
+ * If not, it changes to \ref SOCK_CLOSED after timeout occurs (\ref Sn_IR[TIMEOUT] = '1').
+ */
+#define SOCK_SYNRECV        0x16
+
+/**
+ * @brief Success to connect
+ * @details This indicates the status of the connection of Socket n.\n
+ * It changes to \ref SOCK_ESTABLISHED when the <b>TCP SERVER</b>processed the SYN packet from the <b>TCP CLIENT</b>during \ref SOCK_LISTEN, or
+ * when the CONNECT command is successful.\n
+ * During \ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
+ */
+#define SOCK_ESTABLISHED    0x17
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_FIN_WAIT       0x18
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_CLOSING        0x1A
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_TIME_WAIT      0x1B
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
+ * This is half-closing status, and data can be transferred.\n
+ * For full-closing, DISCON command is used. But For just-closing, @ref Sn_CR_CLOSE command is used.
+ */
+#define SOCK_CLOSE_WAIT     0x1C
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
+ * It changes to \ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs  (\ref Sn_IR[TIMEOUT] = '1').
+ */
+#define SOCK_LAST_ACK       0x1D
+
+/**
+ * @brief UDP socket
+ * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010).\n
+ * It changes to SOCK_UDP when Sn_MR(P[3:0]) = 010 and @ref Sn_CR_OPEN command is ordered.\n
+ * Unlike TCP mode, data can be transfered without the connection-process.
+ */
+#define SOCK_UDP			0x22 ///< udp socket 
+
+/**
+ * @brief IP raw mode socket
+ * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when @ref Sn_MR (P3:P0) is
+ * Sn_MR_IPRAW and @ref Sn_CR_OPEN command is used.\n
+ * IP Packet can be transferred without a connection similar to the UDP mode.
+*/
+#define SOCK_IPRAW			0x32 ///< ip raw mode socket 
+
+/**
+ * @brief MAC raw mode socket
+ * @details This indicates Socket 0 is opened in MACRAW mode (@ref Sn_MR(P[3:0]) = '100' and n=0) and is valid only in Socket 0.\n
+ * It changes to SOCK_MACRAW when @ref Sn_MR(P[3:0]) = '100' and @ref Sn_CR_OPEN command is ordered.\n
+ * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
+ */
+#define SOCK_MACRAW			0x42 ///< mac raw mode socket 
+
+/**
+ * @brief PPPoE mode socket
+ * @details It is the status that SOCKET0 is open as PPPoE mode. It is changed to SOCK_PPPoE in case of S0_CR=OPEN and S0_MR
+ * (P3:P0)=S0_MR_PPPoE.\n
+ * It is temporarily used at the PPPoE
+connection.
+ */
+#define SOCK_PPPOE			0x5F ///< pppoe socket 
+
+// IP PROTOCOL 
+#define IPPROTO_IP			0 ///< Dummy for IP 
+#define IPPROTO_ICMP		   1 ///< Control message protocol 
+#define IPPROTO_IGMP		   2 ///< Internet group management protocol 
+#define IPPROTO_GGP			3 ///< GW^2 (deprecated) 
+#define IPPROTO_TCP			6 ///< TCP 
+#define IPPROTO_PUP			12 ///< PUP 
+#define IPPROTO_UDP			17 ///< UDP 
+#define IPPROTO_IDP			22 ///< XNS idp 
+#define IPPROTO_ND			77 ///< UNOFFICIAL net disk protocol 
+#define IPPROTO_RAW			255 ///< Raw IP packet 
+
+/**
+ * @brief Enter a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n \n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * \sa WIZCHIP_CRITICAL_EXIT()
+ */
+#define WIZCHIP_CRITICAL_ENTER()    WIZCHIP.CRIS._enter()
+
+#ifdef _exit
+#undef _exit
+#endif
+
+/**
+ * @brief Exit a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n\n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * @sa WIZCHIP_CRITICAL_ENTER()
+ */
+#define WIZCHIP_CRITICAL_EXIT()     WIZCHIP.CRIS._exit()
+
+
+
+////////////////////////
+// Basic I/O Function //
+////////////////////////
+//
+//M20150601 :  uint16_t AddrSel --> uint32_t AddrSel
+//
+/**
+ * @ingroup Basic_IO_function_W5100
+ * @brief It reads 1 byte value from a register.
+ * @param AddrSel Register address
+ * @return The value of register
+ */
+uint8_t  WIZCHIP_READ (uint32_t AddrSel);
+
+/**
+ * @ingroup Basic_IO_function_W5100
+ * @brief It writes 1 byte value to a register.
+ * @param AddrSel Register address
+ * @param wb Write data
+ * @return void
+ */
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
+
+/**
+ * @ingroup Basic_IO_function_W5100
+ * @brief It reads sequence data from registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to read data
+ * @param len Data length
+ */
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5100
+ * @brief It writes sequence data to registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to write data
+ * @param len Data length
+ */
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+
+/////////////////////////////////
+// Common Register IO function //
+/////////////////////////////////
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set Mode Register
+ * @param (uint8_t)mr The value to be set.
+ * @sa getMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define setMR(mr) 	WIZCHIP_WRITE(MR,mr)
+#else
+   #define setMR(mr)    (*((uint8_t*)MR) = mr)
+#endif
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get @ref MR.
+ * @return uint8_t. The value of Mode register.
+ * @sa setMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define getMR() 		WIZCHIP_READ(MR)
+#else
+   #define getMR()      (*(uint8_t*)MR)
+#endif
+   
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set @ref GAR.
+ * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
+ * @sa getGAR()
+ */
+#define setGAR(gar) \
+		WIZCHIP_WRITE_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get @ref GAR.
+ * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
+ * @sa setGAR()
+ */
+#define getGAR(gar) \
+		WIZCHIP_READ_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set @ref SUBR.
+ * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
+ * @note If subr is null pointer, set the backup subnet to SUBR. \n
+ *       If subr is 0.0.0.0, back up SUBR and clear it. \n
+ *       Otherwize, set subr to SUBR
+ * @sa getSUBR()
+ */
+#define setSUBR(subr) \
+      WIZCHIP_WRITE_BUF(SUBR,subr,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get @ref SUBR.
+ * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
+ * @sa setSUBR()
+ */
+#define getSUBR(subr) \
+		WIZCHIP_READ_BUF(SUBR, subr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set @ref SHAR.
+ * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
+ * @sa getSHAR()
+ */
+#define setSHAR(shar) \
+		WIZCHIP_WRITE_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get @ref SHAR.
+ * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
+ * @sa setSHAR()
+ */
+#define getSHAR(shar) \
+		WIZCHIP_READ_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set @ref SIPR.
+ * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
+ * @sa getSIPR()
+*/
+#define setSIPR(sipr) \
+		WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get @ref SIPR.
+ * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
+ * @sa setSIPR()
+ */
+#define getSIPR(sipr) \
+		WIZCHIP_READ_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set \ref IR register
+ * @param (uint8_t)ir Value to set \ref IR register.
+ * @sa getIR()
+ */
+#define setIR(ir) \
+		WIZCHIP_WRITE(IR, (ir & 0xA0))
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref IR register
+ * @return uint8_t. Value of \ref IR register.
+ * @sa setIR()
+ */
+#define getIR() \
+		(WIZCHIP_READ(IR) & 0xA0)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set \ref _IMR_ register
+ * @param (uint8_t)imr Value to set @ref _IMR_ register.
+ * @sa getIMR()
+ */
+#define setIMR(imr) \
+		WIZCHIP_WRITE(_IMR_, imr)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref _IMR_ register
+ * @return uint8_t. Value of @ref _IMR_ register.
+ * @sa setIMR()
+ */
+#define getIMR() \
+		WIZCHIP_READ(_IMR_)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set \ref _RTR_ register
+ * @param (uint16_t)rtr Value to set @ref _RTR_ register.
+ * @sa getRTR()
+ */
+#define setRTR(rtr)   {\
+		WIZCHIP_WRITE(_RTR_,   (uint8_t)(rtr >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref _RTR_ register
+ * @return uint16_t. Value of @ref _RTR_ register.
+ * @sa setRTR()
+ */
+#define getRTR() \
+		(((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1)))
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set \ref _RCR_ register
+ * @param (uint8_t)rcr Value to set @ref _RCR_ register.
+ * @sa getRCR()
+ */
+#define setRCR(rcr) \
+		WIZCHIP_WRITE(_RCR_, rcr)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref _RCR_ register
+ * @return uint8_t. Value of @ref _RCR_ register.
+ * @sa setRCR()
+ */
+#define getRCR() \
+		WIZCHIP_READ(_RCR_)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref RMSR register
+ * @sa getRMSR()
+ */
+#define setRMSR(rmsr)   \
+      WIZCHIP_WRITE(RMSR) // Receicve Memory Size
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref RMSR register
+ * @return uint8_t. Value of @ref RMSR register.
+ * @sa setRMSR()
+ */
+ #define getRMSR()   \
+      WIZCHIP_READ() // Receicve Memory Size
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref TMSR register
+ * @sa getTMSR()
+ */
+#define setTMSR(rmsr)   \
+      WIZCHIP_WRITE(TMSR) // Receicve Memory Size
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref TMSR register
+ * @return uint8_t. Value of @ref TMSR register.
+ * @sa setTMSR()
+ */
+
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref PATR register
+ * @return uint16_t. Value to set \ref PATR register
+ */
+#define getPATR() \
+		(((uint16_t)WIZCHIP_READ(PATR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PATR,1)))
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref PPPALGO register
+ * @return uint8_t. Value to set \ref PPPALGO register
+ */
+#define getPPPALGO() \
+		WIZCHIP_READ(PPPALGO)
+
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set \ref PTIMER register
+ * @param (uint8_t)ptimer Value to set \ref PTIMER register.
+ * @sa getPTIMER()
+ */
+#define setPTIMER(ptimer) \
+		WIZCHIP_WRITE(PTIMER, ptimer)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref PTIMER register
+ * @return uint8_t. Value of @ref PTIMER register.
+ * @sa setPTIMER()
+ */
+#define getPTIMER() \
+		WIZCHIP_READ(PTIMER)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Set \ref PMAGIC register
+ * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
+ * @sa getPMAGIC()
+ */
+#define setPMAGIC(pmagic) \
+		WIZCHIP_WRITE(PMAGIC, pmagic)
+
+/**
+ * @ingroup Common_register_access_function_W5100
+ * @brief Get \ref PMAGIC register
+ * @return uint8_t. Value of @ref PMAGIC register.
+ * @sa setPMAGIC()
+ */
+#define getPMAGIC() \
+		WIZCHIP_READ(PMAGIC)
+
+///////////////////////////////////
+// Socket N register I/O function //
+///////////////////////////////////
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_MR register
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ * @param mr Value to set @ref Sn_MR
+ * @sa getSn_MR()
+ */
+#define setSn_MR(sn, mr) \
+		WIZCHIP_WRITE(Sn_MR(sn),mr)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_MR register
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ * @return Value of @ref Sn_MR.
+ * @sa setSn_MR()
+ */
+#define getSn_MR(sn) \
+	WIZCHIP_READ(Sn_MR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)cr Value to set @ref Sn_CR
+ * @sa getSn_CR()
+ */
+#define setSn_CR(sn, cr) \
+		WIZCHIP_WRITE(Sn_CR(sn), cr)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_CR.
+ * @sa setSn_CR()
+ */
+#define getSn_CR(sn) \
+		WIZCHIP_READ(Sn_CR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)ir Value to set @ref Sn_IR
+ * @sa getSn_IR()
+ */
+#define setSn_IR(sn, ir) \
+		WIZCHIP_WRITE(Sn_IR(sn), ir)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_IR.
+ * @sa setSn_IR()
+ */
+#define getSn_IR(sn) \
+		WIZCHIP_READ(Sn_IR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_SR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_SR.
+ */
+#define getSn_SR(sn) \
+		WIZCHIP_READ(Sn_SR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)port Value to set @ref Sn_PORT.
+ * @sa getSn_PORT()
+ */
+#define setSn_PORT(sn, port)  { \
+		WIZCHIP_WRITE(Sn_PORT(sn),   (uint8_t)(port >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_PORT.
+ * @sa setSn_PORT()
+ */
+#define getSn_PORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa getSn_DHAR()
+ */
+#define setSn_DHAR(sn, dhar) \
+		WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa setSn_DHAR()
+ */
+#define getSn_DHAR(sn, dhar) \
+		WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
+ * @sa getSn_DIPR()
+ */
+#define setSn_DIPR(sn, dipr) \
+		WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
+ * @sa SetSn_DIPR()
+ */
+#define getSn_DIPR(sn, dipr) \
+		WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)dport Value to set @ref Sn_DPORT
+ * @sa getSn_DPORT()
+ */
+#define setSn_DPORT(sn, dport) { \
+		WIZCHIP_WRITE(Sn_DPORT(sn),   (uint8_t) (dport>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t)  dport); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_DPORT.
+ * @sa setSn_DPORT()
+ */
+#define getSn_DPORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)mss Value to set @ref Sn_MSSR
+ * @sa setSn_MSSR()
+ */
+#define setSn_MSSR(sn, mss) { \
+		WIZCHIP_WRITE(Sn_MSSR(sn),   (uint8_t)(mss>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_MSSR.
+ * @sa setSn_MSSR()
+ */
+#define getSn_MSSR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_PROTO register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)proto Value to set \ref Sn_PROTO
+ * @sa getSn_PROTO()
+ */
+#define setSn_PROTO(sn, proto) \
+		WIZCHIP_WRITE(Sn_TOS(sn), tos)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_PROTO register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_PROTO.
+ * @sa setSn_PROTO()
+ */
+#define getSn_PROTO(sn) \
+		WIZCHIP_READ(Sn_TOS(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)tos Value to set @ref Sn_TOS
+ * @sa getSn_TOS()
+ */
+#define setSn_TOS(sn, tos) \
+		WIZCHIP_WRITE(Sn_TOS(sn), tos)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @return uint8_t. Value of Sn_TOS.
+ * @sa setSn_TOS()
+ */
+#define getSn_TOS(sn) \
+		WIZCHIP_READ(Sn_TOS(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @param (uint8_t)ttl Value to set @ref Sn_TTL
+ * @sa getSn_TTL()
+ */
+#define setSn_TTL(sn, ttl) \
+		WIZCHIP_WRITE(Sn_TTL(sn), ttl)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @return uint8_t. Value of @ref Sn_TTL.
+ * @sa setSn_TTL()
+ */
+#define getSn_TTL(sn) \
+		WIZCHIP_READ(Sn_TTL(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_RXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @param (uint8_t)rxmemsize Value to set \ref Sn_RXMEM_SIZE
+ * @sa getSn_RXMEM_SIZE()
+ */
+#define  setSn_RXMEM_SIZE(sn, rxmemsize) \
+      WIZCHIP_WRITE(RMSR, (WIZCHIP_READ(RMSR) & ~(0x03 << (2*sn))) | (rxmemsize << (2*sn)))
+#define  setSn_RXBUF_SIZE(sn,rxmemsize) setSn_RXMEM_SIZE(sn,rxmemsize)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_RXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_RXMEM.
+ * @sa setSn_RXMEM_SIZE()
+ */
+#define  getSn_RXMEM_SIZE(sn) \
+      ((WIZCHIP_READ(RMSR) & (0x03 << (2*sn))) >> (2*sn))
+#define  getSn_RXBUF_SIZE(sn) getSn_RXMEM_SIZE(sn)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_TXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)txmemsize Value to set \ref Sn_TXMEM_SIZE
+ * @sa getSn_TXMEM_SIZE()
+ */
+#define setSn_TXMEM_SIZE(sn, txmemsize) \
+      WIZCHIP_WRITE(TMSR, (WIZCHIP_READ(TMSR) & ~(0x03 << (2*sn))) | (txmemsize << (2*sn)))
+#define  setSn_TXBUF_SIZE(sn, txmemsize) setSn_TXMEM_SIZE(sn,txmemsize)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_TXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_TXMEM_SIZE.
+ * @sa setSn_TXMEM_SIZE()
+ */
+#define  getSn_TXMEM_SIZE(sn) \
+      ((WIZCHIP_READ(TMSR) & (0x03 << (2*sn))) >> (2*sn))
+#define  getSn_TXBUF_SIZE(sn) getSn_TXMEM_SIZE(sn)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_TX_FSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_FSR.
+ */
+uint16_t getSn_TX_FSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_TX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_RD.
+ */
+#define getSn_TX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
+ * @sa GetSn_TX_WR()
+ */
+#define setSn_TX_WR(sn, txwr) { \
+		WIZCHIP_WRITE(Sn_TX_WR(sn),   (uint8_t)(txwr>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \
+		}
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_WR.
+ * @sa setSn_TX_WR()
+ */
+#define getSn_TX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_RX_RSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_RX_RSR.
+ */
+uint16_t getSn_RX_RSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
+ * @sa getSn_RX_RD()
+ */
+#define setSn_RX_RD(sn, rxrd) { \
+		WIZCHIP_WRITE(Sn_RX_RD(sn),   (uint8_t)(rxrd>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @regurn uint16_t. Value of @ref Sn_RX_RD.
+ * @sa setSn_RX_RD()
+ */
+#define getSn_RX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_RX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)rxwr Value to set \ref Sn_RX_WR
+ * @sa getSn_RX_WR()
+ */
+#define setSn_RX_WR(sn, rxwr) { \
+		WIZCHIP_WRITE(Sn_RX_WR(sn),   (uint8_t)(rxwr>>8)); \
+	   WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1), (uint8_t) rxwr); \
+	}
+
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_RX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_RX_WR.
+ */
+#define getSn_RX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Set @ref Sn_FRAG register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)frag Value to set \ref Sn_FRAG
+ * @sa getSn_FRAG()
+ */
+#define setSn_FRAG(sn, frag) { \
+		WIZCHIP_WRITE(Sn_FRAG(sn),  (uint8_t)(frag >>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get @ref Sn_FRAG register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_FRAG.
+ * @sa setSn_FRAG()
+ */
+#define getSn_FRAG(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get the max RX buffer size of socket sn
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Max buffer size
+ */
+#define getSn_RxMAX(sn) \
+		((uint16_t)(1 << getSn_RXMEM_SIZE(sn)) << 10)
+
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get the max TX buffer size of socket sn
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Max buffer size
+ */
+#define getSn_TxMAX(sn) \
+		((uint16_t)(1 << getSn_TXMEM_SIZE(sn)) << 10)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get the mask of socket sn RX buffer.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Mask value
+ */
+#define getSn_RxMASK(sn) \
+		(getSn_RxMAX(sn) - 1)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get the mask of socket sn TX buffer
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Mask value
+ */
+#define getSn_TxMASK(sn) \
+		(getSn_TxMAX(sn) - 1)
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get the base address of socket sn RX buffer.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n RX buffer base address.
+ */
+uint32_t getSn_RxBASE(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5100
+ * @brief Get the base address of socket sn TX buffer.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n TX buffer base address.
+ */
+uint32_t getSn_TxBASE(uint8_t sn);
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+/**
+ * @ingroup Basic_IO_function_W5100
+ * @brief It copies data to internal TX memory
+ *
+ * @details This function reads the Tx write pointer register and after that,
+ * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory
+ * and updates the Tx write pointer register.
+ * This function is being called by send() and sendto() function also.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param wizdata Pointer buffer to write data
+ * @param len Data length
+ * @sa wiz_recv_data()
+ */
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5100
+ * @brief It copies data to your buffer from internal RX memory
+ *
+ * @details This function read the Rx read pointer register and after that,
+ * it copies the received data from internal RX memory
+ * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes.
+ * This function is being called by recv() also.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param wizdata Pointer buffer to read data
+ * @param len Data length
+ * @sa wiz_send_data()
+ */
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5100
+ * @brief It discard the received data in RX memory.
+ * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param len Data length
+ */
+void wiz_recv_ignore(uint8_t sn, uint16_t len);
+
+/// @cond DOXY_APPLY_CODE
+#endif
+/// @endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_W5100_H_
+
+
+

+ 514 - 0
lib/ioLibrary_Driver/Ethernet/W5100S/w5100s.c

@@ -0,0 +1,514 @@
+//*****************************************************************************
+//
+//! \file w5100S.c
+//! \brief W5100S HAL Interface.
+//! \version 1.0.0
+//! \date 2018/03/29
+//! \par  Revision history
+//!       <2018/03/29> 1st Release
+//! \author Peter
+//! 
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include "w5100s.h"
+
+#if   (_WIZCHIP_ == W5100S)
+/**
+@brief  This function writes the data into W5100S registers.
+*/
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
+{
+   uint8_t spi_data[4];
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
+   if(!WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+      WIZCHIP.IF.SPI._write_byte(0xF0);
+      WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >>  8);
+      WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >>  0);
+      WIZCHIP.IF.SPI._write_byte(wb);    // Data write (write 1byte data)
+   }
+   else     // burst operation
+   {
+      spi_data[0] = 0xF0;
+		spi_data[1] = (AddrSel & 0xFF00) >>  8;
+		spi_data[2] = (AddrSel & 0x00FF) >>  0;
+		spi_data[3] = wb;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 4);
+   }
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
+   if(!WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+	   WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >>  8);
+	   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >>  0);
+	   WIZCHIP.IF.SPI._write_byte(0xF0);
+	   WIZCHIP.IF.SPI._write_byte(wb);    // Data write (write 1byte data)
+   }
+   else     // burst operation
+   {
+      spi_data[0] = (AddrSel & 0xFF00) >>  8;
+		spi_data[1] = (AddrSel & 0x00FF) >>  0;
+		spi_data[2] = 0xF0;
+		spi_data[3] = wb;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 4);
+
+   }
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+
+   //add indirect bus 
+   //M20150601 : Rename the function for integrating with ioLibrary
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));	
+   //WIZCHIP.IF.BUS._write_byte(IDM_DR,wb);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));	
+   WIZCHIP.IF.BUS._write_data(IDM_DR,wb);
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!"
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+/**
+@brief  This function reads the value from W5100S registers.
+*/
+uint8_t  WIZCHIP_READ(uint32_t AddrSel)
+{
+   uint8_t ret;
+   uint8_t spi_data[3];
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ ==  _WIZCHIP_IO_MODE_SPI_))
+   if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+        WIZCHIP.IF.SPI._write_byte(0x0F);
+        WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >>  8);
+        WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >>  0);
+   }
+   else
+   {
+        spi_data[0] = 0x0F;
+        spi_data[1] = (AddrSel & 0xFF00) >>  8;
+        spi_data[2] = (AddrSel & 0x00FF) >>  0;
+        WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+   }
+   ret = WIZCHIP.IF.SPI._read_byte(); 
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
+   if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// burst operation
+	{
+        WIZCHIP.IF.SPI._write_byte((AddrSel & 0xFF00) >>  8);
+        WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF) >>  0);
+        WIZCHIP.IF.SPI._write_byte(0x0F);
+   }
+   else
+   {
+		spi_data[0] = (AddrSel & 0xFF00) >>  8;
+		spi_data[1] = (AddrSel & 0x00FF) >>  0;
+		spi_data[2] = 0x0F
+		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+   }
+   ret = WIZCHIP.IF.SPI._read_byte();
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+
+   //add indirect bus
+   //M20150601 : Rename the function for integrating with ioLibrary
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));	
+   //ret = WIZCHIP.IF.BUS._read_byte(IDM_DR);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
+   ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
+
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!"   
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+   return ret;
+}
+
+
+/**
+@brief  This function writes into W5100S memory(Buffer)
+*/ 
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint8_t spi_data[3];
+   uint16_t i = 0;
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();   //M20150601 : Moved here.
+
+#if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_))
+
+   if(!WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+      WIZCHIP.IF.SPI._write_byte(0xF0);
+      WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >>  8);
+      WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >>  0);
+
+      for(i = 0; i < len; i++)
+      {
+         WIZCHIP.IF.SPI._write_byte(pBuf[i]);    // Data write (write 1byte data)
+      }
+   }
+   else     // burst operation
+   {
+		spi_data[0] = 0xF0;
+		spi_data[1] = (((uint16_t)(AddrSel+i)) & 0xFF00) >>  8;
+		spi_data[2] = (((uint16_t)(AddrSel+i)) & 0x00FF) >>  0;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+		WIZCHIP.IF.SPI._write_burst(pBuf, len);
+   }
+
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
+   if(!WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+      WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0xFF00) >>  8);
+      WIZCHIP.IF.SPI._write_byte((((uint16_t)(AddrSel+i)) & 0x00FF) >>  0);
+      WIZCHIP.IF.SPI._write_byte(0xF0);
+
+      for(i = 0; i < len; i++)
+      {
+         WIZCHIP.IF.SPI._write_byte(pBuf[i]);    // Data write (write 1byte data)
+      }
+   }
+   else     // burst operation
+   {
+		spi_data[0] = (((uint16_t)(AddrSel+i)) & 0xFF00) >>  8;
+		spi_data[1] = (((uint16_t)(AddrSel+i)) & 0x00FF) >>  0;
+      spi_data[2] = 0xF0;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+		WIZCHIP.IF.SPI._write_burst(pBuf, len);
+   }
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+   //M20150601 : Rename the function for integrating with ioLibrary  
+   /*
+   WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI);     
+   WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));
+   for(i = 0 ; i < len; i++)
+      WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]);
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);   
+   */
+   setMR(getMR()|MR_AI);     
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));
+   for(i = 0 ; i < len; i++)
+      WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]);
+   setMR(getMR() & ~MR_AI);   
+
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!!"
+#endif
+   
+   WIZCHIP.CS._deselect();  //M20150601 : Moved here.
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+/**
+@brief  This function reads into W5100S memory(Buffer)
+*/ 
+
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint8_t spi_data[3];
+   uint16_t i = 0;
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();   //M20150601 : Moved here.
+   
+#if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_) )
+   if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+      WIZCHIP.IF.SPI._write_byte(0x0F);
+      WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >>  8);
+      WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >>  0);
+
+      for(i = 0; i < len; i++)
+      {
+         pBuf[i] = WIZCHIP.IF.SPI._read_byte(); 
+      }
+   }           
+   else																// burst operation
+   {
+		spi_data[0] = 0x0F;
+		spi_data[1] = (uint16_t)((AddrSel+i) & 0xFF00) >>  8;
+		spi_data[2] = (uint16_t)((AddrSel+i) & 0x00FF) >>  0;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+		WIZCHIP.IF.SPI._read_burst(pBuf, len);
+
+   }
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_5500_) )
+   if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+      WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0xFF00) >>  8);
+      WIZCHIP.IF.SPI._write_byte((uint16_t)((AddrSel+i) & 0x00FF) >>  0);
+      WIZCHIP.IF.SPI._write_byte(0x0F);
+   
+      for(i = 0; i < len; i++)
+      {
+         pBuf[i] = WIZCHIP.IF.SPI._read_byte();
+      }
+   }
+   else																// burst operation
+   {
+		spi_data[0] = (uint16_t)((AddrSel+i) & 0xFF00) >>  8;
+		spi_data[1] = (uint16_t)((AddrSel+i) & 0x00FF) >>  0;
+      spi_data[2] = 0x0F;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+		WIZCHIP.IF.SPI._read_burst(pBuf, len);
+   }
+
+
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+   //M20150601 : Rename the function for integrating with ioLibrary  
+   /*
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI);    
+   WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x00FF));	
+   for(i = 0 ; i < len; i++)
+      pBuf[i]	= WIZCHIP.IF.BUS._read_byte(IDM_DR);
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); 
+   */
+   setMR(getMR() | MR_AI);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0xFF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x00FF));	
+   for(i = 0 ; i < len; i++)
+      pBuf[i]	= WIZCHIP.IF.BUS._read_data(IDM_DR);
+   setMR(getMR() & ~MR_AI); 
+   
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5100S. !!!!"
+#endif
+
+   WIZCHIP.CS._deselect();    //M20150601 : Moved Here.
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+///////////////////////////////////
+// Socket N regsiter IO function //
+///////////////////////////////////
+
+uint16_t getSn_TX_FSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_TX_FSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+
+uint16_t getSn_RX_RSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_RX_RSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+uint32_t getSn_RxBASE(uint8_t sn)
+{
+   int8_t  i;
+#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
+   uint32_t rxbase = _W5100S_IO_BASE_ + _WIZCHIP_IO_RXBUF_;
+#else   
+   uint32_t rxbase = _WIZCHIP_IO_RXBUF_;
+#endif   
+   for(i = 0; i < sn; i++)
+      rxbase += getSn_RxMAX(i);
+
+   return rxbase;
+}
+
+uint32_t getSn_TxBASE(uint8_t sn)
+{
+   int8_t  i;
+#if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
+   uint32_t txbase = _W5100S_IO_BASE_ + _WIZCHIP_IO_TXBUF_;
+#else   
+   uint32_t txbase = _WIZCHIP_IO_TXBUF_;
+#endif   
+   for(i = 0; i < sn; i++)
+      txbase += getSn_TxMAX(i);
+   return txbase;
+}
+
+/**
+@brief  This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip.
+
+This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
+register. User should read upper byte first and lower byte later to get proper value.
+And this function is being used for copy the data form application buffer to Transmite
+buffer of the chip. It calculate the actual physical address where one has to write
+the data in transmite buffer. Here also take care of the condition while it exceed
+the Tx memory uper-bound of socket.
+
+*/
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+  uint16_t ptr;
+  uint16_t size;
+  uint16_t dst_mask;
+  uint16_t dst_ptr;
+
+  ptr = getSn_TX_WR(sn);
+
+  dst_mask = ptr & getSn_TxMASK(sn);
+  dst_ptr = getSn_TxBASE(sn) + dst_mask;
+  
+  if (dst_mask + len > getSn_TxMAX(sn)) 
+  {
+    size = getSn_TxMAX(sn) - dst_mask;
+    WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
+    wizdata += size;
+    size = len - size;
+    dst_ptr = getSn_TxBASE(sn);
+    WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
+  } 
+  else
+  {
+    WIZCHIP_WRITE_BUF(dst_ptr, wizdata, len);
+  }
+
+  ptr += len;
+
+  setSn_TX_WR(sn, ptr);  
+}
+
+
+/**
+@brief  This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer.
+
+This function read the Rx read pointer register
+and after copy the data from receive buffer update the Rx write pointer register.
+User should read upper byte first and lower byte later to get proper value.
+It calculate the actual physical address where one has to read
+the data from Receive buffer. Here also take care of the condition while it exceed
+the Rx memory uper-bound of socket.
+*/
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+  uint16_t ptr;
+  uint16_t size;
+  uint16_t src_mask;
+  uint16_t src_ptr;
+
+  ptr = getSn_RX_RD(sn);
+  
+  src_mask = (uint32_t)ptr & getSn_RxMASK(sn);
+  src_ptr = (getSn_RxBASE(sn) + src_mask);
+
+  
+  if( (src_mask + len) > getSn_RxMAX(sn) ) 
+  {
+    size = getSn_RxMAX(sn) - src_mask;
+    WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
+    wizdata += size;
+    size = len - size;
+	src_ptr = getSn_RxBASE(sn);
+    WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, size);
+  } 
+  else
+  {
+    WIZCHIP_READ_BUF(src_ptr, (uint8_t*)wizdata, len);
+  }
+    
+  ptr += len;
+  
+  setSn_RX_RD(sn, ptr);
+}
+
+void wiz_recv_ignore(uint8_t sn, uint16_t len)
+{
+  uint16_t ptr;
+
+  ptr = getSn_RX_RD(sn);
+  
+  ptr += len;
+  setSn_RX_RD(sn,ptr);
+}
+
+void wiz_mdio_write(uint8_t PHYMDIO_regadr, uint16_t var)
+{
+    WIZCHIP_WRITE(PHYRAR,PHYMDIO_regadr);
+    WIZCHIP_WRITE(PHYDIR, (uint8_t)(var >> 8));
+    WIZCHIP_WRITE(PHYDIR+1, (uint8_t)(var));
+    WIZCHIP_WRITE(PHYACR, PHYACR_WRITE);
+    while(WIZCHIP_READ(PHYACR));  //wait for command complete
+}
+
+uint16_t wiz_mdio_read(uint8_t PHYMDIO_regadr)
+{
+    WIZCHIP_WRITE(PHYRAR,PHYMDIO_regadr);
+    WIZCHIP_WRITE(PHYACR, PHYACR_READ);
+    while(WIZCHIP_READ(PHYACR));  //wait for command complete
+    return ((uint16_t)WIZCHIP_READ(PHYDOR) << 8) | WIZCHIP_READ(PHYDOR+1);
+}
+
+void wiz_delay_ms(uint32_t milliseconds)
+{
+	uint32_t i;
+	for(i = 0 ; i < milliseconds ; i++)
+	{
+		//Write any values to clear the TCNTCLKR register
+		setTCNTCLKR(0xff);
+
+		// Wait until counter register value reaches 10.(10 = 1ms : TCNTR is 100us tick counter register)
+		while(getTCNTR() < 0x0a){}
+	}
+}
+
+#endif

+ 3323 - 0
lib/ioLibrary_Driver/Ethernet/W5100S/w5100s.h

@@ -0,0 +1,3323 @@
+//* ****************************************************************************
+//! \file w5100S.h
+//! \brief W5100S HAL Header File.
+//! \version 1.0.0
+//! \date 2018/03/29
+//! \par  Revision history
+//!       <2018/03/29> 1st Release
+//! \author Peter
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+
+#ifndef	_W5100S_H_
+#define	_W5100S_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "wizchip_conf.h"
+
+/// \cond DOXY_APPLY_CODE
+#if   (_WIZCHIP_ == W5100S)
+/// \endcond
+
+#define _WIZCHIP_SN_BASE_  (0x0400)
+#define _WIZCHIP_SN_SIZE_  (0x0100)
+#define _WIZCHIP_IO_TXBUF_ (0x4000) /* Internal Tx buffer address of the iinchip */
+#define _WIZCHIP_IO_RXBUF_ (0x6000) /* Internal Rx buffer address of the iinchip */
+
+
+#define WIZCHIP_CREG_BLOCK      	      0x00   ///< Common register block
+#define WIZCHIP_SREG_BLOCK(N)    	   (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block
+
+#define WIZCHIP_OFFSET_INC(ADDR, N)    (ADDR + N) ///< Increase offset address
+
+#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
+   #define _W5100S_IO_BASE_     _WIZCHIP_IO_BASE_
+#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_)
+	#define IDM_OR             ((_WIZCHIP_IO_BASE  + 0x0000))
+	#define IDM_AR0            ((_WIZCHIP_IO_BASE_ + 0x0001))
+	#define IDM_AR1            ((_WIZCHIP_IO_BASE_ + 0x0002))
+	#define IDM_DR             ((_WIZCHIP_IO_BASE_ + 0x0003))
+	#define _W5100S_IO_BASE_    0x0000
+#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define _W5100S_IO_BASE_    0x0000
+#endif
+
+///////////////////////////////////////
+// Definition For Legacy Chip Driver //
+///////////////////////////////////////
+#define IINCHIP_READ(ADDR)                WIZCHIP_READ(ADDR)               ///< The defined for legacy chip driver
+#define IINCHIP_WRITE(ADDR,VAL)           WIZCHIP_WRITE(ADDR,VAL)          ///< The defined for legacy chip driver
+#define IINCHIP_READ_BUF(ADDR,BUF,LEN)    WIZCHIP_READ_BUF(ADDR,BUF,LEN)   ///< The defined for legacy chip driver
+#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN)   WIZCHIP_WRITE(ADDR,BUF,LEN)      ///< The defined for legacy chip driver
+
+
+//-----------    defgroup --------------------------------
+
+/**
+ * @defgroup W5100S W5100S
+ * @brief WHIZCHIP register defines and I/O functions of @b W5100S.
+ *
+ * - @ref WIZCHIP_register_W5100S: @ref Common_register_group_W5100S and @ref Socket_register_group_W5100S
+ * - @ref WIZCHIP_IO_Functions_W5100S: @ref Basic_IO_function_W5100S, @ref Common_register_access_function_W5100S and @ref Special_function_W5100S
+ */
+
+ /**
+ * @defgroup WIZCHIP_register_W5100S WIZCHIP register
+ * @ingroup W5100S
+ * @brief WIZCHIP register defines register group of <b> W5100S </b>.
+ *
+ * - \ref Common_register_group_W5100S : Common register group W5100S
+ * - \ref Socket_register_group_W5100S : \c SOCKET n register group W5100S
+ */
+
+
+/**
+ * @defgroup WIZCHIP_IO_Functions_W5100S WIZCHIP I/O functions
+ * @ingroup W5100S
+ * @brief This supports the basic I/O functions for \ref WIZCHIP_register_W5100S.
+ *
+ * - <b> Basic I/O function </b> \n
+ *   WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF(), wiz_recv_data(), wiz_recv_ignore(), wiz_send_data() \n\n
+ *
+ * - \ref Common_register_group_W5100S <b>access functions</b> \n
+ * 	-# @b Mode \n
+ *    getMR(), setMR()
+ * 	-# @b Interrupt \n
+ *    getIR(), setIR(), getIMR(), setIMR(),
+ * 	-# <b> Network Information </b> \n
+ *    getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
+ * 	-# @b Retransmission \n
+ *    getRCR(), setRCR(), getRTR(), setRTR()
+ * 	-# @b PPPoE \n
+ *    getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC()
+ *
+ * - \ref Socket_register_group_W5100S <b>access functions</b> \n
+ *   -# <b> SOCKET control</b> \n
+ *      getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IR(), setSn_IR()
+ *   -# <b> SOCKET information</b> \n
+ *      getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
+ *      getSn_MSSR(), setSn_MSSR()
+ *   -# <b> SOCKET communication </b> \n
+ *      getSn_RXMEM_SIZE(), setSn_RXMEM_SIZE(), getSn_TXMEM_SIZE(), setSn_TXMEM_SIZE() \n
+ *      getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
+ *      getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
+ *      getSn_TX_FSR(), getSn_RX_RSR()
+ *   -# <b> IP header field </b> \n
+ *      getSn_FRAG(), setSn_FRAG(),  getSn_TOS(), setSn_TOS() \n
+ *      getSn_TTL(), setSn_TTL()
+ */
+
+/**
+ * @defgroup Common_register_group_W5100S Common register
+ * @ingroup WIZCHIP_register_W5100S
+ * @brief Common register group\n
+ * It set the basic for the networking\n
+ * It set the configuration such as interrupt, network information, ICMP, etc.
+ * @details
+ * @sa MR : Mode register.
+ * @sa GAR, SUBR, SHAR, SIPR
+ * @sa IR, Sn_IR, _IMR_  : Interrupt.
+ * @sa _RTR_, _RCR_ : Data retransmission.
+ * @sa PTIMER, PMAGIC : PPPoE.
+ */
+
+
+ /**
+ * @defgroup Socket_register_group_W5100S Socket register
+ * @ingroup WIZCHIP_register_W5100S
+ * @brief Socket register group\n
+ * Socket register configures and control SOCKETn which is necessary to data communication.
+ * @details
+ * @sa Sn_MR, Sn_CR, Sn_IR : SOCKETn Control
+ * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
+ * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_FRAGR : Internet protocol.
+ * @sa Sn_RXMEM_SIZE, Sn_TXMEM_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
+ */
+
+ /**
+ * @defgroup Basic_IO_function_W5100S Basic I/O function
+ * @ingroup WIZCHIP_IO_Functions_W5100S
+ * @brief These are basic input/output functions to read values from register or write values to register.
+ */
+
+/**
+ * @defgroup Common_register_access_function_W5100S Common register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5100S
+ * @brief These are functions to access <b>common registers</b>.
+ */
+
+/**
+ * @defgroup Socket_register_access_function_W5100S Socket register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5100S
+ * @brief These are functions to access <b>socket registers</b>.
+ */
+
+ /**
+ * @defgroup Special_function_W5100S Special functions
+ * @ingroup WIZCHIP_IO_Functions_W5100S
+ * @brief These are special functions to access to the PHY
+ */
+
+ //-----------------------------------------------------------------------------------
+
+//----------------------------- W5100S Common Registers IOMAP -----------------------------
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Mode Register address(R/W)\n
+ * \ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
+ * @details Each bit of \ref MR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>AI</td> <td>IND</td> </tr>
+ * </table>
+ * - \ref MR_RST		 	: Reset
+ * - \ref MR_PB         	: Ping block
+ * - \ref MR_PPPOE      	: PPPoE mode
+ * - \ref MR_AI         	: Address Auto-Increment in Indirect Bus Interface
+ * - \ref MR_IND         	: Indirect Bus Interface mode
+ */
+#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
+   #define MR					(_WIZCHIP_IO_BASE_ + (0x0000))  // Mode
+#else
+   #define MR					(_W5100S_IO_BASE_ + (0x0000))  // Mode
+#endif
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Gateway IP Register address(R/W)
+ * @details \ref GAR configures the default gateway address.
+ */
+#define GAR     			(_W5100S_IO_BASE_ + (0x0001))  // GW Address
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Subnet mask Register address(R/W)
+ * @details \ref SUBR configures the subnet mask address.
+ */
+#define SUBR    			(_W5100S_IO_BASE_ + (0x0005)) // SN Mask Address
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Source MAC Register address(R/W)
+ * @details \ref SHAR configures the source hardware address.
+ */
+#define SHAR    			(_W5100S_IO_BASE_ + (0x0009)) // Source Hardware Address
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Source IP Register address(R/W)
+ * @details \ref SIPR configures the source IP address.
+ */
+#define SIPR    			(_W5100S_IO_BASE_ + (0x000F)) // Source IP Address
+
+// Reserved					(_W5100S_IO_BASE_ + (0x0013))
+// Reserved					(_W5100S_IO_BASE_ + (0x0014))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Interrupt Register(R/W)
+ * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host.
+ * If \ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
+ * Each bit of \ref IR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>CONFLICT</td> <td>UNREACH</td> <td>PPPoE</td> <td>Reserved</td> <td>S3_INT</td> <td>S2_INT</td> <td>S1_INT</td> <td>S0_INT</td> </tr>
+ * </table>
+ * - \ref IR_CONFLICT : IP conflict
+ * - \ref IR_UNREACH  : Destination unreachable
+ * - \ref IR_PPPoE	 : PPPoE connection close
+ * - \ref IR_SOCK(3)  : SOCKET 3 Interrupt
+ * - \ref IR_SOCK(2)  : SOCKET 2 Interrupt
+ * - \ref IR_SOCK(1)  : SOCKET 1 Interrupt
+ * - \ref IR_SOCK(0)  : SOCKET 0 Interrupt
+ */
+#define IR					(_W5100S_IO_BASE_ + (0x0015)) // Interrupt
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Socket Interrupt Mask Register(R/W)
+ * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR.
+ * When a bit of \ref _IMR_ is and the corresponding bit of \ref IR is set, Interrupt will be issued.
+ */
+#define _IMR_    			(_W5100S_IO_BASE_ + (0x0016)) // Socket Interrupt Mask
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Timeout register address( 1 is 100us )(R/W)
+ * @details \ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of \ref _RTR_ is x07D0or 000
+ * And so the default timeout period is 200ms(100us X 2000). During the time configured by \ref _RTR_, W5100S waits for the peer response
+ * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
+ * If the peer does not respond within the \ref _RTR_ time, W5100S retransmits the packet or issues timeout.
+ */
+#define _RTR_     			(_W5100S_IO_BASE_ + (0x0017)) // Retry Time
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Retry count register(R/W)
+ * @details \ref _RCR_ configures the number of time of retransmission.
+ * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (\ref Sn_IR_TIMEOUT = '1').
+ */
+#define _RCR_				(_W5100S_IO_BASE_ + (0x0019)) // Retry Count
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Receive Memory Size Register
+ * @details \ref RMSR register configures RX bufffer Size of the SOCKET
+ * The sum of the RX buffers can not exceed 8kB.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>S3-1</td> <td>S3-0</td> <td>S2-1</td> <td>S2-0</td> <td>S1-1</td> <td>S1-0</td> <td>S0-1</td> <td>S0-0</td> </tr>
+ * </table>
+ * <table>
+ * 		<tr> <td>Memory Size</td><td>Sn-1</td><td>Sn-0</td> </tr>
+ * 		<tr> <td>1KB</td><td>0</td><td>0</td> </tr>
+ * 		<tr> <td>2KB</td><td>0</td><td>1</td> </tr>
+ * 		<tr> <td>4KB</td><td>1</td><td>0</td> </tr>
+ * 		<tr> <td>8KB</td><td>1</td><td>1</td> </tr>
+ * </table>
+ */
+#define RMSR				(_W5100S_IO_BASE_ + (0x001A)) // Receive Memory Size
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Transmit Memory Size Register
+ * @details \ref TMSR register configures TX bufffer Size of the SOCKET
+ * The sum of the TX buffers can not exceed 8kB.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>S3-1</td> <td>S3-0</td> <td>S2-1</td> <td>S2-0</td> <td>S1-1</td> <td>S1-0</td> <td>S0-1</td> <td>S0-0</td> </tr>
+ * </table>
+ * <table>
+ * 		<tr> <td>Memory Size</td><td>Sn-1</td><td>Sn-0</td> </tr>
+ * 		<tr> <td>1KB</td><td>0</td><td>0</td> </tr>
+ * 		<tr> <td>2KB</td><td>0</td><td>1</td> </tr>
+ * 		<tr> <td>4KB</td><td>1</td><td>0</td> </tr>
+ * 		<tr> <td>8KB</td><td>1</td><td>1</td> </tr>
+ * </table>
+ */
+#define TMSR				(_W5100S_IO_BASE_ + (0x001B)) // Transmit Memory Size
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Interrupt register 2
+ * @details \ref IR2 indicates the interrupt status.
+ * Each bit of IR2 will be still until the bit will be written to by the host.
+ * <table>
+ * 		<tr>  <td>7:1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>Reserved</td> <td>WOL</td> </tr>
+ * </table>
+ * - \ref IR2_WOL : WOL MAGIC PACKET Interrupt Mask
+ */
+#define IR2					(_W5100S_IO_BASE_ + (0x0020))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Interrupt mask register 2
+ * @details \ref IMR2 Each bit of IMR2 corresponds to each bit of IR2.
+ * When a bit of IMR2 is and the corresponding bit of IR2 is set, Interrupt will be issued.
+ */
+#define IMR2				(_W5100S_IO_BASE_ + (0x0021))
+
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PPP LCP Request Timer register  in PPPoE mode(R)
+ * @details \ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
+ */
+#define PTIMER				(_W5100S_IO_BASE_ + (0x0028)) // PPP LCP RequestTimer
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PPP LCP Magic number register  in PPPoE mode(R)
+ * @details \ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
+ */
+#define PMAGIC				(_W5100S_IO_BASE_ + (0x0029)) // PPP LCP Magic number
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Unreachable IP address register
+ * @details \ref
+ */
+#define UIPR				(_W5100S_IO_BASE_ + (0x002A))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Unreachable Port register
+ * @details \ref
+ */
+#define UPORTR				(_W5100S_IO_BASE_  + (0x002E))
+
+/* register for W5100S only */
+
+/*------------------------------------------ Common registers ------------------------------------------*/
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief MR2 Mode register 2
+ * @details \reg
+ */
+#define MR2					(_W5100S_IO_BASE_ + (0x0030))
+
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Destination Hardware address in PPPoE
+ * @details \reg
+ */
+#define PHAR				(_W5100S_IO_BASE_ + (0x0032))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Session ID in PPPoE
+ * @details \reg
+ */
+#define PSIDR				(_W5100S_IO_BASE_ + (0x0038))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Maximum receive Unit in PPPoE
+ * @details \reg
+ */
+#define PMRUR				(_W5100S_IO_BASE_ + (0x003A))
+
+
+/*------------------------------------------ PHY registers ------------------------------------------*/
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY status register
+ * @details \reg
+ */
+#define PHYSR				(_W5100S_IO_BASE_ + (0x003C))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY status register(hidden)
+ * @details \reg
+ */
+#define PHYSR1				(_W5100S_IO_BASE_ + (0x003D))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Address value
+ * @details \reg
+ */
+#define PHYAR				(_W5100S_IO_BASE_ + (0x003E))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Register address
+ * @details \reg
+ */
+#define PHYRAR				(_W5100S_IO_BASE_ + (0x003F))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Data input register
+ * @details \reg
+ */
+#define PHYDIR				(_W5100S_IO_BASE_ + (0x0040))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY data output register
+ * @details \reg
+ */
+#define PHYDOR				(_W5100S_IO_BASE_ + (0x0042))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Action register
+ * @details \reg
+ */
+#define PHYACR				(_W5100S_IO_BASE_ + (0x0044))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Division register
+ * @details \reg
+ */
+#define PHYDIVR				(_W5100S_IO_BASE_ + (0x0045))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Control register 0
+ * @details \reg
+ */
+#define PHYCR0					(_W5100S_IO_BASE_ + (0x0046))
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Control register 1
+ * @details \reg
+ */
+#define PHYCR1					(_W5100S_IO_BASE_ + (0x0047))
+
+/*------------------------------------------ Socket Less registers ------------------------------------------*/
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Socket-less control register
+ * @details \reg
+ */
+#define SLCR				(_W5100S_IO_BASE_ + (0x004C))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Socket-less retry time register
+ * @details \reg
+ */
+#define SLRTR				(_W5100S_IO_BASE_ + (0x004D))
+
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Socket-less retry count register
+ * @details \reg
+ */
+#define SLRCR				(_W5100S_IO_BASE_ + (0x004F))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Socket-less peer IP address register
+ * @details \reg
+ */
+#define SLPIPR				(_W5100S_IO_BASE_ + (0x0050))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Socket-less peer hardware address register
+ * @details \reg
+ */
+#define SLPHAR				(_W5100S_IO_BASE_ + (0x0054))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Ping sequence number register
+ * @details \reg
+ */
+#define PINGSEQR				(_W5100S_IO_BASE_ + (0x005A))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Ping ID register
+ * @details \reg
+ */
+#define PINGIDR				(_W5100S_IO_BASE_ + (0x005C))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Socket-less interrupt mask register
+ * @details \reg
+ */
+#define SLIMR				(_W5100S_IO_BASE_ + (0x005E))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief  Socket-less interrupt register
+ * @details \reg
+ */
+#define SLIR				(_W5100S_IO_BASE_ + (0x005F))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief DBGOUT(hidden)
+ * @details \reg
+ */
+#define DBGOUT				(_W5100S_IO_BASE_ + (0x0060))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief NICMAXCOLR(hidden)
+ * @details \reg
+ */
+#define NICMAXCOLR			(_W5100S_IO_BASE_ + (0x0063))
+/*------------------------------------------ CFG registers ------------------------------------------*/
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Chip Configuration locking register
+ * @details \reg
+ */
+#define CHIPLCKR				(_W5100S_IO_BASE_ + (0x0070))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Network Configuration locking register
+ * @details \reg
+ */
+#define NETLCKR				(_W5100S_IO_BASE_ + (0x0071))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief PHY Configuration locking register
+ * @details \reg
+ */
+#define PHYLCKR				(_W5100S_IO_BASE_ + (0x0072))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief version register
+ * @details \reg
+ */
+#define VERR				(_W5100S_IO_BASE_ + (0x0080))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Core 100us Counter register
+ * @details \reg
+ */
+#define TCNTR				(_W5100S_IO_BASE_ + (0x0082))
+
+/**
+ * @ingroup Common_register_group_W5100S
+ * @brief Core 100us Counter clear register
+ * @details \reg
+ */
+#define TCNTCLKR			(_W5100S_IO_BASE_ + (0x0088))
+
+//----------------------------- W5100S Socket Registers -----------------------------
+
+//--------------------------- For Backward Compatibility ---------------------------
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief socket Mode register(R/W)
+ * @details \ref Sn_MR configures the option or protocol type of Socket n.\n\n
+ * Each bit of \ref Sn_MR defined as the following.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>MULTI</td> <td>MF</td> <td>ND/MC</td> <td>Reserved</td> <td>Protocol[3]</td> <td>Protocol[2]</td> <td>Protocol[1]</td> <td>Protocol[0]</td> </tr>
+ * </table>
+ * - \ref Sn_MR_MULTI	: Support UDP Multicasting
+ * - \ref Sn_MR_MF	   : Support MACRAW
+ * - \ref Sn_MR_ND		: No Delayed Ack(TCP) flag
+ * - \ref Sn_MR_MC   	: IGMP version used <b>in UDP mulitcasting</b>
+ * - <b>Protocol</b>
+ * <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ * </table>
+ * - <b>In case of Socket 0</b>
+ *  <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>1</td> <td>PPPoE</td>   </tr>
+ * </table>
+ *	 - \ref Sn_MR_MACRAW	: MAC LAYER RAW SOCK \n
+ *  - \ref Sn_MR_UDP		: UDP
+ *  - \ref Sn_MR_TCP		: TCP
+ *  - \ref Sn_MR_CLOSE	: Unused socket
+ *  @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0000)) // socket Mode register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket command register(R/W)
+ * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
+ * After W5100S accepts the command, the \ref Sn_CR register is automatically cleared to 0x00.
+ * Even though \ref Sn_CR is cleared to 0x00, the command is still being processed.\n
+ * To check whether the command is completed or not, please check the \ref Sn_IR or \ref Sn_SR.
+ * - \ref Sn_CR_OPEN 		: Initialize or open socket.
+ * - \ref Sn_CR_LISTEN 		: Wait connection request in TCP mode(<b>Server mode</b>)
+ * - \ref Sn_CR_CONNECT 	: Send connection request in TCP mode(<b>Client mode</b>)
+ * - \ref Sn_CR_DISCON 		: Send closing request in TCP mode.
+ * - \ref Sn_CR_CLOSE   	: Close socket.
+ * - \ref Sn_CR_SEND    	: Update TX buffer pointer and send data.
+ * - \ref Sn_CR_SEND_MAC	: Send data with MAC address, so without ARP process.
+ * - \ref Sn_CR_SEND_KEEP 	: Send keep alive message.
+ * - \ref Sn_CR_RECV		: Update RX buffer pointer and receive data.
+ * - <b>In case of S0_MR(P3:P0) = S0_MR_PPPoE</b>
+ *  <table>
+ * 		<tr>   <td><b>Value</b></td> <td><b>Symbol</b></td> <td><b>Description</b></td></tr>
+ * 		<tr>   <td>0x23</td> <td>PCON</td> <td>PPPoE connection begins by transmitting PPPoE discovery packet</td>  </tr>
+ * 		<tr>   <td>0x24</td> <td>PDISCON</td> <td>Closes PPPoE connection</td>  </tr>
+ * 		<tr>   <td>0x25</td> <td>PCR</td> <td>In each phase, it transmits REQ message.</td> </tr>
+ * 		<tr>   <td>0x26</td> <td>PCN</td> <td>In each phase, it transmits NAK message.</td> </tr>
+ * 		<tr>   <td>0x27</td> <td>PCJ</td> <td>In each phase, it transmits REJECT message.</td> </tr>
+ * </table>
+ */
+#define Sn_CR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0001)) // channel Sn_CR register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket interrupt register(R)
+ * @details \ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
+ * When an interrupt occurs and the corresponding bit \ref IR_SOCK(N) in \ref _IMR_ are set, \ref IR_SOCK(N) in \ref IR becomes '1'.\n
+ * In order to clear the \ref Sn_IR bit, the host should write the bit to \n
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>PRECV</td> <td>PFAIL</td> <td>PNEXT</td> <td>SEND_OK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr>
+ * </table>
+ * - \ref Sn_IR_PRECV : <b>PPP Receive Interrupt</b>
+ * - \ref Sn_IR_PFAIL : <b>PPP Fail Interrupt</b>
+ * - \ref Sn_IR_PNEXT : <b>PPP Next Phase Interrupt</b>
+ * - \ref Sn_IR_SENDOK : <b>SEND_OK Interrupt</b>
+ * - \ref Sn_IR_TIMEOUT : <b>TIMEOUT Interrupt</b>
+ * - \ref Sn_IR_RECV : <b>RECV Interrupt</b>
+ * - \ref Sn_IR_DISCON : <b>DISCON Interrupt</b>
+ * - \ref Sn_IR_CON : <b>CON Interrupt</b>
+ */
+#define Sn_IR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0002)) // channel interrupt register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket status register(R)
+ * @details \ref Sn_SR indicates the status of Socket n.\n
+ * The status of Socket n is changed by \ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
+ * @par Normal status
+ * - \ref SOCK_CLOSED 		: Closed
+ * - \ref SOCK_INIT   		: Initiate state
+ * - \ref SOCK_LISTEN    	: Listen state
+ * - \ref SOCK_ESTABLISHED 	: Success to connect
+ * - \ref SOCK_CLOSE_WAIT   : Closing state
+ * - \ref SOCK_UDP   		: UDP socket
+ * - \ref SOCK_MACRAW  		: MAC raw mode socket
+ *@par Temporary status during changing the status of Socket n.
+ * - \ref SOCK_SYNSENT   	: This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
+ * - \ref SOCK_SYNRECV    	: It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
+ * - \ref SOCK_FIN_WAIT		: Connection state
+ * - \ref SOCK_CLOSING		: Closing state
+ * - \ref SOCK_TIME_WAIT	: Closing state
+ * - \ref SOCK_LAST_ACK 	: Closing state
+ */
+#define Sn_SR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0003)) // channel status register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief source port register(R/W)
+ * @details \ref Sn_PORT configures the source port number of Socket n.
+ * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered.
+*/
+#define Sn_PORT(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0004)) // source port register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Peer MAC register address(R/W)
+ * @details \ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
+ * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
+ */
+#define Sn_DHAR(sn)     (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0006)) // Peer MAC register address
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Peer IP register address(R/W)
+ * @details \ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP client mode, it configures an IP address of TCP server before CONNECT command.
+ * In TCP server mode, it indicates an IP address of TCP client after successfully establishing connection.
+ * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
+ */
+#define Sn_DIPR(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x000C)) // Peer IP register address
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Peer port register address(R/W)
+ * @details \ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP clientmode, it configures the listen port number of TCP server before CONNECT command.
+ * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
+ * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
+ */
+#define Sn_DPORT(sn)    (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0010)) // Peer port register address
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
+ * @details \ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
+ */
+#define Sn_MSSR(sn)	   (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0012)) // Maximum Segment Size(Sn_MSSR0) register address
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief IP Protocol(PROTO) Register(R/W)
+ * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is
+ * valid only in IPRAW mode, and ignored in other modes.
+ */
+#define Sn_PROTO(sn)	   (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0014)) // Protocol of IP Header field register in IP raw mode
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief IP Type of Service(TOS) Register(R/W)
+ * @details \ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TOS(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + 0x0015) // IP Type of Service(TOS) Register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief IP Time to live(TTL) Register(R/W)
+ * @details \ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TTL(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0016)) // IP Time to live(TTL) Register
+
+// Reserved					(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0017))
+// Reserved					(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0018))
+// Reserved					(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0019))
+// Reserved					(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001A))
+// Reserved					(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001B))
+// Reserved					(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001C))
+// Reserved					(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001D))
+
+
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Receive memory size register(R/W)
+ * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n.
+ * Socket n RX Buffer Block size can be configured with 1,2,4 and 8Kbytes.
+ * If a different size is configured, the data cannot be normally received from a peer.
+ * Although Socket n RX Buffer Block size is initially configured to 2Kbytes,
+ * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 8Kbytes.
+ * When exceeded, the data reception error is occurred.
+ */
+#define Sn_RXBUF_SIZE(sn)   (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001E))
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Transmit memory size register(R/W)
+ * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4 and 8Kbytes.
+ * If a different size is configured, the data cannot be normally transmitted to a peer.
+ * Although Socket n TX Buffer Block size is initially configured to 2Kbytes,
+ * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 8Kbytes.
+ * When exceeded, the data transmission error is occurred.
+ */
+#define Sn_TXBUF_SIZE(sn)   (_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001F))
+
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Transmit free memory size register(R)
+ * @details \ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by \ref Sn_TXMEM_SIZE.
+ * Data bigger than \ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
+ * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
+ * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
+ * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
+ */
+#define Sn_TX_FSR(sn)	(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0020)) // Transmit free memory size register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Transmit memory read pointer register address(R)
+ * @details \ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.
+ * After its initialization, it is auto-increased by SEND command.
+ * SEND command transmits the saved data from the current \ref Sn_TX_RD to the \ref Sn_TX_WR in the Socket n TX Buffer.
+ * After transmitting the saved data, the SEND command increases the \ref Sn_TX_RD as same as the \ref Sn_TX_WR.
+ * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_TX_RD(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0022)) // Transmit memory read pointer register address
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Transmit memory write pointer register address(R/W)
+ * @details \ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.\n
+ * It should be read or be updated like as follows.\n
+ * 1. Read the starting address for saving the transmitting data.\n
+ * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
+ * 3. After saving the transmitting data, update \ref Sn_TX_WR to the increased value as many as transmitting data size.
+ * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
+ * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
+ */
+#define Sn_TX_WR(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0024)) // Transmit memory write pointer register address
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Received data size register(R)
+ * @details \ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
+ * \ref Sn_RX_RSR does not exceed the \ref Sn_RXMEM_SIZE and is calculated as the difference between
+ * Socket n RX Write Pointer (\ref Sn_RX_WR)and Socket n RX Read Pointer (\ref Sn_RX_RD)
+ */
+#define Sn_RX_RSR(sn)	(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0026)) // Received data size register
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Read point of Receive memory(R/W)
+ * @details \ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
+ * 1. Read the starting save address of the received data.\n
+ * 2. Read data from the starting address of Socket n RX Buffer.\n
+ * 3. After reading the received data, Update \ref Sn_RX_RD to the increased value as many as the reading size.
+ * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
+ * update with the lower 16bits value ignored the carry bit.\n
+ * 4. Order RECV command is for notifying the updated \ref Sn_RX_RD to W5100S.
+ */
+#define Sn_RX_RD(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0028)) // Read point of Receive memory
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Write point of Receive memory(R)
+ * @details \ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
+ * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_RX_WR(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002A)) // Write point of Receive memory
+
+
+//todo
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket interrupt mask register
+ * @details Register address to configure the interrupt mask of the socket
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ *
+ */
+#define Sn_IMR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002C))
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket fragment field register
+ * @details Register to configure the Fragment field of IP Header
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ */
+#define Sn_FRAGR(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002D)) // and +1
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket Mode register 2
+ * @details Register to set mode 2
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ */
+#define Sn_MR2(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002F))
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket n Keep Alive Timer Register
+ * @details Register to set the transmission period of keep alive packet.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ */
+#define Sn_KPALVTR(sn)		(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0030))
+
+/** todo delete
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket n Timer Status Register
+ * @details
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ */
+//#define Sn_TSR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0031))
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket n Retry Time-value Register
+ * @details Register to set the retry time value
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ */
+#define Sn_RTR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0032))
+
+/**
+ * @ingroup Socket_register_group_W5100S
+ * @brief Socket n Retry Count-value Register
+ * @details Register to set the retry count value
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ */
+#define Sn_RCR(sn)			(_W5100S_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0034))
+
+
+/*----------------------------- W5100S Register values  -----------------------------*/
+
+/* MODE register values */
+/**
+ * @brief Reset
+ * @details If this bit is  All internal registers will be initialized. It will be automatically cleared as after S/W reset.
+ */
+#define MR_RST				0x80 ///< reset
+
+
+/**
+ * @brief Ping block
+ * @details 0 : Disable Ping block\n
+ * 1 : Enable Ping block\n
+ * If the bit is  it blocks the response to a ping request.
+ */
+#define MR_PB				0x10 ///< ping block
+
+/**
+ * @brief Enable PPPoE
+ * @details 0 : DisablePPPoE mode\n
+ * 1 : EnablePPPoE mode\n
+ * If you use ADSL, this bit should be '1'.
+ */
+#define MR_PPPOE			0x08 ///< enable pppoe
+
+/**
+ * @brief Address Auto-Increment in Indirect Bus Interface
+ * @details 0 : Disable auto-increment \n
+ * 1 : Enable auto-incremente \n
+ * At the Indirect Bus Interface mode, if this bit is set as the address will
+ * be automatically increased by 1 whenever read and write are performed.
+ */
+#define MR_AI				0x02 ///< auto-increment in indirect mode
+
+/**
+ * @brief Indirect Bus Interface mode
+ * @details 0 : Disable Indirect bus Interface mode \n
+ * 1 : Enable Indirect bus Interface mode \n
+ * If this bit is set as Indirect Bus Interface mode is set.
+ */
+#define MR_IND				0x01 ///< enable indirect mode
+
+/* IR register values */
+/**
+ * @brief Check IP conflict.
+ * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
+ */
+#define IR_CONFLICT			0x80 ///< check ip confict
+
+/**
+ * @brief Get the destination unreachable message in UDP sending.
+ * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as
+ * When this bit is  Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR.
+ */
+#define IR_UNREACH			0x40 ///< check destination unreachable
+
+/**
+ * @brief Get the PPPoE close message.
+ * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
+ */
+#define IR_PPPoE			0x20 ///< get the PPPoE close message
+
+/**
+ * @brief Socket interrupt bit
+ * @details Indicates whether each socket interrupt has occured.
+ */
+#define IR_SOCK(sn)		(0x01 << sn)	///< check socket interrupt
+
+/**
+ * @brief IP conflict interrupt mask bit
+ * @details If this bit is set, IP conflict interrupt is enabled.
+ */
+#define IMR_CONFLICT		0x80
+
+/**
+ * @brief Destination port unreachable interrupt mask bit
+ * @details If this bit is set, destination port unreachable interrupt is enabled.
+ */
+#define IMR_UNREACH			0x40
+
+/**
+ * @brief PADT/LCPT interrupt mask bit(PPPoE)
+ * @details If this bit is set, PADT/LCPT interrupt is enabled.
+ */
+#define IMR_PPPoE			0x20
+
+/**
+ * @brief Socket interrupt mask bit
+ * @details If this bit is set, each socket interrupt is enabled.
+ */
+#define IMR_SOCK(sn)		(0x01 << sn)
+
+/**
+ * @brief Socket-less command register bit
+ * @details ARP command
+ */
+#define SLCMD_ARP		(1<<1)
+
+/**
+ * @brief Socket-less command register bit
+ * @details ARP command
+ */
+#define SLCMD_PING		(1<<0)
+
+/**
+ * @brief Socket-less command interrupt and interrupt mask register bit
+ * @details Request command time out interrupt and interrupt mask
+ */
+#define SLIR_TIMEOUT		(1<<2)
+
+/**
+* @brief Socket less command interrupt and interrupt mask register bit
+* @details Socket less command ARP interrupt and interrupt mask
+*/
+#define SLIR_ARP (1<<1)
+
+/**
+* @brief Socket less command interrupt and interrupt mask register bit
+* @details Socket less command PING interrupt and interruptmask
+*/
+#define SLIR_PING (1<<0)
+
+
+
+// Sn_MR values
+/* Sn_MR Default values */
+/**
+ * @brief Unused socket
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_CLOSE			0x00 ///< unused socket
+
+/**
+ * @brief TCP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_TCP			0x01 ///< TCP
+
+/**
+ * @brief UDP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_UDP       0x02 ///< UDP
+#define Sn_MR_IPRAW     0x03 ///< IP LAYER RAW SOCK
+
+/**
+ * @brief MAC LAYER RAW SOCK
+ * @details This configures the protocol mode of Socket n.
+ * @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR_MACRAW		0x04 ///< MAC LAYER RAW SOCK
+
+/**
+ * @brief PPPoE
+ * @details This configures the protocol mode of Socket n.
+ * @note PPPoE mode should be only used in Socket 0.
+ */
+#define Sn_MR_PPPoE			0x05 ///< PPPoE
+
+/**
+ * @brief No Delayed Ack(TCP), Multicast flag
+ * @details 0 : Disable No Delayed ACK option\n
+ * 1 : Enable No Delayed ACK option\n
+ * This bit is applied only during TCP mode (P[3:0] = 001).\n
+ * When this bit is  It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
+ * When this bit is  It sends the ACK packet after waiting for the timeout time configured by \ref _RTR_.
+ */
+#define Sn_MR_ND			0x20 ///< No Delayed Ack(TCP) flag
+
+/**
+ * @brief Support UDP Multicasting
+ * @details 0 : using IGMP version 2\n
+ * 1 : using IGMP version 1\n
+ * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = '1')
+ * It configures the version for IGMP messages (Join/Leave/Report).
+ */
+#define Sn_MR_MC			Sn_MR_ND ///< Select IGMP version 1(0) or 2(1)
+
+/**
+ * @brief MAC filter enable in @ref Sn_MR_MACRAW mode
+ * @details 0 : disable MAC Filtering\n
+ * 1 : enable MAC Filtering\n
+ * This bit is applied only during MACRAW mode(P[3:0] = 100.\n
+ * When set as  W5100S can only receive broadcasting packet or packet sent to itself.
+ * When this bit is  W5100S can receive all packets on Ethernet.
+ * If user wants to implement Hybrid TCP/IP stack,
+ * it is recommended that this bit is set as for reducing host overhead to process the all received packets.
+ */
+#define Sn_MR_MF			0x40 ///< Use MAC filter
+#define Sn_MR_MFEN      Sn_MR_MF
+
+
+/* Sn_MR Default values */
+/**
+ * @brief Support UDP Multicasting
+ * @details 0 : disable Multicasting\n
+ * 1 : enable Multicasting\n
+ * This bit is applied only during UDP mode(P[3:0] = 010).\n
+ * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
+ * before Socket n is opened by OPEN command of \ref Sn_CR.
+ */
+#define Sn_MR_MULTI			0x80 ///< support multicating
+
+/* Sn_CR values */
+/**
+ * @brief Initialize or open socket
+ * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
+ * The table below shows the value of \ref Sn_SR corresponding to \ref Sn_MR.\n
+ * <table>
+ *   <tr>  <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td>            		 </tr>
+ *   <tr>  <td>Sn_MR_CLOSE  (000)</td> <td>--</td>         	   		 </tr>
+ *   <tr>  <td>Sn_MR_TCP  (001)</td> <td>SOCK_INIT (0x13)</td>  		 </tr>
+ *   <tr>  <td>Sn_MR_UDP  (010)</td>  <td>SOCK_UDP (0x22)</td>  		 </tr>
+ *   <tr>  <td>S0_MR_IPRAW  (011)</td>  <td>SOCK_IPRAW (0x32)</td>  </tr>
+ *   <tr>  <td>S0_MR_MACRAW  (100)</td>  <td>SOCK_MACRAW (0x42)</td>  </tr>
+ *   <tr>  <td>S0_MR_PPPoE  (101)</td>  <td>SOCK_PPPoE (0x5F)</td>  </tr>
+ * </table>
+ */
+#define Sn_CR_OPEN			0x01 ///< initialize or open socket
+
+/**
+ * @brief Wait connection request in TCP mode(Server mode)
+ * @details This is valid only in TCP mode (Sn_MR(P3:P0) = \ref Sn_MR_TCP).//
+ * In this mode, Socket n operates as a 'TCP server' and waits for connection-request (SYN packet) from any 'TCP client'.//
+ * The \ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.//
+ * When a 'TCP client' connection request is successfully established,
+ * the \ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes
+ * But when a 'TCP client' connection request is failed, Sn_IR(3) becomes and the status of \ref Sn_SR changes to SOCK_CLOSED.
+ */
+#define Sn_CR_LISTEN		0x02 ///< wait connection request in tcp mode(Server mode)
+
+/**
+ * @brief Send connection request in TCP mode(Client mode)
+ * @details  To connect, a connect-request (SYN packet) is sent to <b>TCP server</b>configured by \ref Sn_DIPR & Sn_DPORT(destination address & port).
+ * If the connect-request is successful, the \ref Sn_SR is changed to \ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
+ * The connect-request fails in the following three cases.\n
+ * 1. When a @b ARPTO occurs (\ref Sn_IR[3] = '1') because destination hardware address is not acquired through the ARP-process.\n
+ * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) ='1')\n
+ * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, \ref Sn_SR is changed to \ref SOCK_CLOSED.
+ * @note This is valid only in TCP mode and operates when Socket n acts as <b>TCP client</b>
+ */
+#define Sn_CR_CONNECT		0x04 ///< send connection request in tcp mode(Client mode)
+
+/**
+ * @brief Send closing request in TCP mode
+ * @details Regardless of <b>TCP server</b>or <b>TCP client</b> the DISCON command processes the disconnect-process (<b>Active close</b>or <b>Passive close</b>.\n
+ * @par Active close
+ * it transmits disconnect-request(FIN packet) to the connected peer\n
+ * @par Passive close
+ * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
+ * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), \ref Sn_SR is changed to \ref SOCK_CLOSED.\n
+ * Otherwise, TCPTO occurs (Sn_IR(3)='1') and then \ref Sn_SR is changed to \ref SOCK_CLOSED.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_DISCON		0x08 ///< send closing reqeuset in tcp mode
+
+/**
+ * @brief Close socket
+ * @details Sn_SR is changed to \ref SOCK_CLOSED.
+ */
+#define Sn_CR_CLOSE         0x10
+
+/**
+ * @brief Update TX buffer pointer and send data
+ * @details SEND transmits all the data in the Socket n TX buffer.\n
+ * For more details, please refer to Socket n TX Free Size Register (\ref Sn_TX_FSR), Socket n,
+ * TX Write Pointer Register(\ref Sn_TX_WR), and Socket n TX Read Pointer Register(\ref Sn_TX_RD).
+ */
+#define Sn_CR_SEND          0x20
+
+/**
+ * @brief Send data with MAC address, so without ARP process
+ * @details The basic operation is same as SEND.\n
+ * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
+ * But SEND_MAC transmits data without the automatic ARP-process.\n
+ * In this case, the destination hardware address is acquired from \ref Sn_DHAR configured by host, instead of APR-process.
+ * @note Valid only in UDP mode.
+ */
+#define Sn_CR_SEND_MAC      0x21
+
+/**
+ * @brief Send keep alive message
+ * @details It checks the connection status by sending 1byte keep-alive packet.\n
+ * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_SEND_KEEP     0x22
+
+/**
+ * @brief Update RX buffer pointer and receive data
+ * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (\ref Sn_RX_RD).\n
+ * For more details, refer to Socket n RX Received Size Register (\ref Sn_RX_RSR), Socket n RX Write Pointer Register (\ref Sn_RX_WR),
+ * and Socket n RX Read Pointer Register (\ref Sn_RX_RD).
+ */
+#define Sn_CR_RECV          0x40
+
+/**
+ * @brief
+ * @details
+ */
+#define Sn_CR_IGMP_JOIN			0x23
+
+/**
+ * @brief
+ * @details
+ */
+#define Sn_CR_IGMP_LEAVE		0x24
+
+
+/* Sn_IR values */
+
+/**
+ * @brief SEND_OK Interrupt
+ * @details This is issued when SEND command is completed.
+ */
+#define Sn_IR_SENDOK		0x10 ///< complete sending
+
+/**
+ * @brief TIMEOUT Interrupt
+ * @details This is issued when ARPTO or TCPTO occurs.
+ */
+#define Sn_IR_TIMEOUT		0x08 ///< assert timeout
+
+/**
+ * @brief RECV Interrupt
+ * @details This is issued whenever data is received from a peer.
+ */
+#define Sn_IR_RECV          0x04
+
+/**
+ * @brief DISCON Interrupt
+ * @details This is issued when FIN or FIN/ACK packet is received from a peer.
+ */
+#define Sn_IR_DISCON        0x02
+
+/**
+ * @brief CON Interrupt
+ * @details This is issued one time when the connection with peer is successful and then \ref Sn_SR is changed to \ref SOCK_ESTABLISHED.
+ */
+#define Sn_IR_CON           0x01
+
+/* Sn_SR values */
+/**
+ * @brief Closed
+ * @details This indicates that Socket n is released.\n
+ * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to \ref SOCK_CLOSED regardless of previous status.
+ */
+#define SOCK_CLOSED			0x00 ///< closed
+
+/**
+ * @brief Initiate state
+ * @details This indicates Socket n is opened with TCP mode.\n
+ * It is changed to \ref SOCK_INIT when Sn_MR(P[3:0]) = 001)and OPEN command is ordered.\n
+ * After \ref SOCK_INIT, user can use LISTEN /CONNECT command.
+ */
+#define SOCK_INIT 			0x13 ///< init state
+
+/**
+ * @brief Listen state
+ * @details This indicates Socket n is operating as <b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer (<b>TCP client</b>).\n
+ * It will change to \ref SOCK_ESTABLISHED when the connection-request is successfully accepted.\n
+ * Otherwise it will change to \ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = '1').
+ */
+#define SOCK_LISTEN         0x14
+
+/**
+ * @brief Connection state
+ * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
+ * It is temporarily shown when \ref Sn_SR is changed from \ref SOCK_INIT to \ref SOCK_ESTABLISHED by CONNECT command.\n
+ * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to \ref SOCK_ESTABLISHED.\n
+ * Otherwise, it changes to \ref SOCK_CLOSED after TCPTO (\ref Sn_IR[TIMEOUT] = '1') is occurred.
+ */
+#define SOCK_SYNSENT        0x15
+
+/**
+ * @brief Connection state
+ * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
+ * If socket n sends the response (SYN/ACK  packet) to the peer successfully,  it changes to \ref SOCK_ESTABLISHED. \n
+ * If not, it changes to \ref SOCK_CLOSED after timeout occurs (\ref Sn_IR[TIMEOUT] = '1').
+ */
+#define SOCK_SYNRECV        0x16
+
+/**
+ * @brief Success to connect
+ * @details This indicates the status of the connection of Socket n.\n
+ * It changes to \ref SOCK_ESTABLISHED when the <b>TCP SERVER</b>processed the SYN packet from the <b>TCP CLIENT</b>during \ref SOCK_LISTEN, or
+ * when the CONNECT command is successful.\n
+ * During \ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
+ */
+#define SOCK_ESTABLISHED    0x17
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_FIN_WAIT       0x18
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_CLOSING        0x1A
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_TIME_WAIT      0x1B
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
+ * This is half-closing status, and data can be transferred.\n
+ * For full-closing, DISCON command is used. But For just-closing, @ref Sn_CR_CLOSE command is used.
+ */
+#define SOCK_CLOSE_WAIT     0x1C
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
+ * It changes to \ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs  (\ref Sn_IR[TIMEOUT] = '1').
+ */
+#define SOCK_LAST_ACK       0x1D
+
+/**
+ * @brief UDP socket
+ * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010).\n
+ * It changes to SOCK_UDP when Sn_MR(P[3:0]) = 010 and @ref Sn_CR_OPEN command is ordered.\n
+ * Unlike TCP mode, data can be transfered without the connection-process.
+ */
+#define SOCK_UDP			0x22 ///< udp socket
+
+/**
+ * @brief IP raw mode socket
+ * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when @ref Sn_MR (P3:P0) is
+ * Sn_MR_IPRAW and @ref Sn_CR_OPEN command is used.\n
+ * IP Packet can be transferred without a connection similar to the UDP mode.
+*/
+#define SOCK_IPRAW			0x32 ///< ip raw mode socket
+
+/**
+ * @brief MAC raw mode socket
+ * @details This indicates Socket 0 is opened in MACRAW mode (@ref Sn_MR(P[3:0]) = '100' and n=0) and is valid only in Socket 0.\n
+ * It changes to SOCK_MACRAW when @ref Sn_MR(P[3:0]) = '100' and @ref Sn_CR_OPEN command is ordered.\n
+ * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
+ */
+#define SOCK_MACRAW			0x42 ///< mac raw mode socket
+
+/**
+ * @brief PPPoE mode socket
+ * @details It is the status that SOCKET0 is open as PPPoE mode. It is changed to SOCK_PPPoE in case of S0_CR=OPEN and S0_MR
+ * (P3:P0)=S0_MR_PPPoE.\n
+ * It is temporarily used at the PPPoE
+connection.
+ */
+#define SOCK_PPPOE			0x5F ///< pppoe socket
+
+// IP PROTOCOL
+#define IPPROTO_IP			0 ///< Dummy for IP
+#define IPPROTO_ICMP		   1 ///< Control message protocol
+#define IPPROTO_IGMP		   2 ///< Internet group management protocol
+#define IPPROTO_GGP			3 ///< GW^2 (deprecated)
+#define IPPROTO_TCP			6 ///< TCP
+#define IPPROTO_PUP			12 ///< PUP
+#define IPPROTO_UDP			17 ///< UDP
+#define IPPROTO_IDP			22 ///< XNS idp
+#define IPPROTO_ND			77 ///< UNOFFICIAL net disk protocol
+#define IPPROTO_RAW			255 ///< Raw IP packet
+
+
+
+/*----------------------------- W5100S !!Only!! Register values  -----------------------------*/
+
+//todo
+/* MODE2 register values */
+
+/**
+ * @brief	Clock select bit
+ * @details	With this bit, system clock can be selected to be 25Mhz or 100Mhz
+ * 1: 25Mhz
+ * 0: 100Mhz (default)
+ */
+#define MR2_CLKSEL				(1<<7)
+
+/**
+ * @brief	Interrupt pin enable bit
+ * @details	This bit enables interrupt.
+ * 1: Enable interrupt
+ * 0: Disable interrupt
+ */
+#define MR2_G_IEN				(1<<6)
+
+
+/**
+ * @brief	No TCP Reset Packet send
+ * @details This bit prevents sending reset packet.
+ * 1: Block TCP reset packet send
+ * 0: TCP Reset packet send
+ */
+#define MR2_NOTCPRST			(1<<5)
+
+/**
+ * @brief	Unreachable Packet Send Block bit
+ * @details	This bit prevents sending Destination Port Unreachable Packet.
+ * 1: Block Destination Port Unreachable Packet Send
+ * 0: Destination Port Unreachable Packet Send
+ */
+#define MR2_UDPURB				(1<<4)
+
+/**
+ * @brief Wake On LAN
+ * @details This bit enables WOL packet to be received.
+ * 1: WOL packet can be received.
+ * 0: WOL packet cannot be received.
+ */
+#define MR2_WOL					(1<<3)
+
+/**todo
+ * @brief MACRAW No Size Check
+ * @details
+ */
+#define MR2_MNOSCHK				(1<<2)
+
+/**
+ * @brief	UDP force ARP
+ * @details This bit can enables to force ARP for each send command.
+ * 1: UDP Force ARP Enable
+ * 0: UDP Force ARP Disable.
+ *
+ */
+#define MR2_UDPFARP				(1<<1)
+
+/**todo
+ * @brief	Skip SRC Hardware Address
+ * @details	This bit can enables to receive without checking the hardware address of the peer.
+ * 1:
+ */
+#define MR2_SSRCHA				(1<<0)
+
+
+
+/* Common interrupt register 2 values */
+
+/**todo
+ * @brief magic packet
+ * @details
+ */
+#define IR2_MGC				(1<<1)
+
+/**todo
+ * @brief Magic packet interrupt mask bit
+ * @details If this bit is set, each socket interrupt is enabled.
+ */
+#define IMR2_MGC			(1<<1)
+
+/**todo
+ * @brief
+ * @details
+ */
+//#define IR2_MGD				(1<<1) /* Reserved */
+
+
+/* PHY status register 0 values */
+
+/**todo
+ * @brief Ethernet CABLE OFF Signal
+ * @details
+ */
+#define PHYSR_CABOFF				(1<<7)
+
+/**todo
+ * @brief
+ * @details
+ */
+#define PHYSR_MD2				(1<<5)
+
+/**todo
+ * @brief
+ * @details
+ */
+#define PHYSR_MD1				(1<<4)
+
+/**todo
+ * @brief
+ * @details
+ */
+#define PHYSR_MD0				(1<<3)
+
+/**todo
+ * @brief
+ * @details
+ */
+#define PHYSR_DUP				(1<<2)
+
+/**todo
+ * @brief
+ * @details
+ */
+#define PHYSR_SPD				(1<<1)
+
+/**todo
+ * @brief LINKDONE register
+ * @details If 1 Linked successfully, if 0 no link
+ */
+#define PHYSR_LNK				(1<<0)
+
+
+/* PHY status register 10 values */
+
+/**
+ * @brieftodo
+ * @details
+ */
+#define PHYSR1_RXPG				(1<<2)
+
+/**
+ * @brieftodo
+ * @details
+ */
+#define PHYSR1_LPI				(1<<1)
+
+/**
+ * @brieftodo
+ * @details
+ */
+#define PHYSR1_CLDN				(1<<0)
+
+#define PHYCR_AUTONEGO_ENABLE	(0<<2)
+#define PHYCR_AUTONEGO_DISABLE	(1<<2)
+
+#define PHYCR_SPD_10			(1<<1)
+#define PHYCR_SPD_100			(0<<1)
+
+#define PHYCR_HALF_DUP			(1<<0)
+#define PHYCR_FULL_DUP			(0<<0)
+
+#define PHYCR1_RST				(0<<0)
+
+#define	PHYCR1_PWDN_ENABLE		(1<<5)
+#define	PHYCR1_PWDN_DISABLE		(0<<5)
+
+
+/* Socket n MODE register 2 values */
+
+/**
+ * @brief Broadcast Blocking bit in MACRAW mode
+ * @details In MACRAW mode, this bit is set to ????to block the broadcast packet.
+ */
+#define Sn_MR2_MBBLK  			(1<<6)
+
+/**
+ * @brief Multicast Blocking bit in MACRAW mode
+ * @details In MACRAW mode, this bit is set to ????to block the multicast packet.
+ */
+#define Sn_MR2_MMBLK  			(1<<5)
+
+/**
+ * @brief IPv6 packet Blocking bit in MACRAW mode
+ * @details In MACRAW mode, this bit is set to ????to block the IPv6 packet.
+ */
+#define Sn_MR2_IPV6BLK  		(1<<4)
+
+
+/**
+ * @brief Broadcast Blocking bit in UDP mode
+ * @details In UDP mode, this bit is set to ????to block the broadcast packet.
+ */
+#define Sn_MR2_UBBLK			(1<<1)
+
+
+/**
+ * @brief TCP Force PSH bit
+ * @details When the SOCKET transmits data in TCP mode, PSH Flag is set to all packets.
+ */
+#define Sn_MR2_FPSH			Sn_MR2_UBBLK
+
+/**
+ * @brief Unicast Blocking bit in UDP mode
+ * @details In UDP mode, this bit is set to ????to block the Unicast packet.
+ */
+#define Sn_MR2_UUBLK			(1<<0)
+
+/*----------------------------For PHY Control-------------------------------*/
+
+/********************/
+/* Register Address */
+/********************/
+
+//Basic mode control register, basic register
+#define PHYMDIO_BMCR				0x00
+
+//Basic mode status register, basic register
+#define PHYMDIO_BMSR				0x01
+
+//--------------------------------------Not used-------------------------------------------//
+////PHY identifier register 1, extended register
+//#define PHY_IDR1				0x02	//not used
+//
+////PHY identifier register 2, extended register
+//#define PHY_IDR2				0x03	//not used
+//
+////Auto-negotiation advertisement register, extended register
+//#define PHY_ANAR				0x04	//not used
+//
+////Auto-negotiation link partner ability register, extended register
+//#define PHY_ANLPAR				0x05	//not used
+//
+////Auto-negotiation expansion register, extended register
+//#define PHY_ANER				0x06	//not used
+//
+////Auto-negotiation next page transmit
+//#define PHY_ANNP				0x07	//not used
+//
+////Auto-negotiation link partner of the next page receive
+//#define PHY_ANLPNP				0x08	//not used
+//
+////MMD access control register
+//#define PHY_REGCR				0x09	//not used
+//
+////MMD access address data register
+//#define PHY_ADDAR				0x0e	//not used
+//--------------------------------------Not used-------------------------------------------//
+
+/********************/
+/* Bit definitions  */
+/********************/
+
+//For BMCR register
+#define BMCR_RESET				(1<<15)
+#define BMCR_MLOOPBACK			(1<<14)
+#define BMCR_SPEED				(1<<13)
+#define BMCR_AUTONEGO			(1<<12)
+#define BMCR_PWDN				(1<<11)
+#define BMCR_ISOLATE			(1<<10)
+#define BMCR_RSTNEGO			(1<<9)
+#define BMCR_DUP				(1<<8)
+#define BMCR_COLTEST			(1<<7)
+
+//For BMSR register
+#define BMSR_AUTONEGO_COMPL		(1<<5)
+#define BMSR_REMOTE_FAULT		(1<<4)
+#define BMSR_LINK_STATUS		(1<<2)
+#define BMSR_JAB_DETECT			(1<<1)
+#define EXTENDED_CAPA			(1<<0)
+
+//--------------------------------------Not used-------------------------------------------//
+////For ANAR register
+//#define ANAR_NP					(1<<15)
+//#define ANAR_ACK				(1<<14)
+//#define ANAR_RF					(1<<13)
+//#define ANAR_ASM				(3<<10)
+//#define ANAR_T4					(1<<9)
+//#define ANAR_TX_FD				(1<<8)
+//#define ANAR_TX_HD				(1<<7)
+//#define ANAR_10_FD				(1<<6)
+//#define ANAR_10_HD				(1<<5)
+//#define ANAR_SELECTOR			(0x1F<<0)
+//
+////For ANAR register
+//#define ANLPAR_NP				(1<<15)
+//#define ANLPAR_ACK				(1<<14)
+//#define ANLPAR_RF				(1<<13)
+//#define ANLPAR_LP_DIR			(1<<11)
+//#define ANLPAR_PAUSE			(1<<10)
+//#define ANLPAR_T4				(1<<9)
+//#define ANLPAR_TX_FD			(1<<8)
+//#define ANLPAR_TX_HD			(1<<7)
+//#define ANLPAR_10_FD			(1<<6)
+//#define ANLPAR_10_HD			(1<<5)
+//#define ANLPAR_SELECTOR			(0x1F<<0)
+
+/**/
+/* MDIO register*/
+//PCS_CTL_1			|		PCS control 1 register
+//PCS_STS_1			|		PCS status 1 register
+//EEE_ABILITY  		|		EEE capability register
+//WAKE_ER_CNTR		|		EEE wake error counter
+//EEE_ADVR 			|		EEE Advertisement register
+//EEE_LPAR 			|		EEE link partner ability register
+
+//--------------------------------------Not used-------------------------------------------//
+
+/********************/
+/*Functions for PHY */
+/********************/
+//todo move this definition to bit area
+#define PHYACR_READ			0x02
+#define PHYACR_WRITE		0x01
+
+
+
+
+/**
+ * @brief Enter a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n \n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * \sa WIZCHIP_CRITICAL_EXIT()
+ */
+#define WIZCHIP_CRITICAL_ENTER()    WIZCHIP.CRIS._enter()
+
+#ifdef _exit
+#undef _exit
+#endif
+
+/**
+ * @brief Exit a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n\n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * @sa WIZCHIP_CRITICAL_ENTER()
+ */
+#define WIZCHIP_CRITICAL_EXIT()     WIZCHIP.CRIS._exit()
+
+
+
+////////////////////////
+// Basic I/O Function //
+////////////////////////
+//
+//M20150601 :  uint16_t AddrSel --> uint32_t AddrSel
+//
+/**
+ * @ingroup Basic_IO_function_W5100S 
+ * @brief It reads 1 byte value from a register.
+ * @param AddrSel Register address
+ * @return The value of register
+ */
+uint8_t  WIZCHIP_READ (uint32_t AddrSel);
+
+/**
+ * @ingroup Basic_IO_function_W5100S
+ * @brief It writes 1 byte value to a register.
+ * @param AddrSel Register address
+ * @param wb Write data
+ * @return void
+ */
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
+
+/**
+ * @ingroup Basic_IO_function_W5100S
+ * @brief It reads sequence data from registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to read data
+ * @param len Data length
+ */
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5100S
+ * @brief It writes sequence data to registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to write data
+ * @param len Data length
+ */
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+
+/////////////////////////////////
+// Common Register IO function //
+/////////////////////////////////
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set Mode Register
+ * @param (uint8_t)mr The value to be set.
+ * @sa getMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define setMR(mr) 	WIZCHIP_WRITE(MR,mr)
+#else
+   #define setMR(mr)    (*((uint8_t*)MR) = mr)
+#endif
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get @ref MR.
+ * @return uint8_t. The value of Mode register.
+ * @sa setMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define getMR() 		WIZCHIP_READ(MR)
+#else
+   #define getMR()      (*(uint8_t*)MR)
+#endif
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set @ref GAR.
+ * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
+ * @sa getGAR()
+ */
+#define setGAR(gar) \
+		WIZCHIP_WRITE_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get @ref GAR.
+ * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
+ * @sa setGAR()
+ */
+#define getGAR(gar) \
+		WIZCHIP_READ_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set @ref SUBR.
+ * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
+ * @note If subr is null pointer, set the backup subnet to SUBR. \n
+ *       If subr is 0.0.0.0, back up SUBR and clear it. \n
+ *       Otherwize, set subr to SUBR
+ * @sa getSUBR()
+ */
+#define setSUBR(subr) \
+      WIZCHIP_WRITE_BUF(SUBR,subr,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get @ref SUBR.
+ * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
+ * @sa setSUBR()
+ */
+#define getSUBR(subr) \
+		WIZCHIP_READ_BUF(SUBR, subr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set @ref SHAR.
+ * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
+ * @sa getSHAR()
+ */
+#define setSHAR(shar) \
+		WIZCHIP_WRITE_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get @ref SHAR.
+ * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
+ * @sa setSHAR()
+ */
+#define getSHAR(shar) \
+		WIZCHIP_READ_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set @ref SIPR.
+ * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
+ * @sa getSIPR()
+*/
+#define setSIPR(sipr) \
+		WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get @ref SIPR.
+ * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
+ * @sa setSIPR()
+ */
+#define getSIPR(sipr) \
+		WIZCHIP_READ_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref IR register
+ * @param (uint8_t)ir Value to set \ref IR register.
+ * @sa getIR()
+ */
+#define setIR(ir) \
+		WIZCHIP_WRITE(IR, (ir & 0xE0)) //peter 2016.11.07 unreachable interrupt bit added
+		//WIZCHIP_WRITE(IR, (ir & 0xA0))
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref IR register
+ * @return uint8_t. Value of \ref IR register.
+ * @sa setIR()
+ */
+#define getIR() \
+		(WIZCHIP_READ(IR) & 0xE0) //peter 2016.11.07 unreachable interrupt bit added
+		//(WIZCHIP_READ(IR) & 0xA0)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref _IMR_ register
+ * @param (uint8_t)imr Value to set @ref _IMR_ register.
+ * @sa getIMR()
+ */
+#define setIMR(imr) \
+		WIZCHIP_WRITE(_IMR_, imr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref _IMR_ register
+ * @return uint8_t. Value of @ref _IMR_ register.
+ * @sa setIMR()
+ */
+#define getIMR() \
+		WIZCHIP_READ(_IMR_)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref _RTR_ register
+ * @param (uint16_t)rtr Value to set @ref _RTR_ register.
+ * @sa getRTR()
+ */
+#define setRTR(rtr)   {\
+		WIZCHIP_WRITE(_RTR_,   (uint8_t)(rtr >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref _RTR_ register
+ * @return uint16_t. Value of @ref _RTR_ register.
+ * @sa setRTR()
+ */
+#define getRTR() \
+		(((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1)))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref _RCR_ register
+ * @param (uint8_t)rcr Value to set @ref _RCR_ register.
+ * @sa getRCR()
+ */
+#define setRCR(rcr) \
+		WIZCHIP_WRITE(_RCR_, rcr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref _RCR_ register
+ * @return uint8_t. Value of @ref _RCR_ register.
+ * @sa setRCR()
+ */
+#define getRCR() \
+		WIZCHIP_READ(_RCR_)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref RMSR register
+ * @sa getRMSR()
+ */
+#define setRMSR(rmsr)   \
+      WIZCHIP_WRITE(RMSR,rmsr) // Receicve Memory Size
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref RMSR register
+ * @return uint8_t. Value of @ref RMSR register.
+ * @sa setRMSR()
+ */
+ #define getRMSR()   \
+      WIZCHIP_READ(RMSR) // Receicve Memory Size
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref TMSR register
+ * @sa getTMSR()
+ */
+#define setTMSR(tmsr)   \
+      WIZCHIP_WRITE(TMSR,tmsr) // Receicve Memory Size
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref TMSR register
+ * @return uint8_t. Value of @ref TMSR register.
+ * @sa setTMSR()
+ */
+#define getTMSR()	\
+	WIZCHIP_READ(TMSR)
+
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PATR register
+ * @return uint16_t. Value to set \ref PATR register
+ */
+#define getPATR() \
+		(((uint16_t)WIZCHIP_READ(PATR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PATR,1)))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PPPALGO register
+ * @return uint8_t. Value to set \ref PPPALGO register
+ */
+#define getPPPALGO() \
+		WIZCHIP_READ(PPPALGO)
+
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PTIMER register
+ * @param (uint8_t)ptimer Value to set \ref PTIMER register.
+ * @sa getPTIMER()
+ */
+#define setPTIMER(ptimer) \
+		WIZCHIP_WRITE(PTIMER, ptimer)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PTIMER register
+ * @return uint8_t. Value of @ref PTIMER register.
+ * @sa setPTIMER()
+ */
+#define getPTIMER() \
+		WIZCHIP_READ(PTIMER)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PMAGIC register
+ * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
+ * @sa getPMAGIC()
+ */
+#define setPMAGIC(pmagic) \
+		WIZCHIP_WRITE(PMAGIC, pmagic)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PMAGIC register
+ * @return uint8_t. Value of @ref PMAGIC register.
+ * @sa setPMAGIC()
+ */
+#define getPMAGIC() \
+		WIZCHIP_READ(PMAGIC)
+
+
+//todo Functions for W5100S
+
+/*----------------------------------------------------------------------*/
+/*								W5100S only								*/
+/*----------------------------------------------------------------------*/
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref IR2 register
+ * @param (uint8_t)ir2 Value to set @ref IR2 register.
+ * @sa getIR2()
+ */
+#define setIR2(ir2) \
+		WIZCHIP_WRITE(IR2, ir2)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref IR2 register
+ * @return uint8_t. Value of @ref IR2 register.
+ * @sa setIR2()
+ */
+#define getIR2() \
+		WIZCHIP_READ(IR2)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref IMR2 register
+ * @param (uint8_t)imr2 Value to set @ref IMR2 register.
+ * @sa setIMR2()
+ */
+#define setIMR2(imr2) \
+		WIZCHIP_WRITE(IMR2,imr2)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref IMR2 register
+ * @return uint8_t. Value of @ref IMR2 register.
+ * @sa getIMR2()
+ */
+#define getIMR2() \
+		WIZCHIP_READ(IMR2)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref UIPR(Unreachable IP Address Register) registers
+ * @param (uint8_t*)uipr Value to set @ref UIPR registers.
+ * @sa setUIPR()
+ */
+#define setUIPR(uipr) \
+		WIZCHIP_WRITE_BUF(UIPR,uipr,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref UIPR(Unreachable IP Address Register) registers
+ * @param (uint8_t*)uipr Value to get @ref UIPR registers
+ * @sa setUIPR()
+ */
+#define getUIPR(uipr) \
+		WIZCHIP_READ_BUF(UIPR,uipr,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref UPORTR(Unreachable Port Address Register) register
+ * @param (uint16_t)uportr Value to set @ref UPORTR register.
+ * @sa getUPORTR()
+ */
+#define	setUPORTR(uportr) {\
+		WIZCHIP_WRITE(UPORTR, (uint8_t)(uportr >> 8)); \
+		WIZCHIP_WRITE(UPORTR+1, (uint8_t) uportr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref UPORTR(Unreachable Port Address Register) register
+ * @return uint16_t. Value of @ref UPORTR register.
+ * @sa setUPORTR()
+ */
+#define getUPORTR() \
+		(((uint16_t)WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(UPORTR+1))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref MR2 register
+ * @param (uint8_t)mr2 Value to set @ref MR2 registers.
+ * @sa getMR2()
+ */
+#define setMR2(mr2) \
+		WIZCHIP_WRITE(MR2,mr2)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref MR2 register
+ * @return uint8_t. Value of @ref MR2 register.
+ * @sa setMR2()
+ */
+#define getMR2() \
+		WIZCHIP_READ(MR2)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHAR registers
+ * @param (uint8_t*)phar Value to set @ref PHAR registers.
+ * @sa getPHAR()
+ */
+#define setPHAR(phar) \
+		WIZCHIP_WRITE_BUF(PHAR,phar,6)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHAR registers
+ * @param (uint8_t*)phar Pointer variable to get @ref PHAR registers.
+ * @sa setPHAR()
+ */
+#define getPHAR(phar) \
+		WIZCHIP_READ_BUF(PHAR,phar,6)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PSIDR register
+ * @param (uint16_t)psidr Value to set @ref PSIDR register.
+ * @sa getPSIDR()
+ */
+#define setPSIDR(psidr) {\
+		WIZCHIP_WRITE(PSIDR, (uint8_t)(psidr >> 8)); \
+		WIZCHIP_WRITE(PSIDR+1, (uint8_t) psidr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PSIDR register
+ * @return uint16_t. Value of @ref PSIDR register.
+ * @sa setPSIDR()
+ */
+#define getPSIDR() \
+		(((uint16_t)WIZCHIP_READ(PSIDR) << 8) + WIZCHIP_READ(PSIDR+1))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PMRUR register
+ * @param (uint16_t)pmrur Value to set @ref PMRUR register.
+ * @sa getPMRUR()
+ */
+#define setPMRUR(pmrur) {\
+		WIZCHIP_WRITE(PMRUR, (uint8_t)(pmrur >> 8)); \
+		WIZCHIP_WRITE(PMRUR+1, (uint8_t) pmrur); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PMRUR register
+ * @return uint16_t. Value of @ref PMRUR register.
+ * @sa setPMRUR()
+ */
+#define getPMRUR() \
+		(((uint16_t)WIZCHIP_READ(PMRUR) << 8) + WIZCHIP_READ(PMRUR+1))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYSR register
+ * @return uint8_t. Value of @ref PHYSR register.
+ * @sa setPHYSR()
+ */
+#define getPHYSR()	\
+		WIZCHIP_READ(PHYSR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYSR1 register
+ * @return uint8_t. Value of @ref PHYSR1 register.
+ * @sa setPHYSR1()
+ */
+#define getPHYSR1()	\
+		WIZCHIP_READ(PHYSR1)
+
+/**
+ * For internal uses
+ * The address of the PHY is fixed as "0x0A".
+ */
+#define getPHYAR() \
+		WIZCHIP_READ(PHYAR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYRAR register
+ * @return uint8_t. Value of @ref PHYRAR register.
+ * @sa setPHYRAR()
+ */
+#define getPHYRAR() \
+		WIZCHIP_READ(PHYRAR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHYRR register
+ * @param (uint8_t)phyrar Value to set @ref PHYRR register.
+ * @sa getPHYRR()
+ */
+#define setPHYRR(phyrar) \
+		WIZCHIP_WRITE(PHYRAR, phyrar)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYDIR register
+ * @return uint16_t. Value of @ref PHYDIR register.
+ * @sa setPHYRAR()
+ */
+//read the value of the phy data input register
+#define getPHYDIR() \
+		(((uint16_t)WIZCHIP_READ(PHYDIR+1) << 8) + WIZCHIP_READ(PHYDIR))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHYDIR register
+ * @param (uint16_t)phydir Value to set @ref PHYDIR register.
+ * @sa getPHYDIR()
+ */
+//write the value of the phy data input register
+#define setPHYDIR(phydir) {\
+		WIZCHIP_WRITE(PHYDIR+1, (uint8_t)(phydir >> 8)); \
+		WIZCHIP_WRITE(PHYDIR, (uint8_t) phydir); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYDOR register
+ * @return uint16_t. Value of @ref PHYDOR register.
+ * @sa setPHYDOR()
+ */
+//read the value of the phy data output register
+#define getPHYDOR()	\
+		(((uint16_t)WIZCHIP_READ(PHYDOR+1) << 8) + WIZCHIP_READ(PHYDOR))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHYDOR register
+ * @param (uint16_t)phydor Value to set @ref PHYDOR register.
+ * @sa getPHYDOR()
+ */
+//write the value of the phy data output register
+#define setPHYDOR(phydor) {\
+		WIZCHIP_WRITE(PHYDOR, (uint8_t)(phydor >> 8)); \
+		WIZCHIP_WRITE(PHYDOR+1, (uint8_t) phydor); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYACR register
+ * @return uint8_t. Value of @ref PHYACR register.
+ * @sa setPHYACR()
+ */
+//read the value of the phy action register ***This register will be cleared automatically***
+#define getPHYACR() \
+		WIZCHIP_READ(PHYACR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHYACR register
+ * @param (uint8_t)phyacr Value to set @ref PHYACR register.
+ * @sa getPHYACR()
+ */
+//write the value of the phy action register
+#define setPHYACR(phyacr)	\
+		WIZCHIP_WRITE(PHYACR,phyacr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHYDIVR register
+ * @param (uint8_t)phydivr Value to set @ref PHYDIVR register.
+ * @sa getPHYDIVR()
+ */
+#define setPHYDIVR(phydivr)	\
+		WIZCHIP_WRITE(PHYDIVR, phydivr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYDIVR register
+ * @return uint8_t. Value of @ref PHYDIVR register.
+ * @sa setPHYDIVR()
+ */
+#define getPHYDIVR()	\
+		WIZCHIP_READ(PHYDIVR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHYCR0 register
+ * @param (uint8_t)phych0 Value to set @ref PHYCR0 register.
+ * @sa getPHYCR0()
+ */
+#define setPHYCR0(phych0)		\
+		WIZCHIP_WRITE(PHYCR0,phych0)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYCR0 register
+ * @return uint8_t. Value of @ref PHYCR0 register.
+ * @sa setPHYCR0()
+ */
+#define getPHYCR0()	\
+		WIZCHIP_READ(PHYCR0)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PHYCR1 register
+ * @param (uint8_t)phycr1 Value to set @ref PHYCR1 register.
+ * @sa getPHYCR1()
+ */
+#define setPHYCR1(phycr1)	\
+		WIZCHIP_WRITE(PHYCR1,phycr1)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PHYCR1 register
+ * @return uint8_t. Value of @ref PHYCR1 register.
+ * @sa setPHYCR1()
+ */
+#define getPHYCR1() \
+		WIZCHIP_READ(PHYCR1)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref SLCR register
+ * @param (uint8_t)rqcr Value to set @ref SLCR register.
+ * @sa getSLCR()
+ */
+#define setSLCR(rqcr)	\
+		WIZCHIP_WRITE(SLCR, rqcr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref RQCR register
+ * @return uint8_t. Value of @ref RQCR register.
+ * @sa setRQCR()
+ */
+#define getSLCR()	\
+		WIZCHIP_READ(RQCR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref SLRTR register
+ * @param (uint16_t)slrtr Value to set @ref SLRTR register.
+ * @sa getSLRTR()
+ */
+#define setSLRTR(slrtr)	\
+		WIZCHIP_WRITE(SLRTR, (uint8_t)(slrtr >> 8)); \
+		WIZCHIP_WRITE(SLRTR+1, (uint8_t) slrtr); \
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref SLRTR register
+ * @return uint16_t. Value of @ref SLRTR register.
+ * @sa setSLRTR()
+ */
+#define getSLRTR()	\
+		(((uint16_t)WIZCHIP_READ(SLRTR) << 8) + WIZCHIP_READ(SLRTR+1))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref SLRCR register
+ * @param (uint8_t)slrcr Value to set @ref SLRCR register.
+ * @sa getSLRCR()
+ */
+#define setSLRCR(slrcr)	\
+		WIZCHIP_WRITE(SLRCR,slrcr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref SLRCR register
+ * @return uint8_t. Value of @ref SLRCR register.
+ * @sa setSLRCR()
+ */
+#define getSLRCR()	\
+		WIZCHIP_READ(SLRCR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref SLPIPR registers
+ * @param (uint8_t*)slpipr Values to set @ref SLPIPR registers.
+ * @sa getSLPIPR()
+ */
+#define setSLPIPR(slpipr)	\
+		WIZCHIP_WRITE_BUF(SLPIPR,slpipr,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref SLPIPR registers
+ * @param (uint8_t*)slpipr Values to get @ref SLPIPR registers.
+ * @sa getSLPIPR()
+ */
+#define getSLPIPR(slpipr)	\
+		WIZCHIP_READ_BUF(SLPIPR,slpipr,4)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref SLPHAR registers
+ * @param (uint8_t*)slphar Values to set @ref SLPHAR registers.
+ * @sa getSLPHAR()
+ */
+#define setSLPHAR(slphar) \
+		WIZCHIP_WRITE_BUF(SLPHAR,slphar,6)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref SLPHAR registers
+ * @param (uint8_t*)slphar Values to get @ref SLPHAR registers.
+ * @sa getSLPHAR()
+ */
+#define getSLPHAR(slphar) \
+		WIZCHIP_READ_BUF(SLPHAR,slphar,6)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PINGSEQR register
+ * @param (uint16_t)pingseqr Value to set @ref PINGSEQR register.
+ * @sa getPINGSEQR()
+ */
+#define setPINGSEQR(pingseqr) {\
+		WIZCHIP_WRITE(PINGSEQR, (uint8_t)(pingseqr >> 8)); \
+		WIZCHIP_WRITE(PINGSEQR+1, (uint8_t) pingseqr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PINGSEQR register
+ * @return uint16_t. Value of @ref PINGSEQR register.
+ * @sa setPINGSEQR()
+ */
+#define getPINGSEQR() \
+		(((uint16_t)WIZCHIP_READ(PINGSEQR) << 8) + WIZCHIP_READ(PINGSEQR+1))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref PINGIDR register
+ * @param (uint16_t)pingidr Value to set @ref PINGIDR register.
+ * @sa getPINGIDR()
+ */
+#define setPINGIDR(pingidr) {\
+		WIZCHIP_WRITE(PINGIDR, (uint8_t)(pingidr >> 8)); \
+		WIZCHIP_WRITE(PINGIDR+1, (uint8_t) pingidr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref PINGIDR register
+ * @return uint16_t. Value of @ref PINGIDR register.
+ * @sa setPINGIDR()
+ */
+#define getPINGIDR()	\
+		(((uint16_t)WIZCHIP_READ(PINGIDR) << 8) + WIZCHIP_READ(PINGIDR+1))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref SLIMR register
+ * @param (uint8_t)slimr Value to set @ref SLIMR register.
+ * @sa getSLIMR()
+ */
+#define setSLIMR(slimr)	\
+		WIZCHIP_WRITE(SLIMR, slimr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref SLIMR register
+ * @return uint8_t. Value of @ref SLIMR register.
+ * @sa setSLIMR()
+ */
+#define getSLIMR()	\
+		WIZCHIP_READ(SLIMR)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref SLIR register
+ * @param (uint8_t)slir Value to set @ref SLIR register.
+ * @sa getSLIMR()
+ */
+#define setSLIR(slir)	\
+		WIZCHIP_WRITE(SLIR, slir)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref SLIMR register
+ * @return uint8_t. Value of @ref SLIMR register.
+ * @sa setSLIMR()
+ */
+#define getSLIR()	\
+		WIZCHIP_READ(SLIR)
+
+/*Hidden functions for W5100S*/
+#define setDBGOUT(dbgout) 	{\
+		WIZCHIP_WRITE(DBGOUT,(uint8_t)(dbgout >> 16));	\
+		WIZCHIP_WRITE(DBGOUT,(uint8_t)(dbgout >> 8));	\
+		WIZCHIP_WRITE(DBGOUT,(uint8_t)(dbgout));		\
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref NICMAXCOLR register
+ * @param (uint8_t)nicmaxcolr Value to set @ref NICMAXCOLR register.
+ * @sa getNICMAXCOLR()
+ */
+#define setNICMAXCOLR(nicmaxcolr)	\
+		WIZCHIP_WRITE(NICMAXCOLR,nicmaxcolr)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref NICMAXCOLR register
+ * @return uint8_t. Value of @ref NICMAXCOLR register.
+ * @sa setNICMAXCOLR()
+ */
+#define getNICMAXCOLR()	\
+		WIZCHIP_READ(NICMAXCOLR)
+
+/*Clock lock/unlock*/
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief LOCK Chip Information
+ * @sa CHIPULLOCK()
+ */
+#define CHIPLOCK()	\
+		WIZCHIP_WRITE(CHIPLCKR,0xff)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Unlock Chip Information
+ * @sa CHIPLOCK()
+ */
+#define CHIPUNLOCK()	\
+		WIZCHIP_WRITE(CHIPLCKR,0xCE)
+
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief LOCK Chip Information
+ * @sa CHIPULLOCK()
+ */
+/*Network information lock/unlock*/
+#define NETLOCK()	\
+		WIZCHIP_WRITE(NETLCKR,0x3A)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Unlock Chip Information
+ * @sa CHIPLOCK()
+ */
+#define NETUNLOCK()	\
+		WIZCHIP_WRITE(NETLCKR,0xC5)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Lock PHYCR0,CR1 Information
+ * @sa CHIPULLOCK()
+ */
+/*PHY CR0,CR1 lock/unlock*/
+#define PHYLOCK()	\
+		WIZCHIP_WRITE(PHYLCKR,0xff)
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Lock PHYCR0,CR1 Information
+ * @sa CHIPULLOCK()
+ */
+#define PHYUNLOCK()	\
+		WIZCHIP_WRITE(PHYLCKR,0x53)
+
+/**
+ * @ingroup Version register_access_function_W5100SS
+ * @brief Get version information.
+ * @return uint16_t. It must be "0x51"
+ */
+#define getVER() \
+		(WIZCHIP_READ(VERR))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Get \ref TCNTR register
+ * @return uint16_t. Value of @ref TCNTR register.
+ * @sa setNTCNTR()
+ */
+/*Get 100us internal counter*/
+#define getTCNTR()	\
+		(((uint16_t)WIZCHIP_READ(TCNTR) << 8) + WIZCHIP_READ(TCNTR+1))
+
+/**
+ * @ingroup Common_register_access_function_W5100S
+ * @brief Set \ref TCNTR register
+ * @param (uint8_t)
+  Value to set @ref TCNTR register.
+ * @sa getTCNTCLKR()
+ */
+/*Reset 100us internal counter(TCNTR)*/
+#define setTCNTCLKR(var)	\
+		WIZCHIP_WRITE(TCNTCLKR, var)
+
+/*w5100s only end*/
+
+
+
+
+
+///////////////////////////////////
+// Socket N register I/O function //
+///////////////////////////////////
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_MR register
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ * @param mr Value to set @ref Sn_MR
+ * @sa getSn_MR()
+ */
+#define setSn_MR(sn, mr) \
+		WIZCHIP_WRITE(Sn_MR(sn),mr)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_MR register
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ * @return Value of @ref Sn_MR.
+ * @sa setSn_MR()
+ */
+#define getSn_MR(sn) \
+	WIZCHIP_READ(Sn_MR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)cr Value to set @ref Sn_CR
+ * @sa getSn_CR()
+ */
+#define setSn_CR(sn, cr) \
+		WIZCHIP_WRITE(Sn_CR(sn), cr)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_CR.
+ * @sa setSn_CR()
+ */
+#define getSn_CR(sn) \
+		WIZCHIP_READ(Sn_CR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)ir Value to set @ref Sn_IR
+ * @sa getSn_IR()
+ */
+#define setSn_IR(sn, ir) \
+		WIZCHIP_WRITE(Sn_IR(sn), ir)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_IR.
+ * @sa setSn_IR()
+ */
+#define getSn_IR(sn) \
+		WIZCHIP_READ(Sn_IR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_SR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_SR.
+ */
+#define getSn_SR(sn) \
+		WIZCHIP_READ(Sn_SR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)port Value to set @ref Sn_PORT.
+ * @sa getSn_PORT()
+ */
+#define setSn_PORT(sn, port)  { \
+		WIZCHIP_WRITE(Sn_PORT(sn),   (uint8_t)(port >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_PORT.
+ * @sa setSn_PORT()
+ */
+#define getSn_PORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa getSn_DHAR()
+ */
+#define setSn_DHAR(sn, dhar) \
+		WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa setSn_DHAR()
+ */
+#define getSn_DHAR(sn, dhar) \
+		WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
+ * @sa getSn_DIPR()
+ */
+#define setSn_DIPR(sn, dipr) \
+		WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
+ * @sa SetSn_DIPR()
+ */
+#define getSn_DIPR(sn, dipr) \
+		WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)dport Value to set @ref Sn_DPORT
+ * @sa getSn_DPORT()
+ */
+#define setSn_DPORT(sn, dport) { \
+		WIZCHIP_WRITE(Sn_DPORT(sn),   (uint8_t) (dport>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t)  dport); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_DPORT.
+ * @sa setSn_DPORT()
+ */
+#define getSn_DPORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)mss Value to set @ref Sn_MSSR
+ * @sa setSn_MSSR()
+ */
+#define setSn_MSSR(sn, mss) { \
+		WIZCHIP_WRITE(Sn_MSSR(sn),   (uint8_t)(mss>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_MSSR.
+ * @sa setSn_MSSR()
+ */
+#define getSn_MSSR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_PROTO register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)proto Value to set \ref Sn_PROTO
+ * @sa getSn_PROTO()
+ */
+#define setSn_PROTO(sn, proto) \
+		WIZCHIP_WRITE(Sn_PROTO(sn), proto)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_PROTO register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_PROTO.
+ * @sa setSn_PROTO()
+ */
+#define getSn_PROTO(sn) \
+		WIZCHIP_READ(Sn_PROTO(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)tos Value to set @ref Sn_TOS
+ * @sa getSn_TOS()
+ */
+#define setSn_TOS(sn, tos) \
+		WIZCHIP_WRITE(Sn_TOS(sn), tos)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @return uint8_t. Value of Sn_TOS.
+ * @sa setSn_TOS()
+ */
+#define getSn_TOS(sn) \
+		WIZCHIP_READ(Sn_TOS(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @param (uint8_t)ttl Value to set @ref Sn_TTL
+ * @sa getSn_TTL()
+ */
+#define setSn_TTL(sn, ttl) \
+		WIZCHIP_WRITE(Sn_TTL(sn), ttl)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @return uint8_t. Value of @ref Sn_TTL.
+ * @sa setSn_TTL()
+ */
+#define getSn_TTL(sn) \
+		WIZCHIP_READ(Sn_TTL(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_RXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @param (uint8_t)rxmemsize Value to set \ref Sn_RXMEM_SIZE
+ * @sa getSn_RXMEM_SIZE()
+ */
+#define  setSn_RXMEM_SIZE(sn, rxmemsize) \
+      WIZCHIP_WRITE(RMSR, (WIZCHIP_READ(RMSR) & ~(0x03 << (2*sn))) | (rxmemsize << (2*sn)))
+#define setSn_RXBUF_SIZE(sn,rxmemsize) setSn_RXMEM_SIZE(sn,rxmemsize)
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_RXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_RXMEM.
+ * @sa setSn_RXMEM_SIZE()
+ */
+#define  getSn_RXMEM_SIZE(sn) \
+      ((WIZCHIP_READ(RMSR) & (0x03 << (2*sn))) >> (2*sn))
+#define  getSn_RXBUF_SIZE(sn) getSn_RXMEM_SIZE(sn)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_TXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)txmemsize Value to set \ref Sn_TXMEM_SIZE
+ * @sa getSn_TXMEM_SIZE()
+ */
+#define setSn_TXMEM_SIZE(sn, txmemsize) \
+      WIZCHIP_WRITE(TMSR, (WIZCHIP_READ(TMSR) & ~(0x03 << (2*sn))) | (txmemsize << (2*sn)))
+#define  setSn_TXBUF_SIZE(sn, txmemsize) setSn_TXMEM_SIZE(sn,txmemsize)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_TXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_TXMEM_SIZE.
+ * @sa setSn_TXMEM_SIZE()
+ */
+#define  getSn_TXMEM_SIZE(sn) \
+      ((WIZCHIP_READ(TMSR) & (0x03 << (2*sn))) >> (2*sn))
+#define  getSn_TXBUF_SIZE(sn) getSn_TXMEM_SIZE(sn)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_TX_FSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_FSR.
+ */
+uint16_t getSn_TX_FSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_TX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_RD.
+ */
+#define getSn_TX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
+ * @sa GetSn_TX_WR()
+ */
+#define setSn_TX_WR(sn, txwr) { \
+		WIZCHIP_WRITE(Sn_TX_WR(sn),   (uint8_t)(txwr>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \
+		}
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_WR.
+ * @sa setSn_TX_WR()
+ */
+#define getSn_TX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_RX_RSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_RX_RSR.
+ */
+uint16_t getSn_RX_RSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
+ * @sa getSn_RX_RD()
+ */
+#define setSn_RX_RD(sn, rxrd) { \
+		WIZCHIP_WRITE(Sn_RX_RD(sn),   (uint8_t)(rxrd>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @regurn uint16_t. Value of @ref Sn_RX_RD.
+ * @sa setSn_RX_RD()
+ */
+#define getSn_RX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_RX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)rxwr Value to set \ref Sn_RX_WR
+ * @sa getSn_RX_WR()
+ */
+#define setSn_RX_WR(sn, rxwr) { \
+		WIZCHIP_WRITE(Sn_RX_WR(sn),   (uint8_t)(rxwr>>8)); \
+	   WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1), (uint8_t) rxwr); \
+	}
+
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_RX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_RX_WR.
+ */
+#define getSn_RX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set @ref Sn_FRAGR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)frag Value to set \ref Sn_FRAGR
+ * @sa getSn_FRAG()
+ */
+#define setSn_FRAGR(sn, fragr) { \
+		WIZCHIP_WRITE(Sn_FRAGR(sn),  (uint8_t)(fragr >>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAGR(sn),1), (uint8_t) fragr); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get @ref Sn_FRAGR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_FRAGR.
+ * @sa setSn_FRAG()
+ */
+#define getSn_FRAGR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_FRAGR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAGR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the max RX buffer size of socket sn
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Max buffer size
+ */
+#define getSn_RxMAX(sn) \
+		((uint16_t)(0x0001 << getSn_RXMEM_SIZE(sn)) << 10)
+
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the max TX buffer size of socket sn
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Max buffer size
+ */
+#define getSn_TxMAX(sn) \
+		((uint16_t)(0x0001 << getSn_TXMEM_SIZE(sn)) << 10)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the mask of socket sn RX buffer.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Mask value
+ */
+#define getSn_RxMASK(sn) \
+		(getSn_RxMAX(sn) - 1)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the mask of socket sn TX buffer
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Mask value
+ */
+#define getSn_TxMASK(sn) \
+		(getSn_TxMAX(sn) - 1)
+
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the base address of socket sn RX buffer.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n RX buffer base address.
+ */
+uint32_t getSn_RxBASE(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the base address of socket sn TX buffer.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n TX buffer base address.
+ */
+uint32_t getSn_TxBASE(uint8_t sn);
+
+
+/*socket register W5100S only*/
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set the interrupt mask register of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)imr Value to set \ref Sn_IMR
+ * @sa getSn_IMR(sn)
+ */
+#define setSn_IMR(sn,imr)	\
+		WIZCHIP_WRITE(Sn_IMR(sn),imr)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the interrupt mask register of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n interrupt mask register.
+ */
+#define getSn_IMR(sn)	\
+		WIZCHIP_READ(Sn_IMR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set the Sn_MR2 value of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param mr2 Value of Sn_MR2 register to set.
+ */
+#define setSn_MR2(sn,mr2)	\
+		WIZCHIP_WRITE(Sn_MR2(sn), mr2)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the Sn_MR2 value of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n Sn_MR2 register.
+ */
+#define getSn_MR2(sn)	\
+		WIZCHIP_READ(Sn_MR2(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set the Sn_KPALVTR value of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param kpalvtr Value of the Sn_KPALVTR register to set.
+ */
+#define setSn_KPALVTR(sn,kpalvtr)	\
+		WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvtr)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the Sn_KPALVTR value of socket sn
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of the Sn_KPALVTR register.
+ */
+#define getSn_KPALVTR(sn)	\
+		WIZCHIP_READ(Sn_KPALVTR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the Sn_TSR register of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of the Socket n Sn_TSR register.
+ */
+#define	getSn_TSR(sn)	\
+		WIZCHIP_READ(Sn_TSR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set the Sn_RTR register of socket sn.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)rtr Value of the Socket n Sn_RTR register to set.
+ */
+#define	setSn_RTR(sn,rtr)	{ \
+		WIZCHIP_WRITE(Sn_RTR(sn),   (uint8_t)(rtr >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RTR(sn),1), (uint8_t) rtr); \
+		}
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the Sn_RTR register of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of the Socket n Sn_RTR register.
+ */
+#define getSn_RTR(sn)	\
+		(((uint16_t)WIZCHIP_READ(Sn_RTR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RTR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Set the Sn_RCR register of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of the Socket n Sn_RCR register to set.
+ */
+#define setSn_RCR(sn,rcr)	\
+		WIZCHIP_WRITE(Sn_RCR(sn),rcr)
+
+/**
+ * @ingroup Socket_register_access_function_W5100S
+ * @brief Get the Sn_RCR of socket sn.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of the Socket n Sn_RCR.
+ */
+#define getSn_RCR(sn)	\
+		WIZCHIP_READ(Sn_RCR(sn))
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+/**
+ * @ingroup Basic_IO_function_W5100S
+ * @brief It copies data to internal TX memory
+ *
+ * @details This function reads the Tx write pointer register and after that,
+ * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory
+ * and updates the Tx write pointer register.
+ * This function is being called by send() and sendto() function also.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param wizdata Pointer buffer to write data
+ * @param len Data length
+ * @sa wiz_recv_data()
+ */
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5100S
+ * @brief It copies data to your buffer from internal RX memory
+ *
+ * @details This function read the Rx read pointer register and after that,
+ * it copies the received data from internal RX memory
+ * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes.
+ * This function is being called by recv() also.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param wizdata Pointer buffer to read data
+ * @param len Data length
+ * @sa wiz_send_data()
+ */
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5100S
+ * @brief It discard the received data in RX memory.
+ * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param len Data length
+ */
+void wiz_recv_ignore(uint8_t sn, uint16_t len);
+
+/**
+ * @ingroup Special_function_W5100S
+ * @brief Write data to the PHY via MDC/MDIO interface.
+ * @details Write command data to the PHY via MDC/MDIO interface.
+ * @param (uint8_t)PHYMDIO_regadr Address of the PHY register. It should be PHYMDIO_BMCR or PHYMDIO_BMSR.
+ * @param (uint16_t)var Data to write to the PHY register. Please refer to the bit definitions of the BMCR and BMSR register.
+ */
+void wiz_mdio_write(uint8_t PHYMDIO_regadr, uint16_t var);
+
+/**
+ * @ingroup Special_function_W5100S
+ * @brief Read data from the PHY via MDC/MDIO interface.
+ * @details Read command or status data from the PHY via MDC/MDIO interface.
+ * @param (uint8_t)PHYMDIO_regadr Address of the PHY register. It should be PHYMDIO_BMCR or PHYMDIO_BMSR.
+ * @return The value of the PHY register
+ */
+uint16_t wiz_mdio_read(uint8_t PHYMDIO_regadr);
+
+/**
+ * @ingroup Special_function_W5100S
+ * @brief Delay function
+ * @details Delay function using internal 100us timer of the W5100S
+ * @param (uint32_t)ms Time to delay in milliseconds.
+ */
+void wiz_delay_ms(uint32_t ms);
+
+/// @cond DOXY_APPLY_CODE
+#endif
+/// @endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_W5100S_H_
+
+
+

+ 353 - 0
lib/ioLibrary_Driver/Ethernet/W5200/w5200.c

@@ -0,0 +1,353 @@
+//*****************************************************************************
+//
+//! \file w5200.c
+//! \brief W5200 HAL Interface.
+//! \version 1.0.0
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! 
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include "w5200.h"
+
+#if   (_WIZCHIP_ == 5200)
+/**
+@brief  This function writes the data into W5200 registers.
+*/
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
+{
+	WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+   WIZCHIP.IF.SPI._write_byte(_W5200_SPI_WRITE_);  // Data write command and Write data length upper
+   WIZCHIP.IF.SPI._write_byte(0x01);  // Write data length lower
+   WIZCHIP.IF.SPI._write_byte(wb);    // Data write (write 1byte data)
+
+#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
+
+   //add indirect bus 
+   //M20150601 : Rename the function for integrating with W5300
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));	
+   //WIZCHIP.IF.BUS._write_byte(IDM_DR,wb);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));	
+   WIZCHIP.IF.BUS._write_data(IDM_DR,wb);
+
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!"
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+/**
+@brief  This function reads the value from W5200 registers.
+*/
+uint8_t  WIZCHIP_READ(uint32_t AddrSel)
+{
+   uint8_t ret;
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+   WIZCHIP.IF.SPI._write_byte(_W5200_SPI_READ_);                             // Read data length upper    
+   WIZCHIP.IF.SPI._write_byte(0x01);                             // Data length lower  
+   ret = WIZCHIP.IF.SPI._read_byte(); 
+
+#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
+
+   //add indirect bus
+   //M20150601 : Rename the function for integrating with W5300
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   //WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));	
+   //ret = WIZCHIP.IF.BUS._read_byte(IDM_DR);
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));	
+   ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
+   	
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!"   
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+   return ret;
+}
+
+
+/**
+@brief  This function writes into W5200 memory(Buffer)
+*/ 
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint16_t i = 0;
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+  WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+  WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+  WIZCHIP.IF.SPI._write_byte(_W5200_SPI_WRITE_ | ((len & 0x7F00) >> 8));         // Write data op code and length upper    
+  WIZCHIP.IF.SPI._write_byte((len & 0x00FF) >> 0);         // length lower
+  for(i = 0; i < len; i++)
+     WIZCHIP.IF.SPI._write_byte(pBuf[i]);
+
+#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
+   //M20150601 : Rename the function for integrating with W5300
+   /*
+   WIZCHIP_WRITE(MR,WIZCHIP_READ(MR) | MR_AI);     
+   WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));
+   for(i = 0 ; i < len; i++)
+      WIZCHIP.IF.BUS._write_byte(IDM_DR,pBuf[i]);
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);   
+   */
+   setMR(getMR() | MR_AI);     
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));
+   for(i = 0 ; i < len; i++)
+      WIZCHIP.IF.BUS._write_data(IDM_DR,pBuf[i]);
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI);   
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!!"
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+/**
+@brief  This function reads into W5200 memory(Buffer)
+*/ 
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint16_t i = 0;
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_))
+  WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+  WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+  WIZCHIP.IF.SPI._write_byte( _W5200_SPI_READ_ | ((len & 0x7F00) >> 8));         // Write data op code and length upper    
+  WIZCHIP.IF.SPI._write_byte((len & 0x00FF) >> 0);         // length lower
+  for(i = 0; i < len; i++)
+    pBuf[i] = WIZCHIP.IF.SPI._read_byte();
+ 
+#elif ( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) )
+   //M20150601 : Rename the function for integrating with W5300
+   /*
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) | MR_AI);    
+   WIZCHIP.IF.BUS._write_byte(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.BUS._write_byte(IDM_AR1,(AddrSel & 0x000000FF));	
+   for(i = 0 ; i < len; i++)
+      pBuf[i]	= WIZCHIP.IF.BUS._read_byte(IDM_DR);
+   WIZCHIP_WRITE(MR, WIZCHIP_READ(MR) & ~MR_AI); 
+   */
+   setMR(getMR() | MR_AI);    
+   WIZCHIP.IF.BUS._write_data(IDM_AR0,(AddrSel & 0x0000FF00) >>  8);
+   WIZCHIP.IF.BUS._write_data(IDM_AR1,(AddrSel & 0x000000FF));	
+   for(i = 0 ; i < len; i++)
+      pBuf[i]	= WIZCHIP.IF.BUS._read_data(IDM_DR);
+   setMR(getMR() & ~MR_AI); 
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5200. !!!!"
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+///////////////////////////////////
+// Socket N regsiter IO function //
+///////////////////////////////////
+
+uint16_t getSn_TX_FSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_TX_FSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+
+uint16_t getSn_RX_RSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_RX_RSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+
+uint16_t getSn_RxBASE(uint8_t sn)
+{
+   int8_t  i;
+   uint16_t rxbase = _WIZCHIP_IO_RXBUF_;
+   for(i = 0; i < sn; i++)
+      rxbase += getSn_RxMAX(i);
+   return rxbase;
+}
+
+uint16_t getSn_TxBASE(uint8_t sn)
+{
+   int8_t  i;
+   uint16_t txbase = _WIZCHIP_IO_TXBUF_;
+   for(i = 0; i < sn; i++)
+      txbase += getSn_TxMAX(i);
+   return txbase;
+}
+
+/**
+@brief  This function is being called by send() and sendto() function also. for copy the data form application buffer to Transmite buffer of the chip.
+
+This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
+register. User should read upper byte first and lower byte later to get proper value.
+And this function is being used for copy the data form application buffer to Transmite
+buffer of the chip. It calculate the actual physical address where one has to write
+the data in transmite buffer. Here also take care of the condition while it exceed
+the Tx memory uper-bound of socket.
+
+*/
+                                        
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+  
+  uint16_t ptr;
+  uint16_t size;
+  uint16_t dst_mask;
+  uint8_t * dst_ptr;
+
+  ptr = getSn_TX_WR(sn);
+
+
+  dst_mask = (uint32_t)ptr & getSn_TxMASK(sn);
+  dst_ptr = (uint8_t*)((uint32_t)getSn_TxBASE(sn) + dst_mask);
+  
+  if (dst_mask + len > getSn_TxMAX(sn)) 
+  {
+    size = getSn_TxMAX(sn) - dst_mask;
+    WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, size);
+    wizdata += size;
+    size = len - size;
+    dst_ptr = (uint8_t*)((uint32_t)getSn_TxBASE(sn));
+    WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, size);
+  } 
+  else
+  {
+    WIZCHIP_WRITE_BUF((uint32_t)dst_ptr, wizdata, len);
+  }
+
+  ptr += len;
+
+  setSn_TX_WR(sn, ptr);  
+}
+
+
+/**
+@brief  This function is being called by recv() also. This function is being used for copy the data form Receive buffer of the chip to application buffer.
+
+This function read the Rx read pointer register
+and after copy the data from receive buffer update the Rx write pointer register.
+User should read upper byte first and lower byte later to get proper value.
+It calculate the actual physical address where one has to read
+the data from Receive buffer. Here also take care of the condition while it exceed
+the Rx memory uper-bound of socket.
+*/
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+  uint16_t ptr;
+  uint16_t size;
+  uint16_t src_mask;
+  uint8_t * src_ptr;
+
+  ptr = getSn_RX_RD(sn);
+  
+  src_mask = (uint32_t)ptr & getSn_RxMASK(sn);
+  src_ptr = (uint8_t *)((uint32_t)getSn_RxBASE(sn) + src_mask);
+  
+  if( (src_mask + len) > getSn_RxMAX(sn) ) 
+  {
+    size = getSn_RxMAX(sn) - src_mask;
+    WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
+    wizdata += size;
+    size = len - size;
+    src_ptr = (uint8_t*)((uint32_t)getSn_RxBASE(sn));
+    WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, size);
+  } 
+  else
+  {
+    WIZCHIP_READ_BUF((uint32_t)src_ptr, (uint8_t*)wizdata, len);
+  }
+    
+  ptr += len;
+  
+  setSn_RX_RD(sn, ptr);
+}
+
+void wiz_recv_ignore(uint8_t sn, uint16_t len)
+{
+  uint16_t ptr;
+
+  ptr = getSn_RX_RD(sn);
+  
+  ptr += len;
+  setSn_RX_RD(sn,ptr);
+}
+
+#endif

+ 2110 - 0
lib/ioLibrary_Driver/Ethernet/W5200/w5200.h

@@ -0,0 +1,2110 @@
+//* ****************************************************************************
+//! \file w5200.h
+//! \brief W5200 HAL Header File.
+//! \version 1.0.0
+//! \date 2015/03/23
+//! \par  Revision history
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#ifndef	_W5200_H
+#define	_W5200_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "wizchip_conf.h"
+
+/// \cond DOXY_APPLY_CODE
+#if   (_WIZCHIP_ == 5200)
+/// \endcond
+
+#define _WIZCHIP_SN_BASE_  (0x4000)
+#define _WIZCHIP_SN_SIZE_  (0x0100)
+#define _WIZCHIP_IO_TXBUF_ (0x8000) /* Internal Tx buffer address of the iinchip */
+#define _WIZCHIP_IO_RXBUF_ (0xC000) /* Internal Rx buffer address of the iinchip */
+
+#define _W5200_SPI_READ_   (0x00 << 7) ///< SPI interface Read operation in Control Phase
+#define _W5200_SPI_WRITE_  (0x01 << 7) ///< SPI interface Write operation in Control Phase
+
+#define WIZCHIP_CREG_BLOCK      	    0x00   ///< Common register block
+#define WIZCHIP_SREG_BLOCK(N)    	   (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block
+
+#define WIZCHIP_OFFSET_INC(ADDR, N)    (ADDR + N) ///< Increase offset address
+
+#if  (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_)
+	#define IDM_AR0            ((_WIZCHIP_IO_BASE_ + 0x0001))
+	#define IDM_AR1            ((_WIZCHIP_IO_BASE_ + 0x0002))
+	#define IDM_DR             ((_WIZCHIP_IO_BASE_ + 0x0003))
+	#define _W5200_IO_BASE_    0x0000
+#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define _W5200_IO_BASE_    0x0000
+#endif
+
+///////////////////////////////////////
+// Definition For Legacy Chip Driver //
+///////////////////////////////////////
+#define IINCHIP_READ(ADDR)                WIZCHIP_READ(ADDR)               ///< The defined for legacy chip driver
+#define IINCHIP_WRITE(ADDR,VAL)           WIZCHIP_WRITE(ADDR,VAL)          ///< The defined for legacy chip driver
+#define IINCHIP_READ_BUF(ADDR,BUF,LEN)    WIZCHIP_READ_BUF(ADDR,BUF,LEN)   ///< The defined for legacy chip driver
+#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN)   WIZCHIP_WRITE(ADDR,BUF,LEN)      ///< The defined for legacy chip driver
+
+
+//-----------    defgroup --------------------------------
+
+/**
+ * @defgroup W5200 W5200
+ * @brief WHIZCHIP register defines and I/O functions of @b W5200.
+ *
+ * - @ref WIZCHIP_register_W5200 : @ref Common_register_group_W5200 and @ref Socket_register_group_W5200
+ * - @ref WIZCHIP_IO_Functions_W5200 : @ref Basic_IO_function_W5200, @ref Common_register_access_function_W5200 and @ref Socket_register_group_W5200
+ */
+ 
+ /**
+ * @defgroup WIZCHIP_register_W5200 WIZCHIP register
+ * @ingroup W5200
+ * @brief WIZCHIP register defines register group of <b> W5200 </b>.
+ *
+ * - \ref Common_register_group_W5200 : Common register group w5200
+ * - \ref Socket_register_group_W5200 : \c SOCKET n register group w5200
+ */
+ 
+
+/**
+ * @defgroup WIZCHIP_IO_Functions_W5200 WIZCHIP I/O functions
+ * @ingroup W5200 
+ * @brief This supports the basic I/O functions for \ref WIZCHIP_register_W5200.
+ *
+ * - <b> Basic I/O function </b> \n
+ *   WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n
+ *
+ * - \ref Common_register_group_W5200 <b>access functions</b> \n
+ * 	-# @b Mode \n
+ *    getMR(), setMR()
+ * 	-# @b Interrupt \n
+ *    getIR(), setIR(), getIMR(), setIMR(), getIR2(), setIR2(), getIMR2(), setIMR2(), getINTLEVEL(), setINTLEVEL()
+ * 	-# <b> Network Information </b> \n
+ *    getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
+ * 	-# @b Retransmission \n
+ *    getRCR(), setRCR(), getRTR(), setRTR()
+ * 	-# @b PPPoE \n
+ *    getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC()
+ * 	-# @b etc. \n
+ *    getPHYSTATUS(), getVERSIONR() \n\n
+ *
+ * - \ref Socket_register_group_W5200 <b>access functions</b> \n
+ *   -# <b> SOCKET control</b> \n
+ *      getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR()
+ *   -# <b> SOCKET information</b> \n
+ *      getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
+ *      getSn_MSSR(), setSn_MSSR()
+ *   -# <b> SOCKET communication </b> \n
+ *      getSn_RXMEM_SIZE(), setSn_RXMEM_SIZE(), getSn_TXMEM_SIZE(), setSn_TXMEM_SIZE() \n
+ *      getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
+ *      getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
+ *      getSn_TX_FSR(), getSn_RX_RSR()
+ *   -# <b> IP header field </b> \n
+ *      getSn_FRAG(), setSn_FRAG(),  getSn_TOS(), setSn_TOS() \n
+ *      getSn_TTL(), setSn_TTL()
+ */
+ 
+/**
+ * @defgroup Common_register_group_W5200 Common register
+ * @ingroup WIZCHIP_register_W5200
+ * @brief Common register group\n
+ * It set the basic for the networking\n
+ * It set the configuration such as interrupt, network information, ICMP, etc.
+ * @details
+ * @sa MR : Mode register.
+ * @sa GAR, SUBR, SHAR, SIPR
+ * @sa INTLEVEL, IR, _IMR_, IR2, IMR2 : Interrupt.
+ * @sa _RTR_, _RCR_ : Data retransmission.
+ * @sa PTIMER, PMAGIC : PPPoE.
+ * @sa PHYSTATUS, VERSIONR : etc.
+ */
+
+
+ /**
+ * @defgroup Socket_register_group_W5200 Socket register
+ * @ingroup WIZCHIP_register_W5200
+ * @brief Socket register group\n
+ * Socket register configures and control SOCKETn which is necessary to data communication.
+ * @details
+ * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control
+ * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
+ * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_FRAG : Internet protocol.
+ * @sa Sn_RXMEM_SIZE, Sn_TXMEM_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
+ */
+ 
+ /**
+ * @defgroup Basic_IO_function_W5200 Basic I/O function
+ * @ingroup WIZCHIP_IO_Functions_W5200
+ * @brief These are basic input/output functions to read values from register or write values to register.
+ */
+
+/**
+ * @defgroup Common_register_access_function_W5200 Common register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5200
+ * @brief These are functions to access <b>common registers</b>.
+ */
+ 
+/**
+ * @defgroup Socket_register_access_function_W5200 Socket register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5200
+ * @brief These are functions to access <b>socket registers</b>.
+ */
+ 
+ //-----------------------------------------------------------------------------------
+
+//----------------------------- W5200 Common Registers IOMAP -----------------------------
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Mode Register address(R/W)\n
+ * \ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
+ * @details Each bit of \ref MR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>AI</td> <td>IND</td> </tr>
+ * </table>
+ * - \ref MR_RST		 	: Reset
+ * - \ref MR_WOL       		: Wake on LAN
+ * - \ref MR_PB         	: Ping block
+ * - \ref MR_PPPOE      	: PPPoE mode
+ * - \ref MR_AI         	: Address Auto-Increment in Indirect Bus Interface
+ * - \ref MR_IND         	: Indirect Bus Interface mode
+ */
+#if  (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) 
+   #define MR					(_WIZCHIP_IO_BASE_ + (0x0000))  // Mode
+#else   
+   #define MR					(_W5200_IO_BASE_ + (0x0000))  // Mode
+#endif   
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Gateway IP Register address(R/W)
+ * @details \ref GAR configures the default gateway address.
+ */
+#define GAR     			(_W5200_IO_BASE_ + (0x0001))  // GW Address
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Subnet mask Register address(R/W)
+ * @details \ref SUBR configures the subnet mask address.
+ */
+#define SUBR    			(_W5200_IO_BASE_ + (0x0005)) // SN Mask Address
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Source MAC Register address(R/W)
+ * @details \ref SHAR configures the source hardware address.
+ */
+#define SHAR    			(_W5200_IO_BASE_ + (0x0009)) // Source Hardware Address
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Source IP Register address(R/W)
+ * @details \ref SIPR configures the source IP address.
+ */
+#define SIPR    			(_W5200_IO_BASE_ + (0x000F)) // Source IP Address
+
+// Reserved					(_W5200_IO_BASE_ + (0x0013))
+// Reserved					(_W5200_IO_BASE_ + (0x0014))
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Interrupt Register(R/W)
+ * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host.
+ * If \ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
+ * Each bit of \ref IR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>CONFLICT</td> <td>Reserved</td> <td>PPPoE</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr>
+ * </table>
+ * - \ref IR_CONFLICT : IP conflict
+ * - \ref IR_PPPoE	  : PPPoE connection close
+ */
+#define IR					(_W5200_IO_BASE_ + (0x0015)) // Interrupt
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Socket Interrupt Mask Register(R/W)
+ * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR2.
+ * When a bit of \ref _IMR_ is and the corresponding bit of \ref IR2 is  Interrupt will be issued.
+ * In other words, if a bit of \ref _IMR_, an interrupt will be not issued even if the corresponding bit of \ref IR2 is set
+ * @note  This Register is same operated as <b>SMIR<b> of W5100, W5300 and W5550.\n
+ *        So, \ref setSIMR() set a value to _IMR_ for integrating with ioLibrary
+ */
+#define _IMR_    			(_W5200_IO_BASE_ + (0x0016)) // Socket Interrupt Mask
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Timeout register address( 1 is 100us )(R/W)
+ * @details \ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of \ref _RTR_ is x07D0.
+ * And so the default timeout period is 200ms(100us X 2000). During the time configured by \ref _RTR_, W5200 waits for the peer response
+ * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
+ * If the peer does not respond within the \ref _RTR_ time, W5200 retransmits the packet or issues timeout.
+ */
+#define _RTR_     			(_W5200_IO_BASE_ + (0x0017)) // Retry Time
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Retry count register(R/W)
+ * @details \ref _RCR_ configures the number of time of retransmission.
+ * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (\ref Sn_IR_TIMEOUT = '1').
+ */
+#define _RCR_      			(_W5200_IO_BASE_ + (0x0019)) // Retry Count
+
+// Reserved					(_W5200_IO_BASE_ + (0x001A))
+// Reserved					(_W5200_IO_BASE_ + (0x001B))
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief PPP LCP Request Timer register  in PPPoE mode(R)
+ * @details \ref PATR notifies authentication method that has been agreed at the connection with
+ * PPPoE Server. W5200 supports two types of Authentication method - PAP and CHAP.
+ */
+#define PATR            (_W5200_IO_BASE_ + (0x001C))
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief PPP LCP Request Timer register  in PPPoE mode(R)
+ * @details \ref PPPALGO notifies authentication algorithm in PPPoE mode. For detailed information,
+ * please refer to PPPoE application note.
+ */
+#define PPPALGO  			(_W5200_IO_BASE_ + (0x001E)) // Authentication Algorithm in PPPoE
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief chip version register address(R)
+ * @details \ref VERSIONR always indicates the W5200 version as @b 0x03.
+ */
+#define VERSIONR			(_W5200_IO_BASE_ + (0x001F)) // Chip version
+
+// Reserved					(_W5200_IO_BASE_ + (0x0020))
+// Reserved					(_W5200_IO_BASE_ + (0x0021))
+// Reserved					(_W5200_IO_BASE_ + (0x0022))
+// Reserved					(_W5200_IO_BASE_ + (0x0023))
+// Reserved					(_W5200_IO_BASE_ + (0x0024))
+// Reserved					(_W5200_IO_BASE_ + (0x0025))
+// Reserved					(_W5200_IO_BASE_ + (0x0026))
+// Reserved					(_W5200_IO_BASE_ + (0x0027))
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief PPP LCP Request Timer register  in PPPoE mode(R)
+ * @details \ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
+ */
+#define PTIMER  			(_W5200_IO_BASE_ + (0x0028)) // PPP LCP RequestTimer
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief PPP LCP Magic number register  in PPPoE mode(R)
+ * @details \ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
+ */
+#define PMAGIC   			(_W5200_IO_BASE_ + (0x0029)) // PPP LCP Magic number
+
+// Reserved					(_W5200_IO_BASE_ + (0x002A))
+// Reserved					(_W5200_IO_BASE_ + (0x002B))
+// Reserved					(_W5200_IO_BASE_ + (0x002C))
+// Reserved					(_W5200_IO_BASE_ + (0x002D))
+// Reserved					(_W5200_IO_BASE_ + (0x002E))
+// Reserved					(_W5200_IO_BASE_ + (0x002F))
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Set Interrupt low level timer register address(R/W)
+ * @details \ref INTLEVEL configures the Interrupt Assert Time.
+ */
+#define INTLEVEL       	(_W5200_IO_BASE_ + (0x0030)) // Interrupt Low Level Timer
+
+// Reserved					(_W5200_IO_BASE_ + (0x0032))
+// Reserved					(_W5200_IO_BASE_ + (0x0033))
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Socket Interrupt Register(R/W)
+ * @details \ref IR2 indicates the interrupt status of Socket.\n
+ * Each bit of \ref IR2 be still until \ref Sn_IR is cleared by the host.\n
+ * If \ref Sn_IR is not equal to x00 the n-th bit of \ref IR2 is and INTn PIN is asserted until \ref IR2 is x00 */
+#define IR2	         	(_W5200_IO_BASE_ + (0x0034)) // Socket Interrupt
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief PHYSTATUS(R/W)
+ * @details \ref PHYSTATUS is the Register to indicate W5200 status of PHY.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>Reserved</td> <td>Reserved</td> <td>LINK</td> <td>POWERSAVE</td> <td>POWERDOWN</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr>
+ * </table>
+ * - \ref PHYSTATUS_LINK : Link Status Register[Read Only]
+ * - \ref PHYSTATUS_POWERSAVE : Power save mode of PHY[R/W]
+ * - \ref PHYSTATUS_POWERDOWN : Power down mode of PHY[R/W]
+ */
+#define PHYSTATUS       (_W5200_IO_BASE_ + (0x0035)) // PHY Status
+
+/**
+ * @ingroup Common_register_group_W5200
+ * @brief Interrupt mask register(R/W)
+ * @details \ref IMR2 is used to mask interrupts. Each bit of \ref _IMR_ corresponds to each bit of \ref IR.
+ * When a bit of \ref IMR2 is and the corresponding bit of \ref IR is  an interrupt will be issued. In other words,
+ * if a bit of \ref IMR2 is  an interrupt will not be issued even if the corresponding bit of \ref IR is \n\n
+ * Each bit of \ref IMR2 defined as the following.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>IM_IR7</td> <td>Reserved</td> <td>IM_IR5</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr>
+ * </table>
+ * - \ref IM_IR7 : IP Conflict Interrupt Mask
+ * - \ref IM_IR5 : PPPoE Close Interrupt Mask
+ * @note  This Register is same operated as <b>_IMR_<b> of W5100, W5300 and W5550.\n
+ *        So, \ref setIMR() set a value to IMR2 for integrating with ioLibrary
+ */
+#define IMR2     			(_W5200_IO_BASE_ + (0x0036)) // Interrupt Mask
+
+
+//----------------------------- W5200 Socket Registers -----------------------------
+
+//--------------------------- For Backward Compatibility ---------------------------
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief socket Mode register(R/W)
+ * @details \ref Sn_MR configures the option or protocol type of Socket n.\n\n
+ * Each bit of \ref Sn_MR defined as the following.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>MULTI</td> <td>MF</td> <td>ND/MC</td> <td>Reserved</td> <td>Protocol[3]</td> <td>Protocol[2]</td> <td>Protocol[1]</td> <td>Protocol[0]</td> </tr>
+ * </table>
+ * - \ref Sn_MR_MULTI	: Support UDP Multicasting
+ * - \ref Sn_MR_MF	    : Support MACRAW
+ * - \ref Sn_MR_ND		: No Delayed Ack(TCP) flag
+ * - \ref Sn_MR_MC   	: IGMP version used <b>in UDP mulitcasting</b>
+ * - <b>Protocol</b>
+ * <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ * </table>
+ * - <b>In case of Socket 0</b>
+ *  <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>1</td> <td>PPPoE</td>   </tr>
+ * </table> 
+ *	- \ref Sn_MR_MACRAW	: MAC LAYER RAW SOCK \n
+ *  - \ref Sn_MR_UDP		: UDP
+ *  - \ref Sn_MR_TCP		: TCP
+ *  - \ref Sn_MR_CLOSE	: Unused socket
+ *  @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR(sn)			(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0000)) // socket Mode register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Socket command register(R/W)
+ * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
+ * After W5200 accepts the command, the \ref Sn_CR register is automatically cleared to 0x00.
+ * Even though \ref Sn_CR is cleared to 0x00, the command is still being processed.\n
+ * To check whether the command is completed or not, please check the \ref Sn_IR or \ref Sn_SR.
+ * - \ref Sn_CR_OPEN 		: Initialize or open socket.
+ * - \ref Sn_CR_LISTEN 		: Wait connection request in TCP mode(<b>Server mode</b>)
+ * - \ref Sn_CR_CONNECT 	: Send connection request in TCP mode(<b>Client mode</b>)
+ * - \ref Sn_CR_DISCON 		: Send closing request in TCP mode.
+ * - \ref Sn_CR_CLOSE   	: Close socket.
+ * - \ref Sn_CR_SEND    	: Update TX buffer pointer and send data.
+ * - \ref Sn_CR_SEND_MAC	: Send data with MAC address, so without ARP process.
+ * - \ref Sn_CR_SEND_KEEP 	: Send keep alive message.
+ * - \ref Sn_CR_RECV		: Update RX buffer pointer and receive data.
+ * - <b>In case of S0_MR(P3:P0) = S0_MR_PPPoE</b>
+ *  <table>
+ * 		<tr>   <td><b>Value</b></td> <td><b>Symbol</b></td> <td><b>Description</b></td></tr>
+ * 		<tr>   <td>0x23</td> <td>PCON</td> <td>PPPoE connection begins by transmitting PPPoE discovery packet</td>  </tr>
+ * 		<tr>   <td>0x24</td> <td>PDISCON</td> <td>Closes PPPoE connection</td>  </tr>
+ * 		<tr>   <td>0x25</td> <td>PCR</td> <td>In each phase, it transmits REQ message.</td> </tr>
+ * 		<tr>   <td>0x26</td> <td>PCN</td> <td>In each phase, it transmits NAK message.</td> </tr>
+ * 		<tr>   <td>0x27</td> <td>PCJ</td> <td>In each phase, it transmits REJECT message.</td> </tr>
+ * </table> 
+ */
+#define Sn_CR(sn)			(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0001)) // channel Sn_CR register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Socket interrupt register(R)
+ * @details \ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
+ * When an interrupt occurs and the corresponding bit of \ref Sn_IMR is  the corresponding bit of \ref Sn_IR becomes \n
+ * In order to clear the \ref Sn_IR bit, the host should write the bit to \n
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>PRECV</td> <td>PFAIL</td> <td>PNEXT</td> <td>SEND_OK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr>
+ * </table>
+ * - \ref Sn_IR_PRECV : <b>PPP Receive Interrupt</b>
+ * - \ref Sn_IR_PFAIL : <b>PPP Fail Interrupt</b>
+ * - \ref Sn_IR_PNEXT : <b>PPP Next Phase Interrupt</b>
+ * - \ref Sn_IR_SENDOK : <b>SEND_OK Interrupt</b>
+ * - \ref Sn_IR_TIMEOUT : <b>TIMEOUT Interrupt</b>
+ * - \ref Sn_IR_RECV : <b>RECV Interrupt</b>
+ * - \ref Sn_IR_DISCON : <b>DISCON Interrupt</b>
+ * - \ref Sn_IR_CON : <b>CON Interrupt</b>
+ */
+#define Sn_IR(sn)			(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0002)) // channel interrupt register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Socket status register(R)
+ * @details \ref Sn_SR indicates the status of Socket n.\n
+ * The status of Socket n is changed by \ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
+ * @par Normal status
+ * - \ref SOCK_CLOSED 		: Closed
+ * - \ref SOCK_INIT   		: Initiate state
+ * - \ref SOCK_LISTEN    	: Listen state
+ * - \ref SOCK_ESTABLISHED 	: Success to connect
+ * - \ref SOCK_CLOSE_WAIT   : Closing state
+ * - \ref SOCK_UDP   		: UDP socket
+ * - \ref SOCK_MACRAW  		: MAC raw mode socket
+ *@par Temporary status during changing the status of Socket n.
+ * - \ref SOCK_SYNSENT   	: This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
+ * - \ref SOCK_SYNRECV    	: It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
+ * - \ref SOCK_FIN_WAIT		: Connection state
+ * - \ref SOCK_CLOSING		: Closing state
+ * - \ref SOCK_TIME_WAIT	: Closing state
+ * - \ref SOCK_LAST_ACK 	: Closing state
+ */
+#define Sn_SR(sn)			(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0003)) // channel status register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief source port register(R/W)
+ * @details \ref Sn_PORT configures the source port number of Socket n.
+ * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered.
+*/
+#define Sn_PORT(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0004)) // source port register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Peer MAC register address(R/W)
+ * @details \ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
+ * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
+ */
+#define Sn_DHAR(sn)     (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0006)) // Peer MAC register address
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Peer IP register address(R/W)
+ * @details \ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP client mode, it configures an IP address of TCP server before CONNECT command.
+ * In TCP server mode, it indicates an IP address of TCP client after successfully establishing connection.
+ * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
+ */
+#define Sn_DIPR(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x000C)) // Peer IP register address
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Peer port register address(R/W)
+ * @details \ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP clientmode, it configures the listen port number of TCP server before CONNECT command.
+ * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
+ * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
+ */
+#define Sn_DPORT(sn)    (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0010)) // Peer port register address
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
+ * @details \ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
+ */
+#define Sn_MSSR(sn)	   (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0012)) // Maximum Segment Size(Sn_MSSR0) register address
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief IP Protocol(PROTO) Register(R/W)
+ * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is
+ * valid only in IPRAW mode, and ignored in other modes.
+ */
+#define Sn_PROTO(sn)	   (_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0014)) // Protocol of IP Header field register in IP raw mode
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief IP Type of Service(TOS) Register(R/W)
+ * @details \ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TOS(sn)			(WIZCHIP_SREG_BLOCK(sn) + 0x0015) // IP Type of Service(TOS) Register 
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief IP Time to live(TTL) Register(R/W)
+ * @details \ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TTL(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0016)) // IP Time to live(TTL) Register 
+
+// Reserved					(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0017))
+// Reserved					(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0018))
+// Reserved					(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0019))
+// Reserved					(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001A))
+// Reserved					(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001B))
+// Reserved					(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001C))
+// Reserved					(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001D))
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Receive memory size register(R/W)
+ * @details \ref Sn_RXMEM_SIZE configures the RX buffer block size of Socket n.
+ * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
+ * If a different size is configured, the data cannot be normally received from a peer.
+ * Although Socket n RX Buffer Block size is initially configured to 2Kbytes,
+ * user can re-configure its size using \ref Sn_RXMEM_SIZE. The total sum of \ref Sn_RXMEM_SIZE can not be exceed 16Kbytes.
+ * When exceeded, the data reception error is occurred.
+ */
+#define Sn_RXMEM_SIZE(sn)	(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001E)) // Receive memory size reigster
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Transmit memory size register(R/W)
+ * @details \ref Sn_TXMEM_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
+ * If a different size is configured, the data can't be normally transmitted to a peer.
+ * Although Socket n TX Buffer Block size is initially configured to 2Kbytes,
+ * user can be re-configure its size using \ref Sn_TXMEM_SIZE. The total sum of \ref Sn_TXMEM_SIZE can not be exceed 16Kbytes.
+ * When exceeded, the data transmission error is occurred.
+ */
+#define Sn_TXMEM_SIZE(sn)	(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x001F)) // Transmit memory size reigster
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Transmit free memory size register(R)
+ * @details \ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by \ref Sn_TXMEM_SIZE.
+ * Data bigger than \ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
+ * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
+ * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
+ * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
+ */
+#define Sn_TX_FSR(sn)	(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0020)) // Transmit free memory size register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Transmit memory read pointer register address(R)
+ * @details \ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.
+ * After its initialization, it is auto-increased by SEND command.
+ * SEND command transmits the saved data from the current \ref Sn_TX_RD to the \ref Sn_TX_WR in the Socket n TX Buffer.
+ * After transmitting the saved data, the SEND command increases the \ref Sn_TX_RD as same as the \ref Sn_TX_WR.
+ * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_TX_RD(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0022)) // Transmit memory read pointer register address
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Transmit memory write pointer register address(R/W)
+ * @details \ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001), it is re-initialized while connecting with TCP.\n
+ * It should be read or be updated like as follows.\n
+ * 1. Read the starting address for saving the transmitting data.\n
+ * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
+ * 3. After saving the transmitting data, update \ref Sn_TX_WR to the increased value as many as transmitting data size.
+ * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
+ * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
+ */
+#define Sn_TX_WR(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0024)) // Transmit memory write pointer register address
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Received data size register(R)
+ * @details \ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
+ * \ref Sn_RX_RSR does not exceed the \ref Sn_RXMEM_SIZE and is calculated as the difference between
+ * Socket n RX Write Pointer (\ref Sn_RX_WR)and Socket n RX Read Pointer (\ref Sn_RX_RD)
+ */
+#define Sn_RX_RSR(sn)	(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0026)) // Received data size register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Read point of Receive memory(R/W)
+ * @details \ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
+ * 1. Read the starting save address of the received data.\n
+ * 2. Read data from the starting address of Socket n RX Buffer.\n
+ * 3. After reading the received data, Update \ref Sn_RX_RD to the increased value as many as the reading size.
+ * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
+ * update with the lower 16bits value ignored the carry bit.\n
+ * 4. Order RECV command is for notifying the updated \ref Sn_RX_RD to W5200.
+ */
+#define Sn_RX_RD(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x0028)) // Read point of Receive memory
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Write point of Receive memory(R)
+ * @details \ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
+ * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_RX_WR(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002A)) // Write point of Receive memory
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief socket interrupt mask register(R)
+ * @details \ref Sn_IMR masks the interrupt of Socket n.
+ * Each bit corresponds to each bit of \ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of \ref Sn_IMR is 
+ * the corresponding bit of \ref Sn_IR becomes  When both the corresponding bit of \ref Sn_IMR and \ref Sn_IR are and the n-th bit of \ref IR is 
+ * Host is interrupted by asserted INTn PIN to low.
+ */
+#define Sn_IMR(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002C)) // socket interrupt mask register
+
+/**
+ * @ingroup Socket_register_group_W5200
+ * @brief Fragment field value in IP header register(R/W)
+ * @details \ref Sn_FRAG configures the FRAG(Fragment field in IP header).
+ */
+#define Sn_FRAG(sn)		(_W5200_IO_BASE_ + WIZCHIP_SREG_BLOCK(sn) + (0x002D)) // frag field value in IP header register
+
+
+//----------------------------- W5200 Register values  -----------------------------
+
+/* MODE register values */
+/**
+ * @brief Reset
+ * @details If this bit is  All internal registers will be initialized. It will be automatically cleared as after S/W reset.
+ */
+#define MR_RST				0x80 ///< reset 
+
+/**
+ * @brief Wake on LAN
+ * @details 0 : Disable WOL mode\n
+ * 1 : Enable WOL mode\n
+ * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low.
+ * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (\ref Sn_MR) for opening Socket.)
+ * @note The magic packet over UDP supported by W5200 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and
+ * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode.
+ */
+#define MR_WOL				0x20 ///< Wake on Lan 
+
+/**
+ * @brief Ping block
+ * @details 0 : Disable Ping block\n
+ * 1 : Enable Ping block\n
+ * If the bit is  it blocks the response to a ping request.
+ */
+#define MR_PB				0x10 ///< ping block 
+
+/**
+ * @brief Enable PPPoE
+ * @details 0 : DisablePPPoE mode\n
+ * 1 : EnablePPPoE mode\n
+ * If you use ADSL, this bit should be '1'.
+ */
+#define MR_PPPOE			0x08 ///< enable pppoe 
+
+/**
+ * @brief Address Auto-Increment in Indirect Bus Interface
+ * @details 0 : Disable auto-increment \n
+ * 1 : Enable auto-incremente \n
+ * At the Indirect Bus Interface mode, if this bit is set as ��1��, the address will
+ * be automatically increased by 1 whenever read and write are performed.
+ */
+#define MR_AI				0x02 ///< auto-increment in indirect mode 
+
+/**
+ * @brief Indirect Bus Interface mode
+ * @details 0 : Disable Indirect bus Interface mode \n
+ * 1 : Enable Indirect bus Interface mode \n
+ * If this bit is set as ��1��, Indirect Bus Interface mode is set.
+ */
+#define MR_IND				0x01 ///< enable indirect mode 
+
+/* IR register values */
+/**
+ * @brief Check IP conflict.
+ * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
+ */
+#define IR_CONFLICT			0x80 ///< check ip confict 
+
+/**
+ * @brief Get the PPPoE close message.
+ * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
+ */
+#define IR_PPPoE			0x20 ///< get the PPPoE close message 
+
+/**
+ * @brief Link Status [Read Only]
+ * @details 0: Link down \n 1: Link up \n
+ */
+#define PHYSTATUS_LINK				0x20
+
+/**
+ * @brief Power save mode of PHY
+ * @details 0: Disable Power save mode \n 1: Enable Power save mode \n
+ */
+#define PHYSTATUS_POWERSAVE				0x10
+
+/**
+ * @brief Power down mode of PHY
+ * @details 0: Disable Power down mode \n 1: Enable Power down mode\n
+ */
+#define PHYSTATUS_POWERDOWN				0x08
+
+// Sn_MR values 
+/* Sn_MR Default values */
+/**
+ * @brief Unused socket
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_CLOSE			0x00 ///< unused socket 
+
+/**
+ * @brief TCP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_TCP			0x01 ///< TCP 
+
+/**
+ * @brief UDP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_UDP       0x02 ///< UDP 
+#define Sn_MR_IPRAW     0x03 ///< IP LAYER RAW SOCK 
+
+/**
+ * @brief MAC LAYER RAW SOCK
+ * @details This configures the protocol mode of Socket n.
+ * @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR_MACRAW		0x04 ///< MAC LAYER RAW SOCK 
+
+/**
+ * @brief PPPoE
+ * @details This configures the protocol mode of Socket n.
+ * @note PPPoE mode should be only used in Socket 0.
+ */
+#define Sn_MR_PPPOE			0x05 ///< PPPoE 
+
+/**
+ * @brief No Delayed Ack(TCP), Multicast flag
+ * @details 0 : Disable No Delayed ACK option\n
+ * 1 : Enable No Delayed ACK option\n
+ * This bit is applied only during TCP mode (P[3:0] = 001).\n
+ * When this bit is  It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
+ * When this bit is  It sends the ACK packet after waiting for the timeout time configured by \ref _RTR_.
+ */
+#define Sn_MR_ND			0x20 ///< No Delayed Ack(TCP) flag 
+
+/* Sn_MR Default values */
+/**
+ * @brief Support UDP Multicasting
+ * @details 0 : disable Multicasting\n
+ * 1 : enable Multicasting\n
+ * This bit is applied only during UDP mode(P[3:0] = 010).\n
+ * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
+ * before Socket n is opened by OPEN command of \ref Sn_CR.
+ */
+#define Sn_MR_MC			Sn_MR_ND ///< Select IGMP version 1(0) or 2(1) 
+
+/**
+ * @brief Multicast Blocking in \ref Sn_MR_MACRAW mode
+ * @details 0 : using IGMP version 2\n
+ * 1 : using IGMP version 1\n
+ * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = '1')
+ * It configures the version for IGMP messages (Join/Leave/Report).
+ */
+#define Sn_MR_MF			0x40 ///< Use MAC filter
+#define Sn_MR_MFEN      Sn_MR_MF
+
+/* Sn_MR Default values */
+/**
+ * @brief Support UDP Multicasting
+ * @details 0 : disable Multicasting\n
+ * 1 : enable Multicasting\n
+ * This bit is applied only during UDP mode(P[3:0] = 010).\n
+ * To use multicasting, \ref Sn_DIPR & \ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
+ * before Socket n is opened by OPEN command of \ref Sn_CR.
+ */
+#define Sn_MR_MULTI			0x80 ///< support multicating 
+
+/* Sn_CR values */
+/**
+ * @brief Initialize or open socket
+ * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
+ * The table below shows the value of \ref Sn_SR corresponding to \ref Sn_MR.\n
+ * <table>
+ *   <tr>  <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td>            		 </tr>
+ *   <tr>  <td>Sn_MR_CLOSE  (000)</td> <td>--</td>         	   		 </tr>
+ *   <tr>  <td>Sn_MR_TCP  (001)</td> <td>SOCK_INIT (0x13)</td>  		 </tr>
+ *   <tr>  <td>Sn_MR_UDP  (010)</td>  <td>SOCK_UDP (0x22)</td>  		 </tr>
+ *   <tr>  <td>S0_MR_IPRAW  (011)</td>  <td>SOCK_IPRAW (0x32)</td>  </tr>
+ *   <tr>  <td>S0_MR_MACRAW  (100)</td>  <td>SOCK_MACRAW (0x42)</td>  </tr>
+ *   <tr>  <td>S0_MR_PPPoE  (101)</td>  <td>SOCK_PPPoE (0x5F)</td>  </tr>
+ * </table>
+ */
+#define Sn_CR_OPEN			0x01 ///< initialize or open socket 
+
+/**
+ * @brief Wait connection request in TCP mode(Server mode)
+ * @details This is valid only in TCP mode (Sn_MR(P3:P0) = \ref Sn_MR_TCP).//
+ * In this mode, Socket n operates as a 'TCP server' and waits for connection-request (SYN packet) from any 'TCP client'.//
+ * The \ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.//
+ * When a 'TCP client' connection request is successfully established,
+ * the \ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes 
+ * But when a 'TCP client' connection request is failed, Sn_IR(3) becomes and the status of \ref Sn_SR changes to SOCK_CLOSED.
+ */
+#define Sn_CR_LISTEN		0x02 ///< wait connection request in tcp mode(Server mode) 
+
+/**
+ * @brief Send connection request in TCP mode(Client mode)
+ * @details  To connect, a connect-request (SYN packet) is sent to <b>TCP server</b>configured by \ref Sn_DIPR & Sn_DPORT(destination address & port).
+ * If the connect-request is successful, the \ref Sn_SR is changed to \ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
+ * The connect-request fails in the following three cases.\n
+ * 1. When a @b ARPTO occurs (\ref Sn_IR[3] = '1') because destination hardware address is not acquired through the ARP-process.\n
+ * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) ='1')\n
+ * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, \ref Sn_SR is changed to \ref SOCK_CLOSED.
+ * @note This is valid only in TCP mode and operates when Socket n acts as <b>TCP client</b>
+ */
+#define Sn_CR_CONNECT		0x04 ///< send connection request in tcp mode(Client mode) 
+
+/**
+ * @brief Send closing request in TCP mode
+ * @details Regardless of <b>TCP server</b>or <b>TCP client</b> the DISCON command processes the disconnect-process (<b>Active close</b>or <b>Passive close</b>.\n
+ * @par Active close
+ * it transmits disconnect-request(FIN packet) to the connected peer\n
+ * @par Passive close
+ * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
+ * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), \ref Sn_SR is changed to \ref SOCK_CLOSED.\n
+ * Otherwise, TCPTO occurs (Sn_IR(3)='1') and then \ref Sn_SR is changed to \ref SOCK_CLOSED.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_DISCON		0x08 ///< send closing reqeuset in tcp mode 
+
+/**
+ * @brief Close socket
+ * @details Sn_SR is changed to \ref SOCK_CLOSED.
+ */
+#define Sn_CR_CLOSE         0x10
+
+/**
+ * @brief Update TX buffer pointer and send data
+ * @details SEND transmits all the data in the Socket n TX buffer.\n
+ * For more details, please refer to Socket n TX Free Size Register (\ref Sn_TX_FSR), Socket n,
+ * TX Write Pointer Register(\ref Sn_TX_WR), and Socket n TX Read Pointer Register(\ref Sn_TX_RD).
+ */
+#define Sn_CR_SEND          0x20
+
+/**
+ * @brief Send data with MAC address, so without ARP process
+ * @details The basic operation is same as SEND.\n
+ * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
+ * But SEND_MAC transmits data without the automatic ARP-process.\n
+ * In this case, the destination hardware address is acquired from \ref Sn_DHAR configured by host, instead of APR-process.
+ * @note Valid only in UDP mode.
+ */
+#define Sn_CR_SEND_MAC      0x21
+
+/**
+ * @brief Send keep alive message
+ * @details It checks the connection status by sending 1byte keep-alive packet.\n
+ * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_SEND_KEEP     0x22
+
+/**
+ * @brief Update RX buffer pointer and receive data
+ * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (\ref Sn_RX_RD).\n
+ * For more details, refer to Socket n RX Received Size Register (\ref Sn_RX_RSR), Socket n RX Write Pointer Register (\ref Sn_RX_WR),
+ * and Socket n RX Read Pointer Register (\ref Sn_RX_RD).
+ */
+#define Sn_CR_RECV          0x40
+
+/**
+ * @brief PPPoE connection
+ * @details PPPoE connection begins by transmitting PPPoE discovery packet
+ */
+#define Sn_CR_PCON			0x23
+
+/**
+ * @brief Closes PPPoE connection
+ * @details Closes PPPoE connection
+ */		 
+#define Sn_CR_PDISCON		0x24		 
+
+/**
+ * @brief REQ message transmission
+ * @details In each phase, it transmits REQ message.
+ */
+#define Sn_CR_PCR			0x25		 
+
+/**
+ * @brief NAK massage transmission
+ * @details In each phase, it transmits NAK message.
+ */
+#define Sn_CR_PCN			0x26		
+
+/**
+ * @brief REJECT message transmission
+ * @details In each phase, it transmits REJECT message.
+ */
+#define Sn_CR_PCJ			0x27		
+
+/* Sn_IR values */
+/**
+ * @brief PPP Receive Interrupt
+ * @details PPP Receive Interrupts when the option which is not supported is received.
+ */
+#define Sn_IR_PRECV			0x80	
+
+/**
+ * @brief PPP Fail Interrupt
+ * @details PPP Fail Interrupts when PAP Authentication is failed.
+ */	
+#define Sn_IR_PFAIL			0x40		
+
+/**
+ * @brief PPP Next Phase Interrupt
+ * @details PPP Next Phase Interrupts when the phase is changed during ADSL connection process.
+ */
+#define Sn_IR_PNEXT			0x20		
+
+/**
+ * @brief SEND_OK Interrupt
+ * @details This is issued when SEND command is completed.
+ */
+#define Sn_IR_SENDOK		0x10 ///< complete sending 
+
+/**
+ * @brief TIMEOUT Interrupt
+ * @details This is issued when ARPTO or TCPTO occurs.
+ */
+#define Sn_IR_TIMEOUT		0x08 ///< assert timeout 
+
+/**
+ * @brief RECV Interrupt
+ * @details This is issued whenever data is received from a peer.
+ */
+#define Sn_IR_RECV          0x04
+
+/**
+ * @brief DISCON Interrupt
+ * @details This is issued when FIN or FIN/ACK packet is received from a peer.
+ */
+#define Sn_IR_DISCON        0x02
+
+/**
+ * @brief CON Interrupt
+ * @details This is issued one time when the connection with peer is successful and then \ref Sn_SR is changed to \ref SOCK_ESTABLISHED.
+ */
+#define Sn_IR_CON           0x01
+
+/* Sn_SR values */
+/**
+ * @brief Closed
+ * @details This indicates that Socket n is released.\n
+ * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to \ref SOCK_CLOSED regardless of previous status.
+ */
+#define SOCK_CLOSED			0x00 ///< closed 
+
+/**
+ * @brief Initiate state
+ * @details This indicates Socket n is opened with TCP mode.\n
+ * It is changed to \ref SOCK_INIT when Sn_MR(P[3:0]) = 001)and OPEN command is ordered.\n
+ * After \ref SOCK_INIT, user can use LISTEN /CONNECT command.
+ */
+#define SOCK_INIT 			0x13 ///< init state 
+
+/**
+ * @brief Listen state
+ * @details This indicates Socket n is operating as <b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer (<b>TCP client</b>).\n
+ * It will change to \ref SOCK_ESTABLISHED when the connection-request is successfully accepted.\n
+ * Otherwise it will change to \ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = '1').
+ */
+#define SOCK_LISTEN         0x14
+
+/**
+ * @brief Connection state
+ * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
+ * It is temporarily shown when \ref Sn_SR is changed from \ref SOCK_INIT to \ref SOCK_ESTABLISHED by CONNECT command.\n
+ * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to \ref SOCK_ESTABLISHED.\n
+ * Otherwise, it changes to \ref SOCK_CLOSED after TCPTO (\ref Sn_IR[TIMEOUT] = '1') is occurred.
+ */
+#define SOCK_SYNSENT        0x15
+
+/**
+ * @brief Connection state
+ * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
+ * If socket n sends the response (SYN/ACK  packet) to the peer successfully,  it changes to \ref SOCK_ESTABLISHED. \n
+ * If not, it changes to \ref SOCK_CLOSED after timeout occurs (\ref Sn_IR[TIMEOUT] = '1').
+ */
+#define SOCK_SYNRECV        0x16
+
+/**
+ * @brief Success to connect
+ * @details This indicates the status of the connection of Socket n.\n
+ * It changes to \ref SOCK_ESTABLISHED when the <b>TCP SERVER</b>processed the SYN packet from the <b>TCP CLIENT</b>during \ref SOCK_LISTEN, or
+ * when the CONNECT command is successful.\n
+ * During \ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
+ */
+#define SOCK_ESTABLISHED    0x17
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_FIN_WAIT       0x18
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_CLOSING        0x1A
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to \ref SOCK_CLOSED.
+ */
+#define SOCK_TIME_WAIT      0x1B
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
+ * This is half-closing status, and data can be transferred.\n
+ * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used.
+ */
+#define SOCK_CLOSE_WAIT     0x1C
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
+ * It changes to \ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs  (\ref Sn_IR[TIMEOUT] = '1').
+ */
+#define SOCK_LAST_ACK       0x1D
+
+/**
+ * @brief UDP socket
+ * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010).\n
+ * It changes to SOCK_UDP when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n
+ * Unlike TCP mode, data can be transfered without the connection-process.
+ */
+#define SOCK_UDP			0x22 ///< udp socket 
+
+/**
+* @brief IP raw mode socket
+ * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when Sn_MR (P3:P0) is
+ * Sn_MR_IPRAW and OPEN command is used.\n
+ * IP Packet can be transferred without a connection similar to the UDP mode.
+*/
+#define SOCK_IPRAW			0x32 ///< ip raw mode socket 
+
+/**
+ * @brief MAC raw mode socket
+ * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n
+ * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100)and OPEN command is ordered.\n
+ * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
+ */
+#define SOCK_MACRAW			0x42 ///< mac raw mode socket 
+
+/**
+ * @brief PPPoE mode socket
+ * @details It is the status that SOCKET0 is open as PPPoE mode. It is changed to SOCK_PPPoE in case of S0_CR=OPEN and S0_MR
+ * (P3:P0)=S0_MR_PPPoE.\n
+ * It is temporarily used at the PPPoE
+connection.
+ */
+#define SOCK_PPPOE			0x5F ///< pppoe socket 
+
+// IP PROTOCOL 
+#define IPPROTO_IP			0 ///< Dummy for IP 
+#define IPPROTO_ICMP		   1 ///< Control message protocol 
+#define IPPROTO_IGMP		   2 ///< Internet group management protocol 
+#define IPPROTO_GGP			3 ///< GW^2 (deprecated) 
+#define IPPROTO_TCP			6 ///< TCP 
+#define IPPROTO_PUP			12 ///< PUP 
+#define IPPROTO_UDP			17 ///< UDP 
+#define IPPROTO_IDP			22 ///< XNS idp 
+#define IPPROTO_ND			77 ///< UNOFFICIAL net disk protocol 
+#define IPPROTO_RAW			255 ///< Raw IP packet 
+
+/**
+ * @brief Enter a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n \n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * \sa WIZCHIP_CRITICAL_EXIT()
+ */
+#define WIZCHIP_CRITICAL_ENTER()    WIZCHIP.CRIS._enter()
+
+#ifdef _exit
+#undef _exit
+#endif
+
+/**
+ * @brief Exit a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n\n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * @sa WIZCHIP_CRITICAL_ENTER()
+ */
+#define WIZCHIP_CRITICAL_EXIT()     WIZCHIP.CRIS._exit()
+
+
+
+////////////////////////
+// Basic I/O Function //
+////////////////////////
+/**
+ * @ingroup Basic_IO_function_W5200
+ * @brief It reads 1 byte value from a register.
+ * @param AddrSel Register address
+ * @return The value of register
+ */
+uint8_t  WIZCHIP_READ (uint32_t AddrSel);
+
+/**
+ * @ingroup Basic_IO_function_W5200
+ * @brief It writes 1 byte value to a register.
+ * @param AddrSel Register address
+ * @param wb Write data
+ * @return void
+ */
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
+
+/**
+ * @ingroup Basic_IO_function_W5200
+ * @brief It reads sequence data from registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to read data
+ * @param len Data length
+ */
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5200
+ * @brief It writes sequence data to registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to write data
+ * @param len Data length
+ */
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+
+/////////////////////////////////
+// Common Register IO function //
+/////////////////////////////////
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set Mode Register
+ * @param (uint8_t)mr The value to be set.
+ * @sa getMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define setMR(mr) 	WIZCHIP_WRITE(MR,mr)
+#else 
+   #define setMR(mr)    (*((uint8_t*)MR) = mr)
+#endif
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get @ref MR.
+ * @return uint8_t. The value of Mode register.
+ * @sa setMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #define getMR() 		WIZCHIP_READ(MR)
+#else
+   #define getMR()      (*(uint8_t*)MR)
+#endif
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set @ref GAR.
+ * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
+ * @sa getGAR()
+ */
+#define setGAR(gar) \
+		WIZCHIP_WRITE_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get @ref GAR.
+ * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
+ * @sa setGAR()
+ */
+#define getGAR(gar) \
+		WIZCHIP_READ_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set @ref SUBR.
+ * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
+ * @note If subr is null pointer, set the backup subnet to SUBR. \n
+ *       If subr is 0.0.0.0, back up SUBR and clear it. \n
+ *       Otherwize, set subr to SUBR
+ * @sa getSUBR()
+ */
+#define setSUBR(subr) \
+   WIZCHIP_WRITE_BUF(SUBR, subr,4)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get @ref SUBR.
+ * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
+ * @sa setSUBR()
+ */
+#define getSUBR(subr) \
+		WIZCHIP_READ_BUF(SUBR, subr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set @ref SHAR.
+ * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
+ * @sa getSHAR()
+ */
+#define setSHAR(shar) \
+		WIZCHIP_WRITE_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get @ref SHAR.
+ * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
+ * @sa setSHAR()
+ */
+#define getSHAR(shar) \
+		WIZCHIP_READ_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set @ref SIPR.
+ * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
+ * @sa getSIPR()
+*/
+#define setSIPR(sipr) \
+		WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get @ref SIPR.
+ * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
+ * @sa setSIPR()
+ */
+#define getSIPR(sipr) \
+		WIZCHIP_READ_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref IR register
+ * @param (uint8_t)ir Value to set \ref IR register.
+ * @sa getIR()
+ */
+#define setIR(ir) \
+		WIZCHIP_WRITE(IR, (ir & 0xA0))
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref IR register
+ * @return uint8_t. Value of \ref IR register.
+ * @sa setIR()
+ */
+#define getIR() \
+		(WIZCHIP_READ(IR) & 0xA0)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref IMR2 register
+ * @param (uint8_t)imr Value to set @ref IMR2 register.
+ * @sa getIMR()
+ */
+//M20150410 : Replace _IMR_ with IMR2 for integrating with ioLibrary
+/*
+#define setIMR(imr) \
+		WIZCHIP_WRITE(_IMR_, imr)
+*/		
+#define setIMR(imr) \
+		WIZCHIP_WRITE(IMR2, imr & 0xA0)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref IMR2 register
+ * @return uint8_t. Value of @ref IMR2 register.
+ * @sa setIMR()
+ */
+//M20150410 : Replace _IMR_ with IMR2 for integrating with ioLibrary
+/*
+#define getIMR() \
+		WIZCHIP_READ(_IMR_)
+*/		
+#define getIMR() \
+		(WIZCHIP_READ(IMR2) & 0xA0)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref _RTR_ register
+ * @param (uint16_t)rtr Value to set @ref _RTR_ register.
+ * @sa getRTR()
+ */
+#define setRTR(rtr)   {\
+		WIZCHIP_WRITE(_RTR_,   (uint8_t)(rtr >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref _RTR_ register
+ * @return uint16_t. Value of @ref _RTR_ register.
+ * @sa setRTR()
+ */
+#define getRTR() \
+		(((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1)))
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref _RCR_ register
+ * @param (uint8_t)rcr Value to set @ref _RCR_ register.
+ * @sa getRCR()
+ */
+#define setRCR(rcr) \
+		WIZCHIP_WRITE(_RCR_, rcr)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref _RCR_ register
+ * @return uint8_t. Value of @ref _RCR_ register.
+ * @sa setRCR()
+ */
+#define getRCR() \
+		WIZCHIP_READ(_RCR_)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref PATR register
+ * @return uint16_t. Value to set \ref PATR register
+ */
+#define getPATR() \
+		(((uint16_t)WIZCHIP_READ(PATR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PATR,1)))
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref PPPALGO register
+ * @return uint8_t. Value to set \ref PPPALGO register
+ */
+#define getPPPALGO() \
+		WIZCHIP_READ(PPPALGO)
+
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref VERSIONR register
+ * @return uint8_t. Value to set \ref VERSIONR register
+ */
+#define getVERSIONR() \
+		WIZCHIP_READ(VERSIONR)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref PTIMER register
+ * @param (uint8_t)ptimer Value to set \ref PTIMER register.
+ * @sa getPTIMER()
+ */
+#define setPTIMER(ptimer) \
+		WIZCHIP_WRITE(PTIMER, ptimer)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref PTIMER register
+ * @return uint8_t. Value of @ref PTIMER register.
+ * @sa setPTIMER()
+ */
+#define getPTIMER() \
+		WIZCHIP_READ(PTIMER)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref PMAGIC register
+ * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
+ * @sa getPMAGIC()
+ */
+#define setPMAGIC(pmagic) \
+		WIZCHIP_WRITE(PMAGIC, pmagic)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref PMAGIC register
+ * @return uint8_t. Value of @ref PMAGIC register.
+ * @sa setPMAGIC()
+ */
+#define getPMAGIC() \
+		WIZCHIP_READ(PMAGIC)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set @ref INTLEVEL register
+ * @param (uint16_t)intlevel Value to set @ref INTLEVEL register.
+ * @sa getINTLEVEL()
+ */
+#define setINTLEVEL(intlevel)  {\
+		WIZCHIP_WRITE(INTLEVEL,   (uint8_t)(intlevel >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \
+	}
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get @ref INTLEVEL register
+ * @return uint16_t. Value of @ref INTLEVEL register.
+ * @sa setINTLEVEL()
+ */
+#define getINTLEVEL() \
+		(((uint16_t)WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1)))
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref IR2 register
+ * @param (uint8_t)ir2 Value to set \ref IR2 register.
+ * @sa getIR2()
+ */
+#define setIR2(ir2) \
+		WIZCHIP_WRITE(IR2, ir2)
+#define  setSIR(ir2)    setIR2(ir2)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref IR2 register
+ * @return uint8_t. Value of \ref IR2 register.
+ * @sa setIR2()
+ */
+#define getIR2() \
+	WIZCHIP_READ(IR2)
+#define  getSIR()       getIR2()
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref PHYSTATUS register
+ * @return uint8_t. Value to set \ref PHYSTATUS register.
+ */
+#define getPHYSTATUS() \
+		WIZCHIP_READ(PHYSTATUS)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Set \ref _IMR_ register
+ * @param (uint8_t)imr2 Value to set \ref IMR2 register.
+ * @sa getIMR2()
+ * @note If possible, Don't use this function. Instead, Use setSIMR() for compatible with ioLibrary.
+ */
+ //M20150410 : Replace IMR2 with _IMR_ for integrating with ioLibrary
+/*
+#define setIMR2(imr2) \
+		WIZCHIP_WRITE(IMR2, (imr2 & 0xA0))
+*/		
+#define setIMR2(imr2) \
+		WIZCHIP_WRITE(_IMR_, imr2)
+#define  setSIMR(imr2)  setIMR2(imr2)
+
+/**
+ * @ingroup Common_register_access_function_W5200
+ * @brief Get \ref _IMR_ register
+ * @return uint8_t. Value of \ref IMR2 register.
+ * @sa setIMR2()
+ */
+ //M20150410 : Replace IMR2 with _IMR_ for integrating with ioLibrary
+/*
+#define getIMR2() \
+		(WIZCHIP_READ(IMR2) & 0xA0)
+*/		
+#define getIMR2() \
+		WIZCHIP_READ(_IMR_)
+#define getSIMR()      getIMR2()
+///////////////////////////////////
+// Socket N register I/O function //
+///////////////////////////////////
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_MR register
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ * @param mr Value to set @ref Sn_MR
+ * @sa getSn_MR()
+ */
+#define setSn_MR(sn, mr) \
+		WIZCHIP_WRITE(Sn_MR(sn),mr)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_MR register
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b> expect <b>bit 4</b>.
+ * @return Value of @ref Sn_MR.
+ * @sa setSn_MR()
+ */
+#define getSn_MR(sn) \
+	WIZCHIP_READ(Sn_MR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)cr Value to set @ref Sn_CR
+ * @sa getSn_CR()
+ */
+#define setSn_CR(sn, cr) \
+		WIZCHIP_WRITE(Sn_CR(sn), cr)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_CR.
+ * @sa setSn_CR()
+ */
+#define getSn_CR(sn) \
+		WIZCHIP_READ(Sn_CR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)ir Value to set @ref Sn_IR
+ * @sa getSn_IR()
+ */
+#define setSn_IR(sn, ir) \
+		WIZCHIP_WRITE(Sn_IR(sn), ir)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_IR.
+ * @sa setSn_IR()
+ */
+#define getSn_IR(sn) \
+		WIZCHIP_READ(Sn_IR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)imr Value to set @ref Sn_IMR
+ * @sa getSn_IMR()
+*/
+#define setSn_IMR(sn, imr) \
+		WIZCHIP_WRITE(Sn_IMR(sn), imr)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_IMR.
+ * @sa setSn_IMR()
+ */
+#define getSn_IMR(sn) \
+		WIZCHIP_READ(Sn_IMR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_SR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_SR.
+ */
+#define getSn_SR(sn) \
+		WIZCHIP_READ(Sn_SR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)port Value to set @ref Sn_PORT.
+ * @sa getSn_PORT()
+ */
+#define setSn_PORT(sn, port)  { \
+		WIZCHIP_WRITE(Sn_PORT(sn),   (uint8_t)(port >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_PORT.
+ * @sa setSn_PORT()
+ */
+#define getSn_PORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa getSn_DHAR()
+ */
+#define setSn_DHAR(sn, dhar) \
+		WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa setSn_DHAR()
+ */
+#define getSn_DHAR(sn, dhar) \
+		WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
+ * @sa getSn_DIPR()
+ */
+#define setSn_DIPR(sn, dipr) \
+		WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
+ * @sa SetSn_DIPR()
+ */
+#define getSn_DIPR(sn, dipr) \
+		WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)dport Value to set @ref Sn_DPORT
+ * @sa getSn_DPORT()
+ */
+#define setSn_DPORT(sn, dport) { \
+		WIZCHIP_WRITE(Sn_DPORT(sn),   (uint8_t) (dport>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t)  dport); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_DPORT.
+ * @sa setSn_DPORT()
+ */
+#define getSn_DPORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)mss Value to set @ref Sn_MSSR
+ * @sa setSn_MSSR()
+ */
+#define setSn_MSSR(sn, mss) { \
+		WIZCHIP_WRITE(Sn_MSSR(sn),   (uint8_t)(mss>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_MSSR.
+ * @sa setSn_MSSR()
+ */
+#define getSn_MSSR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_PROTO register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)proto Value to set \ref Sn_PROTO
+ * @sa getSn_PROTO()
+ */
+//M20150601 : Fixed Wrong Register address
+/*
+#define setSn_PROTO(sn, proto) \
+		WIZCHIP_WRITE(Sn_TOS(sn), tos)
+*/
+#define setSn_PROTO(sn, proto) \
+		WIZCHIP_WRITE(Sn_PROTO(sn), proto)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_PROTO register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_PROTO.
+ * @sa setSn_PROTO()
+ */
+//M20150601 : Fixed Wrong Register address
+/*
+#define getSn_PROTO(sn) \
+		WIZCHIP_READ(Sn_TOS(sn))
+*/
+#define getSn_PROTO(sn) \
+		WIZCHIP_READ(Sn_PROTO(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)tos Value to set @ref Sn_TOS
+ * @sa getSn_TOS()
+ */
+#define setSn_TOS(sn, tos) \
+		WIZCHIP_WRITE(Sn_TOS(sn), tos)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @return uint8_t. Value of Sn_TOS.
+ * @sa setSn_TOS()
+ */
+#define getSn_TOS(sn) \
+		WIZCHIP_READ(Sn_TOS(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @param (uint8_t)ttl Value to set @ref Sn_TTL
+ * @sa getSn_TTL()
+ */
+#define setSn_TTL(sn, ttl) \
+		WIZCHIP_WRITE(Sn_TTL(sn), ttl)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @return uint8_t. Value of @ref Sn_TTL.
+ * @sa setSn_TTL()
+ */
+#define getSn_TTL(sn) \
+		WIZCHIP_READ(Sn_TTL(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_RXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @param (uint8_t)rxmemsize Value to set \ref Sn_RXMEM_SIZE
+ * @sa getSn_RXMEM_SIZE()
+ */
+#define setSn_RXMEM_SIZE(sn, rxmemsize) \
+		WIZCHIP_WRITE(Sn_RXMEM_SIZE(sn),rxmemsize)
+
+#define  setSn_RXBUF_SIZE(sn,rxmemsize) setSn_RXMEM_SIZE(sn,rxmemsize)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_RXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_RXMEM.
+ * @sa setSn_RXMEM_SIZE()
+ */
+#define getSn_RXMEM_SIZE(sn) \
+		WIZCHIP_READ(Sn_RXMEM_SIZE(sn))
+
+#define  getSn_RXBUF_SIZE(sn) getSn_RXMEM_SIZE(sn)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_TXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)txmemsize Value to set \ref Sn_TXMEM_SIZE
+ * @sa getSn_TXMEM_SIZE()
+ */
+#define setSn_TXMEM_SIZE(sn, txmemsize) \
+		WIZCHIP_WRITE(Sn_TXMEM_SIZE(sn), txmemsize)
+
+#define  setSn_TXBUF_SIZE(sn, txmemsize) setSn_TXMEM_SIZE(sn,txmemsize)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_TXMEM_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_TXMEM_SIZE.
+ * @sa setSn_TXMEM_SIZE()
+ */
+#define getSn_TXMEM_SIZE(sn) \
+		WIZCHIP_READ(Sn_TXMEM_SIZE(sn))
+
+#define  getSn_TXBUF_SIZE(sn) getSn_TXMEM_SIZE(sn)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_TX_FSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_FSR.
+ */
+uint16_t getSn_TX_FSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_TX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_RD.
+ */
+#define getSn_TX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
+ * @sa GetSn_TX_WR()
+ */
+#define setSn_TX_WR(sn, txwr) { \
+		WIZCHIP_WRITE(Sn_TX_WR(sn),   (uint8_t)(txwr>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \
+		}
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_TX_WR.
+ * @sa setSn_TX_WR()
+ */
+#define getSn_TX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_RX_RSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_RX_RSR.
+ */
+uint16_t getSn_RX_RSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
+ * @sa getSn_RX_RD()
+ */
+#define setSn_RX_RD(sn, rxrd) { \
+		WIZCHIP_WRITE(Sn_RX_RD(sn),   (uint8_t)(rxrd>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_RX_RD.
+ * @sa setSn_RX_RD()
+ */
+#define getSn_RX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_RX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)rxwr Value to set \ref Sn_RX_WR
+ * @sa getSn_RX_WR()
+ */
+#define setSn_RX_WR(sn, rxwr) { \
+		WIZCHIP_WRITE(Sn_RX_WR(sn),   (uint8_t)(rxwr>>8)); \
+	   WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1), (uint8_t) rxwr); \
+	}
+
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_RX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_RX_WR.
+ */
+#define getSn_RX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)imr Value to set \ref Sn_IMR
+ * @sa getSn_IMR()
+ */
+#define setSn_IMR(sn ,imr) \
+		WIZCHIP_WRITE(Sn_IMR(sn), imr)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_IMR.
+ * @sa setSn_IMR()
+ */
+#define getSn_IMR(sn) \
+		WIZCHIP_READ(Sn_IMR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Set @ref Sn_FRAG register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint16_t)frag Value to set \ref Sn_FRAG
+ * @sa getSn_FRAG()
+ */
+#define setSn_FRAG(sn, frag) { \
+		WIZCHIP_WRITE(Sn_FRAG(sn),  (uint8_t)(frag >>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get @ref Sn_FRAG register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of @ref Sn_FRAG.
+ * @sa setSn_FRAG()
+ */
+#define getSn_FRAG(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get the max RX buffer size of socket sn
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Max buffer size
+ */
+#define getSn_RxMAX(sn) \
+		((uint16_t)getSn_RXMEM_SIZE(sn) << 10)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get the max TX buffer size of socket sn
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Max buffer size
+ */
+#define getSn_TxMAX(sn) \
+		((uint16_t)getSn_TXMEM_SIZE(sn) << 10)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get the mask of socket sn RX buffer.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Mask value
+ */
+#define getSn_RxMASK(sn) \
+		((uint16_t)getSn_RxMAX(sn) - 1)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get the mask of socket sn TX buffer
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Mask value
+ */
+#define getSn_TxMASK(sn) \
+		((uint16_t)getSn_TxMAX(sn) - 1)
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get the base address of socket sn RX buffer.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n RX buffer base address.
+ */
+uint16_t getSn_RxBASE(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5200
+ * @brief Get the base address of socket sn TX buffer.
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint16_t. Value of Socket n TX buffer base address.
+ */
+uint16_t getSn_TxBASE(uint8_t sn);
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+/**
+ * @ingroup Basic_IO_function_W5200
+ * @brief It copies data to internal TX memory
+ *
+ * @details This function reads the Tx write pointer register and after that,
+ * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory
+ * and updates the Tx write pointer register.
+ * This function is being called by send() and sendto() function also.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param wizdata Pointer buffer to write data
+ * @param len Data length
+ * @sa wiz_recv_data()
+ */
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5200
+ * @brief It copies data to your buffer from internal RX memory
+ *
+ * @details This function read the Rx read pointer register and after that,
+ * it copies the received data from internal RX memory
+ * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes.
+ * This function is being called by recv() also.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param wizdata Pointer buffer to read data
+ * @param len Data length
+ * @sa wiz_send_data()
+ */
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5200
+ * @brief It discard the received data in RX memory.
+ * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param len Data length
+ */
+void wiz_recv_ignore(uint8_t sn, uint16_t len);
+
+/// \cond DOXY_APPLY_CODE
+#endif
+/// \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_W5200_H_
+
+
+

+ 225 - 0
lib/ioLibrary_Driver/Ethernet/W5300/w5300.c

@@ -0,0 +1,225 @@
+//*****************************************************************************
+//
+//! \file w5300.h
+//! \brief W5300 HAL implement File.
+//! \version 1.0.0
+//! \date 2015/05/01
+//! \par  Revision history
+//!       <2015/05/01> 1st Released for integrating with ioLibrary 
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2015, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include "wizchip_conf.h"
+
+#if _WIZCHIP_ == 5300
+
+   extern uint8_t sock_remained_byte[_WIZCHIP_SOCK_NUM_];
+   extern uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_];
+
+
+/***********************
+ * Basic I/O  Function *
+ ***********************/
+ 
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint16_t wb )
+{
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
+   #if(_WIZCHIP_IO_BUS_WIDTH_ == 8)
+      WIZCHIP.IF.BUS._write_data(AddrSel,  (uint8_t)(wb>>8));
+      WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(AddrSel,1),(uint8_t)wb);
+   #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
+      WIZCHIP.IF.BUS._write_data(AddrSel,  wb);   
+   #else
+      #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
+   #endif
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+   #if(_WIZCHIP_IO_BUS_WIDTH_ == 8)
+      WIZCHIP.IF.BUS._write_data(IDM_AR,                      (uint8_t)(AddrSel >> 8));
+      WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_AR,1),(uint8_t)AddrSel);
+      WIZCHIP.IF.BUS._write_data(IDM_DR,(uint8_t)(wb>>8));
+      WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_DR,1),(uint8_t)wb);         
+   #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
+      WIZCHIP.IF.BUS._write_data(IDM_AR, (uint16_t)AddrSel);
+      WIZCHIP.IF.BUS._write_data(IDM_DR, wb);
+   #else
+      #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
+   #endif
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5300. !!!"
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+uint16_t WIZCHIP_READ(uint32_t AddrSel)
+{
+   uint16_t ret;
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+#if ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_) )
+   #if (_WIZCHIP_IO_BUS_WIDTH_ == 8)
+      ret = (((uint16_t)WIZCHIP.IF.BUS._read_data(AddrSel)) << 8) | 
+            (((uint16_t)WIZCHIP.IF.BUS._read_data(WIZCHIP_OFFSET_INC(AddrSel,1))) & 0x00FF) ;   
+   #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
+      ret = WIZCHIP.IF.BUS._read_data(AddrSel);
+   #else
+      #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
+   #endif         
+#elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) )
+   #if(_WIZCHIP_IO_BUS_WIDTH_ == 8)
+      WIZCHIP.IF.BUS._write_data(IDM_AR,                      (uint8_t)(AddrSel >> 8));
+      WIZCHIP.IF.BUS._write_data(WIZCHIP_OFFSET_INC(IDM_AR,1),(uint8_t)AddrSel);
+      ret = (((uint16_t)WIZCHIP.IF.BUS._read_data(IDM_DR)) << 8) | 
+            (((uint16_t)WIZCHIP.IF.BUS._read_data(WIZCHIP_OFFSET_INC(IDM_DR,1))) & 0x00FF);
+   #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
+      WIZCHIP.IF.BUS._write_data(IDM_AR, (uint16_t)AddrSel);
+      ret = WIZCHIP.IF.BUS._read_data(IDM_DR);
+   #else
+      #error "Abnoraml _WIZCHIP_IO_BUS_WIDTH_. Should be 8 or 16"
+   #endif
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_ in W5300. !!!"
+#endif
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+   return ret;
+}
+
+
+void setTMSR(uint8_t sn,uint8_t tmsr)
+{
+   uint16_t tmem;
+   tmem = WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE)));
+   if(sn & 0x01)  tmem = (tmem & 0xFF00) | (((uint16_t)tmsr ) & 0x00FF) ;
+   else tmem =  (tmem & 0x00FF) | (((uint16_t)tmsr) << 8) ;
+   WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE)),tmem);
+}
+   
+uint8_t getTMSR(uint8_t sn)
+{
+   if(sn & 0x01)
+      return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE))) & 0x00FF);
+   return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(TMS01R, (sn & 0xFE))) >> 8);
+}
+
+void setRMSR(uint8_t sn,uint8_t rmsr)
+{
+   uint16_t rmem;
+   rmem = WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE)));
+   if(sn & 0x01)  rmem = (rmem & 0xFF00) | (((uint16_t)rmsr ) & 0x00FF) ;
+   else rmem =  (rmem & 0x00FF) | (((uint16_t)rmsr) << 8) ;
+   WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE)),rmem);
+}
+   
+uint8_t getRMSR(uint8_t sn)
+{
+   if(sn & 0x01)
+      return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE))) & 0x00FF);
+   return (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(RMS01R, (sn & 0xFE))) >> 8);
+}
+
+uint32_t getSn_TX_FSR(uint8_t sn)
+{
+   uint32_t free_tx_size=0;
+   uint32_t free_tx_size1=1;
+   while(1)
+   {
+      free_tx_size = (((uint32_t)WIZCHIP_READ(Sn_TX_FSR(sn))) << 16) | 
+                     (((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),2))) & 0x0000FFFF);                           // read
+      if(free_tx_size == free_tx_size1) break;  // if first == sencond, Sn_TX_FSR value is valid.                                                          
+      free_tx_size1 = free_tx_size;             // save second value into first                                                   
+   }                                                                       
+   return free_tx_size;                                                    
+}                                                                          
+
+uint32_t getSn_RX_RSR(uint8_t sn)
+{
+   uint32_t received_rx_size=0;
+   uint32_t received_rx_size1=1;
+   while(1)
+   {
+      received_rx_size = (((uint32_t)WIZCHIP_READ(Sn_RX_RSR(sn))) << 16) | 
+                         (((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),2))) & 0x0000FFFF);
+      if(received_rx_size == received_rx_size1) break;                                                                         
+      received_rx_size1 = received_rx_size;                                      // if first == sencond, Sn_RX_RSR value is valid.
+   }                                                                             // save second value into first                
+   return received_rx_size + (uint32_t)((sock_pack_info[sn] & 0x02) ? 1 : 0);   
+}
+
+
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint32_t len)
+{
+   uint32_t i = 0;
+   if(len == 0)  return;
+   
+   for(i = 0; i < len ; i += 2)
+      setSn_TX_FIFOR(sn, (((uint16_t)wizdata[i]) << 8) | (((uint16_t)wizdata[i+1]) & 0x00FF))
+}
+
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint32_t len)
+{
+   uint16_t rd = 0;
+   uint32_t i = 0;
+   
+   if(len == 0) return;
+      
+   for(i = 0; i < len; i++)
+   {
+      if((i & 0x01)==0)
+      {
+         rd = getSn_RX_FIFOR(sn);
+         wizdata[i]   = (uint8_t)(rd >> 8);
+      }
+      else  wizdata[i] = (uint8_t)rd;  // For checking the memory access violation
+   }
+   sock_remained_byte[sn] = (uint8_t)rd; // back up the remaind fifo byte.
+}
+
+void wiz_recv_ignore(uint8_t sn, uint32_t len)
+{
+   uint32_t i = 0;
+   for(i = 0; i < len ; i += 2) getSn_RX_FIFOR(sn);
+}
+
+
+#endif

+ 2336 - 0
lib/ioLibrary_Driver/Ethernet/W5300/w5300.h

@@ -0,0 +1,2336 @@
+#ifndef	_W5300_H_
+#define	_W5300_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//*****************************************************************************
+//
+//! \file w5300.h
+//! \brief W5300 HAL Header File.
+//! \version 1.0.0
+//! \date 2015/05/01
+//! \par  Revision history
+//!       <2015/05/01> 1st Released for integrating with ioLibrary 
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2015, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include <stdint.h>
+#include "wizchip_conf.h"
+
+/// \cond DOXY_APPLY_CODE
+#if   (_WIZCHIP_ == 5300)
+/// \endcond
+
+#define _WIZCHIP_SN_BASE_  (0x0200)
+#define _WIZCHIP_SN_SIZE_  (0x0040)
+
+
+#define WIZCHIP_CREG_BLOCK      	      0x00   ///< Common register block
+#define WIZCHIP_SREG_BLOCK(N)    	   (_WIZCHIP_SN_BASE_+ _WIZCHIP_SN_SIZE_*N) ///< Socket N register block
+
+#define WIZCHIP_OFFSET_INC(ADDR, N)    (ADDR + N) ///< Increase offset address
+
+#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_DIR_)
+   #define _W5300_IO_BASE_     _WIZCHIP_IO_BASE_
+#elif (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_)
+	#define IDM_AR             ((_WIZCHIP_IO_BASE_ + 0x0002))  ///< Indirect mode address register
+	#define IDM_DR             ((_WIZCHIP_IO_BASE_ + 0x0004))  ///< Indirect mode data register
+	#define _W5300_IO_BASE_    0x0000
+#elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)
+   #error "Unkonw _WIZCHIP_IO_MODE_"
+#endif
+
+///////////////////////////////////////
+// Definition For Legacy Chip Driver //
+///////////////////////////////////////
+#define IINCHIP_READ(ADDR)                WIZCHIP_READ(ADDR)               ///< The defined for legacy chip driver
+#define IINCHIP_WRITE(ADDR,VAL)           WIZCHIP_WRITE(ADDR,VAL)          ///< The defined for legacy chip driver
+//#define IINCHIP_READ_BUF(ADDR,BUF,LEN)    WIZCHIP_READ_BUF(ADDR,BUF,LEN)   ///< The defined for legacy chip driver
+//#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN)   WIZCHIP_WRITE(ADDR,BUF,LEN)      ///< The defined for legacy chip driver
+
+//--------------------------  defgroup ---------------------------------
+/**
+ * @defgroup W5300 W5300
+ *
+ * @brief WHIZCHIP register defines and I/O functions of @b W5300.
+ *
+ * - @ref WIZCHIP_register_W5300 : @ref Common_register_group_W5300 and @ref Socket_register_group_W5300
+ * - @ref WIZCHIP_IO_Functions_W5300 : @ref Basic_IO_function_W5300, @ref Common_register_access_function_W5300 and @ref Socket_register_access_function_W5300
+ */
+ 
+ 
+/**
+ * @defgroup WIZCHIP_register_W5300 WIZCHIP register
+ * @ingroup W5300
+ *
+ * @brief WHIZCHIP register defines register group of @b W5300.
+ *
+ * - @ref Common_register_group_W5300 : Common register group
+ * - @ref Socket_register_group_W5300 : \c SOCKET n register group
+ */
+
+
+/**
+ * @defgroup WIZCHIP_IO_Functions_W5300 WIZCHIP I/O functions
+ * @ingroup W5300
+ *
+ * @brief This supports the basic I/O functions for @ref WIZCHIP_register_W5300.
+ *
+ * - <b> Basic I/O function </b> \n
+ *   WIZCHIP_READ(), WIZCHIP_WRITE() \n\n
+ *
+ * - @ref Common_register_group_W5300 <b>access functions</b> \n
+ * 	-# @b Mode \n
+ *    getMR(), setMR()
+ * 	-# @b Interrupt \n
+ *    getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR()
+ * 	-# <b> Network Information </b> \n
+ *    getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
+ * 	-# @b Retransmission \n
+ *    getRCR(), setRCR(), getRTR(), setRTR()
+ * 	-# @b PPPoE \n
+ *    getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU()
+ * 	-# <b> ICMP packet </b>\n
+ *    getUIPR(), getUPORTR()
+ *    -# @b Socket Memory \n
+ *    getMTYPER(), setMTYPER() \n
+ *    getTMS01R(), getTMS23R(), getTMS45R(), getTMS67R(), setTMS01R(), setTMS23R(), setTMS45R(), setTMS67R() \n
+ *    getRMS01R(), getRMS23R(), getRMS45R(), getRMS67R(), setRMS01R(), setRMS23R(), setRMS45R(), setRMS67R() \n 
+ * 	-# @b etc. \n
+ *    getPn_BRDYR(), setPn_BRDYR(), getPn_BDPTHR(), setPn_BDPTHR(), getIDR() \n\n
+ *
+ * - \ref Socket_register_group_W5300 <b>access functions</b> \n
+ *   -# <b> SOCKET control</b> \n
+ *      getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR()
+ *   -# <b> SOCKET information</b> \n
+ *      getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
+ *      getSn_MSSR(), setSn_MSSR()
+ *   -# <b> SOCKET communication </b> \n
+ *      getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n
+ *      getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
+ *      getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
+ *      getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR()
+ *   -# <b> IP header field </b> \n
+ *      getSn_FRAG(), setSn_FRAG(),  getSn_TOS(), setSn_TOS() \n
+ *      getSn_TTL(), setSn_TTL()
+ */
+
+
+/**
+ * @defgroup Common_register_group_W5300 Common register
+ * @ingroup WIZCHIP_register_W5300
+ *
+ * @brief Common register group\n
+ * It set the basic for the networking\n
+ * It set the configuration such as interrupt, network information, ICMP, etc.
+ * @details
+ * @sa MR : Mode register.
+ * @sa GAR, SUBR, SHAR, SIPR : Network Configuration
+ * @sa IR, _IMR_ : Interrupt.
+ * @sa MTYPER, TMS01R,TMS23R, TMS45R, TMS67R,RMS01R,RMS23R, RMS45R, RMS67R : Socket TX/RX memory
+ * @sa _RTR_, _RCR_ : Data retransmission.
+ * @sa PTIMER, PMAGIC, PSID, PDHAR : PPPoE.
+ * @sa UIPR, UPORTR, FMTUR : ICMP message.
+ * @sa Pn_BRDYR, Pn_BDPTHR, IDR : etc.
+ */
+  
+ 
+/**
+ * @defgroup Socket_register_group_W5300 Socket register
+ * @ingroup WIZCHIP_register_W5300
+ *
+ * @brief Socket register group.\n
+ * Socket register configures and control SOCKETn which is necessary to data communication.
+ * @details
+ * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control
+ * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
+ * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol.
+ * @sa Sn_TX_WRSR, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR, Sn_TX_FIFOR, Sn_RX_FIFOR : Data communication
+ */
+ 
+ 
+ /**
+ * @defgroup Basic_IO_function_W5300 Basic I/O function
+ * @ingroup WIZCHIP_IO_Functions_W5300
+ * @brief These are basic input/output functions to read values from register or write values to register.
+ */
+
+/**
+ * @defgroup Common_register_access_function_W5300 Common register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5300
+ * @brief These are functions to access <b>common registers</b>.
+ */
+
+/**
+ * @defgroup Socket_register_access_function_W5300 Socket register access functions
+ * @ingroup WIZCHIP_IO_Functions_W5300
+ * @brief These are functions to access <b>socket registers</b>.
+ */
+
+//------------------------------- defgroup end --------------------------------------------
+
+//----------------------------- W5300 Common Registers -----------------------------
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Mode Register address(R/W)\n
+ * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
+ * @details Each bit of @ref MR defined as follows.
+ * <table>
+ * 		<tr>  <td>15</td> <td>14</td> <td>13</td> <td>12</td> <td>11</td> <td>10</td> <td>9</td> <td>8</td>   </tr>
+ * 		<tr>  <td>DBW</td> <td>MPF</td> <td colspan=3>WDF</td><td>RDF</td> <td>Reserved</td> <td>FS</td> 
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>FARP</td> <td>Reserved</td> </tr>
+ * </table>
+ * - \ref MR_DBW        : Data bus width (0 : 8 Bit, 1 : 16 Bit), Read Only
+ * - \ref MR_MPF        : Received a Pause Frame from MAC layer (0 : Normal Frame, 1 : Pause Frame), Read Only
+ * - \ref MR_WDF        : Write Data Fetch time (When CS signal is low, W5300 Fetch a written data by Host after PLL_CLK * MR_WDF)
+ * - \ref MR_RDH        : Read Data Hold time (0 : No use data hold time, 1 : Use data hold time, 2 PLL_CLK)
+ * - \ref MR_FS         : FIFO Swap (0 : Disable Swap, 1 : Enable Swap)
+ * - \ref MR_RST		 	: Reset
+ * - \ref MR_WOL       	: Wake on LAN
+ * - \ref MR_PB         : Ping block
+ * - \ref MR_PPPOE      : PPPoE mode
+ * - \ref MR_FARP			: Force ARP mode
+ */
+#define MR              (_WIZCHIP_IO_BASE_)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Interrupt Register(R/W)
+ * @details \ref IR indicates the interrupt status. Each bit of \ref IR will be still until the bit will be written to by the host.
+ * If \ref IR is not equal to 0x0000 INTn PIN is asserted to low until it is 0x0000\n\n
+ * Each bit of \ref IR defined as follows.
+ * <table>
+ * 		<tr>  <td>15</td> <td>14</td> <td>13</td> <td>12</td> <td>11</td> <td>10</td> <td>9</td> <td>8</td>   </tr>
+ * 		<tr>  <td>IPCF</td> <td>DPUR</td> <td>PPPT</td> <td>FMTU</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>S7_INT</td> <td>S6_INT</td> <td>S5_INT</td> <td>S4_INT</td> <td>S3_INT</td> <td>S2_INT</td> <td>S1_INT</td> <td>S0_INT</td> </tr>
+ * </table>
+ * - \ref IR_IPCF : IP conflict
+ * - \ref IR_DPUR	: Destination Port Unreachable
+ * - \ref IR_PPPT : PPPoE Termination
+ * - \ref IR_FMTU : Fragmented MTU 
+ * - \ref IR_SnINT(n) : Interrupted from SOCKETn
+ *
+ * @note : In W5300, IR is operated same as IR and SIR in other WIZCHIP(5100,5200,W5500)
+ */
+#define IR              (_W5300_IO_BASE_ + 0x02)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Socket Interrupt Mask Register(R/W)
+ * @details Each bit of \ref _IMR_ corresponds to each bit of \ref IR.
+ * When a bit of _IMR_ is and the corresponding bit of \ref IR is  Interrupt will be issued.
+ * In other words, if a bit of _IMR_, an interrupt will be not issued even if the corresponding bit of \ref IR is set
+ * @note : In W5300, _IMR_ is operated same as _IMR_ and SIMR in other WIZCHIP(5100,5200,W5500)
+ */
+#define _IMR_             (_W5300_IO_BASE_ + 0x04)
+
+
+//#define ICFGR           (_W5300_IO_BASE_ + 0x06)
+//#define INTLEVEL        ICFGR
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Source MAC Register address(R/W)
+ * @details @ref SHAR configures the source hardware address.
+ */
+#define SHAR            (_W5300_IO_BASE_ + 0x08)
+
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Gateway IP Register address(R/W)
+ * @details @ref GAR configures the default gateway address.
+ */
+ #define GAR             (_W5300_IO_BASE_ + 0x10)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Subnet mask Register address(R/W)
+ * @details @ref SUBR configures the subnet mask address.
+ */
+#define SUBR            (_W5300_IO_BASE_ + 0x14)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Source IP Register address(R/W)
+ * @details @ref SIPR configures the source IP address.
+ */
+#define SIPR            (_W5300_IO_BASE_ + 0x18)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Timeout register address( 1 is 100us )(R/W)
+ * @details @ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref _RTR_ is x07D0.
+ * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref _RTR_, W5300 waits for the peer response
+ * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
+ * If the peer does not respond within the @ref _RTR_ time, W5300 retransmits the packet or issues timeout.
+ */
+ #define _RTR_          (_W5300_IO_BASE_ + 0x1C)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief Retry count register(R/W)
+ * @details @ref _RCR_ configures the number of time of retransmission.
+ * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (@ref Sn_IR_TIMEOUT = '1').
+ */
+#define _RCR_           (_W5300_IO_BASE_ + 0x1E)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 0 & 1
+ * @details TMS01R configures the TX buffer block size of \c SOCKET 0 & 1.  The default value is configured with 8KB and can be configure from 0 to 64KB with unit 1KB.
+ * But the sum of all SOCKET TX buffer size should be multiple of 8 and the sum of all SOCKET TX and RX memory size can't exceed 128KB.
+ * When exceeded nor multiple of 8, the data transmittion is invalid.
+ */
+#define TMS01R          (_W5300_IO_BASE_ + 0x20)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 2 & 3
+ * @details refer to \ref TMS01R
+ */
+#define TMS23R          (TMS01R + 2) 
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 4 & 5
+ * @details refer to \ref TMS01R
+ */
+#define TMS45R          (TMS01R + 4)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 6 & 7
+ * @details refer to \ref TMS01R
+ */
+#define TMS67R          (TMS01R + 6) 
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 0.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR0           TMS01R
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 1.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR1           (TMSR0 + 1)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 2.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR2           (TMSR0 + 2)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 3.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR3           (TMSR0 + 3)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 4.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR4           (TMSR0 + 4)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 5.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR5           (TMSR0 + 5)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 6.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR6           (TMSR0 + 6)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   TX memory size of \c SOCKET 7.
+ * @details refer to \ref TMS01R
+ */
+#define TMSR7           (TMSR0 + 7)
+
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 0 & 1
+ * @details RMS01R configures the RX buffer block size of \c SOCKET 0 & 1.  The default value is configured with 8KB and can be configure from 0 to 64KB with unit 1KB.
+ * But the sum of all SOCKET RX buffer size should be multiple of 8 and the sum of all SOCKET RX and TX memory size can't exceed 128KB.
+ * When exceeded nor multiple of 8, the data reception is invalid.
+ */
+#define RMS01R          (_W5300_IO_BASE_ + 0x28)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 2 & 3
+ * @details Refer to \ref RMS01R
+ */
+#define RMS23R          (RMS01R + 2)   
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 4 & 5
+ * @details Refer to \ref RMS01R
+ */
+#define RMS45R          (RMS01R + 4)  
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 6 & 7
+ * @details Refer to \ref RMS01R
+ */
+#define RMS67R          (RMS01R + 6)   
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 0.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR0           RMS01R
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 1.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR1           (RMSR0 + 1)
+
+/**
+ * @ingroup Common_register_group_5300
+ * @brief   RX memory size of \c SOCKET 2.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR2           (RMSR0 + 2)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 3.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR3           (RMSR0 + 3)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 4.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR4           (RMSR0 + 4)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 5.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR5           (RMSR0 + 5)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 6.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR6           (RMSR0 + 6)
+
+/**
+ * @ingroup Common_register_group_W5300
+ * @brief   RX memory size of \c SOCKET 7.
+ * @details refer to \ref RMS01R
+ */
+#define RMSR7           (RMSR0 + 7)
+
+
+
+/**
+ *  @ingroup Common_register_group_W5300
+ *  @brief Memory Type Register
+ *  @details W5300’s 128Kbytes data memory (Internal TX/RX memory) is composed of 16 memory blocks
+ *  of 8Kbytes. MTYPER configures type of each 8KB memory block in order to select RX or TX memory. 
+ *  The type of 8KB memory block corresponds to each bit of MTYPER. When the bit is ‘1’, it is used as TX
+ *  memory, and the bit is ‘0’, it is used as RX memory. MTYPER is configured as TX memory type
+ *  from the lower bit. The rest of the bits not configured as TX memory, should be set as ‘0’.
+ */
+#define MTYPER          (_W5300_IO_BASE_ + 0x30)
+
+/**
+ *  @ingroup Common_register_group_W5300
+ *  @brief PPPoE Authentication Type register
+ *  @details It notifies authentication method negotiated with PPPoE server.
+ *  W5300 supports 2 types of authentication methods. 
+ *  - PAP  : 0xC023
+ *  - CHAP : 0xC223
+ */
+#define PATR            (_W5300_IO_BASE_ + 0x32)
+
+//#define PPPALGOR      (_W5300_IO_BASE_ + 0x34)
+
+/**
+ *  @ingroup Common_register_group_W5300
+ *  @brief PPP Link Control Protocol Request Timer Register
+ *  @details It configures transmitting timer of link control protocol (LCP) echo request. Value 1 is about 25ms.
+ */
+#define PTIMER          (_W5300_IO_BASE_ + 0x36)
+
+/**
+ *  @ingroup Common_register_group_W5300
+ *  @brief PPP LCP magic number register
+ *  @details It configures byte value to be used for 4bytes “Magic Number” during LCP negotiation with PPPoE server.
+ */
+#define PMAGICR         (_W5300_IO_BASE_ + 0x38)
+
+//#define PSTATER       (_W5300_IO_BASE_ + 0x3A)
+
+/**
+ *  @ingroup Common_register_group_W5300
+ *  @brief PPPoE session ID register
+ *  @details It notifies PPP session ID to be used for communication with PPPoE server (acquired by PPPoE-process of W5300).
+ */
+#define PSIDR           (_W5300_IO_BASE_ + 0x3C)
+
+/**
+ *  @ingroup Common_register_group_W5300
+ *  @brief PPPoE destination hardware address register
+ *  @details It notifies hardware address of PPPoE server (acquired by PPPoE-process of W5300).
+ */
+#define PDHAR           (_W5300_IO_BASE_ + 0x40)
+
+/**
+ *  @ingroup Common_register_group_W5300 
+ *  @brief Unreachable IP address register 
+ *  @details When trying to transmit UDP data to destination port number which is not open, 
+ *   W5300 can receive ICMP (Destination port unreachable) packet. \n
+ *   In this case, \ref IR_DPUR bit of \ref IR becomes '1'. 
+ *   And destination IP address and unreachable port number of ICMP packet can be acquired through UIPR and \ref UPORTR.
+ */
+#define UIPR            (_W5300_IO_BASE_ + 0x48)
+
+/**
+ *  @ingroup Common_register_group_W5300 
+ *  @brief Unreachable port number register
+ *  @details Refer to \ref UIPR.
+ */
+#define UPORTR          (_W5300_IO_BASE_ + 0x4C)
+
+/**
+ *  @ingroup Common_register_group_W5300 
+ *  @brief Fragment MTU register
+ *  @details When communicating with the peer having a different MTU, W5300 can receive an ICMP(Fragment MTU) packet. 
+ *  At this case, IR(FMTU) becomes ‘1’ and destination IP address and fragment MTU value of ICMP packet can be acquired through UIPR and FMTUR. 
+ *  In order to keep communicating with the peer having Fragment MTU, set the FMTUR first in Sn_MSSR of the SOCKETn, and try the next communication. 
+ */
+#define FMTUR           (_W5300_IO_BASE_ + 0x4E)
+
+//#define Sn_RTCR(n)      (_W5300_IO_BASE_ + 0x50 + n*2)
+
+/**
+ *  @ingroup Common_register_group_W5300 
+ *  @brief PIN 'BRDYn' configure register
+ *  @details It configures the PIN "BRDYn" which is monitoring TX/RX memory status of the specified SOCKET. 
+ *  If the free buffer size of TX memory is same or bigger than the buffer depth of \ref Pn_BDPTHR, 
+ *  or received buffer size of RX memory is same or bigger than the \ref Pn_BDPTHR, 
+ *  PIN "BRDYn" is signaled.
+ * <table>
+ * 		<tr>  <td>15</td> <td>14</td> <td>13</td> <td>12</td> <td>11</td> <td>10</td> <td>9</td> <td>8</td>   </tr>
+ * 		<tr>  <td colspan=8>Reserved, Read as 0</td> </tr>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr>
+ * 		<tr>  <td>PEN</td> <td>MT</td> <td>PPL</td> <td colspan=2>Reserved</td> <td colspan=3>SN</td> </tr>
+ * </table>
+ *
+ * - \ref Pn_PEN           Enable PIN 'BRDYn' (0 : Disable, 1 : Enable)
+ * - \ref Pn_MT            Monitoring Memory type (0 : RX memory, 1 : TX Memory)
+ * - \ref Pn_PPL           PIN Polarity bit of Pn_BRDYR. (0 : Low sensitive, 1 : High sensitive)
+ * - \ref Pn_SN(n)         Monitoring SOCKET number of Pn_BRDYR
+ */
+#define Pn_BRDYR(n)     (_W5300_IO_BASE_ + 0x60 + n*4)
+
+/**
+ *  @ingroup Common_register_group_W5300 
+ *  @brief PIN 'BRDYn' buffer depth Register
+ *  @details It configures buffer depth of PIN "BRDYn". 
+ *  When monitoring TX memory and \ref Sn_TX_FSR is same or bigger than Pn_BDPTHR, the PIN "BRDYn" is signaled. 
+ *  When monitoring RX memory and if \ref Sn_RX_RSR is same or bigger than Pn_BDPTHR, PIN "BRDYn" is signaled. 
+ *  The value for Pn_BDPTHR can't exceed TX/RX memory size allocated by TMSR or RMSR such like as \ref TMS01R or \ref RMS01R.
+ */
+#define Pn_BDPTHR(n)    (_W5300_IO_BASE_ + 0x60 + n*4 + 2)
+
+/**
+ *  @ingroup Common_register_group_W5300 
+ *  @brief W5300 identification register.
+ *  @details Read Only. 0x5300.
+ */
+#define IDR             (_W5300_IO_BASE_ + 0xFE)
+#define VERSIONR        IDR
+
+
+//----------------------------- W5300 SOCKET Registers -----------------------------
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Socket Mode register(R/W)
+ * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n
+ * Each bit of @ref Sn_MR defined as the following.
+ * <table>
+ * 		<tr>  <td>15</td> <td>14</td> <td>13</td> <td>12</td> <td>11</td> <td>10</td> <td>9</td> <td>8</td>   </tr>
+ * 		<tr>  <td colspan=7> Reserved. Read as 0 </td> <td>ALIGN</td> </tr>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>MULTI</td> <td>MF</td> <td>ND/IGMPv</td> <td>Reserved</td> <td colspan=4>PROTOCOL[3:0]</td> </tr>
+ * </table>
+ * - @ref Sn_MR_ALIGN   : Alignment bit of Sn_MR, Only valid in \ref Sn_MR_TCP. (C0 : Include TCP PACK_INFO, 1 : Not include TCP PACK_INFO)
+ * - @ref Sn_MR_MULTI	: Support UDP Multicasting
+ * - @ref Sn_MR_MF	   : Enable MAC Filter (0 : Disable, 1 - Enable), When enabled, W5300 can receive only both own and broadcast packet.
+ * - @ref Sn_MR_ND		: No Delayed Ack(TCP) flag
+ * - @ref Sn_MR_IGMPv 	: IGMP version used <b>in UDP mulitcasting</b>. (0 : Version 2, 1 : Version 2)
+ * - <b>PROTOCOL[3:0]</b>
+ * <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>1</td> <td>1</td> <td>IPCRAW</td>   </tr>
+ *       <tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ *       <tr>   <td>0</td> <td>1</td> <td>0</td> <td>1</td> <td>PPPoE</td>   </tr>
+ * </table>
+ *
+ *  - @ref Sn_MR_PPPoE  : PPPoE 
+ *	 - @ref Sn_MR_MACRAW	: MAC LAYER RAW SOCK
+ *  - @ref Sn_MR_IPRAW  : IP LAYER RAW SOCK 
+ *  - @ref Sn_MR_UDP		: UDP
+ *  - @ref Sn_MR_TCP		: TCP
+ *  - @ref Sn_MR_CLOSE	: Unused socket
+ *  @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x00)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Socket command register(R/W)
+ * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
+ * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00.
+ * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n
+ * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR.
+ * - @ref Sn_CR_OPEN 		: Initialize or open socket.
+ * - @ref Sn_CR_LISTEN 		: Wait connection request in TCP mode(<b>Server mode</b>)
+ * - @ref Sn_CR_CONNECT 	: Send connection request in TCP mode(<b>Client mode</b>)
+ * - @ref Sn_CR_DISCON 		: Send closing request in TCP mode.
+ * - @ref Sn_CR_CLOSE   	: Close socket.
+ * - @ref Sn_CR_SEND    	: Update TX buffer pointer and send data.
+ * - @ref Sn_CR_SEND_MAC	: Send data with MAC address, so without ARP process.
+ * - @ref Sn_CR_SEND_KEEP 	: Send keep alive message.
+ * - @ref Sn_CR_RECV		   : Update RX buffer pointer and receive data.
+ * - @ref Sn_CR_PCON       : PPPoE connection begins by transmitting PPPoE discovery packet.
+ * - @ref Sn_CR_PDISCON    : Closes PPPoE connection.
+ * - @ref Sn_CR_PCR        : In each phase, it transmits REQ message.
+ * - @ref Sn_CR_PCN        : In each phase, it transmits NAK message.
+ * - @ref Sn_CR_PCJ        : In each phase, it transmits REJECT message.
+ */
+#define Sn_CR(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x02)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief socket interrupt mask register(R)
+ * @details @ref Sn_IMR masks the interrupt of Socket n.
+ * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is 
+ * the corresponding bit of @ref Sn_IR becomes  When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is 
+ * Host is interrupted by asserted INTn PIN to low.
+ */
+#define Sn_IMR(n)       (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x04)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Socket interrupt register(R)
+ * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
+ * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is  the corresponding bit of @ref Sn_IR becomes \n
+ * In order to clear the @ref Sn_IR bit, the host should write the bit to \n
+ * <table>
+ * 		<tr>  <td>15</td> <td>14</td> <td>13</td> <td>12</td> <td>11</td> <td>10</td> <td>9</td> <td>8</td>   </tr>
+ * 		<tr>  <td colspan=8> Reserved. Read as 0</td> </tr>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>PRECV</td> <td>PFAIL</td> <td>PNEXT</td> <td>SENDOK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr>
+ * </table>
+ * - \ref Sn_IR_PRECV   : PPP receive
+ * - \ref Sn_IR_PFAIL   : PPP fail
+ * - \ref Sn_IR_PNEXT   : PPP next phase
+ * - \ref Sn_IR_SENDOK  : SENDOK 
+ * - \ref Sn_IR_TIMEOUT : TIMEOUT
+ * - \ref Sn_IR_RECV    : RECV 
+ * - \ref Sn_IR_DISCON  : DISCON
+ * - \ref Sn_IR_CON     : CON
+ */
+#define Sn_IR(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x06)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Socket status register(R)
+ * @details @ref Sn_SSR indicates the status of Socket n.\n
+ * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
+ * @par Normal status
+ * - @ref SOCK_CLOSED 		: Closed
+ * - @ref SOCK_INIT   		: Initiate state
+ * - @ref SOCK_LISTEN    	: Listen state
+ * - @ref SOCK_ESTABLISHED : Success to connect
+ * - @ref SOCK_CLOSE_WAIT  : Closing state
+ * - @ref SOCK_UDP   		: UDP socket
+ * - @ref SOCK_IPRAW       : IPRAW socket
+ * - @ref SOCK_MACRAW  		: MAC raw mode socket
+ * - @ref SOCK_PPPoE       : PPPoE mode Socket
+ *@par Temporary status during changing the status of Socket n.
+ * - @ref SOCK_SYNSENT   	: This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
+ * - @ref SOCK_SYNRECV    	: It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
+ * - @ref SOCK_FIN_WAIT		: Connection state
+ * - @ref SOCK_CLOSING		: Closing state
+ * - @ref SOCK_TIME_WAIT	: Closing state
+ * - @ref SOCK_LAST_ACK 	: Closing state
+ * - @ref SOCK_ARP         : ARP request state 
+ */
+#define Sn_SSR(n)       (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x08)
+#define Sn_SR(n)        Sn_SSR(n)   ///< For Compatible ioLibrary. Refer to @ref Sn_SSR(n)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief source port register(R/W)
+ * @details @ref Sn_PORTR configures the source port number of Socket n.
+ * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered.
+ */
+#define Sn_PORTR(n)     (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0A)
+#define Sn_PORT(n)      Sn_PORTR(n)       ///< For compatible ioLibrary. Refer to @ref Sn_PORTR(n).
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Peer MAC register address(R/W)
+ * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
+ * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
+ */
+#define Sn_DHAR(n)      (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0C)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Peer port register address(R/W)
+ * @details @ref Sn_DPORTR configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP clientmode, it configures the listen port number of TCP serverbefore CONNECT command.
+ * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
+ * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
+ */
+#define Sn_DPORTR(n)    (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x12)
+#define Sn_DPORT(n)     Sn_DPORTR(n)    ///< For compatible ioLibrary. Refer to \ref Sn_DPORTR.
+
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Peer IP register address(R/W)
+ * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP client mode, it configures an IP address of TCP serverbefore CONNECT command.
+ * In TCP server mode, it indicates an IP address of TCP clientafter successfully establishing connection.
+ * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
+ */
+ #define Sn_DIPR(n)      (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x14)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
+ * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
+ */
+#define Sn_MSSR(n)      (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x18)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Keep Alive Timer register(R/W)
+ * @details @ref Sn_KPALVTR configures the transmitting timer of KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode,
+ * and ignored in other modes. The time unit is 5s.
+ * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once.
+ * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process).
+ * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate,
+ * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process).
+ * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'.
+ */
+#define Sn_KPALVTR(n)   (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x1A)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief IP Protocol(PROTO) Register(R/W)
+ * @details \ref Sn_PROTO that sets the protocol number field of the IP header at the IP layer. It is
+ * valid only in IPRAW mode, and ignored in other modes.
+ */
+#define Sn_PROTOR(n)    Sn_KPALVTR(n)
+
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief IP Type of Service(TOS) Register(R/W)
+ * @details @ref Sn_TOSR configures the TOS(Type Of Service field in IP Header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TOSR(n)      (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x1C)
+#define Sn_TOS(n)       Sn_TOSR(n)  ///< For compatible ioLibrary. Refer to Sn_TOSR
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief IP Time to live(TTL) Register(R/W)
+ * @details @ref Sn_TTLR configures the TTL(Time To Live field in IP header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TTLR(n)      (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x1E)
+#define Sn_TTL(n)       Sn_TTLR(n)  ///< For compatible ioLibrary. Refer to Sn_TTLR
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief  SOCKETn TX write size register(R/W)
+ * @details It sets the byte size of the data written in internal TX memory through @ref Sn_TX_FIFOR.
+ * It is set before SEND or SEND_MAC command, and can't be bigger than internal TX memory
+ * size set by TMSR such as @ref TMS01R, TMS23R and etc.
+ */
+#define Sn_TX_WRSR(n)		(_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x20)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Transmit free memory size register(R)
+ * @details Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by TMSR such as @ref TMS01SR.
+ * Data bigger than Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
+ * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
+ * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
+ * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
+ */
+#define Sn_TX_FSR(n)       (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0024)
+
+/**
+ * @ingroup Socket_register_group_w5300
+ * @brief Received data size register(R)
+ * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
+ * @ref Sn_RX_RSR does not exceed the RMSR such as @ref RMS01SR  and is calculated as the difference between
+ * ?Socket n RX Write Pointer (@ref Sn_RX_WR)and Socket n RX Read Pointer (@ref Sn_RX_RD)
+ */
+#define Sn_RX_RSR(n)       (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x0028)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief Fragment field value in IP header register(R/W)
+ * @details @ref Sn_FRAGR configures the FRAG(Fragment field in IP header).
+ */
+#define Sn_FRAGR(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x002C)
+#define Sn_FRAG(n)         Sn_FRAGR(n)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief SOCKET n TX FIFO regsiter
+ * @details It indirectly accesses internal TX memory of SOCKETn.
+ * The internal TX memory can't be accessed directly by the host, but can be accessed through Sn_TX_FIFOR. 
+ * If @ref MR(MT) = '0', only the Host-Write of internal TX memory is allowed through Sn_TX_FIFOR. 
+ * But if @ref MR(MT) is '1', both of Host-Read and Host-Write are allowed.
+ */
+#define Sn_TX_FIFOR(n)     (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x2E)
+
+/**
+ * @ingroup Socket_register_group_W5300
+ * @brief SOCKET n RX FIFO register
+ * @details It indirectly accesses to internal RX memory of SOCKETn.
+ * The internal RX memory can't be directly accessed by the host, but can be accessed through Sn_RX_FIFOR. 
+ * If MR(MT) = '0', only the Host-Read of internal RX memory is allowed through Sn_RX_FIFOR. 
+ * But if MR(MT) is '1', both of Host-Read and Host-Write are allowed. 
+ */
+#define Sn_RX_FIFOR(n)     (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x30)
+
+//#define Sn_TX_SADR(n)      (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x32)
+
+//#define Sn_RX_SADR(n)      (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x34)
+
+//#define Sn_TX_RD(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x36)
+
+//#define Sn_TX_WR(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x38)
+
+//#define Sn_TX_ACK(n)       (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x3A)
+
+//#define Sn_RX_RD(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x3C)
+
+//#define Sn_RX_WR(n)        (_W5300_IO_BASE_ + WIZCHIP_SREG_BLOCK(n) + 0x3E)
+
+
+/************************************/
+/* The bit of MR regsiter defintion */
+/************************************/
+#define MR_DBW             (1 << 15)            /**< Data bus width bit of \ref MR. Read Only. (0 : 8Bit, 1 : 16Bit)*/
+#define MR_MPF             (1 << 14)            /**< Mac layer pause frame bit of \ref MR. (0 : Disable, 1 : Enable)*/
+#define MR_WDF(X)          ((X & 0x07) << 11)   /**< Write data fetch time bit of  \ref MR. Fetch Data from DATA bus after PLL_CLK * MR_WDF[2:0]*/
+#define MR_RDH             (1 << 10)            /**< Read data hold time bit of \ref MR. Hold Data on DATA bus during 2 * PLL_CLK after CS high*/
+#define MR_FS              (1 << 8)             /**< FIFO swap bit of \ref MR. Swap MSB & LSB of \ref Sn_TX_FIFOR & Sn_RX_FIFOR (0 : No swap, 1 : Swap) */
+#define MR_RST             (1 << 7)             /**< S/W reset bit of \ref MR. (0 : Normal Operation,  1 : Reset (automatically clear after reset))*/
+#define MR_MT              (1 << 5)             /**< Memory test bit of \ref MR. (0 : Normal, 1 : Internal Socket memory write & read Test)*/
+#define MR_PB              (1 << 4)             /**< Ping block bit of \ref MR. (0 : Unblock, 1 : Block)*/
+#define MR_PPPoE           (1 << 3)             /**< PPPoE bit of \ref MR. (0 : No use PPPoE, 1: Use PPPoE)*/
+#define MR_DBS             (1 << 2)             /**< Data bus swap of \ref MR. Valid only 16bit mode (0 : No swap, 1 : Swap)*/
+#define MR_IND             (1 << 0)             /**< Indirect mode bit of \ref MR. (0 : Direct mode, 1 : Indirect mode) */
+
+
+/************************************/ 
+/* The bit of IR regsiter definition */ 
+/************************************/ 
+#define IR_IPCF            (1 << 7)             /**< IP conflict bit of \ref IR. To clear, Write the bit to '1'. */
+#define IR_DPUR            (1 << 6)             /**< Destination port unreachable bit of \ref IR. To clear, Write the bit to '1'. */
+#define IR_PPPT            (1 << 5)             /**< PPPoE terminate bit of \ref IR. To clear, Write the bit to '1'. */
+#define IR_FMTU            (1 << 4)             /**< Fragment MTU bit of IR. To clear, Write the bit to '1'. */
+#define IR_SnINT(n)        (0x01 << n)          /**< SOCKETn interrupt occurrence bit of \ref IR. To clear, Clear \ref Sn_IR*/
+
+/*****************************************/ 
+/* The bit of Pn_BRDYR regsiter definition*/ 
+/*****************************************/ 
+#define Pn_PEN             (1 << 7)             /**< PIN 'BRDYn' enable bit of Pn_BRDYR. */
+#define Pn_MT              (1 << 6)             /**< PIN memory type bit of Pn_BRDYR. */
+#define Pn_PPL             (1 << 5)             /**< PIN Polarity bit of Pn_BRDYR. */
+#define Pn_SN(n)           ((n & 0x07) << 0)    /**< What socket to monitor. */
+
+
+/***************************************/ 
+/* The bit of Sn_MR regsiter definition */ 
+/***************************************/ 
+/**
+ * @brief Alignment bit of \ref Sn_MR. 
+ * @details It is valid only in the TCP (\ref Sn_MR_TCP) with TCP communication, 
+ * when every the received DATA packet size is of even number and set as '1', 
+ * data receiving performance can be improved by removing PACKET-INFO(data size) that is attached to every the received DATA packet.
+ */
+#define Sn_MR_ALIGN        (1 << 8)     
+
+/**
+ * @brief Multicasting bit of \ref Sn_MR
+ * @details It is valid only in UDP (\ref Sn_MR_UDP).
+ * In order to implement multicasting, set the IP address and port number in @ref Sn_DIPR and @ref Sn_DPORTR respectively before "OPEN" command(@ref Sn_CR_OPEN).\n
+ * 0 : Disable, 1 : Enable
+ */
+#define Sn_MR_MULTI        (1 << 7)     
+
+/**
+ * @brief  MAC filter bit of \ref Sn_MR
+ * @details It is valid in MACRAW(@ref Sn_MR_MACRAW).
+ * When this bit is set as ‘1’, W5300 can receive packet that is belong in itself or broadcasting. 
+ * When this bit is set as ‘0’, W5300 can receive all packets on Ethernet. 
+ * When using the hybrid TCP/IP stack, it is recommended to be set as ‘1’ for reducing the receiving overhead of host. \n
+ * 0 : Disable, 1 : Enable
+ */
+#define Sn_MR_MF           (1 << 6)             
+
+/**
+ * @brief IGMP version bit of \ref Sn_MR
+ * details It is valid in case of @ref Sn_MR_MULTI='1' and UDP(@ref Sn_MR_UDP).
+ * It configures IGMP version to send IGMP message such as <b>Join/Leave/Report</b> to multicast-group. \n
+ * 0 : IGMPv2, 1 : IGMPv1
+ */
+#define Sn_MR_IGMPv        (1 << 5)
+#define Sn_MR_MC           Sn_MR_IGMPv       ///< For compatible ioLibrary
+
+/**
+ * @brief No delayed ack bit of \ref Sn_MR
+ * @details It is valid in TCP(@ref Sn_MR_TCP).
+ * In case that it is set as '1', ACK packet is transmitted right after receiving DATA packet from the peer. 
+ * It is recommended to be set as '1' for TCP performance improvement.
+ * In case that it is set as '0', ACK packet is transmitted after the time set in @ref _RTR_ regardless of DATA packet receipt.\n
+ * 0 : No use, 1 : Use 
+ */
+#define Sn_MR_ND           (1 << 5)             
+
+/**
+ * @brief No mode
+ * @details This configures the protocol mode of Socket n.
+ * @sa Sn_MR
+ */
+#define Sn_MR_CLOSE        0x00                 
+
+/**
+ * @brief TCP mode 
+ * @details This configures the protocol mode of Socket n.
+ * @sa Sn_MR
+ */
+#define Sn_MR_TCP          0x01                
+
+/**
+ * @brief UDP mode
+ * @details This configures the protocol mode of Socket n.
+ * @sa Sn_MR
+ */
+#define Sn_MR_UDP          0x02                 /**< Protocol bits of \ref Sn_MR. */
+
+/**
+ * @brief IP LAYER RAW mode
+ * @details This configures the protocol mode of Socket n.
+ * @sa Sn_MR 
+ */
+#define Sn_MR_IPRAW        0x03                 /**< Protocol bits of \ref Sn_MR. */
+
+/**
+ * @brief MAC LAYER RAW mode
+ * @details This configures the protocol mode of Socket 0.
+ * @sa Sn_MR 
+ * @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR_MACRAW       0x04 
+
+/**
+ * @brief PPPoE mode
+ * @details This configures the protocol mode of Socket 0.
+ * @sa Sn_MR 
+ * @note PPPoE mode should be only used in Socket 0.
+ */                
+#define Sn_MR_PPPoE        0x05                 /**< Protocol bits of \ref Sn_MR. */
+
+#define SOCK_STREAM        Sn_MR_TCP            /**< For Berkeley Socket API, Refer to @ref Sn_MR_TCP */
+#define SOCK_DGRAM         Sn_MR_UDP            /**< For Berkeley Socket API, Refer to @ref Sn_MR_UDP */
+
+
+
+/******************************/ 
+/* The values of CR definition */ 
+/******************************/
+/**
+ * @brief Initialize or open a socket
+ * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
+ * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n
+ * <table>
+ *   <tr>  <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td>            		 </tr>
+ *   <tr>  <td>Sn_MR_CLOSE  (000)</td> <td></td>         	   		 </tr>
+ *   <tr>  <td>Sn_MR_TCP  (001)</td> <td>SOCK_INIT (0x13)</td>  		 </tr>
+ *   <tr>  <td>Sn_MR_UDP  (010)</td>  <td>SOCK_UDP (0x22)</td>  		 </tr>
+ *   <tr>  <td>Sn_MR_IPRAW  (010)</td>  <td>SOCK_IPRAW (0x32)</td>  		 </tr>
+ *   <tr>  <td>Sn_MR_MACRAW  (100)</td>  <td>SOCK_MACRAW (0x42)</td>  </tr>
+ *   <tr>  <td>Sn_MR_PPPoE  (101)</td>  <td>SOCK_PPPoE (0x5F)</td>  </tr>
+ * </table>
+ */
+#define Sn_CR_OPEN         0x01                 
+
+/**
+ * @brief Wait connection request in TCP mode(Server mode)
+ * @details This is valid only in TCP mode (\ref Sn_MR(P3:P0) = \ref Sn_MR_TCP).
+ * In this mode, Socket n operates as a TCP serverand waits for  connection-request (SYN packet) from any TCP client
+ * The @ref Sn_SR changes the state from \ref SOCK_INIT to \ref SOCKET_LISTEN.
+ * When a TCP clientconnection request is successfully established,
+ * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the @ref Sn_IR(0) becomes 
+ * But when a TCP clientconnection request is failed, @ref Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED.
+ */
+#define Sn_CR_LISTEN       0x02                 
+
+/**
+ * @brief Send connection request in TCP mode(Client mode)
+ * @details  To connect, a connect-request (SYN packet) is sent to <b>TCP server</b>configured by @ref Sn_DIPR & Sn_DPORT(destination address & port).
+ * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
+ * The connect-request fails in the following three cases.\n
+ * 1. When a @b ARPTO occurs (@ref Sn_IR[3] =  '1') because destination hardware address is not acquired through the ARP-process.\n
+ * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) =  )\n
+ * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED.
+ * @note This is valid only in TCP mode and operates when Socket n acts as <b>TCP client</b>
+ */
+#define Sn_CR_CONNECT      0x04                 
+
+/**
+ * @brief Send closing request in TCP mode
+ * @details Regardless of <b>TCP server</b>or <b>TCP client</b> the DISCON command processes the disconnect-process (b>Active close</b>or <b>Passive close</b>.\n
+ * @par Active close
+ * it transmits disconnect-request(FIN packet) to the connected peer\n
+ * @par Passive close
+ * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
+ * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n
+ * Otherwise, @b TCPTO occurs (\ref Sn_IR[3]='1') and then @ref Sn_SR is changed to @ref SOCK_CLOSED.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_DISCON       0x08        
+
+/**
+ * @brief Close socket
+ * @details @ref Sn_SR is changed to @ref SOCK_CLOSED.
+ */
+#define Sn_CR_CLOSE        0x10 
+
+/**
+ * @brief Update TX buffer pointer and send data
+ * @details SEND command transmits all the data in the Socket n TX buffer thru @ref Sn_TX_FIFOR.\n
+ * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR) and Socket TX Write Size register (@ref Sn_TX_WRSR).
+ */
+#define Sn_CR_SEND         0x20                
+
+/**
+ * @brief Send data with MAC address, so without ARP process
+ * @details The basic operation is same as SEND.\n
+ * Normally SEND command transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
+ * But SEND_MAC command transmits data without the automatic ARP-process.\n
+ * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process.
+ * @note Valid only in UDP mode.
+ */
+#define Sn_CR_SEND_MAC     0x21                
+
+/**
+ * @brief Send keep alive message
+ * @details It checks the connection status by sending 1byte keep-alive packet.\n
+ * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_SEND_KEEP    0x22                 
+
+/**
+ * @brief Update RX buffer pointer and receive data
+ * @details RECV completes the processing of the received data in Socket n RX Buffer thru @ref Sn_RX_FIFOR).\n
+ * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR) & @ref Sn_RX_FIFOR.
+ */
+#define Sn_CR_RECV         0x40                 /**< RECV command value of \ref Sn_CR */
+
+#define Sn_CR_PCON         0x23                 /**< PPPoE connection begins by transmitting PPPoE discovery packet. Refer to \ref Sn_CR */
+#define Sn_CR_PDISCON      0x24                 /**< Closes PPPoE connection. Refer to \ref Sn_CR */ 
+#define Sn_CR_PCR          0x25                 /**< In each phase, it transmits REQ message. Refer to \ref Sn_CR */
+#define Sn_CR_PCN          0x26                 /**< In each phase, it transmits NAK message. Refer to \ref Sn_CR */
+#define Sn_CR_PCJ          0x27                 /**< In each phase, it transmits REJECT message. Refer to \ref Sn_CR */
+
+
+/*********************************/ 
+/* The values of Sn_IR definition */ 
+/*********************************/
+#define Sn_IR_PRECV        0x80                 /**< It is set in the case that option data which is not supported is received. Refer to \ref Sn_IR */
+#define Sn_IR_PFAIL        0x40                 /**< It is set in the case that PAP authentication is failed. Refer to \ref Sn_IR */
+#define Sn_IR_PNEXT        0x20                 /**< It is set in the case that the phase is changed during PPPoE connection process. \ref Sn_IR */
+#define Sn_IR_SENDOK       0x10                 /**< It is set when SEND command is completed. Refer to \ref Sn_IR */
+#define Sn_IR_TIMEOUT      0x08                 /**< It is set when ARPTO or TCPTO is occured.  Refer to \ref Sn_IR */
+#define Sn_IR_RECV         0x04                 /**< It is set whenever data is received from a peer.  Refer to \ref Sn_IR */
+#define Sn_IR_DISCON       0x02                 /**< It is set when FIN or FIN/ACK packet is received from a peer.  Refer to \ref Sn_IR */
+#define Sn_IR_CON          0x01                 /**< It is set one time when the connection is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. */
+
+/**********************************/ 
+/* The values of Sn_SSR definition */ 
+/**********************************/
+/**
+ * @brief The state of SOCKET intialized or closed
+ * @details This indicates that Socket n is released.\n
+ * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status.
+ */
+#define SOCK_CLOSED        0x00                 
+
+/**
+ * @brief The state of ARP process
+ * @details It is temporary state for getting a peer MAC address when TCP connect or UDP Data Send\n
+ * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status.
+ */
+#define SOCK_ARP           0x01                 /**< ARP-request is transmitted in order to acquire destination hardware address. */
+
+/**
+ * @brief Initiate state in TCP.
+ * @details This indicates Socket n is opened with TCP mode.\n
+ * It is changed to @ref SOCK_INIT when \ref Sn_MR(P[3:0]) = '001' and OPEN command(\ref Sn_CR_OPEN) is ordered.\n
+ * After SOCK_INIT, user can use LISTEN(@ref Sn_CR_LISTEN)/CONNECT(@ref Sn_CR_CONNET) command.
+ */
+#define SOCK_INIT          0x13                 
+
+/**
+ * @brief Listen state
+ * @details This indicates Socket n is operating as <b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer <b>TCP client</b>.\n
+ * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n
+ * Otherwise it will change to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR_TIMEOUT = '1') is occurred.
+ */
+#define SOCK_LISTEN        0x14                 
+
+/**
+ * @brief Connection state
+ * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
+ * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by @ref Sn_CR_CONNECT command.\n
+ * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n
+ * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR_TIMEOUT = '1') is occurred.
+ */
+#define SOCK_SYNSENT       0x15                 
+
+/**
+ * @brief Connection state
+ * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
+ * If socket n sends the response (SYN/ACK  packet) to the peer successfully,  it changes to @ref SOCK_ESTABLISHED. \n
+ * If not, it changes to @ref SOCK_CLOSED after timeout (@ref Sn_IR_TIMEOUT = '1') is occurred.
+ */
+#define SOCK_SYNRECV       0x16                 
+
+/**
+ * @brief Success to connect
+ * @details This indicates the status of the connection of Socket n.\n
+ * It changes to @ref SOCK_ESTABLISHED when the <b>TCP SERVER</b>processed the SYN packet from the <b>TCP CLIENT</b>during @ref SOCK_LISTEN, or
+ * when the @ref Sn_CR_CONNECT command is successful.\n
+ * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using @ref Sn_CR_SEND or @ref Sn_CR_RECV command.
+ */
+#define SOCK_ESTABLISHED   0x17                 
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout(@ref Sn_CR_TIMTEOUT = '1') is occurred, these change to @ref SOCK_CLOSED.
+ */
+#define SOCK_FIN_WAIT      0x18                 
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
+ */
+#define SOCK_CLOSING       0x1A                 
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
+ */
+#define SOCK_TIME_WAIT     0x1B                
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
+ * This is half-closing status, and data can be transferred.\n
+ * For full-closing, @ref Sn_CR_DISCON command is used. But For just-closing, @ref Sn_CR_CLOSE command is used.
+ */
+#define SOCK_CLOSE_WAIT    0x1C                 
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
+ * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout (@ref Sn_IR_TIMEOUT = '1') is occurred.
+ */
+#define SOCK_LAST_ACK      0x1D                 
+
+/**
+ * @brief UDP socket
+ * @details This indicates Socket n is opened in UDP mode(@ref Sn_MR(P[3:0]) = '010').\n
+ * It changes to SOCK_UDP when @ref Sn_MR(P[3:0]) = '010' and @ref Sn_CR_OPEN command is ordered.\n
+ * Unlike TCP mode, data can be transfered without the connection-process.
+ */
+#define SOCK_UDP           0x22                 
+
+/**
+ * @brief IP raw mode socket
+ * @details TThe socket is opened in IPRAW mode. The SOCKET status is change to SOCK_IPRAW when @ref Sn_MR (P3:P0) is
+ * Sn_MR_IPRAW and @ref Sn_CR_OPEN command is used.\n
+ * IP Packet can be transferred without a connection similar to the UDP mode.
+*/
+#define SOCK_IPRAW         0x32                 
+
+/**
+ * @brief MAC raw mode socket
+ * @details This indicates Socket 0 is opened in MACRAW mode (@ref Sn_MR(P[3:0]) = '100' and n = 0) and is valid only in Socket 0.\n
+ * It changes to SOCK_MACRAW when @ref Sn_MR(P[3:0] = 100)and @ ref Sn_CR_OPEN command is ordered.\n
+ * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
+ */
+#define SOCK_MACRAW        0x42                 /**< SOCKET0 is open as MACRAW mode. */
+
+/**
+ * @brief PPPoE mode socket
+ * @details It is the status that SOCKET0 is opened as PPPoE mode. 
+ * It is changed to SOCK_PPPoE in case of @ref Sn_CR_OPEN command is ordered and @ref Sn_MR(P3:P0)= @ref Sn_MR_PPPoE\n
+ * It is temporarily used at the PPPoE connection.
+ */
+#define SOCK_PPPoE         0x5F                 /**< SOCKET0 is open as PPPoE mode. */
+
+/* IP PROTOCOL */
+#define IPPROTO_IP                   0        //< Dummy for IP 
+#define IPPROTO_ICMP                 1        //< Control message protocol
+#define IPPROTO_IGMP                 2        //< Internet group management protocol
+#define IPPROTO_GGP                  3        //< Gateway^2 (deprecated)
+#define IPPROTO_TCP                  6        //< TCP
+#define IPPROTO_PUP                  12       //< PUP
+#define IPPROTO_UDP                  17       //< UDP
+#define IPPROTO_IDP                  22       //< XNS idp
+#define IPPROTO_ND                   77       //< UNOFFICIAL net disk protocol
+#define IPPROTO_RAW                  255      //< Raw IP packet
+
+
+/**
+ * @brief Enter a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n \n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * \sa WIZCHIP_READ(), WIZCHIP_WRITE()
+ * \sa WIZCHIP_CRITICAL_EXIT()
+ */
+#define WIZCHIP_CRITICAL_ENTER()    WIZCHIP.CRIS._enter()
+
+#ifdef _exit
+#undef _exit
+#endif
+
+/**
+ * @brief Exit a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n\n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * @sa WIZCHIP_READ(), WIZCHIP_WRITE()
+ * @sa WIZCHIP_CRITICAL_ENTER()
+ */
+#define WIZCHIP_CRITICAL_EXIT()     WIZCHIP.CRIS._exit()
+
+////////////////////////
+// Basic I/O Function //
+////////////////////////
+
+/**
+ * @ingroup Basic_IO_function_W5300
+ * @brief It reads 1 byte value from a register.
+ * @param AddrSel Register address
+ * @return The value of register
+ */
+uint16_t  WIZCHIP_READ (uint32_t AddrSel);
+
+/**
+ * @ingroup Basic_IO_function_W5300
+ * @brief It writes 1 byte value to a register.
+ * @param AddrSel Register address
+ * @param wb Write data
+ * @return void
+ */
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint16_t wb );
+
+/***********************************
+ * COMMON Register Access Function *
+ ***********************************/
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set Mode Register
+ * @param (@ref iodata_t)mr The value to be set.
+ * @sa getMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_)
+   #if (_WIZCHIP_IO_BUS_WIDTH_ == 8)
+      #define setMR(mr) \
+         (*((uint8_t*)MR) = (uint8_t)((mr) >> 8)); (*((uint8_t*)WIZCHIP_OFFSET_INC(MR,1)) = (uint8_t)((mr) & 0xFF))
+   #elif (_WIZCHIP_IO_BUS_WIDTH_ == 16)
+      #define setMR(mr)    (*((uint16_t*)MR) = (uint16_t)((mr) & 0xFFFF))
+   #else
+      #error "Unknown _WIZCHIP_IO_BUS_WIDTH_. You should be define _WIZCHIP_IO_BUS_WIDTH as 8 or 16."   
+   #endif
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_"   
+#endif
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref MR.
+ * @return @ref iodata_t. The value of Mode register.
+ * @sa setMR()
+ */
+#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_)
+   #if (_WIZCHIP_IO_BUS_WIDTH_ == 8)
+      #define getMR()    (((uint16_t)(*((uint8_t*)MR)) << 8) + (((uint16_t)(*((uint8_t*)WIZCHIP_OFFSET_INC(MR,1)))) & 0x00FF))
+   #elif(_WIZCHIP_IO_BUS_WIDTH_ == 16)
+      #define getMR()    (*((uint16_t*)MR))
+   #else
+      #error "Unknown _WIZCHIP_IO_BUS_WIDTH_. You should be define _WIZCHIP_IO_BUS_WIDTH as 8 or 16."   
+   #endif
+#else
+   #error "Unknown _WIZCHIP_IO_MODE_"   
+#endif
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set \ref IR register
+ * @param (uint16_t)ir Value to set \ref IR register. 
+ * @sa getIR()
+ */
+#define  setIR(ir) \
+   WIZCHIP_WRITE(IR, ir & 0xF0FF)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get \ref IR register
+ * @return uint8_t. Value of \ref IR register.
+ * @sa setIR()
+ */
+#define  getIR()  \
+   (WIZCHIP_READ(IR) & 0xF0FF)
+
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set \ref _IMR_ register
+ * @param (uint16_t)imr Value to set @ref _IMR_ register.
+ * @sa getIMR()
+ */
+#define  setIMR(imr) \
+   WIZCHIP_WRITE(_IMR_, imr & 0xF0FF)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get \ref _IMR_ register
+ * @return uint16_t. Value of \ref IR register.
+ * @sa setIMR()
+ */
+#define  getIMR() \
+   (WIZCHIP_READ(_IMR_) & 0xF0FF)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set local MAC address
+ * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
+ * @sa getSHAR()
+ */
+#define  setSHAR(shar) { \
+      WIZCHIP_WRITE(SHAR,                       (((uint16_t)((shar)[0])) << 8) + (((uint16_t)((shar)[1])) & 0x00FF)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SHAR,2), (((uint16_t)((shar)[2])) << 8) + (((uint16_t)((shar)[3])) & 0x00FF)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SHAR,4), (((uint16_t)((shar)[4])) << 8) + (((uint16_t)((shar)[5])) & 0x00FF)); \
+   }
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get local MAC address
+ * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
+ * @sa setSHAR()
+ */
+#define  getSHAR(shar) { \
+		(shar)[0] = (uint8_t)(WIZCHIP_READ(SHAR) >> 8); \
+		(shar)[1] = (uint8_t)(WIZCHIP_READ(SHAR));      \
+		(shar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,2)) >> 8); \
+		(shar)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,2))); \
+		(shar)[4] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,4)) >> 8); \
+		(shar)[5] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SHAR,4))); \
+   }		
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set gateway IP address
+ * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
+ * @sa getGAR()
+ */
+#define  setGAR(gar) { \
+      WIZCHIP_WRITE(GAR,                       (((uint16_t)((gar)[0])) << 8) + (((uint16_t)((gar)[1])) & 0x00FF)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(GAR,2), (((uint16_t)((gar)[2])) << 8) + (((uint16_t)((gar)[3])) & 0x00FF)); \
+   }
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get gateway IP address
+ * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
+ * @sa setGAR()
+ */
+#define  getGAR(gar) { \
+		(gar)[0] = (uint8_t)(WIZCHIP_READ(GAR) >> 8); \
+		(gar)[1] = (uint8_t)(WIZCHIP_READ(GAR));      \
+		(gar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(GAR,2)) >> 8); \
+		(gar)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(GAR,2))); \
+   }		
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set subnet mask address
+ * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
+ * @sa getSUBR()
+ */
+#define  setSUBR(subr) { \
+      WIZCHIP_WRITE(SUBR,                       (((uint16_t)((subr)[0])) << 8) + (((uint16_t)((subr)[1])) & 0x00FF)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SUBR,2), (((uint16_t)((subr)[2])) << 8) + (((uint16_t)((subr)[3])) & 0x00FF)); \
+   }
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get subnet mask address
+ * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
+ * @sa setSUBR()
+ */
+#define  getSUBR(subr) { \
+		(subr)[0] = (uint8_t)(WIZCHIP_READ(SUBR) >> 8); \
+		(subr)[1] = (uint8_t)(WIZCHIP_READ(SUBR));      \
+		(subr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SUBR,2)) >> 8); \
+		(subr)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SUBR,2))); \
+   }
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set local IP address
+ * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
+ * @sa getSIPR()
+ */
+#define  setSIPR(sipr) { \
+      WIZCHIP_WRITE(SIPR,                       (((uint16_t)((sipr)[0])) << 8) + (((uint16_t)((sipr)[1])) & 0x00FF)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(SIPR,2), (((uint16_t)((sipr)[2])) << 8) + (((uint16_t)((sipr)[3])) & 0x00FF)); \
+   }
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get local IP address
+ * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
+ * @sa setSIPR()
+ */
+#define  getSIPR(sipr) { \
+		(sipr)[0] = (uint8_t)(WIZCHIP_READ(SIPR) >> 8); \
+		(sipr)[1] = (uint8_t)(WIZCHIP_READ(SIPR));      \
+	   (sipr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SIPR,2)) >> 8); \
+		(sipr)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(SIPR,2))); \
+   }
+
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref _RTR_ register
+ * @param (uint16_t)rtr Value to set @ref _RTR_ register.
+ * @sa getRTR()
+ */
+#define  setRTR(rtr)   \
+		WIZCHIP_WRITE(_RTR_, rtr)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref _RTR_ register
+ * @return uint16_t. Value of @ref _RTR_ register.
+ * @sa setRTR()
+ */
+#define  getRTR() \
+		WIZCHIP_READ(_RTR_)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref _RCR_ register
+ * @param (uint8_t)rcr Value to set @ref _RCR_ register.
+ * @sa getRCR()
+ */
+#define  setRCR(rcr) \
+		WIZCHIP_WRITE(_RCR_, ((uint16_t)rcr)&0x00FF)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref _RCR_ register
+ * @return uint8_t. Value of @ref _RCR_ register.
+ * @sa setRCR()
+ */
+#define  getRCR() \
+		((uint8_t)(WIZCHIP_READ(_RCR_) & 0x00FF))
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref TMS01R register
+ * @param (uint16_t)tms01r Value to set @ref TMS01R register. The lower socket memory size is located at MSB of tms01r.
+ * @sa getTMS01R()
+ */
+#define  setTMS01R(tms01r) \
+   WIZCHIP_WRITE(TMS01R,tms01r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref TMS01R register
+ * @return uint16_t. Value of @ref TMS01R register.
+ * @sa setTMS01R()
+ */
+#define  getTMS01R()  \
+   WIZCHIP_READ(TMS01R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref TMS23R register
+ * @param (uint16_t)tms23r Value to set @ref TMS23R register. The lower socket memory size is located at MSB of tms01r.
+ * @sa getTMS23R()
+ */
+#define  setTMS23R(tms23r) \
+   WIZCHIP_WRITE(TMS23R,tms23r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref TMS23R register
+ * @return uint16_t. Value of @ref TMS23R register.
+ * @sa setTMS23R()
+ */
+#define  getTMS23R()  \
+   WIZCHIP_READ(TMS23R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref TMS45R register
+ * @param (uint16_t)tms45r Value to set @ref TMS45R register. The lower socket memory size is located at MSB of tms45r.
+ * @sa getTMS45R()
+ */
+#define  setTMS45R(tms45r) \
+   WIZCHIP_WRITE(TMS45R,tms45r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref TMS45R register
+ * @return uint16_t. Value of @ref TMS45R register.
+ * @sa setTMS45R()
+ */
+#define  getTMS45R()  \
+   WIZCHIP_READ(TMS45R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref TMS67R register
+ * @param (uint16_t)tms67r Value to set @ref TMS67R register. The lower socket memory size is located at MSB of tms67r.
+ * @sa getTMS67R()
+ */
+#define  setTMS67R(tms67r) \
+   WIZCHIP_WRITE(TMS67R,tms67r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref TMS67R register
+ * @return uint16_t. Value of @ref TMS67R register.
+ * @sa setTMS67R()
+ */
+#define  getTMS67R()  \
+   WIZCHIP_READ(TMS67R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref TMSR0 ~ @ref TMSR7 register
+ * @param (uint8_t)sn Socket number. It should be 0 ~ 7. 
+ * @param (uint8_t)tmsr Value to set @ref TMSR0 ~@ref TMSR7 register. 
+ * @sa getTMSR()
+ */
+void  setTMSR(uint8_t sn,uint8_t tmsr);
+#define setSn_TXBUF_SIZE(sn, tmsr)   setTMSR(sn, tmsr) ///< For compatible ioLibrary
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref TMSR0 ~ @ref TMSR7 register
+ * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
+ * @return uint8_t. Value of @ref TMSR0 ~ @ref TMSR7
+ * @sa getTMSR()
+ */
+uint8_t getTMSR(uint8_t sn);
+#define getSn_TXBUF_SIZE(sn)  getTMSR(sn) ///< For compatible ioLibrary
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref RMS01R register
+ * @param (uint16_t)rms01r Value to set @ref RMS01R register. The lower socket memory size is located at MSB of rms01r.
+ * @sa getRMS01R()
+ */
+#define setRMS01R(rms01r) \
+   WIZCHIP_WRITE(RMS01R,rms01r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref RMS01R register
+ * @return uint16_t. Value of @ref RMS01R register.
+ * @sa setRMS01R()
+ */
+#define getRMS01R()  \
+   WIZCHIP_READ(RMS01R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref RMS23R register
+ * @param (uint16_t)rms23r Value to set @ref RMS23R register. The lower socket memory size is located at MSB of rms01r.
+ * @sa getRMS23R()
+ */
+#define setRMS23R(rms23r) \
+   WIZCHIP_WRITE(RMS23R,rms23r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref RMS23R register
+ * @return uint16_t. Value of @ref RMS23R register.
+ * @sa setRMS23R()
+ */
+#define getRMS23R()  \
+   WIZCHIP_READ(RMS23R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref RMS45R register
+ * @param (uint16_t)rms45r Value to set @ref RMS45R register. The lower socket memory size is located at MSB of rms45r.
+ * @sa getRMS45R()
+ */
+#define setRMS45R(rms45r) \
+   WIZCHIP_WRITE(RMS45R,rms45r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref RMS45R register
+ * @return uint16_t. Value of @ref RMS45R register.
+ * @sa setRMS45R()
+ */
+#define getRMS45R()  \
+   WIZCHIP_READ(RMS45R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref RMS67R register
+ * @param (uint16_t)rms67r Value to set @ref RMS67R register. The lower socket memory size is located at MSB of rms67r.
+ * @sa getRMS67R()
+ */
+#define setRMS67R(rms67r) \
+   WIZCHIP_WRITE(RMS67R,rms67r)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref RMS67R register
+ * @return uint16_t. Value of @ref RMS67R register.
+ * @sa setRMS67R()
+ */
+#define getRMS67R()  \
+   WIZCHIP_READ(RMS67R)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref RMS01R ~ @ref RMS67R register
+ * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
+ * @param (uint8_t)rmsr Value to set @ref RMSR0 ~@ref RMSR7 register. 
+ * @sa getTMSR()
+ */
+void setRMSR(uint8_t sn,uint8_t rmsr);
+#define setSn_RXBUF_SIZE(sn,rmsr)   setRMSR(sn, rmsr)   ///< For compatible ioLibrary
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref RMS01R ~ @ref RMS67R register
+ * @param (uint8_t)sn Socket number. It shoudl be 0 ~ 7.
+ * @return uint8_t. Value of @ref RMSR0 ~ @ref RMSR7 register.
+ * @sa setRMSR()
+ */
+uint8_t getRMSR(uint8_t sn);
+#define getSn_RXBUF_SIZE(sn)  getRMSR(sn)    ///< For compatible ioLibrary
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref MTYPER register
+ * @param (uint16_t)mtyper Value to set @ref MTYPER register. 
+ * @sa getMTYPER()
+ */
+#define setMTYPER(mtype) \
+   WIZCHIP_WRITE(MTYPER, mtype)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref MTYPER register
+ * @return uint16_t. Value of @ref MTYPER register. 
+ * @sa setMTYPER()
+ */
+#define getMTYPER() \
+   WIZCHIP_READ(MTYPER)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref RATR register
+ * @return uint16_t. Value of @ref PATR register.
+ */
+#define getPATR() \
+   WIZCHIP_READ(PATR)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref PTIMER register
+ * @param (uint8_t)ptimer Value to set @ref PTIMER register.
+ * @sa getPTIMER()
+ */
+#define setPTIMER(ptimer) \
+		WIZCHIP_WRITE(PTIMER, ((uint16_t)ptimer) & 0x00FF)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref PTIMER register
+ * @return uint8_t. Value of @ref PTIMER register.
+ * @sa setPTIMER()
+ */
+#define getPTIMER() \
+		((uint8_t)(WIZCHIP_READ(PTIMER) & 0x00FF))
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref PMAGIC register
+ * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
+ * @sa getPMAGIC()
+ */
+#define setPMAGIC(pmagic) \
+		WIZCHIP_WRITE(PMAGIC, ((uint16_t)pmagic) & 0x00FF)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref PMAGIC register
+ * @return uint8_t. Value of @ref PMAGIC register.
+ * @sa setPMAGIC()
+ */
+#define getPMAGIC() \
+		((uint8_t)(WIZCHIP_READ(PMAGIC) & 0x00FF))
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref PSID register
+ * @return uint16_t. Value of @ref PSID register.
+ */
+#define getPSIDR() \
+		WIZCHIP_READ(PSIDR)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref PDHAR register
+ * @param (uint8_t*)pdhar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes.
+ */
+#define getPDHAR(pdhar) { \
+		(pdhar)[0] = (uint8_t)(WIZCHIP_READ(PDHAR) >> 8); \
+		(pdhar)[1] = (uint8_t)(WIZCHIP_READ(PDHAR));      \
+		(pdhar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,2)) >> 8); \
+		(pdhar)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,2))); \
+		(pdhar)[4] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,4)) >> 8); \
+		(pdhar)[5] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(PDHAR,4))); \
+   }
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get unreachable IP address. @ref UIPR
+ * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes.
+ */
+#define getUIPR(uipr) { \
+		(uipr)[0] = (uint8_t)(WIZCHIP_READ(UIPR) >> 8); \
+		(uipr)[1] = (uint8_t)(WIZCHIP_READ(UIPR));      \
+		(uipr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(UIPR,2)) >> 8); \
+		(uipr)[3] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(UIPR,2))); \
+   }
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref UPORTR register
+ * @return uint16_t. Value of @ref UPORTR register.
+ */
+#define getUPORTR() \
+	WIZCHIP_READ(UPORTR)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref FMTUR register
+ * @return uint16_t. Value of @ref FMTUR register.
+ */
+#define getFMTUR() \
+   WIZCHIP_READ(FMTUR)
+
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref Pn_BRDYR register
+ * @return uint8_t. Value of @ref Pn_BRDYR register.
+ */
+#define getPn_BRDYR(p) \
+   ((uint8_t)(WIZCHIP_READ(Pn_BRDYR(p)) & 0x00FF))
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref Pn_BRDYR register
+ * @param p Pin number (p = 0,1,2,3)
+ * @param brdyr Set a value @ref Pn_BRDYR(p). 
+ */
+#define setPn_BRDYR(p, brdyr) \
+   WIZCHIP_WRITE(Pn_BRDYR(p), brdyr & 0x00E7)
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref Pn_BDPTHR register
+ * @param p Pin number (p = 0,1,2,3)
+ * @return uint16_t. Value of @ref Pn_BDPTHR register.
+ */
+#define getPn_BDPTHR(p) \
+   WIZCHIP_READ(Pn_BDPTHR(p))
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Set @ref Pn_BDPTHR register
+ * @param p Pin number (p = 0,1,2,3)
+ * @param bdpthr Value of @ref Pn_BDPTHR
+ */
+#define setPn_BDPTHR(p, bdpthr) \
+   WIZCHIP_WRITE(Pn_BDPTHR(p),bdpthr)
+
+
+/**
+ * @ingroup Common_register_access_function_W5300
+ * @brief Get @ref IDR register
+ * @return uint16_t. Always 0x5300.
+ */
+#define getIDR() \
+   WIZCHIP_READ(IDR)
+
+
+/***********************************
+ * SOCKET Register Access Function *
+ ***********************************/
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_MR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)mr Value to set @ref Sn_MR
+ * @sa getSn_MR()
+ */
+#define setSn_MR(sn, mr) \
+   WIZCHIP_WRITE(Sn_MR(sn),mr)
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_MR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_MR.
+ * @sa setSn_MR()
+ */
+#define getSn_MR(sn) \
+	WIZCHIP_READ(Sn_MR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)cr Value to set @ref Sn_CR
+ * @sa getSn_CR()
+ */
+#define setSn_CR(sn, cr) \
+   WIZCHIP_WRITE(Sn_CR(sn), ((uint16_t)cr) & 0x00FF)
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_CR.
+ * @sa setSn_CR()
+ */
+#define getSn_CR(sn) \
+   ((uint8_t)WIZCHIP_READ(Sn_CR(sn)))
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)imr Value to set @ref Sn_IMR
+ * @sa getSn_IMR()
+ */
+#define setSn_IMR(sn, imr) \
+   WIZCHIP_WRITE(Sn_IMR(sn), ((uint16_t)imr) & 0x00FF)
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_IMR.
+ * @sa setSn_IMR()
+ */
+#define getSn_IMR(sn) \
+   ((uint8_t)WIZCHIP_READ(Sn_IMR(sn)))
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)ir Value to set @ref Sn_IR
+ * @sa getSn_IR()
+ */
+#define setSn_IR(sn, ir) \
+   WIZCHIP_WRITE(Sn_IR(sn), ((uint16_t)ir) & 0x00FF)
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_IR.
+ * @sa setSn_IR()
+ */
+#define getSn_IR(sn) \
+   ((uint8_t)WIZCHIP_READ(Sn_IR(sn)))
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_SR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_SR.
+ */
+#define getSn_SSR(sn) \
+   ((uint8_t)WIZCHIP_READ(Sn_SR(sn)))
+#define getSn_SR(sn) getSn_SSR(sn)  ///< For compatible ioLibrary. Refer to getSn_SSR().
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_PORTR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)port Variable to set @ref Sn_PORTR.
+ * @sa getSn_PORTR()
+ */
+#define setSn_PORTR(sn, port) \
+   WIZCHIP_WRITE(Sn_PORTR(sn), port)
+#define setSn_PORT(sn, port)   setSn_PORTR(sn, port)   ///< For compatible ioLibrary
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_PORTR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Variable of @ref Sn_PORTR.
+ * @sa setSn_PORTR()
+ */
+#define getSn_PORTR(sn) \
+   WIZCHIP_READ(Sn_PORTR(sn))
+#define getSn_PORT(sn)   getSn_PORTR(sn)   ///< For compatible ioLibrary
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa getSn_DHAR()
+ */
+#define setSn_DHAR(sn, dhar) { \
+      WIZCHIP_WRITE(Sn_DHAR(sn),                       (((uint16_t)((dhar)[0])) << 8) + (((uint16_t)((dhar)[1])) & 0x00FF)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),2), (((uint16_t)((dhar)[0])) << 8) + (((uint16_t)((dhar)[1])) & 0x00FF)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),4), (((uint16_t)((dhar)[0])) << 8) + (((uint16_t)((dhar)[1])) & 0x00FF)); \
+   }      
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_MR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa setSn_DHAR()
+ */
+#define getSn_DHAR(sn, dhar) { \
+      (dhar)[0] = (uint8_t)(WIZCHIP_READ(Sn_DHAR(sn)) >> 8); \
+      (dhar)[1] = (uint8_t) WIZCHIP_READ(Sn_DHAR(sn)); \
+      (dhar)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),2)) >> 8); \
+      (dhar)[3] = (uint8_t) WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),2)); \
+      (dhar)[4] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),4)) >> 8); \
+      (dhar)[5] = (uint8_t) WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DHAR(sn),4)); \
+   }
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)dport Value to set @ref Sn_DPORT
+ * @sa getSn_DPORT()
+ */
+#define setSn_DPORTR(sn, dport) \
+   WIZCHIP_WRITE(Sn_DPORTR(sn),dport) 
+#define setSn_DPORT(sn, dport)   setSn_DPORTR(sn,dport) ///< For compatible ioLibrary. Refer to @ref Sn_DPORTR.
+
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_DPORT.
+ * @sa setSn_DPORT()
+ * @note This function is not available because W5300 have a bug to read @ref Sn_DPORTR. \n
+ *       Don't use this function. 
+ */
+#define getSn_DPORTR(sn) \
+   WIZCHIP_READ(Sn_DPORTR(sn))
+#define getSn_DPORT(sn) getSn_DPORTR(sn)  ///< For compatible ioLibrary. Refer to @ref Sn_DPORTR.
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
+ * @sa getSn_DIPR()
+ */
+#define setSn_DIPR(sn, dipr) { \
+		WIZCHIP_WRITE(Sn_DIPR(sn),                       (((uint16_t)((dipr)[0])) << 8) + (((uint16_t)((dipr)[1])) & 0x00FF)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DIPR(sn),2), (((uint16_t)((dipr)[2])) << 8) + (((uint16_t)((dipr)[3])) & 0x00FF)); \
+   }
+   
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
+ * @sa setSn_DIPR()
+ */
+#define getSn_DIPR(sn, dipr) { \
+		(dipr)[0] = (uint8_t)(WIZCHIP_READ(Sn_DIPR(sn)) >> 8); \
+		(dipr)[1] = (uint8_t) WIZCHIP_READ(Sn_DIPR(sn));  \
+		(dipr)[2] = (uint8_t)(WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DIPR(sn),2)) >> 8); \
+		(dipr)[3] = (uint8_t) WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DIPR(sn),2));  \
+   }
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)mss Value to set @ref Sn_MSSR
+ * @sa setSn_MSSR()
+ */
+#define setSn_MSSR(sn, mss) \
+   WIZCHIP_WRITE(Sn_MSSR(sn), mss)
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_MSSR.
+ * @sa setSn_MSSR()
+ */
+#define getSn_MSSR(sn) \
+   WIZCHIP_READ(Sn_MSSR(sn))
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_KPALVTR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR
+ * @sa getSn_KPALVTR()
+ */
+#define setSn_KPALVTR(sn, kpalvt) \
+   WIZCHIP_WRITE(Sn_KPALVTR(sn), (WIZCHIP_READ(Sn_KPALVTR(sn)) & 0x00FF) | (((uint16_t)kpalvt)<<8))
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_KPALVTR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_KPALVTR.
+ * @sa setSn_KPALVTR()
+ */
+#define getSn_KPALVTR(sn) \
+		((uint8_t)(WIZCHIP_READ(Sn_KPALVTR(sn)) >> 8))
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_PROTOR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)proto Value to set \ref Sn_PROTOR
+ * @sa getSn_PROTOR()
+ */
+#define setSn_PROTOR(sn, proto) \
+   WIZCHIP_WRITE(Sn_PROTOR(sn),(WIZCHIP_READ(Sn_PROTOR(sn)) & 0xFF00) | (((uint16_t)proto) & 0x00FF))
+#define setSn_PROTO(sn,proto)    setSn_PROTOR(sn,proto)  ///< For compatible ioLibrary   
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_PROTOR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return uint8_t. Value of @ref Sn_PROTOR.
+ * @sa setSn_PROTOR()
+ */
+#define getSn_PROTOR(sn) \
+   ((uint8_t)WIZCHIP_READ(Sn_PROTOR(sn)))
+#define getSn_PROTO(sn)    getSn_PROTOR(sn)  ///< For compatible ioLibrary   
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_TX_WRSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint32_t)txwrs Value to set @ref Sn_KPALVTR (It should be <= 0x00010000)
+ * @sa getSn_TX_WRSR()
+ */
+#define  setSn_TX_WRSR(sn, txwrs) { \
+      WIZCHIP_WRITE(Sn_TX_WRSR(sn),                       (uint16_t)(((uint32_t)txwrs) >> 16)); \
+      WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WRSR(sn),2), (uint16_t)txwrs); \
+   }
+   
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_TX_WRSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint32_t. Value of Sn_TX_WRSR.
+ * @sa setSn_TX_WRSR()
+ */
+#define  getSn_TX_WRSR(sn) \
+   ( (((uint32_t)WIZCHIP_READ(Sn_TX_WRSR(sn))) << 16) + (((uint32_t)WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WRSR(sn),1))) & 0x0000FFFF) )
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_TX_FSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint32_t. Value of @ref Sn_TX_FSR.
+ */
+uint32_t getSn_TX_FSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_RX_RSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint32_t. Value of @ref Sn_RX_RSR.
+ */
+uint32_t getSn_RX_RSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_TX_FIFOR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)txfifo. Value to set @ref Sn_TX_FIFOR.
+ */
+#define  setSn_TX_FIFOR(sn, txfifo) \
+   WIZCHIP_WRITE(Sn_TX_FIFOR(sn), txfifo);
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_RX_FIFOR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_RX_FIFOR.
+ */
+#define getSn_RX_FIFOR(sn) \
+   WIZCHIP_READ(Sn_RX_FIFOR(sn));
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_TOSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param (uint8_t)tos Value to set @ref Sn_TOSR
+ * @sa getSn_TOSR()
+ */
+#define setSn_TOSR(sn, tos) \
+   WIZCHIP_WRITE(Sn_TOS(sn), ((uint16_t)tos) & 0x00FF)
+#define setSn_TOS(sn,tos)  setSn_TOSR(sn,tos)   ///< For compatible ioLibrar
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_TOSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_ </b>.
+ * @return uint8_t. Value of Sn_TOSR.
+ * @sa setSn_TOSR()
+ */
+#define getSn_TOSR(sn) \
+   ((uint8_t)WIZCHIP_READ(Sn_TOSR(sn)))
+#define getSn_TOS(sn)   getSn_TOSR(sn)    ///< For compatible ioLibrar
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_TTLR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)ttl Value to set @ref Sn_TTLR
+ * @sa getSn_TTLR()
+ */
+#define setSn_TTLR(sn, ttl) \
+   WIZCHIP_WRITE(Sn_TTLR(sn), ((uint16_t)ttl) & 0x00FF)
+#define setSn_TTL(sn,ttl)     setSn_TTLR(sn,ttl)   ///< For compatible ioLibrary
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_TTLR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_TTLR.
+ * @sa setSn_TTLR()
+ */
+#define getSn_TTLR(sn) \
+   ((uint8_t)WIZCHIP_READ(Sn_TTL(sn)))
+#define getSn_TTL(sn)     getSn_TTLR(sn)    ///< For compatible ioLibrary
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Set @ref Sn_FRAGR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)frag Value to set @ref Sn_FRAGR
+ * @sa getSn_FRAGR()
+ */
+#define setSn_FRAGR(sn, frag) \
+   WIZCHIP_WRITE(Sn_FRAGR(sn),  ((uint16_t)frag) & 0x00FF)
+#define setSn_FRAG(sn,frag)   setSn_FRAGR(sn,flag)
+
+/**
+ * @ingroup Socket_register_access_function_W5300
+ * @brief Get @ref Sn_FRAGR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_FRAGR.
+ * @sa setSn_FRAGR()
+ */
+#define getSn_FRAGR(sn) \
+   (WIZCHIP_READ(Sn_FRAG(sn)))
+#define getSn_FRAG(sn)    getSn_FRAGR(sn)
+
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+
+/**  
+ * @brief Socket_register_access_function_W5300
+ * @brief Gets the max buffer size of socket sn passed as parameter.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint32_t. Value of Socket n RX max buffer size.
+ */
+#define getSn_RxMAX(sn) \
+		(((uint32_t)getSn_RXBUF_SIZE(sn)) << 10)		
+
+/**  
+ * @brief Socket_register_access_function_W5300
+ * @brief Gets the max buffer size of socket sn passed as parameters.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint32_t. Value of Socket n TX max buffer size.
+ */
+#define getSn_TxMAX(sn) \
+		(((uint32_t)getSn_TXBUF_SIZE(sn)) << 10)		
+
+/**
+ * @ingroup Basic_IO_function_W5300
+ * @brief It copies data to internal TX memory
+ *
+ * @details This function reads the Tx write pointer register and after that,
+ * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory
+ * and updates the Tx write pointer register.
+ * This function is being called by send() and sendto() function also.
+ *
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param wizdata Pointer buffer to write data
+ * @param len Data length
+ * @sa wiz_recv_data()
+ */
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint32_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5300
+ * @brief It copies data to your buffer from internal RX memory
+ *
+ * @details This function read the Rx read pointer register and after that,
+ * it copies the received data from internal RX memory
+ * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes.
+ * This function is being called by recv() also.
+ *
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param wizdata Pointer buffer to read data
+ * @param len Data length
+ * @sa wiz_send_data()
+ */
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint32_t len);
+
+/**
+ * @ingroup Basic_IO_function_W5300
+ * @brief It discard the received data in RX memory.
+ * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param len Data length
+ */
+void wiz_recv_ignore(uint8_t sn, uint32_t len);
+
+/// \cond DOXY_APPLY_CODE
+#endif
+/// \endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif   // _W5300_H_

+ 267 - 0
lib/ioLibrary_Driver/Ethernet/W5500/w5500.c

@@ -0,0 +1,267 @@
+//*****************************************************************************
+//
+//! \file w5500.c
+//! \brief W5500 HAL Interface.
+//! \version 1.0.2
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2015/02/05> Notice
+//!        The version history is not updated after this point.
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//!       <2014/05/01> V1.0.2
+//!         1. Implicit type casting -> Explicit type casting. Refer to M20140501
+//!            Fixed the problem on porting into under 32bit MCU
+//!            Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
+//!            Thank for your interesting and serious advices.
+//!       <2013/12/20> V1.0.1
+//!         1. Remove warning
+//!         2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
+//!            for loop optimized(removed). refer to M20131220
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+//#include <stdio.h>
+#include "w5500.h"
+
+#define _W5500_SPI_VDM_OP_          0x00
+#define _W5500_SPI_FDM_OP_LEN1_     0x01
+#define _W5500_SPI_FDM_OP_LEN2_     0x02
+#define _W5500_SPI_FDM_OP_LEN4_     0x03
+
+#if   (_WIZCHIP_ == 5500)
+////////////////////////////////////////////////////
+
+uint8_t  WIZCHIP_READ(uint32_t AddrSel)
+{
+   uint8_t ret;
+   uint8_t spi_data[3];
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+   AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
+
+   if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+        WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
+        WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+        WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+   }
+   else																// burst operation
+   {
+        spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
+        spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
+        spi_data[2] = (AddrSel & 0x000000FF) >> 0;
+        WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+   }
+   ret = WIZCHIP.IF.SPI._read_byte();
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+   return ret;
+}
+
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
+{
+   uint8_t spi_data[4];
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+   AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
+
+   //if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   if(!WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+		WIZCHIP.IF.SPI._write_byte(wb);
+   }
+   else									// burst operation
+   {
+		spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
+		spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
+		spi_data[2] = (AddrSel & 0x000000FF) >> 0;
+		spi_data[3] = wb;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 4);
+   }
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+         
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint8_t spi_data[3];
+   uint16_t i;
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+   AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
+
+   if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+		for(i = 0; i < len; i++)
+		   pBuf[i] = WIZCHIP.IF.SPI._read_byte();
+   }
+   else																// burst operation
+   {
+		spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
+		spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
+		spi_data[2] = (AddrSel & 0x000000FF) >> 0;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+		WIZCHIP.IF.SPI._read_burst(pBuf, len);
+   }
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
+{
+   uint8_t spi_data[3];
+   uint16_t i;
+
+   WIZCHIP_CRITICAL_ENTER();
+   WIZCHIP.CS._select();
+
+   AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
+
+   if(!WIZCHIP.IF.SPI._write_burst) 	// byte operation
+   {
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
+		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
+		for(i = 0; i < len; i++)
+			WIZCHIP.IF.SPI._write_byte(pBuf[i]);
+   }
+   else									// burst operation
+   {
+		spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
+		spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
+		spi_data[2] = (AddrSel & 0x000000FF) >> 0;
+		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
+		WIZCHIP.IF.SPI._write_burst(pBuf, len);
+   }
+
+   WIZCHIP.CS._deselect();
+   WIZCHIP_CRITICAL_EXIT();
+}
+
+
+uint16_t getSn_TX_FSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_TX_FSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+
+uint16_t getSn_RX_RSR(uint8_t sn)
+{
+   uint16_t val=0,val1=0;
+
+   do
+   {
+      val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
+      val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      if (val1 != 0)
+      {
+        val = WIZCHIP_READ(Sn_RX_RSR(sn));
+        val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
+      }
+   }while (val != val1);
+   return val;
+}
+
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+   uint16_t ptr = 0;
+   uint32_t addrsel = 0;
+
+   if(len == 0)  return;
+   ptr = getSn_TX_WR(sn);
+   //M20140501 : implict type casting -> explict type casting
+   //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
+   addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
+   //
+   WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
+   
+   ptr += len;
+   setSn_TX_WR(sn,ptr);
+}
+
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
+{
+   uint16_t ptr = 0;
+   uint32_t addrsel = 0;
+   
+   if(len == 0) return;
+   ptr = getSn_RX_RD(sn);
+   //M20140501 : implict type casting -> explict type casting
+   //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
+   addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
+   //
+   WIZCHIP_READ_BUF(addrsel, wizdata, len);
+   ptr += len;
+   
+   setSn_RX_RD(sn,ptr);
+}
+
+
+void wiz_recv_ignore(uint8_t sn, uint16_t len)
+{
+   uint16_t ptr = 0;
+
+   ptr = getSn_RX_RD(sn);
+   ptr += len;
+   setSn_RX_RD(sn,ptr);
+}
+
+#endif

+ 2165 - 0
lib/ioLibrary_Driver/Ethernet/W5500/w5500.h

@@ -0,0 +1,2165 @@
+//*****************************************************************************
+//
+//! \file w5500.h
+//! \brief W5500 HAL Header File.
+//! \version 1.0.0
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2015/02/05> Notice
+//!        The version history is not updated after this point.
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+//
+
+#ifndef  _W5500_H_
+#define  _W5500_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "wizchip_conf.h"
+
+/// @cond DOXY_APPLY_CODE
+#if   (_WIZCHIP_ == 5500)
+/// @endcond
+
+#define _W5500_IO_BASE_              0x00000000
+
+#define _W5500_SPI_READ_			   (0x00 << 2) //< SPI interface Read operation in Control Phase
+#define _W5500_SPI_WRITE_			   (0x01 << 2) //< SPI interface Write operation in Control Phase
+
+#define WIZCHIP_CREG_BLOCK          0x00 	//< Common register block
+#define WIZCHIP_SREG_BLOCK(N)       (1+4*N) //< Socket N register block
+#define WIZCHIP_TXBUF_BLOCK(N)      (2+4*N) //< Socket N Tx buffer address block
+#define WIZCHIP_RXBUF_BLOCK(N)      (3+4*N) //< Socket N Rx buffer address block
+
+#define WIZCHIP_OFFSET_INC(ADDR, N)    (ADDR + (N<<8)) //< Increase offset address
+
+
+///////////////////////////////////////
+// Definition For Legacy Chip Driver //
+///////////////////////////////////////
+#define IINCHIP_READ(ADDR)                WIZCHIP_READ(ADDR)               ///< The defined for legacy chip driver
+#define IINCHIP_WRITE(ADDR,VAL)           WIZCHIP_WRITE(ADDR,VAL)          ///< The defined for legacy chip driver
+#define IINCHIP_READ_BUF(ADDR,BUF,LEN)    WIZCHIP_READ_BUF(ADDR,BUF,LEN)   ///< The defined for legacy chip driver
+#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN)   WIZCHIP_WRITE(ADDR,BUF,LEN)      ///< The defined for legacy chip driver
+
+//////////////////////////////
+//--------------------------  defgroup ---------------------------------
+/**
+ * @defgroup W5500 W5500
+ *
+ * @brief WHIZCHIP register defines and I/O functions of @b W5500.
+ *
+ * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group
+ * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function
+ */
+ 
+ 
+/**
+ * @defgroup WIZCHIP_register WIZCHIP register
+ * @ingroup W5500
+ *
+ * @brief WHIZCHIP register defines register group of @b W5500.
+ *
+ * - @ref Common_register_group : Common register group
+ * - @ref Socket_register_group : \c SOCKET n register group
+ */
+
+
+/**
+ * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions
+ * @ingroup W5500
+ *
+ * @brief This supports the basic I/O functions for @ref WIZCHIP_register.
+ *
+ * - <b> Basic I/O function </b> \n
+ *   WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n
+ *
+ * - @ref Common_register_group <b>access functions</b> \n
+ * 	-# @b Mode \n
+ *    getMR(), setMR()
+ * 	-# @b Interrupt \n
+ *    getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL()
+ * 	-# <b> Network Information </b> \n
+ *    getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
+ * 	-# @b Retransmission \n
+ *    getRCR(), setRCR(), getRTR(), setRTR()
+ * 	-# @b PPPoE \n
+ *    getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU()
+ * 	-# <b> ICMP packet </b>\n
+ *    getUIPR(), getUPORTR()
+ * 	-# @b etc. \n
+ *    getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n
+ *
+ * - \ref Socket_register_group <b>access functions</b> \n
+ *   -# <b> SOCKET control</b> \n
+ *      getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR()
+ *   -# <b> SOCKET information</b> \n
+ *      getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
+ *      getSn_MSSR(), setSn_MSSR()
+ *   -# <b> SOCKET communication </b> \n
+ *      getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n
+ *      getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
+ *      getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
+ *      getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR()
+ *   -# <b> IP header field </b> \n
+ *      getSn_FRAG(), setSn_FRAG(),  getSn_TOS(), setSn_TOS() \n
+ *      getSn_TTL(), setSn_TTL()
+ */
+
+
+
+/**
+ * @defgroup Common_register_group Common register
+ * @ingroup WIZCHIP_register
+ *
+ * @brief Common register group\n
+ * It set the basic for the networking\n
+ * It set the configuration such as interrupt, network information, ICMP, etc.
+ * @details
+ * @sa MR : Mode register.
+ * @sa GAR, SUBR, SHAR, SIPR
+ * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt.
+ * @sa _RTR_, _RCR_ : Data retransmission.
+ * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE.
+ * @sa UIPR, UPORTR : ICMP message.
+ * @sa PHYCFGR, VERSIONR : etc.
+ */
+ 
+  
+ 
+/**
+ * @defgroup Socket_register_group Socket register
+ * @ingroup WIZCHIP_register
+ *
+ * @brief Socket register group.\n
+ * Socket register configures and control SOCKETn which is necessary to data communication.
+ * @details
+ * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control
+ * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
+ * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol.
+ * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
+ */
+ 
+ 
+ 
+ /**
+ * @defgroup Basic_IO_function Basic I/O function
+ * @ingroup WIZCHIP_IO_Functions
+ * @brief These are basic input/output functions to read values from register or write values to register.
+ */
+
+/**
+ * @defgroup Common_register_access_function Common register access functions
+ * @ingroup WIZCHIP_IO_Functions
+ * @brief These are functions to access <b>common registers</b>.
+ */
+
+/**
+ * @defgroup Socket_register_access_function Socket register access functions
+ * @ingroup WIZCHIP_IO_Functions
+ * @brief These are functions to access <b>socket registers</b>.
+ */
+ 
+//------------------------------- defgroup end --------------------------------------------
+//----------------------------- W5500 Common Registers IOMAP -----------------------------
+/**
+ * @ingroup Common_register_group
+ * @brief Mode Register address(R/W)\n
+ * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
+ * @details Each bit of @ref MR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>FARP</td> <td>Reserved</td> </tr>
+ * </table>
+ * - \ref MR_RST		 	: Reset
+ * - \ref MR_WOL       	: Wake on LAN
+ * - \ref MR_PB         : Ping block
+ * - \ref MR_PPPOE      : PPPoE mode
+ * - \ref MR_FARP			: Force ARP mode
+ */
+#define MR                 (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Gateway IP Register address(R/W)
+ * @details @ref GAR configures the default gateway address.
+ */
+#define GAR                (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Subnet mask Register address(R/W)
+ * @details @ref SUBR configures the subnet mask address.
+ */
+#define SUBR               (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Source MAC Register address(R/W)
+ * @details @ref SHAR configures the source hardware address.
+ */
+#define SHAR               (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Source IP Register address(R/W)
+ * @details @ref SIPR configures the source IP address.
+ */
+#define SIPR               (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Set Interrupt low level timer register address(R/W)
+ * @details @ref INTLEVEL configures the Interrupt Assert Time.
+ */
+#define INTLEVEL           (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Interrupt Register(R/W)
+ * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host.
+ * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
+ * Each bit of @ref IR defined as follows.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>CONFLICT</td> <td>UNREACH</td> <td>PPPoE</td> <td>MP</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr>
+ * </table>
+ * - \ref IR_CONFLICT : IP conflict
+ * - \ref IR_UNREACH  : Destination unreachable
+ * - \ref IR_PPPoE	  : PPPoE connection close
+ * - \ref IR_MP		  : Magic packet
+ */
+#define IR                 (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Interrupt mask register(R/W)
+ * @details @ref _IMR_ is used to mask interrupts. Each bit of @ref _IMR_ corresponds to each bit of @ref IR.
+ * When a bit of @ref _IMR_ is and the corresponding bit of @ref IR is  an interrupt will be issued. In other words,
+ * if a bit of @ref _IMR_ is  an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n
+ * Each bit of @ref _IMR_ defined as the following.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>IM_IR7</td> <td>IM_IR6</td> <td>IM_IR5</td> <td>IM_IR4</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr>
+ * </table>
+ * - \ref IM_IR7 : IP Conflict Interrupt Mask
+ * - \ref IM_IR6 : Destination unreachable Interrupt Mask
+ * - \ref IM_IR5 : PPPoE Close Interrupt Mask
+ * - \ref IM_IR4 : Magic Packet Interrupt Mask
+ */
+//M20150401 : Rename SYMBOE ( Re-define error in a compile) 
+//#define IMR                (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+#define _IMR_                (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Socket Interrupt Register(R/W)
+ * @details @ref SIR indicates the interrupt status of Socket.\n
+ * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n
+ * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */
+#define SIR                (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Socket Interrupt Mask Register(R/W)
+ * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR.
+ * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is  Interrupt will be issued.
+ * In other words, if a bit of @ref SIMR is  an interrupt will be not issued even if the corresponding bit of @ref SIR is 
+ */
+#define SIMR               (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Timeout register address( 1 is 100us )(R/W)
+ * @details @ref _RTR_ configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref _RTR_ is x07D0.
+ * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref _RTR_, W5500 waits for the peer response
+ * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
+ * If the peer does not respond within the @ref _RTR_ time, W5500 retransmits the packet or issues timeout.
+ */
+//M20150401 : Rename SYMBOE ( Re-define error in a compile)  
+//#define RTR                (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+#define _RTR_                (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Retry count register(R/W)
+ * @details @ref _RCR_ configures the number of time of retransmission.
+ * When retransmission occurs as many as ref _RCR_+1 Timeout interrupt is issued (@ref Sn_IR_TIMEOUT = '1').
+ */
+//M20150401 : Rename SYMBOE ( Re-define error in a compile)
+//#define RCR                (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3))  
+#define _RCR_                (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief PPP LCP Request Timer register  in PPPoE mode(R/W)
+ * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
+ */
+#define PTIMER             (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief PPP LCP Magic number register  in PPPoE mode(R/W)
+ * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
+ */
+#define PMAGIC             (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief PPP Destination MAC Register address(R/W)
+ * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process.
+ */
+#define PHAR                (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief PPP Session Identification Register(R/W)
+ * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process.
+ */
+#define PSID               (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief PPP Maximum Segment Size(MSS) register(R/W)
+ * @details @ref PMRU configures the maximum receive unit of PPPoE.
+ */
+#define PMRU               (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Unreachable IP register address in UDP mode(R)
+ * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
+ * which socket is not open and @ref IR_UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates
+ * the destination IP address & port number respectively.
+ */
+#define UIPR               (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief Unreachable Port register address in UDP mode(R)
+ * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
+ * which socket is not open and @ref IR_UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR
+ * indicates the destination IP address & port number respectively.
+ */
+#define UPORTR              (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief PHY Status Register(R/W)
+ * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link.
+ */
+#define PHYCFGR            (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+// Reserved			         (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+/**
+ * @ingroup Common_register_group
+ * @brief chip version register address(R)
+ * @details @ref VERSIONR always indicates the W5500 version as @b 0x04.
+ */
+#define VERSIONR           (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3))
+
+
+//----------------------------- W5500 Socket Registers IOMAP -----------------------------
+/**
+ * @ingroup Socket_register_group
+ * @brief socket Mode register(R/W)
+ * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n
+ * Each bit of @ref Sn_MR defined as the following.
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>MULTI/MFEN</td> <td>BCASTB</td> <td>ND/MC/MMB</td> <td>UCASTB/MIP6B</td> <td>Protocol[3]</td> <td>Protocol[2]</td> <td>Protocol[1]</td> <td>Protocol[0]</td> </tr>
+ * </table>
+ * - @ref Sn_MR_MULTI	: Support UDP Multicasting
+ * - @ref Sn_MR_BCASTB	: Broadcast block <b>in UDP Multicasting</b>
+ * - @ref Sn_MR_ND		: No Delayed Ack(TCP) flag
+ * - @ref Sn_MR_MC   	: IGMP version used <b>in UDP mulitcasting</b>
+ * - @ref Sn_MR_MMB    	: Multicast Blocking <b>in @ref Sn_MR_MACRAW mode</b>
+ * - @ref Sn_MR_UCASTB	: Unicast Block <b>in UDP Multicating</b>
+ * - @ref Sn_MR_MIP6B   : IPv6 packet Blocking <b>in @ref Sn_MR_MACRAW mode</b>
+ * - <b>Protocol</b>
+ * <table>
+ * 		<tr>   <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td>   </tr>
+ * 		<tr>   <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td>   </tr>
+ * </table>
+ *	- @ref Sn_MR_MACRAW	: MAC LAYER RAW SOCK \n
+ *  - @ref Sn_MR_UDP		: UDP
+ *  - @ref Sn_MR_TCP		: TCP
+ *  - @ref Sn_MR_CLOSE	: Unused socket
+ *  @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR(N)           (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Socket command register(R/W)
+ * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
+ * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00.
+ * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n
+ * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR.
+ * - @ref Sn_CR_OPEN 		: Initialize or open socket.
+ * - @ref Sn_CR_LISTEN 		: Wait connection request in TCP mode(<b>Server mode</b>)
+ * - @ref Sn_CR_CONNECT 	: Send connection request in TCP mode(<b>Client mode</b>)
+ * - @ref Sn_CR_DISCON 		: Send closing request in TCP mode.
+ * - @ref Sn_CR_CLOSE   	: Close socket.
+ * - @ref Sn_CR_SEND    	: Update TX buffer pointer and send data.
+ * - @ref Sn_CR_SEND_MAC	: Send data with MAC address, so without ARP process.
+ * - @ref Sn_CR_SEND_KEEP 	: Send keep alive message.
+ * - @ref Sn_CR_RECV		: Update RX buffer pointer and receive data.
+ */
+#define Sn_CR(N)           (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Socket interrupt register(R)
+ * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
+ * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is  the corresponding bit of @ref Sn_IR becomes \n
+ * In order to clear the @ref Sn_IR bit, the host should write the bit to \n
+ * <table>
+ * 		<tr>  <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td>   </tr>
+ * 		<tr>  <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>SEND_OK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr>
+ * </table>
+ * - \ref Sn_IR_SENDOK : <b>SEND_OK Interrupt</b>
+ * - \ref Sn_IR_TIMEOUT : <b>TIMEOUT Interrupt</b>
+ * - \ref Sn_IR_RECV : <b>RECV Interrupt</b>
+ * - \ref Sn_IR_DISCON : <b>DISCON Interrupt</b>
+ * - \ref Sn_IR_CON : <b>CON Interrupt</b>
+ */
+#define Sn_IR(N)           (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Socket status register(R)
+ * @details @ref Sn_SR indicates the status of Socket n.\n
+ * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
+ * @par Normal status
+ * - @ref SOCK_CLOSED 		: Closed
+ * - @ref SOCK_INIT   		: Initiate state
+ * - @ref SOCK_LISTEN    	: Listen state
+ * - @ref SOCK_ESTABLISHED 	: Success to connect
+ * - @ref SOCK_CLOSE_WAIT   : Closing state
+ * - @ref SOCK_UDP   		: UDP socket
+ * - @ref SOCK_MACRAW  		: MAC raw mode socket
+ *@par Temporary status during changing the status of Socket n.
+ * - @ref SOCK_SYNSENT   	: This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
+ * - @ref SOCK_SYNRECV    	: It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
+ * - @ref SOCK_FIN_WAIT		: Connection state
+ * - @ref SOCK_CLOSING		: Closing state
+ * - @ref SOCK_TIME_WAIT	: Closing state
+ * - @ref SOCK_LAST_ACK 	: Closing state
+ */
+#define Sn_SR(N)           (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief source port register(R/W)
+ * @details @ref Sn_PORT configures the source port number of Socket n.
+ * It is valid when Socket n is used in TCP/UDP mode. It should be set before OPEN command is ordered.
+ */
+#define Sn_PORT(N)         (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Peer MAC register address(R/W)
+ * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
+ * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
+ */
+#define Sn_DHAR(N)         (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Peer IP register address(R/W)
+ * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP client mode, it configures an IP address of TCP serverbefore CONNECT command.
+ * In TCP server mode, it indicates an IP address of TCP clientafter successfully establishing connection.
+ * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
+ */
+#define Sn_DIPR(N)         (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Peer port register address(R/W)
+ * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
+ * In TCP clientmode, it configures the listen port number of TCP serverbefore CONNECT command.
+ * In TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
+ * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
+ */
+#define Sn_DPORT(N)        (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
+ * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
+ */
+#define Sn_MSSR(N)         (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+#define Sn_PROTO(N)         (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+// Reserved			         (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief IP Type of Service(TOS) Register(R/W)
+ * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TOS(N)          (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+/**
+ * @ingroup Socket_register_group
+ * @brief IP Time to live(TTL) Register(R/W)
+ * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
+ * It is set before OPEN command.
+ */
+#define Sn_TTL(N)          (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) 
+// Reserved			         (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+// Reserved			         (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Receive memory size register(R/W)
+ * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n.
+ * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
+ * If a different size is configured, the data cannot be normally received from a peer.
+ * Although Socket n RX Buffer Block size is initially configured to 2Kbytes,
+ * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes.
+ * When exceeded, the data reception error is occurred.
+ */
+#define Sn_RXBUF_SIZE(N)   (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Transmit memory size register(R/W)
+ * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
+ * If a different size is configured, the data can�t be normally transmitted to a peer.
+ * Although Socket n TX Buffer Block size is initially configured to 2Kbytes,
+ * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes.
+ * When exceeded, the data transmission error is occurred.
+ */
+#define Sn_TXBUF_SIZE(N)   (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Transmit free memory size register(R)
+ * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE.
+ * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
+ * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
+ * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
+ * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
+ */
+#define Sn_TX_FSR(N)       (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Transmit memory read pointer register address(R)
+ * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.
+ * After its initialization, it is auto-increased by SEND command.
+ * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer.
+ * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR.
+ * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_TX_RD(N)        (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Transmit memory write pointer register address(R/W)
+ * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n
+ * It should be read or be updated like as follows.\n
+ * 1. Read the starting address for saving the transmitting data.\n
+ * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
+ * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size.
+ * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
+ * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
+ */
+#define Sn_TX_WR(N)        (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Received data size register(R)
+ * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
+ * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between
+ * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD)
+ */
+#define Sn_RX_RSR(N)       (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Read point of Receive memory(R/W)
+ * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
+ * 1. Read the starting save address of the received data.\n
+ * 2. Read data from the starting address of Socket n RX Buffer.\n
+ * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size.
+ * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
+ * update with the lower 16bits value ignored the carry bit.\n
+ * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500.
+ */
+#define Sn_RX_RD(N)        (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Write point of Receive memory(R)
+ * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
+ * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
+ * then the carry bit is ignored and will automatically update with the lower 16bits value.
+ */
+#define Sn_RX_WR(N)        (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief socket interrupt mask register(R)
+ * @details @ref Sn_IMR masks the interrupt of Socket n.
+ * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is 
+ * the corresponding bit of @ref Sn_IR becomes  When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is 
+ * Host is interrupted by asserted INTn PIN to low.
+ */
+#define Sn_IMR(N)          (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Fragment field value in IP header register(R/W)
+ * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header).
+ */
+#define Sn_FRAG(N)         (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+/**
+ * @ingroup Socket_register_group
+ * @brief Keep Alive Timer register(R/W)
+ * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode,
+ * and ignored in other modes. The time unit is 5s.
+ * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once.
+ * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process).
+ * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate,
+ * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process).
+ * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'.
+ */
+#define Sn_KPALVTR(N)      (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+//#define Sn_TSR(N)          (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
+
+
+//----------------------------- W5500 Register values  -----------------------------
+
+/* MODE register values */
+/**
+ * @brief Reset
+ * @details If this bit is  All internal registers will be initialized. It will be automatically cleared as after S/W reset.
+ */
+#define MR_RST                       0x80
+
+/**
+ * @brief Wake on LAN
+ * @details 0 : Disable WOL mode\n
+ * 1 : Enable WOL mode\n
+ * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low.
+ * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.)
+ * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and
+ * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode.
+ */
+#define MR_WOL                       0x20
+
+/**
+ * @brief Ping block
+ * @details 0 : Disable Ping block\n
+ * 1 : Enable Ping block\n
+ * If the bit is  it blocks the response to a ping request.
+ */
+#define MR_PB                        0x10
+
+/**
+ * @brief Enable PPPoE
+ * @details 0 : DisablePPPoE mode\n
+ * 1 : EnablePPPoE mode\n
+ * If you use ADSL, this bit should be 
+ */
+#define MR_PPPOE                     0x08
+
+/**
+ * @brief Enable UDP_FORCE_ARP CHECHK
+ * @details 0 : Disable Force ARP mode\n
+ * 1 : Enable Force ARP mode\n
+ * In Force ARP mode, It forces on sending ARP Request whenever data is sent.
+ */
+#define MR_FARP                      0x02
+
+/* IR register values */
+/**
+ * @brief Check IP conflict.
+ * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
+ */
+#define IR_CONFLICT                  0x80
+
+/**
+ * @brief Get the destination unreachable message in UDP sending.
+ * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as 
+ * When this bit is  Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR.
+ */
+#define IR_UNREACH                   0x40
+
+/**
+ * @brief Get the PPPoE close message.
+ * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
+ */
+#define IR_PPPoE                     0x20
+
+/**
+ * @brief Get the magic packet interrupt.
+ * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set.
+ */
+#define IR_MP                        0x10
+
+
+/* PHYCFGR register value */
+#define PHYCFGR_RST                  ~(1<<7)  //< For PHY reset, must operate AND mask.
+#define PHYCFGR_OPMD                 (1<<6)   // Configre PHY with OPMDC value
+#define PHYCFGR_OPMDC_ALLA           (7<<3)
+#define PHYCFGR_OPMDC_PDOWN          (6<<3)
+#define PHYCFGR_OPMDC_NA             (5<<3)
+#define PHYCFGR_OPMDC_100FA          (4<<3)
+#define PHYCFGR_OPMDC_100F           (3<<3)
+#define PHYCFGR_OPMDC_100H           (2<<3)
+#define PHYCFGR_OPMDC_10F            (1<<3)
+#define PHYCFGR_OPMDC_10H            (0<<3)           
+#define PHYCFGR_DPX_FULL             (1<<2)
+#define PHYCFGR_DPX_HALF             (0<<2)
+#define PHYCFGR_SPD_100              (1<<1)
+#define PHYCFGR_SPD_10               (0<<1)
+#define PHYCFGR_LNK_ON               (1<<0)
+#define PHYCFGR_LNK_OFF              (0<<0)
+
+/* IMR register values */
+/**
+ * @brief IP Conflict Interrupt Mask.
+ * @details 0: Disable IP Conflict Interrupt\n
+ * 1: Enable IP Conflict Interrupt
+ */
+#define IM_IR7                  	 0x80
+
+/**
+ * @brief Destination unreachable Interrupt Mask.
+ * @details 0: Disable Destination unreachable Interrupt\n
+ * 1: Enable Destination unreachable Interrupt
+ */
+#define IM_IR6                  	 0x40
+
+/**
+ * @brief PPPoE Close Interrupt Mask.
+ * @details 0: Disable PPPoE Close Interrupt\n
+ * 1: Enable PPPoE Close Interrupt
+ */
+#define IM_IR5                  	 0x20
+
+/**
+ * @brief Magic Packet Interrupt Mask.
+ * @details 0: Disable Magic Packet Interrupt\n
+ * 1: Enable Magic Packet Interrupt
+ */
+#define IM_IR4                  	 0x10
+
+/* Sn_MR Default values */
+/**
+ * @brief Support UDP Multicasting
+ * @details 0 : disable Multicasting\n
+ * 1 : enable Multicasting\n
+ * This bit is applied only during UDP mode(P[3:0] = 010.\n
+ * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
+ * before Socket n is opened by OPEN command of @ref Sn_CR.
+ */
+#define Sn_MR_MULTI                  0x80
+
+/**
+ * @brief Broadcast block in UDP Multicasting.
+ * @details 0 : disable Broadcast Blocking\n
+ * 1 : enable Broadcast Blocking\n
+ * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m
+ * In addition, This bit does when MACRAW mode(P[3:0] = 100
+ */
+#define Sn_MR_BCASTB                 0x40
+
+/**
+ * @brief No Delayed Ack(TCP), Multicast flag
+ * @details 0 : Disable No Delayed ACK option\n
+ * 1 : Enable No Delayed ACK option\n
+ * This bit is applied only during TCP mode (P[3:0] = 001.\n
+ * When this bit is  It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
+ * When this bit is  It sends the ACK packet after waiting for the timeout time configured by @ref _RTR_.
+ */
+#define Sn_MR_ND                     0x20
+
+/**
+ * @brief Unicast Block in UDP Multicasting
+ * @details 0 : disable Unicast Blocking\n
+ * 1 : enable Unicast Blocking\n
+ * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = 
+ */
+#define Sn_MR_UCASTB                 0x10
+
+/**
+ * @brief MAC LAYER RAW SOCK
+ * @details This configures the protocol mode of Socket n.
+ * @note MACRAW mode should be only used in Socket 0.
+ */
+#define Sn_MR_MACRAW                 0x04
+
+#define Sn_MR_IPRAW                  0x03     /**< IP LAYER RAW SOCK */
+
+/**
+ * @brief UDP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_UDP                    0x02
+
+/**
+ * @brief TCP
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_TCP                    0x01
+
+/**
+ * @brief Unused socket
+ * @details This configures the protocol mode of Socket n.
+ */
+#define Sn_MR_CLOSE                  0x00
+
+/* Sn_MR values used with Sn_MR_MACRAW */
+/**
+ * @brief MAC filter enable in @ref Sn_MR_MACRAW mode
+ * @details 0 : disable MAC Filtering\n
+ * 1 : enable MAC Filtering\n
+ * This bit is applied only during MACRAW mode(P[3:0] = 100.\n
+ * When set as  W5500 can only receive broadcasting packet or packet sent to itself.
+ * When this bit is  W5500 can receive all packets on Ethernet.
+ * If user wants to implement Hybrid TCP/IP stack,
+ * it is recommended that this bit is set as for reducing host overhead to process the all received packets.
+ */
+#define Sn_MR_MFEN                   Sn_MR_MULTI
+
+/**
+ * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode
+ * @details 0 : using IGMP version 2\n
+ * 1 : using IGMP version 1\n
+ * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = 
+ * It configures the version for IGMP messages (Join/Leave/Report).
+ */
+#define Sn_MR_MMB                    Sn_MR_ND
+
+/**
+ * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
+ * @details 0 : disable IPv6 Blocking\n
+ * 1 : enable IPv6 Blocking\n
+ * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet.
+ */
+#define Sn_MR_MIP6B                  Sn_MR_UCASTB
+
+/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */
+/**
+ * @brief IGMP version used in UDP mulitcasting
+ * @details 0 : disable Multicast Blocking\n
+ * 1 : enable Multicast Blocking\n
+ * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address.
+ */
+#define Sn_MR_MC                     Sn_MR_ND
+
+/* Sn_MR alternate values */
+/**
+ * @brief For Berkeley Socket API
+ */
+#define SOCK_STREAM                  Sn_MR_TCP
+
+/**
+ * @brief For Berkeley Socket API
+ */
+#define SOCK_DGRAM                   Sn_MR_UDP
+
+
+/* Sn_CR values */
+/**
+ * @brief Initialize or open socket
+ * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
+ * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n
+ * <table>
+ *   <tr>  <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td>            		 </tr>
+ *   <tr>  <td>Sn_MR_CLOSE  (000)</td> <td></td>         	   		 </tr>
+ *   <tr>  <td>Sn_MR_TCP  (001)</td> <td>SOCK_INIT (0x13)</td>  		 </tr>
+ *   <tr>  <td>Sn_MR_UDP  (010)</td>  <td>SOCK_UDP (0x22)</td>  		 </tr>
+ *   <tr>  <td>S0_MR_MACRAW  (100)</td>  <td>SOCK_MACRAW (0x02)</td>  </tr>
+ * </table>
+ */
+#define Sn_CR_OPEN                   0x01
+
+/**
+ * @brief Wait connection request in TCP mode(Server mode)
+ * @details This is valid only in TCP mode (\ref Sn_MR(P3:P0) = \ref Sn_MR_TCP).
+ * In this mode, Socket n operates as a TCP serverand waits for  connection-request (SYN packet) from any TCP client
+ * The @ref Sn_SR changes the state from \ref SOCK_INIT to \ref SOCKET_LISTEN.
+ * When a TCP clientconnection request is successfully established,
+ * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the @ref Sn_IR(0) becomes 
+ * But when a TCP clientconnection request is failed, @ref Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED.
+ */
+#define Sn_CR_LISTEN                 0x02
+
+/**
+ * @brief Send connection request in TCP mode(Client mode)
+ * @details  To connect, a connect-request (SYN packet) is sent to <b>TCP server</b>configured by @ref Sn_DIPR & Sn_DPORT(destination address & port).
+ * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
+ * The connect-request fails in the following three cases.\n
+ * 1. When a @b ARPTO occurs (@ref Sn_IR[3] =  ) because destination hardware address is not acquired through the ARP-process.\n
+ * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) =  )\n
+ * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED.
+ * @note This is valid only in TCP mode and operates when Socket n acts as <b>TCP client</b>
+ */
+#define Sn_CR_CONNECT                0x04
+
+/**
+ * @brief Send closing request in TCP mode
+ * @details Regardless of <b>TCP server</b>or <b>TCP client</b> the DISCON command processes the disconnect-process (b>Active close</b>or <b>Passive close</b>.\n
+ * @par Active close
+ * it transmits disconnect-request(FIN packet) to the connected peer\n
+ * @par Passive close
+ * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
+ * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n
+ * Otherwise, TCPTO occurs (\ref Sn_IR(3)='1') and then @ref Sn_SR is changed to @ref SOCK_CLOSED.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_DISCON                 0x08
+
+/**
+ * @brief Close socket
+ * @details Sn_SR is changed to @ref SOCK_CLOSED.
+ */
+#define Sn_CR_CLOSE                  0x10
+
+/**
+ * @brief Update TX buffer pointer and send data
+ * @details SEND transmits all the data in the Socket n TX buffer.\n
+ * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n,
+ * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD).
+ */
+#define Sn_CR_SEND                   0x20
+
+/**
+ * @brief Send data with MAC address, so without ARP process
+ * @details The basic operation is same as SEND.\n
+ * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
+ * But SEND_MAC transmits data without the automatic ARP-process.\n
+ * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process.
+ * @note Valid only in UDP mode.
+ */
+#define Sn_CR_SEND_MAC               0x21
+
+/**
+ * @brief Send keep alive message
+ * @details It checks the connection status by sending 1byte keep-alive packet.\n
+ * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
+ * @note Valid only in TCP mode.
+ */
+#define Sn_CR_SEND_KEEP              0x22
+
+/**
+ * @brief Update RX buffer pointer and receive data
+ * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n
+ * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR),
+ * and Socket n RX Read Pointer Register (@ref Sn_RX_RD).
+ */
+#define Sn_CR_RECV                   0x40
+
+/* Sn_IR values */
+/**
+ * @brief SEND_OK Interrupt
+ * @details This is issued when SEND command is completed.
+ */
+#define Sn_IR_SENDOK                 0x10
+
+/**
+ * @brief TIMEOUT Interrupt
+ * @details This is issued when ARPTO or TCPTO occurs.
+ */
+#define Sn_IR_TIMEOUT                0x08
+
+/**
+ * @brief RECV Interrupt
+ * @details This is issued whenever data is received from a peer.
+ */
+#define Sn_IR_RECV                   0x04
+
+/**
+ * @brief DISCON Interrupt
+ * @details This is issued when FIN or FIN/ACK packet is received from a peer.
+ */
+#define Sn_IR_DISCON                 0x02
+
+/**
+ * @brief CON Interrupt
+ * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED.
+ */
+#define Sn_IR_CON                    0x01
+
+/* Sn_SR values */
+/**
+ * @brief Closed
+ * @details This indicates that Socket n is released.\n
+ * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status.
+ */
+#define SOCK_CLOSED                  0x00
+
+/**
+ * @brief Initiate state
+ * @details This indicates Socket n is opened with TCP mode.\n
+ * It is changed to @ref SOCK_INIT when @ref Sn_MR(P[3:0]) = 001 and OPEN command is ordered.\n
+ * After @ref SOCK_INIT, user can use LISTEN /CONNECT command.
+ */
+#define SOCK_INIT                    0x13
+
+/**
+ * @brief Listen state
+ * @details This indicates Socket n is operating as <b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer <b>TCP client</b>.\n
+ * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n
+ * Otherwise it will change to @ref SOCK_CLOSED after TCPTO @ref Sn_IR(TIMEOUT) = '1') is occurred.
+ */
+#define SOCK_LISTEN                  0x14
+
+/**
+ * @brief Connection state
+ * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
+ * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n
+ * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n
+ * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = '1') is occurred.
+ */
+#define SOCK_SYNSENT                 0x15
+
+/**
+ * @brief Connection state
+ * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
+ * If socket n sends the response (SYN/ACK  packet) to the peer successfully,  it changes to @ref SOCK_ESTABLISHED. \n
+ * If not, it changes to @ref SOCK_CLOSED after timeout (@ref Sn_IR[TIMEOUT] = '1') is occurred.
+ */
+#define SOCK_SYNRECV                 0x16
+
+/**
+ * @brief Success to connect
+ * @details This indicates the status of the connection of Socket n.\n
+ * It changes to @ref SOCK_ESTABLISHED when the <b>TCP SERVER</b>processed the SYN packet from the <b>TCP CLIENT</b>during @ref SOCK_LISTEN, or
+ * when the CONNECT command is successful.\n
+ * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
+ */
+#define SOCK_ESTABLISHED             0x17
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
+ */
+#define SOCK_FIN_WAIT                0x18
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
+ */
+#define SOCK_CLOSING                 0x1A
+
+/**
+ * @brief Closing state
+ * @details These indicate Socket n is closing.\n
+ * These are shown in disconnect-process such as active-close and passive-close.\n
+ * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
+ */
+#define SOCK_TIME_WAIT               0x1B
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
+ * This is half-closing status, and data can be transferred.\n
+ * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used.
+ */
+#define SOCK_CLOSE_WAIT              0x1C
+
+/**
+ * @brief Closing state
+ * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
+ * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout(@ref Sn_IR[TIMEOUT] = '1') is occurred.
+ */
+#define SOCK_LAST_ACK                0x1D
+
+/**
+ * @brief UDP socket
+ * @details This indicates Socket n is opened in UDP mode(@ref Sn_MR(P[3:0]) = '010').\n
+ * It changes to SOCK_UDP when @ref Sn_MR(P[3:0]) = '010' and @ref Sn_CR_OPEN command is ordered.\n
+ * Unlike TCP mode, data can be transfered without the connection-process.
+ */
+#define SOCK_UDP                     0x22
+
+#define SOCK_IPRAW                   0x32     /**< IP raw mode socket */
+
+/**
+ * @brief MAC raw mode socket
+ * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n
+ * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n
+ * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
+ */
+#define SOCK_MACRAW                  0x42
+
+//#define SOCK_PPPOE                   0x5F
+
+/* IP PROTOCOL */
+#define IPPROTO_IP                   0        //< Dummy for IP 
+#define IPPROTO_ICMP                 1        //< Control message protocol
+#define IPPROTO_IGMP                 2        //< Internet group management protocol
+#define IPPROTO_GGP                  3        //< Gateway^2 (deprecated)
+#define IPPROTO_TCP                  6        //< TCP
+#define IPPROTO_PUP                  12       //< PUP
+#define IPPROTO_UDP                  17       //< UDP
+#define IPPROTO_IDP                  22       //< XNS idp
+#define IPPROTO_ND                   77       //< UNOFFICIAL net disk protocol
+#define IPPROTO_RAW                  255      //< Raw IP packet
+
+
+/**
+ * @brief Enter a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n \n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * \sa WIZCHIP_CRITICAL_EXIT()
+ */
+#define WIZCHIP_CRITICAL_ENTER()    WIZCHIP.CRIS._enter()
+
+#ifdef _exit
+#undef _exit
+#endif
+
+/**
+ * @brief Exit a critical section
+ *
+ * @details It is provided to protect your shared code which are executed without distribution. \n\n
+ *
+ * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
+ * In OS environment, You can replace it to critical section api supported by OS.
+ *
+ * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
+ * @sa WIZCHIP_CRITICAL_ENTER()
+ */
+#define WIZCHIP_CRITICAL_EXIT()     WIZCHIP.CRIS._exit()
+
+
+////////////////////////
+// Basic I/O Function //
+////////////////////////
+
+/**
+ * @ingroup Basic_IO_function
+ * @brief It reads 1 byte value from a register.
+ * @param AddrSel Register address
+ * @return The value of register
+ */
+uint8_t  WIZCHIP_READ (uint32_t AddrSel);
+
+/**
+ * @ingroup Basic_IO_function
+ * @brief It writes 1 byte value to a register.
+ * @param AddrSel Register address
+ * @param wb Write data
+ * @return void
+ */
+void     WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
+
+/**
+ * @ingroup Basic_IO_function
+ * @brief It reads sequence data from registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to read data
+ * @param len Data length
+ */
+void     WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function
+ * @brief It writes sequence data to registers.
+ * @param AddrSel Register address
+ * @param pBuf Pointer buffer to write data
+ * @param len Data length
+ */
+void     WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
+
+/////////////////////////////////
+// Common Register I/O function //
+/////////////////////////////////
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set Mode Register
+ * @param (uint8_t)mr The value to be set.
+ * @sa getMR()
+ */
+#define setMR(mr) \
+	WIZCHIP_WRITE(MR,mr)
+
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get Mode Register
+ * @return uint8_t. The value of Mode register.
+ * @sa setMR()
+ */
+#define getMR() \
+		WIZCHIP_READ(MR)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set gateway IP address
+ * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
+ * @sa getGAR()
+ */
+#define setGAR(gar) \
+		WIZCHIP_WRITE_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get gateway IP address
+ * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
+ * @sa setGAR()
+ */
+#define getGAR(gar) \
+		WIZCHIP_READ_BUF(GAR,gar,4)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set subnet mask address
+ * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
+ * @sa getSUBR()
+ */
+#define setSUBR(subr) \
+		WIZCHIP_WRITE_BUF(SUBR, subr,4)
+
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get subnet mask address
+ * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
+ * @sa setSUBR()
+ */
+#define getSUBR(subr) \
+		WIZCHIP_READ_BUF(SUBR, subr, 4)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set local MAC address
+ * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
+ * @sa getSHAR()
+ */
+#define setSHAR(shar) \
+		WIZCHIP_WRITE_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get local MAC address
+ * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
+ * @sa setSHAR()
+ */
+#define getSHAR(shar) \
+		WIZCHIP_READ_BUF(SHAR, shar, 6)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set local IP address
+ * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
+ * @sa getSIPR()
+ */
+#define setSIPR(sipr) \
+		WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get local IP address
+ * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
+ * @sa setSIPR()
+ */
+#define getSIPR(sipr) \
+		WIZCHIP_READ_BUF(SIPR, sipr, 4)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set INTLEVEL register
+ * @param (uint16_t)intlevel Value to set @ref INTLEVEL register.
+ * @sa getINTLEVEL()
+ */
+#define setINTLEVEL(intlevel)  {\
+		WIZCHIP_WRITE(INTLEVEL,   (uint8_t)(intlevel >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \
+	}
+
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get INTLEVEL register
+ * @return uint16_t. Value of @ref INTLEVEL register.
+ * @sa setINTLEVEL()
+ */
+//M20150401 : Type explict declaration
+/*
+#define getINTLEVEL() \
+		((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1)))
+*/
+#define getINTLEVEL() \
+		(((uint16_t)WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1)))
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref IR register
+ * @param (uint8_t)ir Value to set @ref IR register.
+ * @sa getIR()
+ */
+#define setIR(ir) \
+		WIZCHIP_WRITE(IR, (ir & 0xF0))
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref IR register
+ * @return uint8_t. Value of @ref IR register.
+ * @sa setIR()
+ */
+#define getIR() \
+		(WIZCHIP_READ(IR) & 0xF0)
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref _IMR_ register
+ * @param (uint8_t)imr Value to set @ref _IMR_ register.
+ * @sa getIMR()
+ */
+#define setIMR(imr) \
+		WIZCHIP_WRITE(_IMR_, imr)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref _IMR_ register
+ * @return uint8_t. Value of @ref _IMR_ register.
+ * @sa setIMR()
+ */
+#define getIMR() \
+		WIZCHIP_READ(_IMR_)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref SIR register
+ * @param (uint8_t)sir Value to set @ref SIR register.
+ * @sa getSIR()
+ */
+#define setSIR(sir) \
+		WIZCHIP_WRITE(SIR, sir)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref SIR register
+ * @return uint8_t. Value of @ref SIR register.
+ * @sa setSIR()
+ */
+#define getSIR() \
+		WIZCHIP_READ(SIR)
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref SIMR register
+ * @param (uint8_t)simr Value to set @ref SIMR register.
+ * @sa getSIMR()
+ */
+#define setSIMR(simr) \
+		WIZCHIP_WRITE(SIMR, simr)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref SIMR register
+ * @return uint8_t. Value of @ref SIMR register.
+ * @sa setSIMR()
+ */
+#define getSIMR() \
+		WIZCHIP_READ(SIMR)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref _RTR_ register
+ * @param (uint16_t)rtr Value to set @ref _RTR_ register.
+ * @sa getRTR()
+ */
+#define setRTR(rtr)   {\
+		WIZCHIP_WRITE(_RTR_,   (uint8_t)(rtr >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(_RTR_,1), (uint8_t) rtr); \
+	}
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref _RTR_ register
+ * @return uint16_t. Value of @ref _RTR_ register.
+ * @sa setRTR()
+ */
+//M20150401 : Type explict declaration
+/*
+#define getRTR() \
+		((WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1)))
+*/
+#define getRTR() \
+		(((uint16_t)WIZCHIP_READ(_RTR_) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_RTR_,1)))
+
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref _RCR_ register
+ * @param (uint8_t)rcr Value to set @ref _RCR_ register.
+ * @sa getRCR()
+ */
+#define setRCR(rcr) \
+		WIZCHIP_WRITE(_RCR_, rcr)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref _RCR_ register
+ * @return uint8_t. Value of @ref _RCR_ register.
+ * @sa setRCR()
+ */
+#define getRCR() \
+		WIZCHIP_READ(_RCR_)
+
+//================================================== test done ===========================================================
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref PTIMER register
+ * @param (uint8_t)ptimer Value to set @ref PTIMER register.
+ * @sa getPTIMER()
+ */
+#define setPTIMER(ptimer) \
+		WIZCHIP_WRITE(PTIMER, ptimer)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref PTIMER register
+ * @return uint8_t. Value of @ref PTIMER register.
+ * @sa setPTIMER()
+ */
+#define getPTIMER() \
+		WIZCHIP_READ(PTIMER)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref PMAGIC register
+ * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
+ * @sa getPMAGIC()
+ */
+#define setPMAGIC(pmagic) \
+		WIZCHIP_WRITE(PMAGIC, pmagic)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref PMAGIC register
+ * @return uint8_t. Value of @ref PMAGIC register.
+ * @sa setPMAGIC()
+ */
+#define getPMAGIC() \
+		WIZCHIP_READ(PMAGIC)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref PHAR address
+ * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes.
+ * @sa getPHAR()
+ */
+#define setPHAR(phar) \
+		WIZCHIP_WRITE_BUF(PHAR, phar, 6)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref PHAR address
+ * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes.
+ * @sa setPHAR()
+ */
+#define getPHAR(phar) \
+		WIZCHIP_READ_BUF(PHAR, phar, 6)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref PSID register
+ * @param (uint16_t)psid Value to set @ref PSID register.
+ * @sa getPSID()
+ */
+#define setPSID(psid)  {\
+		WIZCHIP_WRITE(PSID,   (uint8_t)(psid >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \
+	}
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref PSID register
+ * @return uint16_t. Value of @ref PSID register.
+ * @sa setPSID()
+ */
+//uint16_t getPSID(void);
+//M20150401 : Type explict declaration
+/*
+#define getPSID() \
+		((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1)))
+*/
+#define getPSID() \
+		(((uint16_t)WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1)))
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref PMRU register
+ * @param (uint16_t)pmru Value to set @ref PMRU register.
+ * @sa getPMRU()
+ */
+#define setPMRU(pmru) { \
+		WIZCHIP_WRITE(PMRU,   (uint8_t)(pmru>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \
+	}
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref PMRU register
+ * @return uint16_t. Value of @ref PMRU register.
+ * @sa setPMRU()
+ */
+//M20150401 : Type explict declaration
+/*
+#define getPMRU() \
+		((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1)))
+*/
+#define getPMRU() \
+		(((uint16_t)WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1)))
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get unreachable IP address
+ * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes.
+ */
+//M20150401 : Size Error of UIPR (6 -> 4)
+/*
+#define getUIPR(uipr) \
+		WIZCHIP_READ_BUF(UIPR,uipr,6)
+*/
+#define getUIPR(uipr) \
+		WIZCHIP_READ_BUF(UIPR,uipr,4)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref UPORTR register
+ * @return uint16_t. Value of @ref UPORTR register.
+ */
+//M20150401 : Type explict declaration 
+/*
+#define getUPORTR() \
+	((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1)))
+*/
+#define getUPORTR() \
+	(((uint16_t)WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1)))	
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Set @ref PHYCFGR register
+ * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register.
+ * @sa getPHYCFGR()
+ */
+#define setPHYCFGR(phycfgr) \
+		WIZCHIP_WRITE(PHYCFGR, phycfgr)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref PHYCFGR register
+ * @return uint8_t. Value of @ref PHYCFGR register.
+ * @sa setPHYCFGR()
+ */
+#define getPHYCFGR() \
+		WIZCHIP_READ(PHYCFGR)
+
+/**
+ * @ingroup Common_register_access_function
+ * @brief Get @ref VERSIONR register
+ * @return uint8_t. Value of @ref VERSIONR register.
+ */
+#define getVERSIONR() \
+		WIZCHIP_READ(VERSIONR)
+
+/////////////////////////////////////
+
+///////////////////////////////////
+// Socket N register I/O function //
+///////////////////////////////////
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_MR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)mr Value to set @ref Sn_MR
+ * @sa getSn_MR()
+ */
+#define setSn_MR(sn, mr) \
+		WIZCHIP_WRITE(Sn_MR(sn),mr)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_MR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_MR.
+ * @sa setSn_MR()
+ */
+#define getSn_MR(sn) \
+	WIZCHIP_READ(Sn_MR(sn))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)cr Value to set @ref Sn_CR
+ * @sa getSn_CR()
+ */
+#define setSn_CR(sn, cr) \
+		WIZCHIP_WRITE(Sn_CR(sn), cr)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_CR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_CR.
+ * @sa setSn_CR()
+ */
+#define getSn_CR(sn) \
+		WIZCHIP_READ(Sn_CR(sn))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)ir Value to set @ref Sn_IR
+ * @sa getSn_IR()
+ */
+#define setSn_IR(sn, ir) \
+		WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_IR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_IR.
+ * @sa setSn_IR()
+ */
+#define getSn_IR(sn) \
+		(WIZCHIP_READ(Sn_IR(sn)) & 0x1F)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)imr Value to set @ref Sn_IMR
+ * @sa getSn_IMR()
+ */
+#define setSn_IMR(sn, imr) \
+		WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_IMR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_IMR.
+ * @sa setSn_IMR()
+ */
+#define getSn_IMR(sn) \
+		(WIZCHIP_READ(Sn_IMR(sn)) & 0x1F)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_SR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_SR.
+ */
+#define getSn_SR(sn) \
+		WIZCHIP_READ(Sn_SR(sn))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)port Value to set @ref Sn_PORT.
+ * @sa getSn_PORT()
+ */
+#define setSn_PORT(sn, port)  { \
+		WIZCHIP_WRITE(Sn_PORT(sn),   (uint8_t)(port >> 8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_PORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_PORT.
+ * @sa setSn_PORT()
+ */
+//M20150401 : Type explict declaration 
+/*
+#define getSn_PORT(sn) \
+		((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1)))
+*/
+#define getSn_PORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1)))		
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_DHAR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa getSn_DHAR()
+ */
+#define setSn_DHAR(sn, dhar) \
+		WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_MR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
+ * @sa setSn_DHAR()
+ */
+#define getSn_DHAR(sn, dhar) \
+		WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
+ * @sa getSn_DIPR()
+ */
+#define setSn_DIPR(sn, dipr) \
+		WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_DIPR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
+ * @sa setSn_DIPR()
+ */
+#define getSn_DIPR(sn, dipr) \
+		WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)dport Value to set @ref Sn_DPORT
+ * @sa getSn_DPORT()
+ */
+#define setSn_DPORT(sn, dport) { \
+		WIZCHIP_WRITE(Sn_DPORT(sn),   (uint8_t) (dport>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t)  dport); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_DPORT register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_DPORT.
+ * @sa setSn_DPORT()
+ */
+//M20150401 : Type explict declaration
+/*
+#define getSn_DPORT(sn) \
+		((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)))
+*/
+#define getSn_DPORT(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)))		
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)mss Value to set @ref Sn_MSSR
+ * @sa setSn_MSSR()
+ */
+#define setSn_MSSR(sn, mss) { \
+		WIZCHIP_WRITE(Sn_MSSR(sn),   (uint8_t)(mss>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_MSSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_MSSR.
+ * @sa setSn_MSSR()
+ */
+//M20150401 : Type explict declaration
+/*
+#define getSn_MSSR(sn) \
+		((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1)))
+*/
+#define getSn_MSSR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1)))		
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)tos Value to set @ref Sn_TOS
+ * @sa getSn_TOS()
+ */
+#define setSn_TOS(sn, tos) \
+		WIZCHIP_WRITE(Sn_TOS(sn), tos)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_TOS register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of Sn_TOS.
+ * @sa setSn_TOS()
+ */
+#define getSn_TOS(sn) \
+		WIZCHIP_READ(Sn_TOS(sn))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)ttl Value to set @ref Sn_TTL
+ * @sa getSn_TTL()
+ */
+#define setSn_TTL(sn, ttl) \
+		WIZCHIP_WRITE(Sn_TTL(sn), ttl)
+
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_TTL register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_TTL.
+ * @sa setSn_TTL()
+ */
+#define getSn_TTL(sn) \
+		WIZCHIP_READ(Sn_TTL(sn))
+
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_RXBUF_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE
+ * @sa getSn_RXBUF_SIZE()
+ */
+#define setSn_RXBUF_SIZE(sn, rxbufsize) \
+		WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize)
+
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_RXBUF_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_RXBUF_SIZE.
+ * @sa setSn_RXBUF_SIZE()
+ */
+#define getSn_RXBUF_SIZE(sn) \
+		WIZCHIP_READ(Sn_RXBUF_SIZE(sn))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_TXBUF_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE
+ * @sa getSn_TXBUF_SIZE()
+ */
+#define setSn_TXBUF_SIZE(sn, txbufsize) \
+		WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_TXBUF_SIZE register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_TXBUF_SIZE.
+ * @sa setSn_TXBUF_SIZE()
+ */
+#define getSn_TXBUF_SIZE(sn) \
+		WIZCHIP_READ(Sn_TXBUF_SIZE(sn))
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_TX_FSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_TX_FSR.
+ */
+uint16_t getSn_TX_FSR(uint8_t sn);
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_TX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_TX_RD.
+ */
+//M20150401 : Type explict declaration
+/*
+#define getSn_TX_RD(sn) \
+		((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)))
+*/
+#define getSn_TX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)))		
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
+ * @sa GetSn_TX_WR()
+ */
+#define setSn_TX_WR(sn, txwr) { \
+		WIZCHIP_WRITE(Sn_TX_WR(sn),   (uint8_t)(txwr>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \
+		}
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_TX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_TX_WR.
+ * @sa setSn_TX_WR()
+ */
+//M20150401 : Type explict declaration
+/*
+#define getSn_TX_WR(sn) \
+		((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)))
+*/
+#define getSn_TX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)))		
+
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_RX_RSR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_RX_RSR.
+ */
+uint16_t getSn_RX_RSR(uint8_t sn);
+
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
+ * @sa getSn_RX_RD()
+ */
+#define setSn_RX_RD(sn, rxrd) { \
+		WIZCHIP_WRITE(Sn_RX_RD(sn),   (uint8_t)(rxrd>>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_RX_RD register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_RX_RD.
+ * @sa setSn_RX_RD()
+ */
+//M20150401 : Type explict declaration 
+/*
+#define getSn_RX_RD(sn) \
+		((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1)))
+*/		
+#define getSn_RX_RD(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1)))		
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_RX_WR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_RX_WR.
+ */
+//M20150401 : Type explict declaration
+/*  
+#define getSn_RX_WR(sn) \
+		((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1)))
+*/		
+#define getSn_RX_WR(sn) \
+		(((uint16_t)WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1)))		
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_FRAG register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint16_t)frag Value to set @ref Sn_FRAG
+ * @sa getSn_FRAD()
+ */
+#define setSn_FRAG(sn, frag) { \
+		WIZCHIP_WRITE(Sn_FRAG(sn),  (uint8_t)(frag >>8)); \
+		WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \
+	}
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_FRAG register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of @ref Sn_FRAG.
+ * @sa setSn_FRAG()
+ */
+//M20150401 : Type explict declaration  
+/*
+#define getSn_FRAG(sn) \
+		((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))
+*/		
+#define getSn_FRAG(sn) \
+      (((uint16_t)WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))		
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Set @ref Sn_KPALVTR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR
+ * @sa getSn_KPALVTR()
+ */
+#define setSn_KPALVTR(sn, kpalvt) \
+		WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt)
+
+/**
+ * @ingroup Socket_register_access_function
+ * @brief Get @ref Sn_KPALVTR register
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint8_t. Value of @ref Sn_KPALVTR.
+ * @sa setSn_KPALVTR()
+ */
+#define getSn_KPALVTR(sn) \
+		WIZCHIP_READ(Sn_KPALVTR(sn))
+
+//////////////////////////////////////
+
+/////////////////////////////////////
+// Sn_TXBUF & Sn_RXBUF IO function //
+/////////////////////////////////////
+/**  
+ * @brief Socket_register_access_function
+ * @brief Gets the max buffer size of socket sn passed as parameter.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of Socket n RX max buffer size.
+ */
+//M20150401 : Type explict declaration 
+/*
+#define getSn_RxMAX(sn) \
+		(getSn_RXBUF_SIZE(sn) << 10)
+*/		
+#define getSn_RxMAX(sn) \
+		(((uint16_t)getSn_RXBUF_SIZE(sn)) << 10)		
+
+/**  
+ * @brief Socket_register_access_function
+ * @brief Gets the max buffer size of socket sn passed as parameters.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @return uint16_t. Value of Socket n TX max buffer size.
+ */
+//M20150401 : Type explict declaration 
+/*
+#define getSn_TxMAX(sn) \
+		(getSn_TXBUF_SIZE(sn) << 10)
+*/		
+#define getSn_TxMAX(sn) \
+		(((uint16_t)getSn_TXBUF_SIZE(sn)) << 10)		
+
+/**
+ * @ingroup Basic_IO_function
+ * @brief It copies data to internal TX memory
+ *
+ * @details This function reads the Tx write pointer register and after that,
+ * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory
+ * and updates the Tx write pointer register.
+ * This function is being called by send() and sendto() function also.
+ *
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param wizdata Pointer buffer to write data
+ * @param len Data length
+ * @sa wiz_recv_data()
+ */
+void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function
+ * @brief It copies data to your buffer from internal RX memory
+ *
+ * @details This function read the Rx read pointer register and after that,
+ * it copies the received data from internal RX memory
+ * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes.
+ * This function is being called by recv() also.
+ *
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param wizdata Pointer buffer to read data
+ * @param len Data length
+ * @sa wiz_send_data()
+ */
+void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
+
+/**
+ * @ingroup Basic_IO_function
+ * @brief It discard the received data in RX memory.
+ * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory.
+ * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>.
+ * @param len Data length
+ */
+void wiz_recv_ignore(uint8_t sn, uint16_t len);
+
+/// @cond DOXY_APPLY_CODE
+#endif
+/// @endcond
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif   // _W5500_H_

+ 931 - 0
lib/ioLibrary_Driver/Ethernet/socket.c

@@ -0,0 +1,931 @@
+//*****************************************************************************
+//
+//! \file socket.c
+//! \brief SOCKET APIs Implements file.
+//! \details SOCKET APIs like as Berkeley Socket APIs. 
+//! \version 1.0.3
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2015/02/05> Notice
+//!        The version history is not updated after this point.
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//!       <2014/05/01> V1.0.3. Refer to M20140501
+//!         1. Implicit type casting -> Explicit type casting.
+//!         2. replace 0x01 with PACK_REMAINED in recvfrom()
+//!         3. Validation a destination ip in connect() & sendto(): 
+//!            It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address.
+//!            Copy 4 byte addr value into temporary uint32 variable and then compares it.
+//!       <2013/12/20> V1.0.2 Refer to M20131220
+//!                    Remove Warning.
+//!       <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
+//!                    In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT)
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+#include "socket.h"
+
+//M20150401 : Typing Error
+//#define SOCK_ANY_PORT_NUM  0xC000;
+#define SOCK_ANY_PORT_NUM  0xC000
+
+static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
+static uint16_t sock_io_mode = 0;
+static uint16_t sock_is_sending = 0;
+
+static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
+
+//M20150601 : For extern decleation
+//static uint8_t  sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
+uint8_t  sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
+//
+
+#if _WIZCHIP_ == 5200
+   static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
+#endif
+
+//A20150601 : For integrating with W5300
+#if _WIZCHIP_ == 5300
+   uint8_t sock_remained_byte[_WIZCHIP_SOCK_NUM_] = {0,}; // set by wiz_recv_data()
+#endif
+
+
+#define CHECK_SOCKNUM()   \
+   do{                    \
+      if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM;   \
+   }while(0);             \
+
+#define CHECK_SOCKMODE(mode)  \
+   do{                     \
+      if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE;  \
+   }while(0);              \
+
+#define CHECK_SOCKINIT()   \
+   do{                     \
+      if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
+   }while(0);              \
+
+#define CHECK_SOCKDATA()   \
+   do{                     \
+      if(len == 0) return SOCKERR_DATALEN;   \
+   }while(0);              \
+
+
+
+int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
+{
+	CHECK_SOCKNUM();
+	switch(protocol)
+	{
+      case Sn_MR_TCP :
+         {
+            //M20150601 : Fixed the warning - taddr will never be NULL
+		    /*
+            uint8_t taddr[4];
+            getSIPR(taddr);
+            */
+            uint32_t taddr;
+            getSIPR((uint8_t*)&taddr);
+            if(taddr == 0) return SOCKERR_SOCKINIT;
+	    break;
+         }
+      case Sn_MR_UDP :
+      case Sn_MR_MACRAW :
+	  case Sn_MR_IPRAW :
+         break;
+   #if ( _WIZCHIP_ < 5200 )
+      case Sn_MR_PPPoE :
+         break;
+   #endif
+      default :
+         return SOCKERR_SOCKMODE;
+	}
+	//M20150601 : For SF_TCP_ALIGN & W5300
+	//if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
+	if((flag & 0x04) != 0) return SOCKERR_SOCKFLAG;
+#if _WIZCHIP_ == 5200
+   if(flag & 0x10) return SOCKERR_SOCKFLAG;
+#endif
+	   
+	if(flag != 0)
+	{
+   	switch(protocol)
+   	{
+   	   case Sn_MR_TCP:
+   		  //M20150601 :  For SF_TCP_ALIGN & W5300
+          #if _WIZCHIP_ == 5300
+   		     if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK|SF_TCP_ALIGN))==0) return SOCKERR_SOCKFLAG;
+          #else
+   		     if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
+          #endif
+
+   	      break;
+   	   case Sn_MR_UDP:
+   	      if(flag & SF_IGMP_VER2)
+   	      {
+   	         if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
+   	      }
+   	      #if _WIZCHIP_ == 5500
+      	      if(flag & SF_UNI_BLOCK)
+      	      {
+      	         if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
+      	      }
+   	      #endif
+   	      break;
+   	   default:
+   	      break;
+   	}
+   }
+	close(sn);
+	//M20150601
+	#if _WIZCHIP_ == 5300
+	   setSn_MR(sn, ((uint16_t)(protocol | (flag & 0xF0))) | (((uint16_t)(flag & 0x02)) << 7) );
+    #else
+	   setSn_MR(sn, (protocol | (flag & 0xF0)));
+    #endif
+	if(!port)
+	{
+	   port = sock_any_port++;
+	   if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
+	}
+   setSn_PORT(sn,port);	
+   setSn_CR(sn,Sn_CR_OPEN);
+   while(getSn_CR(sn));
+   //A20150401 : For release the previous sock_io_mode
+   sock_io_mode &= ~(1 <<sn);
+   //
+	sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);   
+   sock_is_sending &= ~(1<<sn);
+   sock_remained_size[sn] = 0;
+   //M20150601 : repalce 0 with PACK_COMPLETED
+   //sock_pack_info[sn] = 0;
+   sock_pack_info[sn] = PACK_COMPLETED;
+   //
+   while(getSn_SR(sn) == SOCK_CLOSED);
+   return (int8_t)sn;
+}	   
+
+int8_t close(uint8_t sn)
+{
+	CHECK_SOCKNUM();
+//A20160426 : Applied the erratum 1 of W5300
+#if   (_WIZCHIP_ == 5300) 
+   //M20160503 : Wrong socket parameter. s -> sn 
+   //if( ((getSn_MR(s)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(s) != getSn_TxMAX(s)) ) 
+   if( ((getSn_MR(sn)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(sn) != getSn_TxMAX(sn)) ) 
+   { 
+      uint8_t destip[4] = {0, 0, 0, 1};
+      // TODO
+      // You can wait for completing to sending data;
+      // wait about 1 second;
+      // if you have completed to send data, skip the code of erratum 1
+      // ex> wait_1s();
+      //     if (getSn_TX_FSR(s) == getSn_TxMAX(s)) continue;
+      // 
+      //M20160503 : The socket() of close() calls close() itself again. It occures a infinite loop - close()->socket()->close()->socket()-> ~
+      //socket(s,Sn_MR_UDP,0x3000,0);
+      //sendto(s,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1).
+      setSn_MR(sn,Sn_MR_UDP);
+      setSn_PORTR(sn, 0x3000);
+      setSn_CR(sn,Sn_CR_OPEN);
+      while(getSn_CR(sn) != 0);
+      while(getSn_SR(sn) != SOCK_UDP);
+      sendto(sn,destip,1,destip,0x3000); // send the dummy data to an unknown destination(0.0.0.1).
+   };   
+#endif 
+	setSn_CR(sn,Sn_CR_CLOSE);
+   /* wait to process the command... */
+	while( getSn_CR(sn) );
+	/* clear all interrupt of the socket. */
+	setSn_IR(sn, 0xFF);
+	//A20150401 : Release the sock_io_mode of socket n.
+	sock_io_mode &= ~(1<<sn);
+	//
+	sock_is_sending &= ~(1<<sn);
+	sock_remained_size[sn] = 0;
+	sock_pack_info[sn] = 0;
+	while(getSn_SR(sn) != SOCK_CLOSED);
+	return SOCK_OK;
+}
+
+int8_t listen(uint8_t sn)
+{
+	CHECK_SOCKNUM();
+   CHECK_SOCKMODE(Sn_MR_TCP);
+	CHECK_SOCKINIT();
+	setSn_CR(sn,Sn_CR_LISTEN);
+	while(getSn_CR(sn));
+   while(getSn_SR(sn) != SOCK_LISTEN)
+   {
+         close(sn);
+         return SOCKERR_SOCKCLOSED;
+   }
+   return SOCK_OK;
+}
+
+
+int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port)
+{
+   CHECK_SOCKNUM();
+   CHECK_SOCKMODE(Sn_MR_TCP);
+   CHECK_SOCKINIT();
+   //M20140501 : For avoiding fatal error on memory align mismatched
+   //if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
+   {
+      uint32_t taddr;
+      taddr = ((uint32_t)addr[0] & 0x000000FF);
+      taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
+      taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
+      taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
+      if( taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
+   }
+   //
+	
+	if(port == 0) return SOCKERR_PORTZERO;
+	setSn_DIPR(sn,addr);
+	setSn_DPORT(sn,port);
+	setSn_CR(sn,Sn_CR_CONNECT);
+   while(getSn_CR(sn));
+   if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
+   while(getSn_SR(sn) != SOCK_ESTABLISHED)
+   {
+		if (getSn_IR(sn) & Sn_IR_TIMEOUT)
+		{
+			setSn_IR(sn, Sn_IR_TIMEOUT);
+            return SOCKERR_TIMEOUT;
+		}
+
+		if (getSn_SR(sn) == SOCK_CLOSED)
+		{
+			return SOCKERR_SOCKCLOSED;
+		}
+	}
+   
+   return SOCK_OK;
+}
+
+int8_t disconnect(uint8_t sn)
+{
+   CHECK_SOCKNUM();
+   CHECK_SOCKMODE(Sn_MR_TCP);
+	setSn_CR(sn,Sn_CR_DISCON);
+	/* wait to process the command... */
+	while(getSn_CR(sn));
+	sock_is_sending &= ~(1<<sn);
+   if(sock_io_mode & (1<<sn)) return SOCK_BUSY;
+	while(getSn_SR(sn) != SOCK_CLOSED)
+	{
+	   if(getSn_IR(sn) & Sn_IR_TIMEOUT)
+	   {
+	      close(sn);
+	      return SOCKERR_TIMEOUT;
+	   }
+	}
+	return SOCK_OK;
+}
+
+int32_t send(uint8_t sn, uint8_t * buf, uint16_t len)
+{
+   uint8_t tmp=0;
+   uint16_t freesize=0;
+   
+   CHECK_SOCKNUM();
+   CHECK_SOCKMODE(Sn_MR_TCP);
+   CHECK_SOCKDATA();
+   tmp = getSn_SR(sn);
+   if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS;
+   if( sock_is_sending & (1<<sn) )
+   {
+      tmp = getSn_IR(sn);
+      if(tmp & Sn_IR_SENDOK)
+      {
+         setSn_IR(sn, Sn_IR_SENDOK);
+         //M20150401 : Typing Error
+         //#if _WZICHIP_ == 5200
+         #if _WIZCHIP_ == 5200
+            if(getSn_TX_RD(sn) != sock_next_rd[sn])
+            {
+               setSn_CR(sn,Sn_CR_SEND);
+               while(getSn_CR(sn));
+               return SOCK_BUSY;
+            }
+         #endif
+         sock_is_sending &= ~(1<<sn);         
+      }
+      else if(tmp & Sn_IR_TIMEOUT)
+      {
+         close(sn);
+         return SOCKERR_TIMEOUT;
+      }
+      else return SOCK_BUSY;
+   }
+   freesize = getSn_TxMAX(sn);
+   if (len > freesize) len = freesize; // check size not to exceed MAX size.
+   while(1)
+   {
+      freesize = getSn_TX_FSR(sn);
+      tmp = getSn_SR(sn);
+      if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
+      {
+         close(sn);
+         return SOCKERR_SOCKSTATUS;
+      }
+      if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
+      if(len <= freesize) break;
+   }
+   wiz_send_data(sn, buf, len);
+   #if _WIZCHIP_ == 5200
+      sock_next_rd[sn] = getSn_TX_RD(sn) + len;
+   #endif
+
+   #if _WIZCHIP_ == 5300
+      setSn_TX_WRSR(sn,len);
+   #endif
+   
+   setSn_CR(sn,Sn_CR_SEND);
+   /* wait to process the command... */
+   while(getSn_CR(sn));
+   sock_is_sending |= (1 << sn);
+   //M20150409 : Explicit Type Casting
+   //return len;
+   return (int32_t)len;
+}
+
+
+int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len)
+{
+   uint8_t  tmp = 0;
+   uint16_t recvsize = 0;
+//A20150601 : For integarating with W5300
+#if   _WIZCHIP_ == 5300
+   uint8_t head[2];
+   uint16_t mr;
+#endif
+//
+   CHECK_SOCKNUM();
+   CHECK_SOCKMODE(Sn_MR_TCP);
+   CHECK_SOCKDATA();
+   
+   recvsize = getSn_RxMAX(sn);
+   if(recvsize < len) len = recvsize;
+      
+//A20150601 : For Integrating with W5300
+#if _WIZCHIP_ == 5300
+   //sock_pack_info[sn] = PACK_COMPLETED;    // for clear      
+   if(sock_remained_size[sn] == 0)
+   {
+#endif
+//
+      while(1)
+      {
+         recvsize = getSn_RX_RSR(sn);
+         tmp = getSn_SR(sn);
+         if (tmp != SOCK_ESTABLISHED)
+         {
+            if(tmp == SOCK_CLOSE_WAIT)
+            {
+               if(recvsize != 0) break;
+               else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
+               {
+                  close(sn);
+                  return SOCKERR_SOCKSTATUS;
+               }
+            }
+            else
+            {
+               close(sn);
+               return SOCKERR_SOCKSTATUS;
+            }
+         }
+         if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
+         if(recvsize != 0) break;
+      };
+#if _WIZCHIP_ == 5300
+   }
+#endif
+
+//A20150601 : For integrating with W5300
+#if _WIZCHIP_ == 5300
+   if((sock_remained_size[sn] == 0) || (getSn_MR(sn) & Sn_MR_ALIGN))
+   {
+      mr = getMR();
+      if((getSn_MR(sn) & Sn_MR_ALIGN)==0)
+      {
+         wiz_recv_data(sn,head,2);
+         if(mr & MR_FS)
+            recvsize = (((uint16_t)head[1]) << 8) | ((uint16_t)head[0]);
+         else
+            recvsize = (((uint16_t)head[0]) << 8) | ((uint16_t)head[1]);
+         sock_pack_info[sn] = PACK_FIRST;
+      }
+      sock_remained_size[sn] = recvsize;
+   }
+   if(len > sock_remained_size[sn]) len = sock_remained_size[sn];
+   recvsize = len;   
+   if(sock_pack_info[sn] & PACK_FIFOBYTE)
+   {
+      *buf = sock_remained_byte[sn];
+      buf++;
+      sock_pack_info[sn] &= ~(PACK_FIFOBYTE);
+      recvsize -= 1;
+      sock_remained_size[sn] -= 1;
+   }
+   if(recvsize != 0)
+   {
+      wiz_recv_data(sn, buf, recvsize);
+      setSn_CR(sn,Sn_CR_RECV);
+      while(getSn_CR(sn));
+   }
+   sock_remained_size[sn] -= recvsize;
+   if(sock_remained_size[sn] != 0)
+   {
+      sock_pack_info[sn] |= PACK_REMAINED;
+      if(recvsize & 0x1) sock_pack_info[sn] |= PACK_FIFOBYTE;
+   }
+   else sock_pack_info[sn] = PACK_COMPLETED;
+   if(getSn_MR(sn) & Sn_MR_ALIGN) sock_remained_size[sn] = 0;
+   //len = recvsize;
+#else   
+   if(recvsize < len) len = recvsize;   
+   wiz_recv_data(sn, buf, len);
+   setSn_CR(sn,Sn_CR_RECV);
+   while(getSn_CR(sn));
+#endif
+     
+   //M20150409 : Explicit Type Casting
+   //return len;
+   return (int32_t)len;
+}
+
+int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port)
+{
+   uint8_t tmp = 0;
+   uint16_t freesize = 0;
+   uint32_t taddr;
+
+   CHECK_SOCKNUM();
+   switch(getSn_MR(sn) & 0x0F)
+   {
+      case Sn_MR_UDP:
+      case Sn_MR_MACRAW:
+//         break;
+//   #if ( _WIZCHIP_ < 5200 )
+      case Sn_MR_IPRAW:
+         break;
+//   #endif
+      default:
+         return SOCKERR_SOCKMODE;
+   }
+   CHECK_SOCKDATA();
+   //M20140501 : For avoiding fatal error on memory align mismatched
+   //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
+   //{
+      //uint32_t taddr;
+      taddr = ((uint32_t)addr[0]) & 0x000000FF;
+      taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
+      taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
+      taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
+   //}
+   //
+   //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
+   if((taddr == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_IPINVALID;
+   if((port  == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_PORTZERO;
+   tmp = getSn_SR(sn);
+//#if ( _WIZCHIP_ < 5200 )
+   if((tmp != SOCK_MACRAW) && (tmp != SOCK_UDP) && (tmp != SOCK_IPRAW)) return SOCKERR_SOCKSTATUS;
+//#else
+//   if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
+//#endif
+      
+   setSn_DIPR(sn,addr);
+   setSn_DPORT(sn,port);      
+   freesize = getSn_TxMAX(sn);
+   if (len > freesize) len = freesize; // check size not to exceed MAX size.
+   while(1)
+   {
+      freesize = getSn_TX_FSR(sn);
+      if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
+      if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
+      if(len <= freesize) break;
+   };
+	wiz_send_data(sn, buf, len);
+
+   #if _WIZCHIP_ < 5500   //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
+      getSIPR((uint8_t*)&taddr);
+      if(taddr == 0)
+      {
+         getSUBR((uint8_t*)&taddr);
+         setSUBR((uint8_t*)"\x00\x00\x00\x00");
+      }
+      else taddr = 0;
+   #endif
+
+//A20150601 : For W5300
+#if _WIZCHIP_ == 5300
+   setSn_TX_WRSR(sn, len);
+#endif
+//   
+	setSn_CR(sn,Sn_CR_SEND);
+	/* wait to process the command... */
+	while(getSn_CR(sn));
+   while(1)
+   {
+      tmp = getSn_IR(sn);
+      if(tmp & Sn_IR_SENDOK)
+      {
+         setSn_IR(sn, Sn_IR_SENDOK);
+         break;
+      }
+      //M:20131104
+      //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
+      else if(tmp & Sn_IR_TIMEOUT)
+      {
+         setSn_IR(sn, Sn_IR_TIMEOUT);
+         //M20150409 : Fixed the lost of sign bits by type casting.
+         //len = (uint16_t)SOCKERR_TIMEOUT;
+         //break;
+         #if _WIZCHIP_ < 5500   //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
+            if(taddr) setSUBR((uint8_t*)&taddr);
+         #endif
+         return SOCKERR_TIMEOUT;
+      }
+      ////////////
+   }
+   #if _WIZCHIP_ < 5500   //M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
+      if(taddr) setSUBR((uint8_t*)&taddr);
+   #endif
+   //M20150409 : Explicit Type Casting
+   //return len;
+   return (int32_t)len;
+}
+
+
+
+int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
+{
+//M20150601 : For W5300   
+#if _WIZCHIP_ == 5300
+   uint16_t mr;
+   uint16_t mr1;
+#else   
+   uint8_t  mr;
+#endif
+//   
+   uint8_t  head[8];
+	uint16_t pack_len=0;
+
+   CHECK_SOCKNUM();
+   //CHECK_SOCKMODE(Sn_MR_UDP);
+//A20150601
+#if _WIZCHIP_ == 5300
+   mr1 = getMR();
+#endif   
+
+   switch((mr=getSn_MR(sn)) & 0x0F)
+   {
+      case Sn_MR_UDP:
+	  case Sn_MR_IPRAW:
+      case Sn_MR_MACRAW:
+         break;
+   #if ( _WIZCHIP_ < 5200 )         
+      case Sn_MR_PPPoE:
+         break;
+   #endif
+      default:
+         return SOCKERR_SOCKMODE;
+   }
+   CHECK_SOCKDATA();
+   if(sock_remained_size[sn] == 0)
+   {
+      while(1)
+      {
+         pack_len = getSn_RX_RSR(sn);
+         if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
+         if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
+         if(pack_len != 0) break;
+      };
+   }
+//D20150601 : Move it to bottom
+// sock_pack_info[sn] = PACK_COMPLETED;
+	switch (mr & 0x07)
+	{
+	   case Sn_MR_UDP :
+	      if(sock_remained_size[sn] == 0)
+	      {
+   			wiz_recv_data(sn, head, 8);
+   			setSn_CR(sn,Sn_CR_RECV);
+   			while(getSn_CR(sn));
+   			// read peer's IP address, port number & packet length
+   	   //A20150601 : For W5300
+   		#if _WIZCHIP_ == 5300
+   		   if(mr1 & MR_FS)
+   		   {
+   		      addr[0] = head[1];
+   		      addr[1] = head[0];
+   		      addr[2] = head[3];
+   		      addr[3] = head[2];
+   		      *port = head[5];
+   		      *port = (*port << 8) + head[4];
+      			sock_remained_size[sn] = head[7];
+      			sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[6];
+   		   }
+            else
+            {
+         #endif
+               addr[0] = head[0];
+      			addr[1] = head[1];
+      			addr[2] = head[2];
+      			addr[3] = head[3];
+      			*port = head[4];
+      			*port = (*port << 8) + head[5];
+      			sock_remained_size[sn] = head[6];
+      			sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
+         #if _WIZCHIP_ == 5300
+            }
+         #endif
+   			sock_pack_info[sn] = PACK_FIRST;
+   	   }
+			if(len < sock_remained_size[sn]) pack_len = len;
+			else pack_len = sock_remained_size[sn];
+			//A20150601 : For W5300
+			len = pack_len;
+			#if _WIZCHIP_ == 5300
+			   if(sock_pack_info[sn] & PACK_FIFOBYTE)
+			   {
+			      *buf++ = sock_remained_byte[sn];
+			      pack_len -= 1;
+			      sock_remained_size[sn] -= 1;
+			      sock_pack_info[sn] &= ~PACK_FIFOBYTE;
+			   }
+			#endif
+			//
+			// Need to packet length check (default 1472)
+			//
+   		wiz_recv_data(sn, buf, pack_len); // data copy.
+			break;
+	   case Sn_MR_MACRAW :
+	      if(sock_remained_size[sn] == 0)
+	      {
+   			wiz_recv_data(sn, head, 2);
+   			setSn_CR(sn,Sn_CR_RECV);
+   			while(getSn_CR(sn));
+   			// read peer's IP address, port number & packet length
+    			sock_remained_size[sn] = head[0];
+   			sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1] -2;
+   			#if _WIZCHIP_ == W5300
+   			if(sock_remained_size[sn] & 0x01)
+   				sock_remained_size[sn] = sock_remained_size[sn] + 1 - 4;
+   			else
+   				sock_remained_size[sn] -= 4;
+			#endif
+   			if(sock_remained_size[sn] > 1514) 
+   			{
+   			   close(sn);
+   			   return SOCKFATAL_PACKLEN;
+   			}
+   			sock_pack_info[sn] = PACK_FIRST;
+   	   }
+			if(len < sock_remained_size[sn]) pack_len = len;
+			else pack_len = sock_remained_size[sn];
+			wiz_recv_data(sn,buf,pack_len);
+		   break;
+   //#if ( _WIZCHIP_ < 5200 )
+		case Sn_MR_IPRAW:
+		   if(sock_remained_size[sn] == 0)
+		   {
+   			wiz_recv_data(sn, head, 6);
+   			setSn_CR(sn,Sn_CR_RECV);
+   			while(getSn_CR(sn));
+   			addr[0] = head[0];
+   			addr[1] = head[1];
+   			addr[2] = head[2];
+   			addr[3] = head[3];
+   			sock_remained_size[sn] = head[4];
+   			//M20150401 : For Typing Error
+   			//sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
+   			sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[5];
+   			sock_pack_info[sn] = PACK_FIRST;
+         }
+			//
+			// Need to packet length check
+			//
+			if(len < sock_remained_size[sn]) pack_len = len;
+			else pack_len = sock_remained_size[sn];
+   		wiz_recv_data(sn, buf, pack_len); // data copy.
+			break;
+   //#endif
+      default:
+         wiz_recv_ignore(sn, pack_len); // data copy.
+         sock_remained_size[sn] = pack_len;
+         break;
+   }
+	setSn_CR(sn,Sn_CR_RECV);
+	/* wait to process the command... */
+	while(getSn_CR(sn)) ;
+	sock_remained_size[sn] -= pack_len;
+	//M20150601 : 
+	//if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
+	if(sock_remained_size[sn] != 0)
+	{
+	   sock_pack_info[sn] |= PACK_REMAINED;
+   #if _WIZCHIP_ == 5300	   
+	   if(pack_len & 0x01) sock_pack_info[sn] |= PACK_FIFOBYTE;
+   #endif	      
+	}
+	else sock_pack_info[sn] = PACK_COMPLETED;
+#if _WIZCHIP_ == 5300	   
+   pack_len = len;
+#endif
+   //
+   //M20150409 : Explicit Type Casting
+   //return pack_len;
+   return (int32_t)pack_len;
+}
+
+
+int8_t  ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg)
+{
+   uint8_t tmp = 0;
+   CHECK_SOCKNUM();
+   switch(cstype)
+   {
+      case CS_SET_IOMODE:
+         tmp = *((uint8_t*)arg);
+         if(tmp == SOCK_IO_NONBLOCK)  sock_io_mode |= (1<<sn);
+         else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn);
+         else return SOCKERR_ARG;
+         break;
+      case CS_GET_IOMODE:   
+         //M20140501 : implict type casting -> explict type casting
+         //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
+         *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
+         //
+         break;
+      case CS_GET_MAXTXBUF:
+         *((uint16_t*)arg) = getSn_TxMAX(sn);
+         break;
+      case CS_GET_MAXRXBUF:    
+         *((uint16_t*)arg) = getSn_RxMAX(sn);
+         break;
+      case CS_CLR_INTERRUPT:
+         if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
+         setSn_IR(sn,*(uint8_t*)arg);
+         break;
+      case CS_GET_INTERRUPT:
+         *((uint8_t*)arg) = getSn_IR(sn);
+         break;
+   #if _WIZCHIP_ != 5100
+      case CS_SET_INTMASK:  
+         if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
+         setSn_IMR(sn,*(uint8_t*)arg);
+         break;
+      case CS_GET_INTMASK:   
+         *((uint8_t*)arg) = getSn_IMR(sn);
+         break;
+   #endif
+      default:
+         return SOCKERR_ARG;
+   }
+   return SOCK_OK;
+}
+
+int8_t  setsockopt(uint8_t sn, sockopt_type sotype, void* arg)
+{
+ // M20131220 : Remove warning
+ //uint8_t tmp;
+   CHECK_SOCKNUM();
+   switch(sotype)
+   {
+      case SO_TTL:
+         setSn_TTL(sn,*(uint8_t*)arg);
+         break;
+      case SO_TOS:
+         setSn_TOS(sn,*(uint8_t*)arg);
+         break;
+      case SO_MSS:
+         setSn_MSSR(sn,*(uint16_t*)arg);
+         break;
+      case SO_DESTIP:
+         setSn_DIPR(sn, (uint8_t*)arg);
+         break;
+      case SO_DESTPORT:
+         setSn_DPORT(sn, *(uint16_t*)arg);
+         break;
+#if _WIZCHIP_ != 5100
+      case SO_KEEPALIVESEND:
+         CHECK_SOCKMODE(Sn_MR_TCP);
+         #if _WIZCHIP_ > 5200
+            if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
+         #endif
+            setSn_CR(sn,Sn_CR_SEND_KEEP);
+            while(getSn_CR(sn) != 0)
+            {
+               // M20131220
+         		//if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
+               if (getSn_IR(sn) & Sn_IR_TIMEOUT)
+         		{
+         			setSn_IR(sn, Sn_IR_TIMEOUT);
+                  return SOCKERR_TIMEOUT;
+         		}
+            }
+         break;
+   #if !( (_WIZCHIP_ == 5100) || (_WIZCHIP_ == 5200) )
+      case SO_KEEPALIVEAUTO:
+         CHECK_SOCKMODE(Sn_MR_TCP);
+         setSn_KPALVTR(sn,*(uint8_t*)arg);
+         break;
+   #endif      
+#endif   
+      default:
+         return SOCKERR_ARG;
+   }   
+   return SOCK_OK;
+}
+
+int8_t  getsockopt(uint8_t sn, sockopt_type sotype, void* arg)
+{
+   CHECK_SOCKNUM();
+   switch(sotype)
+   {
+      case SO_FLAG:
+         *(uint8_t*)arg = getSn_MR(sn) & 0xF0;
+         break;
+      case SO_TTL:
+         *(uint8_t*) arg = getSn_TTL(sn);
+         break;
+      case SO_TOS:
+         *(uint8_t*) arg = getSn_TOS(sn);
+         break;
+      case SO_MSS:   
+         *(uint16_t*) arg = getSn_MSSR(sn);
+         break;
+      case SO_DESTIP:
+         getSn_DIPR(sn, (uint8_t*)arg);
+         break;
+      case SO_DESTPORT:  
+         *(uint16_t*) arg = getSn_DPORT(sn);
+         break;
+   #if _WIZCHIP_ > 5200   
+      case SO_KEEPALIVEAUTO:
+         CHECK_SOCKMODE(Sn_MR_TCP);
+         *(uint16_t*) arg = getSn_KPALVTR(sn);
+         break;
+   #endif      
+      case SO_SENDBUF:
+         *(uint16_t*) arg = getSn_TX_FSR(sn);
+         break;
+      case SO_RECVBUF:
+         *(uint16_t*) arg = getSn_RX_RSR(sn);
+         break;
+      case SO_STATUS:
+         *(uint8_t*) arg = getSn_SR(sn);
+         break;
+      case SO_REMAINSIZE:
+         if(getSn_MR(sn) & Sn_MR_TCP)
+            *(uint16_t*)arg = getSn_RX_RSR(sn);
+         else
+            *(uint16_t*)arg = sock_remained_size[sn];
+         break;
+      case SO_PACKINFO:
+         //CHECK_SOCKMODE(Sn_MR_TCP);
+#if _WIZCHIP_ != 5300
+         if((getSn_MR(sn) == Sn_MR_TCP))
+             return SOCKERR_SOCKMODE;
+#endif
+         *(uint8_t*)arg = sock_pack_info[sn];
+         break;
+      default:
+         return SOCKERR_SOCKOPT;
+   }
+   return SOCK_OK;
+}

+ 489 - 0
lib/ioLibrary_Driver/Ethernet/socket.h

@@ -0,0 +1,489 @@
+//*****************************************************************************
+//
+//! \file socket.h
+//! \brief SOCKET APIs Header file.
+//! \details SOCKET APIs like as berkeley socket api. 
+//! \version 1.0.2
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2015/02/05> Notice
+//!        The version history is not updated after this point.
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//!       <2014/05/01> V1.0.2. Refer to M20140501
+//!         1. Modify the comment : SO_REMAINED -> PACK_REMAINED
+//!         2. Add the comment as zero byte udp data reception in getsockopt(). 
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+/**
+ * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs
+ * @brief WIZnet socket APIs are based on Berkeley socket APIs,  thus it has much similar name and interface.
+ *        But there is a little bit of difference.
+ * @details
+ * <b> Comparison between WIZnet and Berkeley SOCKET APIs </b>
+ * <table>
+ *    <tr>   <td><b>API</b></td> <td><b>WIZnet</b></td> <td><b>Berkeley</b></td>   </tr>
+ *    <tr>   <td>socket()</td> <td>O</td> <td>O</td>   </tr>
+ *    <tr>   <td><b>bind()</b></td> <td>X</td> <td>O</td>   </tr>
+ *    <tr>   <td><b>listen()</b></td> <td>O</td> <td>O</td>   </tr>
+ *    <tr>   <td><b>connect()</b></td> <td>O</td> <td>O</td>   </tr>
+ *    <tr>   <td><b>accept()</b></td> <td>X</td> <td>O</td>   </tr>
+ *    <tr>   <td><b>recv()</b></td> <td>O</td> <td>O</td>    </tr>
+ *    <tr>   <td><b>send()</b></td> <td>O</td> <td>O</td>   </tr>
+ *    <tr>   <td><b>recvfrom()</b></td> <td>O</td> <td>O</td>   </tr>
+ *    <tr>   <td><b>sendto()</b></td> <td>O</td> <td>O</td>    </tr>
+ *    <tr>   <td><b>closesocket()</b></td> <td>O<br>close() & disconnect()</td> <td>O</td>   </tr>
+ * </table>
+ * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but,
+ * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number,
+ * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n
+ * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port.
+ * When the listen SOCKET accepts a connection request from a client, it keeps listening.
+ * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n
+ * Following figure shows network flow diagram by Berkeley SOCKET API.
+ * @image html Berkeley_SOCKET.jpg "<Berkeley SOCKET API>"
+ * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n
+ * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client,
+ * it is changed in order to communicate with the client.
+ * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n
+ * If there're many listen SOCKET with same listen port number and a client requests a connection,
+ * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n
+ * Following figure shows network flow diagram by WIZnet SOCKET API.
+ * @image html WIZnet_SOCKET.jpg "<WIZnet SOCKET API>"
+ */
+#ifndef _SOCKET_H_
+#define _SOCKET_H_
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "wizchip_conf.h"
+
+#define SOCKET                uint8_t  ///< SOCKET type define for legacy driver
+
+#define SOCK_OK               1        ///< Result is OK about socket process.
+#define SOCK_BUSY             0        ///< Socket is busy on processing the operation. Valid only Non-block IO Mode.
+#define SOCK_FATAL            -1000    ///< Result is fatal error about socket process.
+
+#define SOCK_ERROR            0        
+#define SOCKERR_SOCKNUM       (SOCK_ERROR - 1)     ///< Invalid socket number
+#define SOCKERR_SOCKOPT       (SOCK_ERROR - 2)     ///< Invalid socket option
+#define SOCKERR_SOCKINIT      (SOCK_ERROR - 3)     ///< Socket is not initialized or SIPR is Zero IP address when Sn_MR_TCP
+#define SOCKERR_SOCKCLOSED    (SOCK_ERROR - 4)     ///< Socket unexpectedly closed.
+#define SOCKERR_SOCKMODE      (SOCK_ERROR - 5)     ///< Invalid socket mode for socket operation.
+#define SOCKERR_SOCKFLAG      (SOCK_ERROR - 6)     ///< Invalid socket flag
+#define SOCKERR_SOCKSTATUS    (SOCK_ERROR - 7)     ///< Invalid socket status for socket operation.
+#define SOCKERR_ARG           (SOCK_ERROR - 10)    ///< Invalid argument.
+#define SOCKERR_PORTZERO      (SOCK_ERROR - 11)    ///< Port number is zero
+#define SOCKERR_IPINVALID     (SOCK_ERROR - 12)    ///< Invalid IP address
+#define SOCKERR_TIMEOUT       (SOCK_ERROR - 13)    ///< Timeout occurred
+#define SOCKERR_DATALEN       (SOCK_ERROR - 14)    ///< Data length is zero or greater than buffer max size.
+#define SOCKERR_BUFFER        (SOCK_ERROR - 15)    ///< Socket buffer is not enough for data communication.
+
+#define SOCKFATAL_PACKLEN     (SOCK_FATAL - 1)     ///< Invalid packet length. Fatal Error.
+
+/*
+ * SOCKET FLAG
+ */
+#define SF_ETHER_OWN           (Sn_MR_MFEN)        ///< In @ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet
+#define SF_IGMP_VER2           (Sn_MR_MC)          ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2.   
+#define SF_TCP_NODELAY         (Sn_MR_ND)          ///< In @ref Sn_MR_TCP, Use to nodelayed ack.
+#define SF_MULTI_ENABLE        (Sn_MR_MULTI)       ///< In @ref Sn_MR_UDP, Enable multicast mode.
+
+#if _WIZCHIP_ == 5500
+   #define SF_BROAD_BLOCK         (Sn_MR_BCASTB)   ///< In @ref Sn_MR_UDP or @ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500
+   #define SF_MULTI_BLOCK         (Sn_MR_MMB)      ///< In @ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500
+   #define SF_IPv6_BLOCK          (Sn_MR_MIP6B)    ///< In @ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500
+   #define SF_UNI_BLOCK           (Sn_MR_UCASTB)   ///< In @ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500
+#endif
+
+//A201505 : For W5300
+#if _WIZCHIP_ == 5300
+   #define SF_TCP_ALIGN		     0x02			   ///< Valid only \ref Sn_MR_TCP and W5300, refer to \ref Sn_MR_ALIGN
+#endif
+
+#define SF_IO_NONBLOCK           0x01              ///< Socket nonblock io mode. It used parameter in \ref socket().
+
+/*
+ * UDP & MACRAW Packet Infomation
+ */
+#define PACK_FIRST               0x80              ///< In Non-TCP packet, It indicates to start receiving a packet. (When W5300, This flag can be applied)
+#define PACK_REMAINED            0x01              ///< In Non-TCP packet, It indicates to remain a packet to be received. (When W5300, This flag can be applied)
+#define PACK_COMPLETED           0x00              ///< In Non-TCP packet, It indicates to complete to receive a packet. (When W5300, This flag can be applied)
+//A20150601 : For Integrating with W5300
+#define PACK_FIFOBYTE            0x02              ///< Valid only W5300, It indicate to have read already the Sn_RX_FIFOR.
+//
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief Open a socket.
+ * @details Initializes the socket with 'sn' passed as parameter and open.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param protocol Protocol type to operate such as TCP, UDP and MACRAW.
+ * @param port Port number to be bined.
+ * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n
+ *             Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK.
+ * @sa Sn_MR
+ *
+ * @return @b Success : The socket number @b 'sn' passed as parameter\n
+ *         @b Fail    :\n @ref SOCKERR_SOCKNUM     - Invalid socket number\n
+ *                        @ref SOCKERR_SOCKMODE    - Not support socket mode as TCP, UDP, and so on. \n
+ *                        @ref SOCKERR_SOCKFLAG    - Invaild socket flag.
+ */
+int8_t  socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief Close a socket.
+ * @details It closes the socket  with @b'sn' passed as parameter.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ *
+ * @return @b Success : @ref SOCK_OK \n
+ *         @b Fail    : @ref SOCKERR_SOCKNUM - Invalid socket number
+ */
+int8_t  close(uint8_t sn);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief Listen to a connection request from a client.
+ * @details It is listening to a connection request from a client.
+ * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return @b Success : @ref SOCK_OK \n
+ *         @b Fail    :\n @ref SOCKERR_SOCKINIT   - Socket is not initialized \n
+ *                        @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly.
+ */
+int8_t  listen(uint8_t sn);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief Try to connect a server.
+ * @details It requests connection to the server with destination IP address and port number passed as parameter.\n
+ * @note It is valid only in TCP client mode. 
+ *       In block io mode, it does not return until connection is completed.
+ *       In Non-block io mode, it return @ref SOCK_BUSY immediately.
+ *
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
+ * @param port Destination port number.
+ *
+ * @return @b Success : @ref SOCK_OK \n
+ * @b Fail    :\n @ref SOCKERR_SOCKNUM   - Invalid socket number\n
+ *                @ref SOCKERR_SOCKMODE  - Invalid socket mode\n
+ *                @ref SOCKERR_SOCKINIT  - Socket is not initialized\n
+ *                @ref SOCKERR_IPINVALID - Wrong server IP address\n
+ *                @ref SOCKERR_PORTZERO  - Server port zero\n
+ *                @ref SOCKERR_TIMEOUT   - Timeout occurred during request connection\n
+ *                @ref SOCK_BUSY         - In non-block io mode, it returned immediately\n
+ */
+int8_t  connect(uint8_t sn, uint8_t * addr, uint16_t port);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief Try to disconnect a connection socket.
+ * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client.
+ * @note It is valid only in TCP server or client mode. \n
+ *       In block io mode, it does not return until disconnection is completed. \n
+ *       In Non-block io mode, it return @ref SOCK_BUSY immediately. \n
+
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @return @b Success :   @ref SOCK_OK \n
+ *         @b Fail    :\n @ref SOCKERR_SOCKNUM  - Invalid socket number \n
+ *                        @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
+ *                        @ref SOCKERR_TIMEOUT  - Timeout occurred \n
+ *                        @ref SOCK_BUSY        - Socket is busy.
+ */
+int8_t  disconnect(uint8_t sn);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief	Send data to the connected peer in TCP socket.
+ * @details It is used to send outgoing data to the connected socket.
+ * @note    It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n
+ *          In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n
+ *          In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n
+ * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param buf Pointer buffer containing data to be sent.
+ * @param len The byte length of data in buf.
+ * @return	@b Success : The sent data size \n
+ *          @b Fail    : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
+ *                          @ref SOCKERR_TIMEOUT    - Timeout occurred \n
+ *                          @ref SOCKERR_SOCKMODE 	- Invalid operation in the socket \n
+ *                          @ref SOCKERR_SOCKNUM    - Invalid socket number \n
+ *                          @ref SOCKERR_DATALEN    - zero data length \n
+ *                          @ref SOCK_BUSY          - Socket is busy.
+ */
+int32_t send(uint8_t sn, uint8_t * buf, uint16_t len);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief	Receive data from the connected peer.
+ * @details It is used to read incoming data from the connected socket.\n
+ *          It waits for data as much as the application wants to receive.
+ * @note    It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n
+ *          In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer. \n
+ *          In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. \n
+ *
+ * @param sn  Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param buf Pointer buffer to read incoming data.
+ * @param len The max data length of data in buf.
+ * @return	@b Success : The real received data size \n
+ *          @b Fail    :\n
+ *                     @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
+ *                     @ref SOCKERR_SOCKMODE   - Invalid operation in the socket \n
+ *                     @ref SOCKERR_SOCKNUM    - Invalid socket number \n
+ *                     @ref SOCKERR_DATALEN    - zero data length \n
+ *                     @ref SOCK_BUSY          - Socket is busy.
+ */
+int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief	Sends datagram to the peer with destination IP address and port number passed as parameter.
+ * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n
+ *          Even if the connectionless socket has been previously connected to a specific address,
+ *          the address and port number parameters override the destination address for that particular datagram only.
+ * @note    In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>.
+ *          In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough.
+ *
+ * @param sn    Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param buf   Pointer buffer to send outgoing data.
+ * @param len   The byte length of data in buf.
+ * @param addr  Pointer variable of destination IP address. It should be allocated 4 bytes.
+ * @param port  Destination port number.
+ *
+ * @return @b Success : The sent data size \n
+ *         @b Fail    :\n @ref SOCKERR_SOCKNUM     - Invalid socket number \n
+ *                        @ref SOCKERR_SOCKMODE    - Invalid operation in the socket \n
+ *                        @ref SOCKERR_SOCKSTATUS  - Invalid socket status for socket operation \n
+ *                        @ref SOCKERR_DATALEN     - zero data length \n
+ *                        @ref SOCKERR_IPINVALID   - Wrong server IP address\n
+ *                        @ref SOCKERR_PORTZERO    - Server port zero\n
+ *                        @ref SOCKERR_SOCKCLOSED  - Socket unexpectedly closed \n
+ *                        @ref SOCKERR_TIMEOUT     - Timeout occurred \n
+ *                        @ref SOCK_BUSY           - Socket is busy. 
+ */
+int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ * @brief Receive datagram of UDP or MACRAW
+ * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n
+ *          This function is used to receive UDP and MAC_RAW mode, and handle the header as well. 
+ *          This function can divide to received the packet data.
+ *          On the MACRAW SOCKET, the addr and port parameters are ignored.
+ * @note    In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer
+ *          In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer.
+ *
+ * @param sn   Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>.
+ * @param buf  Pointer buffer to read incoming data.
+ * @param len  The max data length of data in buf. 
+ *             When the received packet size <= len, receives data as packet sized.
+ *             When others, receives data as len.
+ * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
+ *             It is valid only when the first call recvfrom for receiving the packet.
+ *             When it is valid, @ref  packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
+ * @param port Pointer variable of destination port number.
+ *             It is valid only when the first call recvform for receiving the packet.
+*             When it is valid, @ref  packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
+ *
+ * @return	@b Success : This function return real received data size for success.\n
+ *          @b Fail    : @ref SOCKERR_DATALEN    - zero data length \n
+ *                       @ref SOCKERR_SOCKMODE   - Invalid operation in the socket \n
+ *                       @ref SOCKERR_SOCKNUM    - Invalid socket number \n
+ *                       @ref SOCKBUSY           - Socket is busy.
+ */
+int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
+
+
+/////////////////////////////
+// SOCKET CONTROL & OPTION //
+/////////////////////////////
+#define SOCK_IO_BLOCK         0  ///< Socket Block IO Mode in @ref setsockopt().
+#define SOCK_IO_NONBLOCK      1  ///< Socket Non-block IO Mode in @ref setsockopt().
+
+/**
+ * @defgroup DATA_TYPE DATA TYPE
+ */
+
+/**
+ * @ingroup DATA_TYPE
+ * @brief The kind of Socket Interrupt.
+ * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR()
+ */
+typedef enum
+{
+   SIK_CONNECTED     = (1 << 0),    ///< connected
+   SIK_DISCONNECTED  = (1 << 1),    ///< disconnected
+   SIK_RECEIVED      = (1 << 2),    ///< data received
+   SIK_TIMEOUT       = (1 << 3),    ///< timeout occurred
+   SIK_SENT          = (1 << 4),    ///< send ok
+   //M20150410 : Remove the comma of last member
+   //SIK_ALL           = 0x1F,        ///< all interrupt
+   SIK_ALL           = 0x1F         ///< all interrupt
+}sockint_kind;
+
+/**
+ * @ingroup DATA_TYPE
+ * @brief The type of @ref ctlsocket().
+ */
+typedef enum
+{
+   CS_SET_IOMODE,          ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK
+   CS_GET_IOMODE,          ///< get socket IO mode
+   CS_GET_MAXTXBUF,        ///< get the size of socket buffer allocated in TX memory
+   CS_GET_MAXRXBUF,        ///< get the size of socket buffer allocated in RX memory
+   CS_CLR_INTERRUPT,       ///< clear the interrupt of socket with @ref sockint_kind
+   CS_GET_INTERRUPT,       ///< get the socket interrupt. refer to @ref sockint_kind
+#if _WIZCHIP_ > 5100
+   CS_SET_INTMASK,         ///< set the interrupt mask of socket with @ref sockint_kind, Not supported in W5100
+   CS_GET_INTMASK          ///< get the masked interrupt of socket. refer to @ref sockint_kind, Not supported in W5100
+#endif
+}ctlsock_type;
+
+
+/**
+ * @ingroup DATA_TYPE
+ * @brief The type of socket option in @ref setsockopt() or @ref getsockopt()
+ */ 
+typedef enum
+{
+   SO_FLAG,           ///< Valid only in getsockopt(), For set flag of socket refer to <I>flag</I> in @ref socket().
+   SO_TTL,              ///< Set TTL. @ref Sn_TTL  ( @ref setSn_TTL(), @ref getSn_TTL() )
+   SO_TOS,              ///< Set TOS. @ref Sn_TOS  ( @ref setSn_TOS(), @ref getSn_TOS() )
+   SO_MSS,              ///< Set MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() )
+   SO_DESTIP,           ///< Set the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() )
+   SO_DESTPORT,         ///< Set the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() )
+#if _WIZCHIP_ != 5100   
+   SO_KEEPALIVESEND,    ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode, Not supported in W5100
+   #if !( (_WIZCHIP_ == 5100) || (_WIZCHIP_ == 5200) )
+      SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode, Not supported in W5100, W5200
+   #endif      
+#endif
+   SO_SENDBUF,          ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR()
+   SO_RECVBUF,          ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR()
+   SO_STATUS,           ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR()
+   SO_REMAINSIZE,       ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode.
+   SO_PACKINFO          ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode.
+}sockopt_type;
+
+/**
+ * @ingroup WIZnet_socket_APIs
+ *  @brief Control socket.
+ *  @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information.
+ *           Refer to @ref ctlsock_type.
+ *  @param sn socket number
+ *  @param cstype type of control socket. refer to @ref ctlsock_type.
+ *  @param arg Data type and value is determined according to @ref ctlsock_type. \n
+ *             <table>
+ *                  <tr> <td> @b cstype </td> <td> @b data type</td><td>@b value</td></tr>
+ *                  <tr> <td> @ref CS_SET_IOMODE \n @ref CS_GET_IOMODE </td> <td> uint8_t </td><td>@ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK</td></tr>
+ *                  <tr> <td> @ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF </td> <td> uint16_t </td><td> 0 ~ 16K </td></tr>
+ *                  <tr> <td> @ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK </td> <td> @ref sockint_kind </td><td> @ref SIK_CONNECTED, etc.  </td></tr> 
+ *             </table>
+ *  @return @b Success @ref SOCK_OK \n
+ *          @b fail    @ref SOCKERR_ARG         - Invalid argument\n
+ */
+int8_t  ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg);
+
+/** 
+ * @ingroup WIZnet_socket_APIs
+ *  @brief set socket options
+ *  @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type.
+ *               
+ *  @param sn socket number
+ *  @param sotype socket option type. refer to @ref sockopt_type
+ *  @param arg Data type and value is determined according to <I>sotype</I>. \n
+ *             <table>
+ *                  <tr> <td> @b sotype </td> <td> @b data type</td><td>@b value</td></tr> 
+ *                  <tr> <td> @ref SO_TTL </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
+ *                  <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
+ *                  <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
+ *                  <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td>  </td></tr> 
+ *                  <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> 
+ *                  <tr> <td> @ref SO_KEEPALIVESEND </td> <td> null </td><td> null </td></tr> 
+ *                  <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> 
+ *             </table>
+ * @return 
+ * - @b Success : @ref SOCK_OK \n
+ * - @b Fail 
+ *  - @ref SOCKERR_SOCKNUM     - Invalid Socket number \n
+ *  - @ref SOCKERR_SOCKMODE    - Invalid socket mode \n
+ *  - @ref SOCKERR_SOCKOPT     - Invalid socket option or its value \n
+ *  - @ref SOCKERR_TIMEOUT     - Timeout occurred when sending keep-alive packet \n
+ */
+int8_t  setsockopt(uint8_t sn, sockopt_type sotype, void* arg);
+
+/** 
+ * @ingroup WIZnet_socket_APIs
+ *  @brief get socket options
+ *  @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type
+ *  @param sn socket number
+ *  @param sotype socket option type. refer to @ref sockopt_type
+ *  @param arg Data type and value is determined according to <I>sotype</I>. \n
+ *             <table>
+ *                  <tr> <td> @b sotype </td> <td>@b data type</td><td>@b value</td></tr>
+ *                  <tr> <td> @ref SO_FLAG </td> <td> uint8_t </td><td> @ref SF_ETHER_OWN, etc... </td> </tr>
+ *                  <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr>
+ *                  <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr>
+ *                  <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td>  </td></tr> 
+ *                  <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td>  </td></tr> 
+ *                  <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> 
+ *                  <tr> <td> @ref SO_SENDBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>  
+ *                  <tr> <td> @ref SO_RECVBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr>  
+ *                  <tr> <td> @ref SO_STATUS </td> <td> uint8_t </td><td> @ref SOCK_ESTABLISHED, etc.. </td></tr>  
+ *                  <tr> <td> @ref SO_REMAINSIZE </td> <td> uint16_t </td><td> 0~ 65535 </td></tr>
+ *                  <tr> <td> @ref SO_PACKINFO </td> <td> uint8_t </td><td> @ref PACK_FIRST, etc... </td></tr>
+ *             </table>
+ * @return 
+ * - @b Success : @ref SOCK_OK \n
+ * - @b Fail 
+ *  - @ref SOCKERR_SOCKNUM     - Invalid Socket number \n
+ *  - @ref SOCKERR_SOCKOPT     - Invalid socket option or its value \n
+ *  - @ref SOCKERR_SOCKMODE    - Invalid socket mode \n
+ * @note
+ *   The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n
+ *   When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, 
+ *   This means the zero byte UDP data(UDP Header only) received.
+  */
+int8_t  getsockopt(uint8_t sn, sockopt_type sotype, void* arg);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif   // _SOCKET_H_

+ 842 - 0
lib/ioLibrary_Driver/Ethernet/wizchip_conf.c

@@ -0,0 +1,842 @@
+//****************************************************************************/
+//!
+//! \file wizchip_conf.c
+//! \brief WIZCHIP Config Header File.
+//! \version 1.0.1
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2015/02/05> Notice
+//!        The version history is not updated after this point.
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//!       <2014/05/01> V1.0.1  Refer to M20140501
+//!        1. Explicit type casting in wizchip_bus_readdata() & wizchip_bus_writedata()
+//            Issued by Mathias ClauBen.
+//!           uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t*
+//!           For remove the warning when pointer type size is not 32bit.
+//!           If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type.
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//!
+//! Redistribution and use in source and binary forms, with or without
+//! modification, are permitted provided that the following conditions
+//! are met:
+//!
+//!     * Redistributions of source code must retain the above copyright
+//! notice, this list of conditions and the following disclaimer.
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution.
+//!     * Neither the name of the <ORGANIZATION> nor the names of its
+//! contributors may be used to endorse or promote products derived
+//! from this software without specific prior written permission.
+//!
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************/
+//A20140501 : for use the type - ptrdiff_t
+#include <stddef.h>
+//
+
+#include "wizchip_conf.h"
+
+/////////////
+//M20150401 : Remove ; in the default callback function such as wizchip_cris_enter(), wizchip_cs_select() and etc.
+/////////////
+
+/**
+ * @brief Default function to enable interrupt.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//void 	  wizchip_cris_enter(void)           {};
+void wizchip_cris_enter(void) {
+}
+
+/**
+ * @brief Default function to disable interrupt.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//void 	  wizchip_cris_exit(void)          {};
+void wizchip_cris_exit(void) {
+}
+
+/**
+ * @brief Default function to select chip.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//void 	wizchip_cs_select(void)            {};
+void wizchip_cs_select(void) {
+}
+
+/**
+ * @brief Default function to deselect chip.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//void 	wizchip_cs_deselect(void)          {};
+void wizchip_cs_deselect(void) {
+}
+
+/**
+ * @brief Default function to read in direct or indirect interface.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//M20150601 : Rename the function for integrating with W5300
+//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); }
+iodata_t wizchip_bus_readdata(uint32_t AddrSel) {
+    return *((volatile iodata_t*)((ptrdiff_t)AddrSel));
+}
+
+/**
+ * @brief Default function to write in direct or indirect interface.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//M20150601 : Rename the function for integrating with W5300
+//void 	wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb)  { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; }
+void wizchip_bus_writedata(uint32_t AddrSel, iodata_t wb) {
+    *((volatile iodata_t*)((ptrdiff_t)AddrSel)) = wb;
+}
+
+/**
+ * @brief Default function to read in SPI interface.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//uint8_t wizchip_spi_readbyte(void)        {return 0;};
+// uint8_t wizchip_spi_readbyte(void) {
+//     return 0;
+// }
+
+/**
+ * @brief Default function to write in SPI interface.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//void 	wizchip_spi_writebyte(uint8_t wb) {};
+//void 	wizchip_spi_writebyte(uint8_t wb) {}
+
+/**
+ * @brief Default function to burst read in SPI interface.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//void 	wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) 	{};
+// void wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) {
+// }
+
+/**
+ * @brief Default function to burst write in SPI interface.
+ * @note This function help not to access wrong address. If you do not describe this function or register any functions,
+ * null function is called.
+ */
+//void 	wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {};
+// void wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {
+// }
+
+/**
+ * @\ref _WIZCHIP instance
+ */
+//
+//M20150401 : For a compiler didnot support a member of structure
+//            Replace the assignment of struct members with the assingment of array
+//
+/*
+_WIZCHIP  WIZCHIP =
+      {
+      .id                  = _WIZCHIP_ID_,
+      .if_mode             = _WIZCHIP_IO_MODE_,
+      .CRIS._enter         = wizchip_cris_enter,
+      .CRIS._exit          = wizchip_cris_exit,
+      .CS._select          = wizchip_cs_select,
+      .CS._deselect        = wizchip_cs_deselect,
+      .IF.BUS._read_byte   = wizchip_bus_readbyte,
+      .IF.BUS._write_byte  = wizchip_bus_writebyte
+//    .IF.SPI._read_byte   = wizchip_spi_readbyte,
+//    .IF.SPI._write_byte  = wizchip_spi_writebyte
+      };
+*/
+_WIZCHIP WIZCHIP = {
+    _WIZCHIP_IO_MODE_,
+    _WIZCHIP_ID_,
+    {wizchip_cris_enter, wizchip_cris_exit},
+    {wizchip_cs_select, wizchip_cs_deselect},
+    {
+        {//M20150601 : Rename the function
+         //wizchip_bus_readbyte,
+         //wizchip_bus_writebyte
+         wizchip_bus_readdata,
+         wizchip_bus_writedata},
+
+    }};
+
+static uint8_t _DNS_[4]; // DNS server ip address
+static dhcp_mode _DHCP_; // DHCP mode
+
+void reg_wizchip_cris_cbfunc(void (*cris_en)(void), void (*cris_ex)(void)) {
+    if(!cris_en || !cris_ex) {
+        WIZCHIP.CRIS._enter = wizchip_cris_enter;
+        WIZCHIP.CRIS._exit = wizchip_cris_exit;
+    } else {
+        WIZCHIP.CRIS._enter = cris_en;
+        WIZCHIP.CRIS._exit = cris_ex;
+    }
+}
+
+void reg_wizchip_cs_cbfunc(void (*cs_sel)(void), void (*cs_desel)(void)) {
+    if(!cs_sel || !cs_desel) {
+        WIZCHIP.CS._select = wizchip_cs_select;
+        WIZCHIP.CS._deselect = wizchip_cs_deselect;
+    } else {
+        WIZCHIP.CS._select = cs_sel;
+        WIZCHIP.CS._deselect = cs_desel;
+    }
+}
+
+//M20150515 : For integrating with W5300
+//void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb))
+void reg_wizchip_bus_cbfunc(
+    iodata_t (*bus_rb)(uint32_t addr),
+    void (*bus_wb)(uint32_t addr, iodata_t wb)) {
+    while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_))
+        ;
+    //M20150601 : Rename call back function for integrating with W5300
+    /*
+   if(!bus_rb || !bus_wb)
+   {
+      WIZCHIP.IF.BUS._read_byte   = wizchip_bus_readbyte;
+      WIZCHIP.IF.BUS._write_byte  = wizchip_bus_writebyte;
+   }
+   else
+   {
+      WIZCHIP.IF.BUS._read_byte   = bus_rb;
+      WIZCHIP.IF.BUS._write_byte  = bus_wb;
+   }
+   */
+    if(!bus_rb || !bus_wb) {
+        WIZCHIP.IF.BUS._read_data = wizchip_bus_readdata;
+        WIZCHIP.IF.BUS._write_data = wizchip_bus_writedata;
+    } else {
+        WIZCHIP.IF.BUS._read_data = bus_rb;
+        WIZCHIP.IF.BUS._write_data = bus_wb;
+    }
+}
+
+void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb)) {
+    while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_))
+        ;
+
+    if(!spi_rb || !spi_wb) {
+        //   WIZCHIP.IF.SPI._read_byte = wizchip_spi_readbyte;
+        //   WIZCHIP.IF.SPI._write_byte = wizchip_spi_writebyte;
+    } else {
+        WIZCHIP.IF.SPI._read_byte = spi_rb;
+        WIZCHIP.IF.SPI._write_byte = spi_wb;
+    }
+}
+
+// 20140626 Eric Added for SPI burst operations
+void reg_wizchip_spiburst_cbfunc(
+    void (*spi_rb)(uint8_t* pBuf, uint16_t len),
+    void (*spi_wb)(uint8_t* pBuf, uint16_t len)) {
+    while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_))
+        ;
+
+    if(!spi_rb || !spi_wb) {
+        //   WIZCHIP.IF.SPI._read_burst = wizchip_spi_readburst;
+        //   WIZCHIP.IF.SPI._write_burst = wizchip_spi_writeburst;
+    } else {
+        WIZCHIP.IF.SPI._read_burst = spi_rb;
+        WIZCHIP.IF.SPI._write_burst = spi_wb;
+    }
+}
+
+int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) {
+#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
+    uint8_t tmp = 0;
+#endif
+    uint8_t* ptmp[2] = {0, 0};
+    switch(cwtype) {
+    case CW_RESET_WIZCHIP:
+        wizchip_sw_reset();
+        break;
+    case CW_INIT_WIZCHIP:
+        if(arg != 0) {
+            ptmp[0] = (uint8_t*)arg;
+            ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
+        }
+        return wizchip_init(ptmp[0], ptmp[1]);
+    case CW_CLR_INTERRUPT:
+        wizchip_clrinterrupt(*((intr_kind*)arg));
+        break;
+    case CW_GET_INTERRUPT:
+        *((intr_kind*)arg) = wizchip_getinterrupt();
+        break;
+    case CW_SET_INTRMASK:
+        wizchip_setinterruptmask(*((intr_kind*)arg));
+        break;
+    case CW_GET_INTRMASK:
+        *((intr_kind*)arg) = wizchip_getinterruptmask();
+        break;
+//M20150601 : This can be supported by W5200, W5500
+//#if _WIZCHIP_ > W5100
+#if(_WIZCHIP_ == W5200 || _WIZCHIP_ == W5500)
+    case CW_SET_INTRTIME:
+        setINTLEVEL(*(uint16_t*)arg);
+        break;
+    case CW_GET_INTRTIME:
+        *(uint16_t*)arg = getINTLEVEL();
+        break;
+#endif
+    case CW_GET_ID:
+        ((uint8_t*)arg)[0] = WIZCHIP.id[0];
+        ((uint8_t*)arg)[1] = WIZCHIP.id[1];
+        ((uint8_t*)arg)[2] = WIZCHIP.id[2];
+        ((uint8_t*)arg)[3] = WIZCHIP.id[3];
+        ((uint8_t*)arg)[4] = WIZCHIP.id[4];
+        ((uint8_t*)arg)[5] = WIZCHIP.id[5];
+        ((uint8_t*)arg)[6] = 0;
+        break;
+#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
+    case CW_RESET_PHY:
+        wizphy_reset();
+        break;
+    case CW_SET_PHYCONF:
+        wizphy_setphyconf((wiz_PhyConf*)arg);
+        break;
+    case CW_GET_PHYCONF:
+        wizphy_getphyconf((wiz_PhyConf*)arg);
+        break;
+    case CW_GET_PHYSTATUS:
+        break;
+    case CW_SET_PHYPOWMODE:
+        return wizphy_setphypmode(*(uint8_t*)arg);
+#endif
+#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
+    case CW_GET_PHYPOWMODE:
+        tmp = wizphy_getphypmode();
+        if((int8_t)tmp == -1) return -1;
+        *(uint8_t*)arg = tmp;
+        break;
+    case CW_GET_PHYLINK:
+        tmp = wizphy_getphylink();
+        if((int8_t)tmp == -1) return -1;
+        *(uint8_t*)arg = tmp;
+        break;
+#endif
+    default:
+        return -1;
+    }
+    return 0;
+}
+
+int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) {
+    switch(cntype) {
+    case CN_SET_NETINFO:
+        wizchip_setnetinfo((wiz_NetInfo*)arg);
+        break;
+    case CN_GET_NETINFO:
+        wizchip_getnetinfo((wiz_NetInfo*)arg);
+        break;
+    case CN_SET_NETMODE:
+        return wizchip_setnetmode(*(netmode_type*)arg);
+    case CN_GET_NETMODE:
+        *(netmode_type*)arg = wizchip_getnetmode();
+        break;
+    case CN_SET_TIMEOUT:
+        wizchip_settimeout((wiz_NetTimeout*)arg);
+        break;
+    case CN_GET_TIMEOUT:
+        wizchip_gettimeout((wiz_NetTimeout*)arg);
+        break;
+    default:
+        return -1;
+    }
+    return 0;
+}
+
+void wizchip_sw_reset(void) {
+    uint8_t gw[4], sn[4], sip[4];
+    uint8_t mac[6];
+//A20150601
+#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
+    uint16_t mr = (uint16_t)getMR();
+    setMR(mr | MR_IND);
+#endif
+    //
+    getSHAR(mac);
+    getGAR(gw);
+    getSUBR(sn);
+    getSIPR(sip);
+    setMR(MR_RST);
+    getMR(); // for delay
+//A2015051 : For indirect bus mode
+#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
+    setMR(mr | MR_IND);
+#endif
+    //
+    setSHAR(mac);
+    setGAR(gw);
+    setSUBR(sn);
+    setSIPR(sip);
+}
+
+int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) {
+    int8_t i;
+#if _WIZCHIP_ < W5200
+    int8_t j;
+#endif
+    int8_t tmp = 0;
+    wizchip_sw_reset();
+    if(txsize) {
+        tmp = 0;
+//M20150601 : For integrating with W5300
+#if _WIZCHIP_ == W5300
+        for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
+            if(txsize[i] >= 64)
+                return -1; //No use 64KB even if W5300 support max 64KB memory allocation
+            tmp += txsize[i];
+            if(tmp > 128) return -1;
+        }
+        if(tmp % 8) return -1;
+#else
+        for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
+            tmp += txsize[i];
+
+#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100 and w5100s
+            if(tmp > 8) return -1;
+#else
+            if(tmp > 16) return -1;
+#endif
+        }
+        for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
+#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100
+            j = 0;
+            while((txsize[i] >> j != 1) && (txsize[i] != 0)) {
+                j++;
+            }
+            setSn_TXBUF_SIZE(i, j);
+#else
+            setSn_TXBUF_SIZE(i, txsize[i]);
+#endif
+        }
+
+#endif
+    }
+
+    if(rxsize) {
+        tmp = 0;
+#if _WIZCHIP_ == W5300
+        for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
+            if(rxsize[i] >= 64)
+                return -1; //No use 64KB even if W5300 support max 64KB memory allocation
+            tmp += rxsize[i];
+            if(tmp > 128) return -1;
+        }
+        if(tmp % 8) return -1;
+#else
+        for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
+            tmp += rxsize[i];
+#if _WIZCHIP_ < W5200 //2016.10.28 peter add condition for w5100 and w5100s
+            if(tmp > 8) return -1;
+#else
+            if(tmp > 16) return -1;
+#endif
+        }
+
+        for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
+#if _WIZCHIP_ < W5200 // add condition for w5100
+            j = 0;
+            while((rxsize[i] >> j != 1) && (txsize[i] != 0)) {
+                j++;
+            }
+            setSn_RXBUF_SIZE(i, j);
+#else
+            setSn_RXBUF_SIZE(i, rxsize[i]);
+#endif
+        }
+#endif
+    }
+    return 0;
+}
+
+void wizchip_clrinterrupt(intr_kind intr) {
+    uint8_t ir = (uint8_t)intr;
+    uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
+#if _WIZCHIP_ < W5500
+    ir |= (1 << 4); // IK_WOL
+#endif
+#if _WIZCHIP_ == W5200
+    ir |= (1 << 6);
+#endif
+
+#if _WIZCHIP_ < W5200
+    sir &= 0x0F;
+#endif
+
+#if _WIZCHIP_ <= W5100S
+    ir |= sir;
+    setIR(ir);
+//A20150601 : For integrating with W5300
+#elif _WIZCHIP_ == W5300
+    setIR(((((uint16_t)ir) << 8) | (((uint16_t)sir) & 0x00FF)));
+#else
+    setIR(ir);
+    //M20200227 : For clear
+    //setSIR(sir);
+    for(ir = 0; ir < 8; ir++) {
+        if(sir & (0x01 << ir)) setSn_IR(ir, 0xff);
+    }
+
+#endif
+}
+
+intr_kind wizchip_getinterrupt(void) {
+    uint8_t ir = 0;
+    uint8_t sir = 0;
+    uint16_t ret = 0;
+#if _WIZCHIP_ <= W5100S
+    ir = getIR();
+    sir = ir & 0x0F;
+//A20150601 : For integrating with W5300
+#elif _WIZCHIP_ == W5300
+    ret = getIR();
+    ir = (uint8_t)(ret >> 8);
+    sir = (uint8_t)ret;
+#else
+    ir = getIR();
+    sir = getSIR();
+#endif
+
+//M20150601 : For Integrating with W5300
+//#if _WIZCHIP_ < W5500
+#if _WIZCHIP_ < W5200
+    ir &= ~(1 << 4); // IK_WOL
+#endif
+#if _WIZCHIP_ == W5200
+    ir &= ~(1 << 6);
+#endif
+    ret = sir;
+    ret = (ret << 8) + ir;
+    return (intr_kind)ret;
+}
+
+void wizchip_setinterruptmask(intr_kind intr) {
+    uint8_t imr = (uint8_t)intr;
+    uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
+#if _WIZCHIP_ < W5500
+    imr &= ~(1 << 4); // IK_WOL
+#endif
+#if _WIZCHIP_ == W5200
+    imr &= ~(1 << 6);
+#endif
+
+#if _WIZCHIP_ < W5200
+    simr &= 0x0F;
+    imr |= simr;
+    setIMR(imr);
+//A20150601 : For integrating with W5300
+#elif _WIZCHIP_ == W5300
+    setIMR(((((uint16_t)imr) << 8) | (((uint16_t)simr) & 0x00FF)));
+#else
+    setIMR(imr);
+    setSIMR(simr);
+#endif
+}
+
+intr_kind wizchip_getinterruptmask(void) {
+    uint8_t imr = 0;
+    uint8_t simr = 0;
+    uint16_t ret = 0;
+#if _WIZCHIP_ < W5200
+    imr = getIMR();
+    simr = imr & 0x0F;
+//A20150601 : For integrating with W5300
+#elif _WIZCHIP_ == W5300
+    ret = getIMR();
+    imr = (uint8_t)(ret >> 8);
+    simr = (uint8_t)ret;
+#else
+    imr = getIMR();
+    simr = getSIMR();
+#endif
+
+#if _WIZCHIP_ < W5500
+    imr &= ~(1 << 4); // IK_WOL
+#endif
+#if _WIZCHIP_ == W5200
+    imr &= ~(1 << 6); // IK_DEST_UNREACH
+#endif
+    ret = simr;
+    ret = (ret << 8) + imr;
+    return (intr_kind)ret;
+}
+
+int8_t wizphy_getphylink(void) {
+    int8_t tmp = PHY_LINK_OFF;
+#if _WIZCHIP_ == W5100S
+    if(getPHYSR() & PHYSR_LNK) tmp = PHY_LINK_ON;
+#elif _WIZCHIP_ == W5200
+    if(getPHYSTATUS() & PHYSTATUS_LINK) tmp = PHY_LINK_ON;
+#elif _WIZCHIP_ == W5500
+    if(getPHYCFGR() & PHYCFGR_LNK_ON) tmp = PHY_LINK_ON;
+
+#else
+    tmp = -1;
+#endif
+    return tmp;
+}
+
+#if _WIZCHIP_ > W5100
+
+int8_t wizphy_getphypmode(void) {
+    int8_t tmp = 0;
+#if _WIZCHIP_ == W5200
+    if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
+        tmp = PHY_POWER_DOWN;
+    else
+        tmp = PHY_POWER_NORM;
+#elif _WIZCHIP_ == 5500
+    if((getPHYCFGR() & PHYCFGR_OPMDC_ALLA) == PHYCFGR_OPMDC_PDOWN)
+        tmp = PHY_POWER_DOWN;
+    else
+        tmp = PHY_POWER_NORM;
+#else
+    tmp = -1;
+#endif
+    return tmp;
+}
+#endif
+
+#if _WIZCHIP_ == W5100S
+void wizphy_reset(void) {
+    uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
+    tmp |= BMCR_RESET;
+    wiz_mdio_write(PHYMDIO_BMCR, tmp);
+    while(wiz_mdio_read(PHYMDIO_BMCR) & BMCR_RESET) {
+    }
+}
+
+void wizphy_setphyconf(wiz_PhyConf* phyconf) {
+    uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
+    if(phyconf->mode == PHY_MODE_AUTONEGO)
+        tmp |= BMCR_AUTONEGO;
+    else {
+        tmp &= ~BMCR_AUTONEGO;
+        if(phyconf->duplex == PHY_DUPLEX_FULL) {
+            tmp |= BMCR_DUP;
+        } else {
+            tmp &= ~BMCR_DUP;
+        }
+        if(phyconf->speed == PHY_SPEED_100) {
+            tmp |= BMCR_SPEED;
+        } else {
+            tmp &= ~BMCR_SPEED;
+        }
+    }
+    wiz_mdio_write(PHYMDIO_BMCR, tmp);
+}
+
+void wizphy_getphyconf(wiz_PhyConf* phyconf) {
+    uint16_t tmp = 0;
+    tmp = wiz_mdio_read(PHYMDIO_BMCR);
+    phyconf->by = PHY_CONFBY_SW;
+    if(tmp & BMCR_AUTONEGO) {
+        phyconf->mode = PHY_MODE_AUTONEGO;
+    } else {
+        phyconf->mode = PHY_MODE_MANUAL;
+        if(tmp & BMCR_DUP)
+            phyconf->duplex = PHY_DUPLEX_FULL;
+        else
+            phyconf->duplex = PHY_DUPLEX_HALF;
+        if(tmp & BMCR_SPEED)
+            phyconf->speed = PHY_SPEED_100;
+        else
+            phyconf->speed = PHY_SPEED_10;
+    }
+}
+
+int8_t wizphy_setphypmode(uint8_t pmode) {
+    uint16_t tmp = 0;
+    tmp = wiz_mdio_read(PHYMDIO_BMCR);
+    if(pmode == PHY_POWER_DOWN) {
+        tmp |= BMCR_PWDN;
+    } else {
+        tmp &= ~BMCR_PWDN;
+    }
+    wiz_mdio_write(PHYMDIO_BMCR, tmp);
+    tmp = wiz_mdio_read(PHYMDIO_BMCR);
+    if(pmode == PHY_POWER_DOWN) {
+        if(tmp & BMCR_PWDN) return 0;
+    } else {
+        if((tmp & BMCR_PWDN) != BMCR_PWDN) return 0;
+    }
+    return -1;
+}
+
+#endif
+#if _WIZCHIP_ == W5500
+void wizphy_reset(void) {
+    uint8_t tmp = getPHYCFGR();
+    tmp &= PHYCFGR_RST;
+    setPHYCFGR(tmp);
+    tmp = getPHYCFGR();
+    tmp |= ~PHYCFGR_RST;
+    setPHYCFGR(tmp);
+}
+
+void wizphy_setphyconf(wiz_PhyConf* phyconf) {
+    uint8_t tmp = 0;
+    if(phyconf->by == PHY_CONFBY_SW)
+        tmp |= PHYCFGR_OPMD;
+    else
+        tmp &= ~PHYCFGR_OPMD;
+    if(phyconf->mode == PHY_MODE_AUTONEGO)
+        tmp |= PHYCFGR_OPMDC_ALLA;
+    else {
+        if(phyconf->duplex == PHY_DUPLEX_FULL) {
+            if(phyconf->speed == PHY_SPEED_100)
+                tmp |= PHYCFGR_OPMDC_100F;
+            else
+                tmp |= PHYCFGR_OPMDC_10F;
+        } else {
+            if(phyconf->speed == PHY_SPEED_100)
+                tmp |= PHYCFGR_OPMDC_100H;
+            else
+                tmp |= PHYCFGR_OPMDC_10H;
+        }
+    }
+    setPHYCFGR(tmp);
+    wizphy_reset();
+}
+
+void wizphy_getphyconf(wiz_PhyConf* phyconf) {
+    uint8_t tmp = 0;
+    tmp = getPHYCFGR();
+    phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
+    switch(tmp & PHYCFGR_OPMDC_ALLA) {
+    case PHYCFGR_OPMDC_ALLA:
+    case PHYCFGR_OPMDC_100FA:
+        phyconf->mode = PHY_MODE_AUTONEGO;
+        break;
+    default:
+        phyconf->mode = PHY_MODE_MANUAL;
+        break;
+    }
+    switch(tmp & PHYCFGR_OPMDC_ALLA) {
+    case PHYCFGR_OPMDC_100FA:
+    case PHYCFGR_OPMDC_100F:
+    case PHYCFGR_OPMDC_100H:
+        phyconf->speed = PHY_SPEED_100;
+        break;
+    default:
+        phyconf->speed = PHY_SPEED_10;
+        break;
+    }
+    switch(tmp & PHYCFGR_OPMDC_ALLA) {
+    case PHYCFGR_OPMDC_100FA:
+    case PHYCFGR_OPMDC_100F:
+    case PHYCFGR_OPMDC_10F:
+        phyconf->duplex = PHY_DUPLEX_FULL;
+        break;
+    default:
+        phyconf->duplex = PHY_DUPLEX_HALF;
+        break;
+    }
+}
+
+void wizphy_getphystat(wiz_PhyConf* phyconf) {
+    uint8_t tmp = getPHYCFGR();
+    phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
+    phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
+}
+
+int8_t wizphy_setphypmode(uint8_t pmode) {
+    uint8_t tmp = 0;
+    tmp = getPHYCFGR();
+    if((tmp & PHYCFGR_OPMD) == 0) return -1;
+    tmp &= ~PHYCFGR_OPMDC_ALLA;
+    if(pmode == PHY_POWER_DOWN)
+        tmp |= PHYCFGR_OPMDC_PDOWN;
+    else
+        tmp |= PHYCFGR_OPMDC_ALLA;
+    setPHYCFGR(tmp);
+    wizphy_reset();
+    tmp = getPHYCFGR();
+    if(pmode == PHY_POWER_DOWN) {
+        if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
+    } else {
+        if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
+    }
+    return -1;
+}
+#endif
+
+void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) {
+    setSHAR(pnetinfo->mac);
+    setGAR(pnetinfo->gw);
+    setSUBR(pnetinfo->sn);
+    setSIPR(pnetinfo->ip);
+    _DNS_[0] = pnetinfo->dns[0];
+    _DNS_[1] = pnetinfo->dns[1];
+    _DNS_[2] = pnetinfo->dns[2];
+    _DNS_[3] = pnetinfo->dns[3];
+    _DHCP_ = pnetinfo->dhcp;
+}
+
+void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) {
+    getSHAR(pnetinfo->mac);
+    getGAR(pnetinfo->gw);
+    getSUBR(pnetinfo->sn);
+    getSIPR(pnetinfo->ip);
+    pnetinfo->dns[0] = _DNS_[0];
+    pnetinfo->dns[1] = _DNS_[1];
+    pnetinfo->dns[2] = _DNS_[2];
+    pnetinfo->dns[3] = _DNS_[3];
+    pnetinfo->dhcp = _DHCP_;
+}
+
+int8_t wizchip_setnetmode(netmode_type netmode) {
+    uint8_t tmp = 0;
+#if _WIZCHIP_ != W5500
+    if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
+#else
+    if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
+#endif
+    tmp = getMR();
+    tmp |= (uint8_t)netmode;
+    setMR(tmp);
+    return 0;
+}
+
+netmode_type wizchip_getnetmode(void) {
+    return (netmode_type)getMR();
+}
+
+void wizchip_settimeout(wiz_NetTimeout* nettime) {
+    setRCR(nettime->retry_cnt);
+    setRTR(nettime->time_100us);
+}
+
+void wizchip_gettimeout(wiz_NetTimeout* nettime) {
+    nettime->retry_cnt = getRCR();
+    nettime->time_100us = getRTR();
+}

+ 661 - 0
lib/ioLibrary_Driver/Ethernet/wizchip_conf.h

@@ -0,0 +1,661 @@
+//*****************************************************************************
+//
+//! \file wizchip_conf.h
+//! \brief WIZCHIP Config Header File.
+//! \version 1.0.0
+//! \date 2013/10/21
+//! \par  Revision history
+//!       <2015/02/05> Notice
+//!        The version history is not updated after this point.
+//!        Download the latest version directly from GitHub. Please visit the our GitHub repository for ioLibrary.
+//!        >> https://github.com/Wiznet/ioLibrary_Driver
+//!       <2013/10/21> 1st Release
+//! \author MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+/**
+ * @defgroup extra_functions 2. WIZnet Extra Functions
+ *
+ * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions.  
+ * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n
+ * 
+ */
+
+#ifndef  _WIZCHIP_CONF_H_
+#define  _WIZCHIP_CONF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+/**
+ * @brief Select WIZCHIP.
+ * @todo You should select one, \b W5100, \b W5100S, \b W5200, \b W5300, \b W5500 or etc. \n\n
+ *       ex> <code> #define \_WIZCHIP_      W5500 </code>
+ */
+
+#define W5100						5100
+#define W5100S						5100+5
+#define W5200						5200
+#define W5300						5300
+#define W5500						5500
+
+#ifndef _WIZCHIP_
+#define _WIZCHIP_                      W5500   // W5100, W5100S, W5200, W5300, W5500
+#endif
+
+#define _WIZCHIP_IO_MODE_NONE_         0x0000
+#define _WIZCHIP_IO_MODE_BUS_          0x0100 /**< Bus interface mode */
+#define _WIZCHIP_IO_MODE_SPI_          0x0200 /**< SPI interface mode */
+//#define _WIZCHIP_IO_MODE_IIC_          0x0400
+//#define _WIZCHIP_IO_MODE_SDIO_         0x0800
+// Add to
+//
+
+#define _WIZCHIP_IO_MODE_BUS_DIR_      (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct  */
+#define _WIZCHIP_IO_MODE_BUS_INDIR_    (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */
+
+#define _WIZCHIP_IO_MODE_SPI_VDM_      (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/
+#define _WIZCHIP_IO_MODE_SPI_FDM_      (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/
+#define _WIZCHIP_IO_MODE_SPI_5500_     (_WIZCHIP_IO_MODE_SPI_ + 3) /**< SPI interface mode for fixed length data mode*/
+
+#if   (_WIZCHIP_ == W5100)
+   #define _WIZCHIP_ID_                "W5100\0"
+/**
+ * @brief Define interface mode.
+ * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
+ */
+// 	#define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_BUS_DIR_
+//	#define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_BUS_INDIR_
+   	   #define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_SPI_
+
+//A20150601 : Define the unit of IO DATA.   
+   typedef   uint8_t   iodata_t;
+//A20150401 : Indclude W5100.h file
+   #include "W5100/w5100.h"
+
+#elif (_WIZCHIP_ == W5100S)
+#define _WIZCHIP_ID_                "W5100S\0"
+/**
+* @brief Define interface mode.
+* @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
+*/
+//	#define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_BUS_INDIR_
+	//#define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_SPI_5500_
+	#define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_SPI_
+
+//A20150601 : Define the unit of IO DATA.
+   typedef   uint8_t   iodata_t;
+//A20150401 : Indclude W5100.h file
+	#include "W5100S/w5100s.h"
+#elif (_WIZCHIP_ == W5200)
+   #define _WIZCHIP_ID_                "W5200\0"
+/**
+ * @brief Define interface mode.
+ * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \	_WIZCHIP_IO_MODE_BUS_INDIR_
+ */
+#ifndef _WIZCHIP_IO_MODE_
+// #define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_BUS_INDIR_
+   #define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_SPI_
+#endif
+//A20150601 : Define the unit of IO DATA.   
+   typedef   uint8_t   iodata_t;
+   #include "W5200/w5200.h"
+#elif (_WIZCHIP_ == W5500)
+  #define _WIZCHIP_ID_                 "W5500\0"
+  
+/**
+ * @brief Define interface mode. \n
+ * @todo Should select interface mode as chip. 
+ *        - @ref \_WIZCHIP_IO_MODE_SPI_ \n
+ *          -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == W5500 \n
+ *          -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == W5500 \n
+ *        - @ref \_WIZCHIP_IO_MODE_BUS_ \n
+ *          - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n
+ *          - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n
+ *        - Others will be defined in future. \n\n
+ *        ex> <code> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ </code>
+ *       
+ */
+#ifndef _WIZCHIP_IO_MODE_
+   //#define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_SPI_FDM_
+   #define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_SPI_VDM_
+#endif
+//A20150601 : Define the unit of IO DATA.   
+   typedef   uint8_t   iodata_t;
+   #include "W5500/w5500.h"
+#elif ( _WIZCHIP_ == W5300)
+   #define _WIZCHIP_ID_                 "W5300\0"
+/**
+ * @brief Define interface mode.
+ * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
+ */
+#ifndef _WIZCHIP_IO_MODE_
+   #define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_BUS_DIR_
+// #define _WIZCHIP_IO_MODE_           _WIZCHIP_IO_MODE_BUS_INDIR_
+#endif
+
+//A20150601 : Define the unit and bus width of IO DATA. 
+   /**
+    * @brief Select the data width 8 or 16 bits.
+    * @todo you should select the bus width. Select one of 8 or 16.
+    */
+   #ifndef _WIZCHIP_IO_BUS_WIDTH_
+   #define _WIZCHIP_IO_BUS_WIDTH_       16  // 8
+   #endif
+   #if _WIZCHIP_IO_BUS_WIDTH_ == 8
+      typedef   uint8_t   iodata_t;
+   #elif _WIZCHIP_IO_BUS_WIDTH_ == 16
+      typedef   uint16_t   iodata_t;
+   #else
+      #error "Unknown _WIZCHIP_IO_BUS_WIDTH_. It should be 8 or 16."	
+   #endif
+//
+   #include "W5300/w5300.h"
+#else
+   #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!"
+#endif
+
+#ifndef _WIZCHIP_IO_MODE_
+   #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!"
+#endif
+
+/**
+ * @brief Define I/O base address when BUS IF mode.
+ * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_,
+ *       @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n
+ *       ex> <code> #define \_WIZCHIP_IO_BASE_      0x00008000 </code>
+ */
+#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
+//	#define _WIZCHIP_IO_BASE_				0x60000000	// for 5100S IND
+	#define _WIZCHIP_IO_BASE_				0x68000000	// for W5300
+#elif _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_
+	#define _WIZCHIP_IO_BASE_				0x00000000	// for 5100S SPI
+#endif
+
+#ifndef _WIZCHIP_IO_BASE_
+#define _WIZCHIP_IO_BASE_              0x00000000  // 0x8000
+#endif
+
+//M20150401 : Typing Error
+//#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS
+#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_
+   #ifndef _WIZCHIP_IO_BASE_
+      #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map."
+   #endif
+#endif   
+
+#if _WIZCHIP_ >= W5200
+   #define _WIZCHIP_SOCK_NUM_   8   ///< The count of independant socket of @b WIZCHIP
+#else
+   #define _WIZCHIP_SOCK_NUM_   4   ///< The count of independant socket of @b WIZCHIP
+#endif      
+
+
+/********************************************************
+* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC.
+*********************************************************/
+/**
+ * @ingroup DATA_TYPE
+ * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200
+ */
+typedef struct __WIZCHIP
+{
+   uint16_t  if_mode;               ///< host interface mode
+   uint8_t   id[8];                 ///< @b WIZCHIP ID such as @b 5100, @b 5100S, @b 5200, @b 5500, and so on.
+   /**
+    * The set of critical section callback func.
+    */
+   struct _CRIS
+   {
+      void (*_enter)  (void);       ///< crtical section enter 
+      void (*_exit) (void);         ///< critial section exit  
+   }CRIS;  
+   /**
+    *  The set of @ref \_WIZCHIP_ select control callback func.
+    */
+   struct _CS
+   {
+      void (*_select)  (void);      ///< @ref \_WIZCHIP_ selected
+      void (*_deselect)(void);      ///< @ref \_WIZCHIP_ deselected
+   }CS;  
+   /**
+    * The set of interface IO callback func.
+    */
+   union _IF
+   {	 
+      /**
+       * For BUS interface IO
+       */
+      //M20156501 : Modify the function name for integrating with W5300
+      //struct
+      //{
+      //   uint8_t  (*_read_byte)  (uint32_t AddrSel);
+      //   void     (*_write_byte) (uint32_t AddrSel, uint8_t wb);
+      //}BUS;      
+      struct
+      {
+         iodata_t  (*_read_data)   (uint32_t AddrSel);
+         void      (*_write_data)  (uint32_t AddrSel, iodata_t wb);
+      }BUS;      
+
+      /**
+       * For SPI interface IO
+       */
+      struct
+      {
+         uint8_t (*_read_byte)   (void);
+         void    (*_write_byte)  (uint8_t wb);
+         void    (*_read_burst)  (uint8_t* pBuf, uint16_t len);
+         void    (*_write_burst) (uint8_t* pBuf, uint16_t len);
+      }SPI;
+      // To be added
+      //
+   }IF;
+}_WIZCHIP;
+
+extern _WIZCHIP  WIZCHIP;
+
+/**
+ * @ingroup DATA_TYPE
+ *  WIZCHIP control type enumration used in @ref ctlwizchip().
+ */
+typedef enum
+{
+   CW_RESET_WIZCHIP,   ///< Resets WIZCHIP by softly
+   CW_INIT_WIZCHIP,    ///< Initializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t.
+   CW_GET_INTERRUPT,   ///< Get Interrupt status of WIZCHIP
+   CW_CLR_INTERRUPT,   ///< Clears interrupt
+   CW_SET_INTRMASK,    ///< Masks interrupt
+   CW_GET_INTRMASK,    ///< Get interrupt mask
+   CW_SET_INTRTIME,    ///< Set interval time between the current and next interrupt. 
+   CW_GET_INTRTIME,    ///< Set interval time between the current and next interrupt. 
+   CW_GET_ID,          ///< Gets WIZCHIP name.
+
+//D20150601 : For no modification your application code
+//#if _WIZCHIP_ ==  W5500
+   CW_RESET_PHY,       ///< Resets internal PHY. Valid Only W5500
+   CW_SET_PHYCONF,     ///< When PHY configured by internal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000
+   CW_GET_PHYCONF,     ///< Get PHY operation mode in internal register. Valid Only W5500
+   CW_GET_PHYSTATUS,   ///< Get real PHY status on operating. Valid Only W5500
+   CW_SET_PHYPOWMODE,  ///< Set PHY power mode as normal and down when PHYSTATUS.OPMD == 1. Valid Only W5500
+//#endif
+//D20150601 : For no modification your application code
+//#if _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
+   CW_GET_PHYPOWMODE,  ///< Get PHY Power mode as down or normal, Valid Only W5100, W5200
+   CW_GET_PHYLINK      ///< Get PHY Link status, Valid Only W5100, W5200
+//#endif
+}ctlwizchip_type;
+
+/**
+ * @ingroup DATA_TYPE
+ *  Network control type enumration used in @ref ctlnetwork().
+ */
+typedef enum
+{
+   CN_SET_NETINFO,  ///< Set Network with @ref wiz_NetInfo
+   CN_GET_NETINFO,  ///< Get Network with @ref wiz_NetInfo
+   CN_SET_NETMODE,  ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode
+   CN_GET_NETMODE,  ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode
+   CN_SET_TIMEOUT,  ///< Set network timeout as retry count and time.
+   CN_GET_TIMEOUT,  ///< Get network timeout as retry count and time.
+}ctlnetwork_type;
+
+/**
+ * @ingroup DATA_TYPE
+ *  Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK
+ *  and CW_GET_INTRMASK is used in @ref ctlnetwork().
+ *  It can be used with OR operation.
+ */
+typedef enum
+{
+#if   _WIZCHIP_ == W5500
+   IK_WOL               = (1 << 4),   ///< Wake On Lan by receiving the magic packet. Valid in W500.
+#elif _WIZCHIP_ == W5300
+   IK_FMTU              = (1 << 4),   ///< Received a ICMP message (Fragment MTU)   
+#endif   
+
+   IK_PPPOE_TERMINATED  = (1 << 5),   ///< PPPoE Disconnected
+
+#if _WIZCHIP_ != W5200
+   IK_DEST_UNREACH      = (1 << 6),   ///< Destination IP & Port Unreachable, No use in W5200
+#endif   
+
+   IK_IP_CONFLICT       = (1 << 7),   ///< IP conflict occurred
+
+   IK_SOCK_0            = (1 << 8),   ///< Socket 0 interrupt
+   IK_SOCK_1            = (1 << 9),   ///< Socket 1 interrupt
+   IK_SOCK_2            = (1 << 10),  ///< Socket 2 interrupt
+   IK_SOCK_3            = (1 << 11),  ///< Socket 3 interrupt
+#if _WIZCHIP_ > W5100S
+   IK_SOCK_4            = (1 << 12),  ///< Socket 4 interrupt, No use in 5100
+   IK_SOCK_5            = (1 << 13),  ///< Socket 5 interrupt, No use in 5100
+   IK_SOCK_6            = (1 << 14),  ///< Socket 6 interrupt, No use in 5100
+   IK_SOCK_7            = (1 << 15),  ///< Socket 7 interrupt, No use in 5100
+#endif   
+
+#if _WIZCHIP_ > W5100S
+   IK_SOCK_ALL          = (0xFF << 8) ///< All Socket interrupt
+#else
+   IK_SOCK_ALL          = (0x0F << 8) ///< All Socket interrupt
+#endif      
+}intr_kind;
+
+#define PHY_CONFBY_HW            0     ///< Configured PHY operation mode by HW pin
+#define PHY_CONFBY_SW            1     ///< Configured PHY operation mode by SW register   
+#define PHY_MODE_MANUAL          0     ///< Configured PHY operation mode with user setting.
+#define PHY_MODE_AUTONEGO        1     ///< Configured PHY operation mode with auto-negotiation
+#define PHY_SPEED_10             0     ///< Link Speed 10
+#define PHY_SPEED_100            1     ///< Link Speed 100
+#define PHY_DUPLEX_HALF          0     ///< Link Half-Duplex
+#define PHY_DUPLEX_FULL          1     ///< Link Full-Duplex
+#define PHY_LINK_OFF             0     ///< Link Off
+#define PHY_LINK_ON              1     ///< Link On
+#define PHY_POWER_NORM           0     ///< PHY power normal mode
+#define PHY_POWER_DOWN           1     ///< PHY power down mode 
+
+
+#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
+/**
+ * @ingroup DATA_TYPE
+ *  It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500,  
+ *  and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n
+ *  Valid only in W5500.
+ */
+typedef struct wiz_PhyConf_t
+{
+      uint8_t by;       ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW
+      uint8_t mode;     ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO
+      uint8_t speed;    ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100
+      uint8_t duplex;   ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL 
+      //uint8_t power;  ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN
+      //uint8_t link;   ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF 
+   }wiz_PhyConf;
+#endif   
+
+/**
+ * @ingroup DATA_TYPE
+ *  It used in setting dhcp_mode of @ref wiz_NetInfo.
+ */
+typedef enum
+{
+   NETINFO_STATIC = 1,    ///< Static IP configuration by manually.
+   NETINFO_DHCP           ///< Dynamic IP configruation from a DHCP sever
+}dhcp_mode;
+
+/**
+ * @ingroup DATA_TYPE
+ *  Network Information for WIZCHIP
+ */
+typedef struct wiz_NetInfo_t
+{
+   uint8_t mac[6];  ///< Source Mac Address
+   uint8_t ip[4];   ///< Source IP Address
+   uint8_t sn[4];   ///< Subnet Mask 
+   uint8_t gw[4];   ///< Gateway IP Address
+   uint8_t dns[4];  ///< DNS server IP Address
+   dhcp_mode dhcp;  ///< 1 - Static, 2 - DHCP
+}wiz_NetInfo;
+
+/**
+ * @ingroup DATA_TYPE
+ *  Network mode
+ */
+typedef enum
+{
+#if _WIZCHIP_ == W5500
+   NM_FORCEARP    = (1<<1),  ///< Force to APP send whenever udp data is sent. Valid only in W5500
+#endif   
+   NM_WAKEONLAN   = (1<<5),  ///< Wake On Lan 
+   NM_PINGBLOCK   = (1<<4),  ///< Block ping-request
+   NM_PPPOE       = (1<<3),  ///< PPPoE mode
+}netmode_type;
+
+/**
+ * @ingroup DATA_TYPE
+ *  Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation.
+ */
+typedef struct wiz_NetTimeout_t
+{
+   uint8_t  retry_cnt;     ///< retry count 
+   uint16_t time_100us;    ///< time unit 100us
+}wiz_NetTimeout;
+
+/**
+ *@brief Registers call back function for critical section of I/O functions such as
+ *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF.
+ *@param cris_en : callback function for critical section enter.
+ *@param cris_ex : callback function for critical section exit.
+ *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions.
+ *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called.
+ */
+void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));
+
+
+/**
+ *@brief Registers call back function for WIZCHIP select & deselect.
+ *@param cs_sel : callback function for WIZCHIP select
+ *@param cs_desel : callback fucntion for WIZCHIP deselect
+ *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions.
+ *@note If you do not describe or register, null function is called.
+ */
+void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));
+
+/**
+ *@brief Registers call back function for bus interface.
+ *@param bus_rb   : callback function to read byte data using system bus
+ *@param bus_wb   : callback function to write byte data using system bus
+ *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function
+ *or register your functions.
+ *@note If you do not describe or register, null function is called.
+ */
+//M20150601 : For integrating with W5300
+//void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb));
+void reg_wizchip_bus_cbfunc(iodata_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, iodata_t wb));
+
+/**
+ *@brief Registers call back function for SPI interface.
+ *@param spi_rb : callback function to read byte using SPI
+ *@param spi_wb : callback function to write byte using SPI
+ *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
+ *or register your functions.
+ *@note If you do not describe or register, null function is called.
+ */
+void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void), void (*spi_wb)(uint8_t wb));
+
+/**
+ *@brief Registers call back function for SPI interface.
+ *@param spi_rb : callback function to burst read using SPI
+ *@param spi_wb : callback function to burst write using SPI
+ *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
+ *or register your functions.
+ *@note If you do not describe or register, null function is called.
+ */
+void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t* pBuf, uint16_t len), void (*spi_wb)(uint8_t* pBuf, uint16_t len));
+
+/**
+ * @ingroup extra_functions
+ * @brief Controls to the WIZCHIP.
+ * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto),
+ * controls interrupt & mask and so on.
+ * @param cwtype : Decides to the control type
+ * @param arg : arg type is dependent on cwtype.
+ * @return  0 : Success \n
+ *         -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP 
+ */          
+int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg);
+
+/**
+ * @ingroup extra_functions
+ * @brief Controls to network.
+ * @details Controls to network environment, mode, timeout and so on.
+ * @param cntype : Input. Decides to the control type
+ * @param arg : Inout. arg type is dependent on cntype.
+ * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n
+ *          0 : Success      
+ */          
+int8_t ctlnetwork(ctlnetwork_type cntype, void* arg);
+
+
+/* 
+ * The following functions are implemented for internal use. 
+ * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork().
+ */
+ 
+/**
+ * @ingroup extra_functions
+ * @brief Reset WIZCHIP by softly.
+ */ 
+void   wizchip_sw_reset(void);
+
+/**
+ * @ingroup extra_functions
+ * @brief Initializes WIZCHIP with socket buffer size
+ * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB.
+ * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB.
+ * @return 0 : succcess \n
+ *        -1 : fail. Invalid buffer size
+ */
+int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);
+
+/** 
+ * @ingroup extra_functions
+ * @brief Clear Interrupt of WIZCHIP.
+ * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
+ */
+void wizchip_clrinterrupt(intr_kind intr);
+
+/** 
+ * @ingroup extra_functions
+ * @brief Get Interrupt of WIZCHIP.
+ * @return @ref intr_kind value operated OR. It can type-cast to uint16_t.
+ */
+intr_kind wizchip_getinterrupt(void);
+
+/** 
+ * @ingroup extra_functions
+ * @brief Mask or Unmask Interrupt of WIZCHIP.
+ * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
+ */
+void wizchip_setinterruptmask(intr_kind intr);
+
+/** 
+ * @ingroup extra_functions
+ * @brief Get Interrupt mask of WIZCHIP.
+ * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t.
+ */
+intr_kind wizchip_getinterruptmask(void);
+
+//todo
+#if _WIZCHIP_ > W5100
+   int8_t wizphy_getphylink(void);              ///< get the link status of phy in WIZCHIP. No use in W5100
+   int8_t wizphy_getphypmode(void);             ///< get the power mode of PHY in WIZCHIP. No use in W5100
+#endif
+
+#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
+   void   wizphy_reset(void);                   ///< Reset phy. Vailid only in W5500
+/**
+ * @ingroup extra_functions
+ * @brief Set the phy information for WIZCHIP without power mode
+ * @param phyconf : @ref wiz_PhyConf
+ */
+   void   wizphy_setphyconf(wiz_PhyConf* phyconf);  
+ /**
+ * @ingroup extra_functions
+ * @brief Get phy configuration information.
+ * @param phyconf : @ref wiz_PhyConf
+ */
+   void   wizphy_getphyconf(wiz_PhyConf* phyconf); 
+ /**
+ * @ingroup extra_functions
+ * @brief Get phy status.
+ * @param phyconf : @ref wiz_PhyConf
+ */ 
+   void   wizphy_getphystat(wiz_PhyConf* phyconf);
+ /**
+ * @ingroup extra_functions
+ * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200
+ * @param pmode Settig value of power down mode.
+ */   
+   int8_t wizphy_setphypmode(uint8_t pmode);    
+#endif
+
+/**
+* @ingroup extra_functions
+ * @brief Set the network information for WIZCHIP
+ * @param pnetinfo : @ref wizNetInfo
+ */
+void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);
+
+/**
+ * @ingroup extra_functions
+ * @brief Get the network information for WIZCHIP
+ * @param pnetinfo : @ref wizNetInfo
+ */
+void wizchip_getnetinfo(wiz_NetInfo* pnetinfo);
+
+/**
+ * @ingroup extra_functions
+ * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. 
+ * @param pnetinfo Value of network mode. Refer to @ref netmode_type.
+ */
+int8_t wizchip_setnetmode(netmode_type netmode);
+
+/**
+ * @ingroup extra_functions
+ * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. 
+ * @return Value of network mode. Refer to @ref netmode_type.
+ */
+netmode_type wizchip_getnetmode(void);
+
+/**
+ * @ingroup extra_functions
+ * @brief Set retry time value(@ref _RTR_) and retry count(@ref _RCR_).
+ * @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission.  
+ * @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout. 
+ */
+void wizchip_settimeout(wiz_NetTimeout* nettime);
+
+/**
+ * @ingroup extra_functions
+ * @brief Get retry time value(@ref _RTR_) and retry count(@ref _RCR_).
+ * @details @ref _RTR_ configures the retransmission timeout period and @ref _RCR_ configures the number of time of retransmission.  
+ * @param nettime @ref _RTR_ value and @ref _RCR_ value. Refer to @ref wiz_NetTimeout. 
+ */
+void wizchip_gettimeout(wiz_NetTimeout* nettime);
+#ifdef __cplusplus
+ }
+#endif
+
+#endif   // _WIZCHIP_CONF_H_

+ 991 - 0
lib/ioLibrary_Driver/Internet/DHCP/dhcp.c

@@ -0,0 +1,991 @@
+//*****************************************************************************
+//
+//! \file dhcp.c
+//! \brief DHCP APIs implement file.
+//! \details Processing DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
+//! \version 1.1.1
+//! \date 2019/10/08
+//! \par  Revision history
+//!       <2019/10/08> compare DHCP server ip address
+//!       <2013/11/18> 1st Release
+//!       <2012/12/20> V1.1.0
+//!         1. Optimize code
+//!         2. Add reg_dhcp_cbfunc()
+//!         3. Add DHCP_stop()
+//!         4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run()
+//!         5. Don't care system endian
+//!         6. Add comments
+//!       <2012/12/26> V1.1.1
+//!         1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization
+//! \author Eric Jung & MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//!
+//! Redistribution and use in source and binary forms, with or without
+//! modification, are permitted provided that the following conditions
+//! are met:
+//!
+//!     * Redistributions of source code must retain the above copyright
+//! notice, this list of conditions and the following disclaimer.
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution.
+//!     * Neither the name of the <ORGANIZATION> nor the names of its
+//! contributors may be used to endorse or promote products derived
+//! from this software without specific prior written permission.
+//!
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include "socket.h"
+#include "dhcp.h"
+
+/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
+
+#ifdef _DHCP_DEBUG_
+#include <stdio.h>
+#endif
+
+#define _DHCP_DEBUG_
+
+/* DHCP state machine. */
+#define STATE_DHCP_INIT 0 ///< Initialize
+#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER
+#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK
+#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased
+#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP
+#define STATE_DHCP_RELEASE 5 ///< No use
+#define STATE_DHCP_STOP 6 ///< Stop processing DHCP
+
+#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG
+#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast   value of flags in @ref RIP_MSG
+
+/* DHCP message OP code */
+#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG
+#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG
+
+/* DHCP message type */
+#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG
+#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG
+#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG
+#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG
+#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG
+#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG
+#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use
+#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use
+
+#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG
+#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG
+
+#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG
+#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG
+#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG
+
+#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time
+
+#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG
+#define RIP_MSG_SIZE (236 + OPT_SIZE) /// Max size of @ref RIP_MSG
+
+/* 
+ * @brief DHCP option and value (cf. RFC1533)
+ */
+enum {
+    padOption = 0,
+    subnetMask = 1,
+    timerOffset = 2,
+    routersOnSubnet = 3,
+    timeServer = 4,
+    nameServer = 5,
+    dns = 6,
+    logServer = 7,
+    cookieServer = 8,
+    lprServer = 9,
+    impressServer = 10,
+    resourceLocationServer = 11,
+    hostName = 12,
+    bootFileSize = 13,
+    meritDumpFile = 14,
+    domainName = 15,
+    swapServer = 16,
+    rootPath = 17,
+    extentionsPath = 18,
+    IPforwarding = 19,
+    nonLocalSourceRouting = 20,
+    policyFilter = 21,
+    maxDgramReasmSize = 22,
+    defaultIPTTL = 23,
+    pathMTUagingTimeout = 24,
+    pathMTUplateauTable = 25,
+    ifMTU = 26,
+    allSubnetsLocal = 27,
+    broadcastAddr = 28,
+    performMaskDiscovery = 29,
+    maskSupplier = 30,
+    performRouterDiscovery = 31,
+    routerSolicitationAddr = 32,
+    staticRoute = 33,
+    trailerEncapsulation = 34,
+    arpCacheTimeout = 35,
+    ethernetEncapsulation = 36,
+    tcpDefaultTTL = 37,
+    tcpKeepaliveInterval = 38,
+    tcpKeepaliveGarbage = 39,
+    nisDomainName = 40,
+    nisServers = 41,
+    ntpServers = 42,
+    vendorSpecificInfo = 43,
+    netBIOSnameServer = 44,
+    netBIOSdgramDistServer = 45,
+    netBIOSnodeType = 46,
+    netBIOSscope = 47,
+    xFontServer = 48,
+    xDisplayManager = 49,
+    dhcpRequestedIPaddr = 50,
+    dhcpIPaddrLeaseTime = 51,
+    dhcpOptionOverload = 52,
+    dhcpMessageType = 53,
+    dhcpServerIdentifier = 54,
+    dhcpParamRequest = 55,
+    dhcpMsg = 56,
+    dhcpMaxMsgSize = 57,
+    dhcpT1value = 58,
+    dhcpT2value = 59,
+    dhcpClassIdentifier = 60,
+    dhcpClientIdentifier = 61,
+    endOption = 255
+};
+
+/*
+ * @brief DHCP message format
+ */
+typedef struct {
+    uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
+    uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
+    uint8_t hlen; ///< @ref DHCP_HLENETHERNET
+    uint8_t hops; ///< @ref DHCP_HOPS
+    uint32_t xid; ///< @ref DHCP_XID  This increase one every DHCP transaction.
+    uint16_t secs; ///< @ref DHCP_SECS
+    uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
+    uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever
+    uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server
+    uint8_t siaddr[4]; ///< No use
+    uint8_t giaddr[4]; ///< No use
+    uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero
+    uint8_t sname[64]; ///< No use
+    uint8_t file[128]; ///< No use
+    uint8_t OPT[OPT_SIZE]; ///< Option
+} RIP_MSG;
+
+uint8_t DHCP_SOCKET; // Socket number for DHCP
+
+uint8_t DHCP_SIP[4]; // DHCP Server IP address
+uint8_t DHCP_REAL_SIP[4]; // For extract my DHCP server in a few DHCP server
+
+// Network information from DHCP Server
+uint8_t OLD_allocated_ip[4] = {
+    0,
+}; // Previous IP address
+uint8_t DHCP_allocated_ip[4] = {
+    0,
+}; // IP address from DHCP
+uint8_t DHCP_allocated_gw[4] = {
+    0,
+}; // Gateway address from DHCP
+uint8_t DHCP_allocated_sn[4] = {
+    0,
+}; // Subnet mask from DHCP
+uint8_t DHCP_allocated_dns[4] = {
+    0,
+}; // DNS address from DHCP
+
+int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state
+int8_t dhcp_retry_count = 0;
+
+uint32_t dhcp_lease_time = INFINITE_LEASETIME;
+volatile uint32_t dhcp_tick_1s = 0; // unit 1 second
+uint32_t dhcp_tick_next = DHCP_WAIT_TIME;
+
+uint32_t DHCP_XID; // Any number
+
+RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing
+
+uint8_t HOST_NAME[] = DCHP_HOST_NAME;
+
+uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address.
+
+/* The default callback function */
+void default_ip_assign(void);
+void default_ip_update(void);
+void default_ip_conflict(void);
+
+/* Callback handler */
+void (*dhcp_ip_assign)(void) =
+    default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */
+void (*dhcp_ip_update)(void) =
+    default_ip_update; /* handler to be called when the IP address from DHCP server is updated */
+void (*dhcp_ip_conflict)(void) =
+    default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */
+
+char NibbleToHex(uint8_t nibble);
+
+/* send DISCOVER message to DHCP server */
+void send_DHCP_DISCOVER(void);
+
+/* send REQEUST message to DHCP server */
+void send_DHCP_REQUEST(void);
+
+/* send DECLINE message to DHCP server */
+void send_DHCP_DECLINE(void);
+
+/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
+int8_t check_DHCP_leasedIP(void);
+
+/* check the timeout in DHCP process */
+uint8_t check_DHCP_timeout(void);
+
+/* Initialize to timeout process.  */
+void reset_DHCP_timeout(void);
+
+/* Parse message as OFFER and ACK and NACK from DHCP server.*/
+int8_t parseDHCPCMSG(void);
+
+/* The default handler of ip assign first */
+void default_ip_assign(void) {
+    setSIPR(DHCP_allocated_ip);
+    setSUBR(DHCP_allocated_sn);
+    setGAR(DHCP_allocated_gw);
+}
+
+/* The default handler of ip changed */
+void default_ip_update(void) {
+    /* WIZchip Software Reset */
+    setMR(MR_RST);
+    getMR(); // for delay
+    default_ip_assign();
+    setSHAR(DHCP_CHADDR);
+}
+
+/* The default handler of ip changed */
+void default_ip_conflict(void) {
+    // WIZchip Software Reset
+    setMR(MR_RST);
+    getMR(); // for delay
+    setSHAR(DHCP_CHADDR);
+}
+
+/* register the call back func. */
+void reg_dhcp_cbfunc(void (*ip_assign)(void), void (*ip_update)(void), void (*ip_conflict)(void)) {
+    dhcp_ip_assign = default_ip_assign;
+    dhcp_ip_update = default_ip_update;
+    dhcp_ip_conflict = default_ip_conflict;
+    if(ip_assign) dhcp_ip_assign = ip_assign;
+    if(ip_update) dhcp_ip_update = ip_update;
+    if(ip_conflict) dhcp_ip_conflict = ip_conflict;
+}
+
+/* make the common DHCP message */
+void makeDHCPMSG(void) {
+    uint8_t bk_mac[6];
+    uint8_t* ptmp;
+    uint8_t i;
+    getSHAR(bk_mac);
+    pDHCPMSG->op = DHCP_BOOTREQUEST;
+    pDHCPMSG->htype = DHCP_HTYPE10MB;
+    pDHCPMSG->hlen = DHCP_HLENETHERNET;
+    pDHCPMSG->hops = DHCP_HOPS;
+    ptmp = (uint8_t*)(&pDHCPMSG->xid);
+    *(ptmp + 0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
+    *(ptmp + 1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
+    *(ptmp + 2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
+    *(ptmp + 3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
+    pDHCPMSG->secs = DHCP_SECS;
+    ptmp = (uint8_t*)(&pDHCPMSG->flags);
+    *(ptmp + 0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
+    *(ptmp + 1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
+
+    pDHCPMSG->ciaddr[0] = 0;
+    pDHCPMSG->ciaddr[1] = 0;
+    pDHCPMSG->ciaddr[2] = 0;
+    pDHCPMSG->ciaddr[3] = 0;
+
+    pDHCPMSG->yiaddr[0] = 0;
+    pDHCPMSG->yiaddr[1] = 0;
+    pDHCPMSG->yiaddr[2] = 0;
+    pDHCPMSG->yiaddr[3] = 0;
+
+    pDHCPMSG->siaddr[0] = 0;
+    pDHCPMSG->siaddr[1] = 0;
+    pDHCPMSG->siaddr[2] = 0;
+    pDHCPMSG->siaddr[3] = 0;
+
+    pDHCPMSG->giaddr[0] = 0;
+    pDHCPMSG->giaddr[1] = 0;
+    pDHCPMSG->giaddr[2] = 0;
+    pDHCPMSG->giaddr[3] = 0;
+
+    pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
+    pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
+    pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
+    pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
+    pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
+    pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
+
+    for(i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
+    for(i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
+    for(i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
+
+    // MAGIC_COOKIE
+    pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
+    pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
+    pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
+    pDHCPMSG->OPT[3] = (uint8_t)(MAGIC_COOKIE & 0x000000FF) >> 0;
+}
+
+/* SEND DHCP DISCOVER */
+void send_DHCP_DISCOVER(void) {
+    uint16_t i;
+    uint8_t ip[4];
+    uint16_t k = 0;
+
+    makeDHCPMSG();
+    DHCP_SIP[0] = 0;
+    DHCP_SIP[1] = 0;
+    DHCP_SIP[2] = 0;
+    DHCP_SIP[3] = 0;
+    DHCP_REAL_SIP[0] = 0;
+    DHCP_REAL_SIP[1] = 0;
+    DHCP_REAL_SIP[2] = 0;
+    DHCP_REAL_SIP[3] = 0;
+
+    k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
+
+    // Option Request Param
+    pDHCPMSG->OPT[k++] = dhcpMessageType;
+    pDHCPMSG->OPT[k++] = 0x01;
+    pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
+
+    // Client identifier
+    pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
+    pDHCPMSG->OPT[k++] = 0x07;
+    pDHCPMSG->OPT[k++] = 0x01;
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
+
+    // host name
+    pDHCPMSG->OPT[k++] = hostName;
+    pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
+    for(i = 0; HOST_NAME[i] != 0; i++) pDHCPMSG->OPT[k++] = HOST_NAME[i];
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
+    pDHCPMSG->OPT[k - (i + 6 + 1)] = i + 6; // length of hostname
+
+    pDHCPMSG->OPT[k++] = dhcpParamRequest;
+    pDHCPMSG->OPT[k++] = 0x06; // length of request
+    pDHCPMSG->OPT[k++] = subnetMask;
+    pDHCPMSG->OPT[k++] = routersOnSubnet;
+    pDHCPMSG->OPT[k++] = dns;
+    pDHCPMSG->OPT[k++] = domainName;
+    pDHCPMSG->OPT[k++] = dhcpT1value;
+    pDHCPMSG->OPT[k++] = dhcpT2value;
+    pDHCPMSG->OPT[k++] = endOption;
+
+    for(i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
+
+    // send broadcasting packet
+    ip[0] = 255;
+    ip[1] = 255;
+    ip[2] = 255;
+    ip[3] = 255;
+
+#ifdef _DHCP_DEBUG_
+    eth_printf("> Send DHCP_DISCOVER");
+#endif
+    sendto(DHCP_SOCKET, (uint8_t*)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
+}
+
+/* SEND DHCP REQUEST */
+void send_DHCP_REQUEST(void) {
+    int i;
+    uint8_t ip[4];
+    uint16_t k = 0;
+
+    makeDHCPMSG();
+
+    if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) {
+        *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00) >> 8);
+        *((uint8_t*)(&pDHCPMSG->flags) + 1) = (DHCP_FLAGSUNICAST & 0x00FF);
+        pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
+        pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
+        pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
+        pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
+        ip[0] = DHCP_SIP[0];
+        ip[1] = DHCP_SIP[1];
+        ip[2] = DHCP_SIP[2];
+        ip[3] = DHCP_SIP[3];
+    } else {
+        ip[0] = 255;
+        ip[1] = 255;
+        ip[2] = 255;
+        ip[3] = 255;
+    }
+
+    k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
+
+    // Option Request Param.
+    pDHCPMSG->OPT[k++] = dhcpMessageType;
+    pDHCPMSG->OPT[k++] = 0x01;
+    pDHCPMSG->OPT[k++] = DHCP_REQUEST;
+
+    pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
+    pDHCPMSG->OPT[k++] = 0x07;
+    pDHCPMSG->OPT[k++] = 0x01;
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
+
+    if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
+    {
+        pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
+        pDHCPMSG->OPT[k++] = 0x04;
+        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
+        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
+        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
+        pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
+
+        pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
+        pDHCPMSG->OPT[k++] = 0x04;
+        pDHCPMSG->OPT[k++] = DHCP_SIP[0];
+        pDHCPMSG->OPT[k++] = DHCP_SIP[1];
+        pDHCPMSG->OPT[k++] = DHCP_SIP[2];
+        pDHCPMSG->OPT[k++] = DHCP_SIP[3];
+    }
+
+    // host name
+    pDHCPMSG->OPT[k++] = hostName;
+    pDHCPMSG->OPT[k++] = 0; // length of hostname
+    for(i = 0; HOST_NAME[i] != 0; i++) pDHCPMSG->OPT[k++] = HOST_NAME[i];
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3] >> 4);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[3]);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4] >> 4);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[4]);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5] >> 4);
+    pDHCPMSG->OPT[k++] = NibbleToHex(DHCP_CHADDR[5]);
+    pDHCPMSG->OPT[k - (i + 6 + 1)] = i + 6; // length of hostname
+
+    pDHCPMSG->OPT[k++] = dhcpParamRequest;
+    pDHCPMSG->OPT[k++] = 0x08;
+    pDHCPMSG->OPT[k++] = subnetMask;
+    pDHCPMSG->OPT[k++] = routersOnSubnet;
+    pDHCPMSG->OPT[k++] = dns;
+    pDHCPMSG->OPT[k++] = domainName;
+    pDHCPMSG->OPT[k++] = dhcpT1value;
+    pDHCPMSG->OPT[k++] = dhcpT2value;
+    pDHCPMSG->OPT[k++] = performRouterDiscovery;
+    pDHCPMSG->OPT[k++] = staticRoute;
+    pDHCPMSG->OPT[k++] = endOption;
+
+    for(i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
+
+#ifdef _DHCP_DEBUG_
+    eth_printf("> Send DHCP_REQUEST");
+#endif
+
+    sendto(DHCP_SOCKET, (uint8_t*)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
+}
+
+/* SEND DHCP DHCPDECLINE */
+void send_DHCP_DECLINE(void) {
+    int i;
+    uint8_t ip[4];
+    uint16_t k = 0;
+
+    makeDHCPMSG();
+
+    k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
+
+    *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00) >> 8);
+    *((uint8_t*)(&pDHCPMSG->flags) + 1) = (DHCP_FLAGSUNICAST & 0x00FF);
+
+    // Option Request Param.
+    pDHCPMSG->OPT[k++] = dhcpMessageType;
+    pDHCPMSG->OPT[k++] = 0x01;
+    pDHCPMSG->OPT[k++] = DHCP_DECLINE;
+
+    pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
+    pDHCPMSG->OPT[k++] = 0x07;
+    pDHCPMSG->OPT[k++] = 0x01;
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
+    pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
+
+    pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
+    pDHCPMSG->OPT[k++] = 0x04;
+    pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
+    pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
+    pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
+    pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
+
+    pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
+    pDHCPMSG->OPT[k++] = 0x04;
+    pDHCPMSG->OPT[k++] = DHCP_SIP[0];
+    pDHCPMSG->OPT[k++] = DHCP_SIP[1];
+    pDHCPMSG->OPT[k++] = DHCP_SIP[2];
+    pDHCPMSG->OPT[k++] = DHCP_SIP[3];
+
+    pDHCPMSG->OPT[k++] = endOption;
+
+    for(i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
+
+    //send broadcasting packet
+    ip[0] = 0xFF;
+    ip[1] = 0xFF;
+    ip[2] = 0xFF;
+    ip[3] = 0xFF;
+
+#ifdef _DHCP_DEBUG_
+    eth_printf("\r\n> Send DHCP_DECLINE");
+#endif
+
+    sendto(DHCP_SOCKET, (uint8_t*)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
+}
+
+/* PARSE REPLY pDHCPMSG */
+int8_t parseDHCPMSG(void) {
+    uint8_t svr_addr[6];
+    uint16_t svr_port;
+    uint16_t len;
+
+    uint8_t* p;
+    uint8_t* e;
+    uint8_t type = 0;
+    uint8_t opt_len;
+
+    if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) {
+        len = recvfrom(DHCP_SOCKET, (uint8_t*)pDHCPMSG, len, svr_addr, &svr_port);
+#ifdef _DHCP_DEBUG_
+        eth_printf(
+            "DHCP message : %d.%d.%d.%d(%d) %d received.",
+            svr_addr[0],
+            svr_addr[1],
+            svr_addr[2],
+            svr_addr[3],
+            svr_port,
+            len);
+#endif
+    } else
+        return 0;
+
+    if(svr_port == DHCP_SERVER_PORT) {
+        // compare mac address
+        if((pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
+           (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
+           (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5])) {
+#ifdef _DHCP_DEBUG_
+            eth_printf("No My DHCP Message. This message is ignored.");
+#endif
+            return 0;
+        }
+        //compare DHCP server ip address
+        if((DHCP_SIP[0] != 0) || (DHCP_SIP[1] != 0) || (DHCP_SIP[2] != 0) || (DHCP_SIP[3] != 0)) {
+            if(((svr_addr[0] != DHCP_SIP[0]) || (svr_addr[1] != DHCP_SIP[1]) ||
+                (svr_addr[2] != DHCP_SIP[2]) || (svr_addr[3] != DHCP_SIP[3])) &&
+               ((svr_addr[0] != DHCP_REAL_SIP[0]) || (svr_addr[1] != DHCP_REAL_SIP[1]) ||
+                (svr_addr[2] != DHCP_REAL_SIP[2]) || (svr_addr[3] != DHCP_REAL_SIP[3]))) {
+#ifdef _DHCP_DEBUG_
+                eth_printf("Another DHCP sever send a response message. This is ignored.");
+#endif
+                return 0;
+            }
+        }
+        p = (uint8_t*)(&pDHCPMSG->op);
+        p = p +
+            240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
+        e = p + (len - 240);
+
+        while(p < e) {
+            switch(*p) {
+            case endOption:
+                p = e; // for break while(p < e)
+                break;
+            case padOption:
+                p++;
+                break;
+            case dhcpMessageType:
+                p++;
+                p++;
+                type = *p++;
+                break;
+            case subnetMask:
+                p++;
+                p++;
+                DHCP_allocated_sn[0] = *p++;
+                DHCP_allocated_sn[1] = *p++;
+                DHCP_allocated_sn[2] = *p++;
+                DHCP_allocated_sn[3] = *p++;
+                break;
+            case routersOnSubnet:
+                p++;
+                opt_len = *p++;
+                DHCP_allocated_gw[0] = *p++;
+                DHCP_allocated_gw[1] = *p++;
+                DHCP_allocated_gw[2] = *p++;
+                DHCP_allocated_gw[3] = *p++;
+                p = p + (opt_len - 4);
+                break;
+            case dns:
+                p++;
+                opt_len = *p++;
+                DHCP_allocated_dns[0] = *p++;
+                DHCP_allocated_dns[1] = *p++;
+                DHCP_allocated_dns[2] = *p++;
+                DHCP_allocated_dns[3] = *p++;
+                p = p + (opt_len - 4);
+                break;
+            case dhcpIPaddrLeaseTime:
+                p++;
+                opt_len = *p++;
+                dhcp_lease_time = *p++;
+                dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
+                dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
+                dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
+#ifdef _DHCP_DEBUG_
+                dhcp_lease_time = 10;
+#endif
+                break;
+            case dhcpServerIdentifier:
+                p++;
+                opt_len = *p++;
+                DHCP_SIP[0] = *p++;
+                DHCP_SIP[1] = *p++;
+                DHCP_SIP[2] = *p++;
+                DHCP_SIP[3] = *p++;
+                DHCP_REAL_SIP[0] = svr_addr[0];
+                DHCP_REAL_SIP[1] = svr_addr[1];
+                DHCP_REAL_SIP[2] = svr_addr[2];
+                DHCP_REAL_SIP[3] = svr_addr[3];
+                break;
+            default:
+                p++;
+                opt_len = *p++;
+                p += opt_len;
+                break;
+            } // switch
+        } // while
+    } // if
+    return type;
+}
+
+uint8_t DHCP_run(void) {
+    uint8_t type;
+    uint8_t ret;
+
+    if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
+
+    if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
+
+    ret = DHCP_RUNNING;
+    type = parseDHCPMSG();
+
+    switch(dhcp_state) {
+    case STATE_DHCP_INIT:
+        DHCP_allocated_ip[0] = 0;
+        DHCP_allocated_ip[1] = 0;
+        DHCP_allocated_ip[2] = 0;
+        DHCP_allocated_ip[3] = 0;
+        send_DHCP_DISCOVER();
+        dhcp_state = STATE_DHCP_DISCOVER;
+        break;
+    case STATE_DHCP_DISCOVER:
+        if(type == DHCP_OFFER) {
+#ifdef _DHCP_DEBUG_
+            eth_printf("> Receive DHCP_OFFER");
+#endif
+            DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
+            DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
+            DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
+            DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
+
+            send_DHCP_REQUEST();
+            dhcp_state = STATE_DHCP_REQUEST;
+        } else {
+            ret = check_DHCP_timeout();
+        }
+        break;
+    case STATE_DHCP_REQUEST:
+        if(type == DHCP_ACK) {
+#ifdef _DHCP_DEBUG_
+            eth_printf("> Receive DHCP_ACK");
+#endif
+            if(check_DHCP_leasedIP()) {
+                // Network info assignment from DHCP
+                dhcp_ip_assign();
+                reset_DHCP_timeout();
+                dhcp_state = STATE_DHCP_LEASED;
+            } else {
+                // IP address conflict occurred
+                reset_DHCP_timeout();
+                dhcp_ip_conflict();
+                dhcp_state = STATE_DHCP_INIT;
+            }
+        } else if(type == DHCP_NAK) {
+#ifdef _DHCP_DEBUG_
+            eth_printf("> Receive DHCP_NACK");
+#endif
+            reset_DHCP_timeout();
+            dhcp_state = STATE_DHCP_DISCOVER;
+        } else {
+            ret = check_DHCP_timeout();
+        }
+        break;
+    case STATE_DHCP_LEASED:
+        ret = DHCP_IP_LEASED;
+        if((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time / 2) < dhcp_tick_1s)) {
+#ifdef _DHCP_DEBUG_
+            eth_printf("> Maintains the IP address ");
+#endif
+            type = 0;
+            OLD_allocated_ip[0] = DHCP_allocated_ip[0];
+            OLD_allocated_ip[1] = DHCP_allocated_ip[1];
+            OLD_allocated_ip[2] = DHCP_allocated_ip[2];
+            OLD_allocated_ip[3] = DHCP_allocated_ip[3];
+            DHCP_XID++;
+            send_DHCP_REQUEST();
+            reset_DHCP_timeout();
+            dhcp_state = STATE_DHCP_REREQUEST;
+        }
+        break;
+    case STATE_DHCP_REREQUEST:
+        ret = DHCP_IP_LEASED;
+        if(type == DHCP_ACK) {
+            dhcp_retry_count = 0;
+            if(OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
+               OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
+               OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
+               OLD_allocated_ip[3] != DHCP_allocated_ip[3]) {
+                ret = DHCP_IP_CHANGED;
+                dhcp_ip_update();
+#ifdef _DHCP_DEBUG_
+                eth_printf(">IP changed.");
+#endif
+            }
+#ifdef _DHCP_DEBUG_
+            else
+                eth_printf(">IP is continued.");
+#endif
+            reset_DHCP_timeout();
+            dhcp_state = STATE_DHCP_LEASED;
+        } else if(type == DHCP_NAK) {
+#ifdef _DHCP_DEBUG_
+            eth_printf("> Receive DHCP_NACK, Failed to maintain ip");
+#endif
+            reset_DHCP_timeout();
+            dhcp_state = STATE_DHCP_DISCOVER;
+        } else
+            ret = check_DHCP_timeout();
+        break;
+    default:
+        break;
+    }
+    return ret;
+}
+
+void DHCP_stop(void) {
+    close(DHCP_SOCKET);
+    dhcp_state = STATE_DHCP_STOP;
+}
+
+uint8_t check_DHCP_timeout(void) {
+    uint8_t ret = DHCP_RUNNING;
+
+    if(dhcp_retry_count < MAX_DHCP_RETRY) {
+        if(dhcp_tick_next < dhcp_tick_1s) {
+            switch(dhcp_state) {
+            case STATE_DHCP_DISCOVER:
+                //					eth_printf("<<timeout>> state : STATE_DHCP_DISCOVER");
+                send_DHCP_DISCOVER();
+                break;
+
+            case STATE_DHCP_REQUEST:
+                //					eth_printf("<<timeout>> state : STATE_DHCP_REQUEST");
+
+                send_DHCP_REQUEST();
+                break;
+
+            case STATE_DHCP_REREQUEST:
+                //					eth_printf("<<timeout>> state : STATE_DHCP_REREQUEST");
+
+                send_DHCP_REQUEST();
+                break;
+
+            default:
+                break;
+            }
+
+            dhcp_tick_1s = 0;
+            dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
+            dhcp_retry_count++;
+        }
+    } else { // timeout occurred
+
+        switch(dhcp_state) {
+        case STATE_DHCP_DISCOVER:
+            dhcp_state = STATE_DHCP_INIT;
+            ret = DHCP_FAILED;
+            break;
+        case STATE_DHCP_REQUEST:
+        case STATE_DHCP_REREQUEST:
+            send_DHCP_DISCOVER();
+            dhcp_state = STATE_DHCP_DISCOVER;
+            break;
+        default:
+            break;
+        }
+        reset_DHCP_timeout();
+    }
+    return ret;
+}
+
+int8_t check_DHCP_leasedIP(void) {
+    uint8_t tmp;
+    int32_t ret;
+
+    //WIZchip RCR value changed for ARP Timeout count control
+    tmp = getRCR();
+    setRCR(0x03);
+
+    // IP conflict detection : ARP request - ARP reply
+    // Broadcasting ARP Request for check the IP conflict using UDP sendto() function
+    ret = sendto(DHCP_SOCKET, (uint8_t*)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
+
+    // RCR value restore
+    setRCR(tmp);
+
+    if(ret == SOCKERR_TIMEOUT) {
+        // UDP send Timeout occurred : allocated IP address is unique, DHCP Success
+
+#ifdef _DHCP_DEBUG_
+        eth_printf("\r\n> Check leased IP - OK");
+#endif
+
+        return 1;
+    } else {
+        // Received ARP reply or etc : IP address conflict occur, DHCP Failed
+        send_DHCP_DECLINE();
+
+        ret = dhcp_tick_1s;
+        while((dhcp_tick_1s - ret) < 2)
+            ; // wait for 1s over; wait to complete to send DECLINE message;
+
+        return 0;
+    }
+}
+
+void DHCP_init(uint8_t s, uint8_t* buf) {
+    uint8_t zeroip[4] = {0, 0, 0, 0};
+    getSHAR(DHCP_CHADDR);
+    if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] |
+        DHCP_CHADDR[5]) == 0x00) {
+        // assigning temporary mac address, you should be set SHAR before call this function.
+        DHCP_CHADDR[0] = 0x00;
+        DHCP_CHADDR[1] = 0x08;
+        DHCP_CHADDR[2] = 0xdc;
+        DHCP_CHADDR[3] = 0x00;
+        DHCP_CHADDR[4] = 0x00;
+        DHCP_CHADDR[5] = 0x00;
+        setSHAR(DHCP_CHADDR);
+    }
+
+    DHCP_SOCKET = s; // SOCK_DHCP
+    pDHCPMSG = (RIP_MSG*)buf;
+    DHCP_XID = 0x12345678;
+    {
+        DHCP_XID += DHCP_CHADDR[3];
+        DHCP_XID += DHCP_CHADDR[4];
+        DHCP_XID += DHCP_CHADDR[5];
+        DHCP_XID += (DHCP_CHADDR[3] ^ DHCP_CHADDR[4] ^ DHCP_CHADDR[5]);
+    }
+    // WIZchip Netinfo Clear
+    setSIPR(zeroip);
+    setGAR(zeroip);
+
+    reset_DHCP_timeout();
+    dhcp_state = STATE_DHCP_INIT;
+}
+
+/* Reset the DHCP timeout count and retry count. */
+void reset_DHCP_timeout(void) {
+    dhcp_tick_1s = 0;
+    dhcp_tick_next = DHCP_WAIT_TIME;
+    dhcp_retry_count = 0;
+}
+
+void DHCP_time_handler(void) {
+    dhcp_tick_1s++;
+}
+
+void getIPfromDHCP(uint8_t* ip) {
+    ip[0] = DHCP_allocated_ip[0];
+    ip[1] = DHCP_allocated_ip[1];
+    ip[2] = DHCP_allocated_ip[2];
+    ip[3] = DHCP_allocated_ip[3];
+}
+
+void getGWfromDHCP(uint8_t* ip) {
+    ip[0] = DHCP_allocated_gw[0];
+    ip[1] = DHCP_allocated_gw[1];
+    ip[2] = DHCP_allocated_gw[2];
+    ip[3] = DHCP_allocated_gw[3];
+}
+
+void getSNfromDHCP(uint8_t* ip) {
+    ip[0] = DHCP_allocated_sn[0];
+    ip[1] = DHCP_allocated_sn[1];
+    ip[2] = DHCP_allocated_sn[2];
+    ip[3] = DHCP_allocated_sn[3];
+}
+
+void getDNSfromDHCP(uint8_t* ip) {
+    ip[0] = DHCP_allocated_dns[0];
+    ip[1] = DHCP_allocated_dns[1];
+    ip[2] = DHCP_allocated_dns[2];
+    ip[3] = DHCP_allocated_dns[3];
+}
+
+uint32_t getDHCPLeasetime(void) {
+    return dhcp_lease_time;
+}
+
+char NibbleToHex(uint8_t nibble) {
+    nibble &= 0x0F;
+    if(nibble <= 9)
+        return nibble + '0';
+    else
+        return nibble + ('A' - 0x0A);
+}

+ 159 - 0
lib/ioLibrary_Driver/Internet/DHCP/dhcp.h

@@ -0,0 +1,159 @@
+//*****************************************************************************
+//
+//! \file dhcp.h
+//! \brief DHCP APIs Header file.
+//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
+//! \version 1.1.1
+//! \date 2019/10/08
+//! \par  Revision history
+//!       <2019/10/08> compare DHCP server ip address
+//!       <2013/11/18> 1st Release
+//!       <2012/12/20> V1.1.0
+//!         1. Move unreferenced DEFINE to dhcp.c
+//!       <2012/12/26> V1.1.1
+//! \author Eric Jung & MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//!
+//! Redistribution and use in source and binary forms, with or without
+//! modification, are permitted provided that the following conditions
+//! are met:
+//!
+//!     * Redistributions of source code must retain the above copyright
+//! notice, this list of conditions and the following disclaimer.
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution.
+//!     * Neither the name of the <ORGANIZATION> nor the names of its
+//! contributors may be used to endorse or promote products derived
+//! from this software without specific prior written permission.
+//!
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+#ifndef _DHCP_H_
+#define _DHCP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * @brief 
+ * @details If you want to display debug & processing message, Define _DHCP_DEBUG_ 
+ * @note    If defined, it depends on <stdio.h>
+ */
+#define _DHCP_DEBUG_
+
+/* Retry to processing DHCP */
+#define MAX_DHCP_RETRY 3 ///< Maximum retry count
+#define DHCP_WAIT_TIME 7 ///< Wait Time 10s
+
+/* UDP port numbers for DHCP */
+#define DHCP_SERVER_PORT 67 ///< DHCP server port number
+#define DHCP_CLIENT_PORT 68 ///< DHCP client port number
+
+#define MAGIC_COOKIE 0x63825363 ///< You should not modify it number.
+
+#define DCHP_HOST_NAME "WIZnet\0"
+
+/* 
+ * @brief return value of @ref DHCP_run()
+ */
+enum {
+    DHCP_FAILED = 0, ///< Processing Fail
+    DHCP_RUNNING, ///< Processing DHCP protocol
+    DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server      (if cbfunc == null, act as default default_ip_assign)
+    DHCP_IP_CHANGED, ///< Change IP address by new ip from DHCP (if cbfunc == null, act as default default_ip_update)
+    DHCP_IP_LEASED, ///< Stand by
+    DHCP_STOPPED ///< Stop processing DHCP protocol
+};
+
+/*
+ * @brief DHCP client initialization (outside of the main loop)
+ * @param s   - socket number
+ * @param buf - buffer for processing DHCP message
+ */
+void DHCP_init(uint8_t s, uint8_t* buf);
+
+/*
+ * @brief DHCP 1s Tick Timer handler
+ * @note SHOULD BE register to your system 1s Tick timer handler 
+ */
+void DHCP_time_handler(void);
+
+/* 
+ * @brief Register call back function 
+ * @param ip_assign   - callback func when IP is assigned from DHCP server first
+ * @param ip_update   - callback func when IP is changed
+ * @param ip_conflict - callback func when the assigned IP is conflict with others.
+ */
+void reg_dhcp_cbfunc(void (*ip_assign)(void), void (*ip_update)(void), void (*ip_conflict)(void));
+
+/*
+ * @brief DHCP client in the main loop
+ * @return    The value is as the follow \n
+ *            @ref DHCP_FAILED     \n
+ *            @ref DHCP_RUNNING    \n
+ *            @ref DHCP_IP_ASSIGN  \n
+ *            @ref DHCP_IP_CHANGED \n
+ * 			  @ref DHCP_IP_LEASED  \n
+ *            @ref DHCP_STOPPED    \n
+ *
+ * @note This function is always called by you main task.
+ */
+uint8_t DHCP_run(void);
+
+/*
+ * @brief Stop DHCP processing
+ * @note If you want to restart. call DHCP_init() and DHCP_run()
+ */
+void DHCP_stop(void);
+
+/* Get Network information assigned from DHCP server */
+/*
+ * @brief Get IP address
+ * @param ip  - IP address to be returned
+ */
+void getIPfromDHCP(uint8_t* ip);
+/*
+ * @brief Get Gateway address
+ * @param ip  - Gateway address to be returned
+ */
+void getGWfromDHCP(uint8_t* ip);
+/*
+ * @brief Get Subnet mask value
+ * @param ip  - Subnet mask to be returned
+ */
+void getSNfromDHCP(uint8_t* ip);
+/*
+ * @brief Get DNS address
+ * @param ip  - DNS address to be returned
+ */
+void getDNSfromDHCP(uint8_t* ip);
+
+/*
+ * @brief Get the leased time by DHCP sever
+ * @return unit 1s
+ */
+uint32_t getDHCPLeasetime(void);
+
+void eth_printf(const char* format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DHCP_H_ */

+ 564 - 0
lib/ioLibrary_Driver/Internet/DNS/dns.c

@@ -0,0 +1,564 @@
+//*****************************************************************************
+//
+//! \file dns.c
+//! \brief DNS APIs Implement file.
+//! \details Send DNS query & Receive DNS reponse.  \n
+//!          It depends on stdlib.h & string.h in ansi-c library
+//! \version 1.1.0
+//! \date 2013/11/18
+//! \par  Revision history
+//!       <2013/10/21> 1st Release
+//!       <2013/12/20> V1.1.0
+//!         1. Remove secondary DNS server in DNS_run
+//!            If 1st DNS_run failed, call DNS_run with 2nd DNS again
+//!         2. DNS_timerHandler -> DNS_time_handler
+//!         3. Remove the unused define
+//!         4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
+//!       <2013/12/20> V1.1.0
+//!
+//! \author Eric Jung & MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//!
+//! Redistribution and use in source and binary forms, with or without
+//! modification, are permitted provided that the following conditions
+//! are met:
+//!
+//!     * Redistributions of source code must retain the above copyright
+//! notice, this list of conditions and the following disclaimer.
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution.
+//!     * Neither the name of the <ORGANIZATION> nor the names of its
+//! contributors may be used to endorse or promote products derived
+//! from this software without specific prior written permission.
+//!
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "socket.h"
+#include "dns.h"
+
+#ifdef _DNS_DEBUG_
+   #include <stdio.h>
+#endif
+
+#define	INITRTT		2000L	/* Initial smoothed response time */
+#define	MAXCNAME	   (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1))	   /* Maximum amount of cname recursion */
+
+#define	TYPE_A		1	   /* Host address */
+#define	TYPE_NS		2	   /* Name server */
+#define	TYPE_MD		3	   /* Mail destination (obsolete) */
+#define	TYPE_MF		4	   /* Mail forwarder (obsolete) */
+#define	TYPE_CNAME	5	   /* Canonical name */
+#define	TYPE_SOA	   6	   /* Start of Authority */
+#define	TYPE_MB		7	   /* Mailbox name (experimental) */
+#define	TYPE_MG		8	   /* Mail group member (experimental) */
+#define	TYPE_MR		9	   /* Mail rename name (experimental) */
+#define	TYPE_NULL	10	   /* Null (experimental) */
+#define	TYPE_WKS	   11	   /* Well-known sockets */
+#define	TYPE_PTR	   12	   /* Pointer record */
+#define	TYPE_HINFO	13	   /* Host information */
+#define	TYPE_MINFO	14	   /* Mailbox information (experimental)*/
+#define	TYPE_MX		15	   /* Mail exchanger */
+#define	TYPE_TXT	   16	   /* Text strings */
+#define	TYPE_ANY	   255	/* Matches any type */
+
+#define	CLASS_IN	   1	   /* The ARPA Internet */
+
+/* Round trip timing parameters */
+#define	AGAIN	      8     /* Average RTT gain = 1/8 */
+#define	LAGAIN      3     /* Log2(AGAIN) */
+#define	DGAIN       4     /* Mean deviation gain = 1/4 */
+#define	LDGAIN      2     /* log2(DGAIN) */
+
+/* Header for all domain messages */
+struct dhdr
+{
+	uint16_t id;   /* Identification */
+	uint8_t	qr;      /* Query/Response */
+#define	QUERY    0
+#define	RESPONSE 1
+	uint8_t	opcode;
+#define	IQUERY   1
+	uint8_t	aa;      /* Authoratative answer */
+	uint8_t	tc;      /* Truncation */
+	uint8_t	rd;      /* Recursion desired */
+	uint8_t	ra;      /* Recursion available */
+	uint8_t	rcode;   /* Response code */
+#define	NO_ERROR       0
+#define	FORMAT_ERROR   1
+#define	SERVER_FAIL    2
+#define	NAME_ERROR     3
+#define	NOT_IMPL       4
+#define	REFUSED        5
+	uint16_t qdcount;	/* Question count */
+	uint16_t ancount;	/* Answer count */
+	uint16_t nscount;	/* Authority (name server) count */
+	uint16_t arcount;	/* Additional record count */
+};
+
+
+uint8_t* pDNSMSG;       // DNS message buffer
+uint8_t  DNS_SOCKET;    // SOCKET number for DNS
+uint16_t DNS_MSGID;     // DNS message ID
+
+uint32_t dns_1s_tick;   // for timout of DNS processing
+static uint8_t retry_count;
+
+/* converts uint16_t from network buffer to a host byte order integer. */
+uint16_t get16(uint8_t * s)
+{
+	uint16_t i;
+	i = *s++ << 8;
+	i = i + *s;
+	return i;
+}
+
+/* copies uint16_t to the network buffer with network byte order. */
+uint8_t * put16(uint8_t * s, uint16_t i)
+{
+	*s++ = i >> 8;
+	*s++ = i;
+	return s;
+}
+
+
+/*
+ *              CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM
+ *
+ * Description : This function converts a compressed domain name to the human-readable form
+ * Arguments   : msg        - is a pointer to the reply message
+ *               compressed - is a pointer to the domain name in reply message.
+ *               buf        - is a pointer to the buffer for the human-readable form name.
+ *               len        - is the MAX. size of buffer.
+ * Returns     : the length of compressed message
+ */
+int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len)
+{
+	uint16_t slen;		/* Length of current segment */
+	uint8_t * cp;
+	int clen = 0;		/* Total length of compressed name */
+	int indirect = 0;	/* Set if indirection encountered */
+	int nseg = 0;		/* Total number of segments in name */
+
+	cp = compressed;
+
+	for (;;)
+	{
+		slen = *cp++;	/* Length of this segment */
+
+		if (!indirect) clen++;
+
+		if ((slen & 0xc0) == 0xc0)
+		{
+			if (!indirect)
+				clen++;
+			indirect = 1;
+			/* Follow indirection */
+			cp = &msg[((slen & 0x3f)<<8) + *cp];
+			slen = *cp++;
+		}
+
+		if (slen == 0)	/* zero length == all done */
+			break;
+
+		len -= slen + 1;
+
+		if (len < 0) return -1;
+
+		if (!indirect) clen += slen;
+
+		while (slen-- != 0) *buf++ = (char)*cp++;
+		*buf++ = '.';
+		nseg++;
+	}
+
+	if (nseg == 0)
+	{
+		/* Root name; represent as single dot */
+		*buf++ = '.';
+		len--;
+	}
+
+	*buf++ = '\0';
+	len--;
+
+	return clen;	/* Length of compressed message */
+}
+
+/*
+ *              PARSE QUESTION SECTION
+ *
+ * Description : This function parses the qeustion record of the reply message.
+ * Arguments   : msg - is a pointer to the reply message
+ *               cp  - is a pointer to the qeustion record.
+ * Returns     : a pointer the to next record.
+ */
+uint8_t * dns_question(uint8_t * msg, uint8_t * cp)
+{
+	int len;
+	char name[MAXCNAME];
+
+	len = parse_name(msg, cp, name, MAXCNAME);
+
+
+	if (len == -1) return 0;
+
+	cp += len;
+	cp += 2;		/* type */
+	cp += 2;		/* class */
+
+	return cp;
+}
+
+
+/*
+ *              PARSE ANSER SECTION
+ *
+ * Description : This function parses the answer record of the reply message.
+ * Arguments   : msg - is a pointer to the reply message
+ *               cp  - is a pointer to the answer record.
+ * Returns     : a pointer the to next record.
+ */
+uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns)
+{
+	int len, type;
+	char name[MAXCNAME];
+
+	len = parse_name(msg, cp, name, MAXCNAME);
+
+	if (len == -1) return 0;
+
+	cp += len;
+	type = get16(cp);
+	cp += 2;		/* type */
+	cp += 2;		/* class */
+	cp += 4;		/* ttl */
+	cp += 2;		/* len */
+
+
+	switch (type)
+	{
+	case TYPE_A:
+		/* Just read the address directly into the structure */
+		ip_from_dns[0] = *cp++;
+		ip_from_dns[1] = *cp++;
+		ip_from_dns[2] = *cp++;
+		ip_from_dns[3] = *cp++;
+		break;
+	case TYPE_CNAME:
+	case TYPE_MB:
+	case TYPE_MG:
+	case TYPE_MR:
+	case TYPE_NS:
+	case TYPE_PTR:
+		/* These types all consist of a single domain name */
+		/* convert it to ascii format */
+		len = parse_name(msg, cp, name, MAXCNAME);
+		if (len == -1) return 0;
+
+		cp += len;
+		break;
+	case TYPE_HINFO:
+		len = *cp++;
+		cp += len;
+
+		len = *cp++;
+		cp += len;
+		break;
+	case TYPE_MX:
+		cp += 2;
+		/* Get domain name of exchanger */
+		len = parse_name(msg, cp, name, MAXCNAME);
+		if (len == -1) return 0;
+
+		cp += len;
+		break;
+	case TYPE_SOA:
+		/* Get domain name of name server */
+		len = parse_name(msg, cp, name, MAXCNAME);
+		if (len == -1) return 0;
+
+		cp += len;
+
+		/* Get domain name of responsible person */
+		len = parse_name(msg, cp, name, MAXCNAME);
+		if (len == -1) return 0;
+
+		cp += len;
+
+		cp += 4;
+		cp += 4;
+		cp += 4;
+		cp += 4;
+		cp += 4;
+		break;
+	case TYPE_TXT:
+		/* Just stash */
+		break;
+	default:
+		/* Ignore */
+		break;
+	}
+
+	return cp;
+}
+
+/*
+ *              PARSE THE DNS REPLY
+ *
+ * Description : This function parses the reply message from DNS server.
+ * Arguments   : dhdr - is a pointer to the header for DNS message
+ *               buf  - is a pointer to the reply message.
+ *               len  - is the size of reply message.
+ * Returns     : -1 - Domain name lenght is too big
+ *                0 - Fail (Timout or parse error)
+ *                1 - Success,
+ */
+int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns)
+{
+	uint16_t tmp;
+	uint16_t i;
+	uint8_t * msg;
+	uint8_t * cp;
+
+	msg = pbuf;
+	memset(pdhdr, 0, sizeof(*pdhdr));
+
+	pdhdr->id = get16(&msg[0]);
+	tmp = get16(&msg[2]);
+	if (tmp & 0x8000) pdhdr->qr = 1;
+
+	pdhdr->opcode = (tmp >> 11) & 0xf;
+
+	if (tmp & 0x0400) pdhdr->aa = 1;
+	if (tmp & 0x0200) pdhdr->tc = 1;
+	if (tmp & 0x0100) pdhdr->rd = 1;
+	if (tmp & 0x0080) pdhdr->ra = 1;
+
+	pdhdr->rcode = tmp & 0xf;
+	pdhdr->qdcount = get16(&msg[4]);
+	pdhdr->ancount = get16(&msg[6]);
+	pdhdr->nscount = get16(&msg[8]);
+	pdhdr->arcount = get16(&msg[10]);
+
+
+	/* Now parse the variable length sections */
+	cp = &msg[12];
+
+	/* Question section */
+	for (i = 0; i < pdhdr->qdcount; i++)
+	{
+		cp = dns_question(msg, cp);
+   #ifdef _DNS_DEUBG_
+      printf("MAX_DOMAIN_NAME is too small, it should be redfine in dns.h");
+   #endif
+		if(!cp) return -1;
+	}
+
+	/* Answer section */
+	for (i = 0; i < pdhdr->ancount; i++)
+	{
+		cp = dns_answer(msg, cp, ip_from_dns);
+   #ifdef _DNS_DEUBG_
+      printf("MAX_DOMAIN_NAME is too small, it should be redfine in dns.h");
+   #endif
+		if(!cp) return -1;
+	}
+
+	/* Name server (authority) section */
+	for (i = 0; i < pdhdr->nscount; i++)
+	{
+		;
+	}
+
+	/* Additional section */
+	for (i = 0; i < pdhdr->arcount; i++)
+	{
+		;
+	}
+
+	if(pdhdr->rcode == 0) return 1;		// No error
+	else return 0;
+}
+
+
+/*
+ *              MAKE DNS QUERY MESSAGE
+ *
+ * Description : This function makes DNS query message.
+ * Arguments   : op   - Recursion desired
+ *               name - is a pointer to the domain name.
+ *               buf  - is a pointer to the buffer for DNS message.
+ *               len  - is the MAX. size of buffer.
+ * Returns     : the pointer to the DNS message.
+ */
+int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len)
+{
+	uint8_t *cp;
+	char *cp1;
+	char sname[MAXCNAME];
+	char *dname;
+	uint16_t p;
+	uint16_t dlen;
+
+	cp = buf;
+
+	DNS_MSGID++;
+	cp = put16(cp, DNS_MSGID);
+	p = (op << 11) | 0x0100;			/* Recursion desired */
+	cp = put16(cp, p);
+	cp = put16(cp, 1);
+	cp = put16(cp, 0);
+	cp = put16(cp, 0);
+	cp = put16(cp, 0);
+
+	strcpy(sname, name);
+	dname = sname;
+	dlen = strlen(dname);
+	for (;;)
+	{
+		/* Look for next dot */
+		cp1 = strchr(dname, '.');
+
+		if (cp1 != NULL) len = cp1 - dname;	/* More to come */
+		else len = dlen;			/* Last component */
+
+		*cp++ = len;				/* Write length of component */
+		if (len == 0) break;
+
+		/* Copy component up to (but not including) dot */
+		strncpy((char *)cp, dname, len);
+		cp += len;
+		if (cp1 == NULL)
+		{
+			*cp++ = 0;			/* Last one; write null and finish */
+			break;
+		}
+		dname += len+1;
+		dlen -= len+1;
+	}
+
+	cp = put16(cp, 0x0001);				/* type */
+	cp = put16(cp, 0x0001);				/* class */
+
+	return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf)));
+}
+
+/*
+ *              CHECK DNS TIMEOUT
+ *
+ * Description : This function check the DNS timeout
+ * Arguments   : None.
+ * Returns     : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur
+ * Note        : timeout : retry count and timer both over.
+ */
+
+int8_t check_DNS_timeout(void)
+{
+
+	if(dns_1s_tick >= DNS_WAIT_TIME)
+	{
+		dns_1s_tick = 0;
+		if(retry_count >= MAX_DNS_RETRY) {
+			retry_count = 0;
+			return -1; // timeout occurred
+		}
+		retry_count++;
+		return 0; // timer over, but no timeout
+	}
+
+	return 1; // no timer over, no timeout occur
+}
+
+
+
+/* DNS CLIENT INIT */
+void DNS_init(uint8_t s, uint8_t * buf)
+{
+	DNS_SOCKET = s; // SOCK_DNS
+	pDNSMSG = buf; // User's shared buffer
+	DNS_MSGID = DNS_MSG_ID;
+}
+
+/* DNS CLIENT RUN */
+int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns)
+{
+	int8_t ret;
+	struct dhdr dhp;
+	uint8_t ip[4];
+	uint16_t len, port;
+	int8_t ret_check_timeout;
+
+	retry_count = 0;
+	dns_1s_tick = 0;
+
+   // Socket open
+   socket(DNS_SOCKET, Sn_MR_UDP, 0, 0);
+
+#ifdef _DNS_DEBUG_
+	printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
+#endif
+
+	len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE);
+	sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
+
+	while (1)
+	{
+		if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0)
+		{
+			if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE;
+			len = recvfrom(DNS_SOCKET, pDNSMSG, len, ip, &port);
+      #ifdef _DNS_DEBUG_
+	      printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len);
+      #endif
+         ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns);
+			break;
+		}
+		// Check Timeout
+		ret_check_timeout = check_DNS_timeout();
+		if (ret_check_timeout < 0) {
+
+#ifdef _DNS_DEBUG_
+			printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
+#endif
+			close(DNS_SOCKET);
+			return 0; // timeout occurred
+		}
+		else if (ret_check_timeout == 0) {
+
+#ifdef _DNS_DEBUG_
+			printf("> DNS Timeout\r\n");
+#endif
+			sendto(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
+		}
+	}
+	close(DNS_SOCKET);
+	// Return value
+	// 0 > :  failed / 1 - success
+	return ret;
+}
+
+
+/* DNS TIMER HANDLER */
+void DNS_time_handler(void)
+{
+	dns_1s_tick++;
+}

+ 109 - 0
lib/ioLibrary_Driver/Internet/DNS/dns.h

@@ -0,0 +1,109 @@
+//*****************************************************************************
+//
+//! \file dns.h
+//! \brief DNS APIs Header file.
+//! \details Send DNS query & Receive DNS reponse. 
+//! \version 1.1.0
+//! \date 2013/11/18
+//! \par  Revision history
+//!       <2013/10/21> 1st Release
+//!       <2013/12/20> V1.1.0
+//!         1. Remove secondary DNS server in DNS_run
+//!            If 1st DNS_run failed, call DNS_run with 2nd DNS again
+//!         2. DNS_timerHandler -> DNS_time_handler
+//!         3. Move the no reference define to dns.c
+//!         4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
+//!       <2013/12/20> V1.1.0
+//!
+//! \author Eric Jung & MidnightCow
+//! \copyright
+//!
+//! Copyright (c)  2013, WIZnet Co., LTD.
+//! All rights reserved.
+//! 
+//! Redistribution and use in source and binary forms, with or without 
+//! modification, are permitted provided that the following conditions 
+//! are met: 
+//! 
+//!     * Redistributions of source code must retain the above copyright 
+//! notice, this list of conditions and the following disclaimer. 
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution. 
+//!     * Neither the name of the <ORGANIZATION> nor the names of its 
+//! contributors may be used to endorse or promote products derived 
+//! from this software without specific prior written permission. 
+//! 
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#ifndef	_DNS_H_
+#define	_DNS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+/*
+ * @brief Define it for Debug & Monitor DNS processing.
+ * @note If defined, it dependens on <stdio.h>
+ */
+//#define _DNS_DEBUG_
+
+#define	MAX_DNS_BUF_SIZE	256		///< maximum size of DNS buffer. */
+/*
+ * @brief Maxium length of your queried Domain name 
+ * @todo SHOULD BE defined it equal as or greater than your Domain name lenght + null character(1)
+ * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack.
+ */
+#define  MAX_DOMAIN_NAME   128       // for example "www.google.com"
+
+#define	MAX_DNS_RETRY     2        ///< Requery Count
+#define	DNS_WAIT_TIME     3        ///< Wait response time. unit 1s.
+
+#define	IPPORT_DOMAIN     53       ///< DNS server port number
+
+#define DNS_MSG_ID         0x1122   ///< ID for DNS message. You can be modifyed it any number
+/*
+ * @brief DNS process initialize
+ * @param s   : Socket number for DNS
+ * @param buf : Buffer for DNS message
+ */
+void DNS_init(uint8_t s, uint8_t * buf);
+
+/*
+ * @brief DNS process
+ * @details Send DNS query and receive DNS response
+ * @param dns_ip        : DNS server ip
+ * @param name          : Domain name to be queryed
+ * @param ip_from_dns   : IP address from DNS server
+ * @return  -1 : failed. @ref MAX_DOMIN_NAME is too small \n
+ *           0 : failed  (Timeout or Parse error)\n
+ *           1 : success
+ * @note This funtion blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME
+ */
+int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns);
+
+/*
+ * @brief DNS 1s Tick Timer handler
+ * @note SHOULD BE register to your system 1s Tick timer handler 
+ */
+void DNS_time_handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _DNS_H_ */

+ 584 - 0
lib/ioLibrary_Driver/Internet/FTPClient/ftpc.c

@@ -0,0 +1,584 @@
+#include "ftpc.h"
+
+un_l2cval remote_ip;
+uint16_t  remote_port;
+un_l2cval local_ip;
+uint16_t  local_port;
+uint8_t connect_state_control_ftpc = 0;
+uint8_t connect_state_data_ftpc = 0;
+uint8_t gModeActivePassiveflag = 0;
+uint8_t FTP_destip[4] = {192, 168, 10, 230};	// For FTP client examples; destination network info
+uint16_t FTP_destport = 21;						// For FTP client examples; destination network info
+uint8_t gMenuStart = 0;
+uint8_t gDataSockReady = 0;
+uint8_t gDataPutGetStart = 0;
+static uint8_t gMsgBuf[20]={0,};
+
+struct ftpc ftpc;
+struct Command Command;
+
+void ftpc_init(uint8_t * src_ip)
+{
+	ftpc.dsock_mode = ACTIVE_MODE;
+
+	local_ip.cVal[0] = src_ip[0];
+	local_ip.cVal[1] = src_ip[1];
+	local_ip.cVal[2] = src_ip[2];
+	local_ip.cVal[3] = src_ip[3];
+	local_port = 35000;
+	strcpy(ftpc.workingdir, "/");
+	socket(CTRL_SOCK, Sn_MR_TCP, FTP_destport, 0x0);
+}
+uint8_t ftpc_run(uint8_t * dbuf)
+{
+#ifndef Need_UARTGetCharBlocking_func
+	uint16_t size = 0;
+	long ret = 0;
+	uint32_t send_byte, recv_byte;
+	uint32_t blocklen;
+	uint32_t remain_filesize;
+	uint32_t remain_datasize;
+	uint8_t msg_c;
+	uint8_t dat[50]={0,};
+	uint32_t totalSize = 0, availableSize = 0;
+
+    switch(getSn_SR(CTRL_SOCK))
+    {
+    	case SOCK_ESTABLISHED :
+    		if(!connect_state_control_ftpc){
+    			printf("%d:FTP Connected\r\n", CTRL_SOCK);
+    			strcpy(ftpc.workingdir, "/");
+    			connect_state_control_ftpc = 1;
+    		}
+    		if(gMenuStart){
+				gMenuStart = 0;
+				printf("\r\n----------------------------------------\r\n");
+				printf("Press menu key\r\n");
+				printf("----------------------------------------\r\n");
+				printf("1> View FTP Server Directory\r\n");
+				printf("2> View My Directory\r\n");
+				printf("3> Sets the type of file to be transferred. Current state : %s\r\n", (ftpc.type==ASCII_TYPE)?"Ascii":"Binary");
+				printf("4> Sets Data Connection. Current state : %s\r\n", (ftpc.dsock_mode==ACTIVE_MODE)?"Active":"Passive");
+				printf("5> Put File to Server\r\n");
+				printf("6> Get File from Server\r\n");
+#if defined(F_FILESYSTEM)
+				printf("7> Delete My File\r\n");
+#endif
+				printf("----------------------------------------\r\n");
+				while(1){
+					msg_c=ftp_getc();
+					if(msg_c=='1'){
+						if(ftpc.dsock_mode==PASSIVE_MODE){
+							sprintf(dat,"PASV\r\n");
+							send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+							Command.First = f_dir;
+							break;
+						}
+						else{
+							wiz_NetInfo gWIZNETINFO;
+							ctlnetwork(CN_GET_NETINFO, (void*) &gWIZNETINFO);
+							sprintf(dat,"PORT %d,%d,%d,%d,%d,%d\r\n", gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3], (uint8_t)(local_port>>8), (uint8_t)(local_port&0x00ff));
+							send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+							Command.First = f_dir;
+
+							gModeActivePassiveflag = 1;
+							break;
+						}
+						break;
+					}
+					else if(msg_c=='5'){
+						if(ftpc.dsock_mode==PASSIVE_MODE){
+							sprintf(dat,"PASV\r\n");
+							send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+							Command.First = f_put;
+							break;
+						}
+						else{
+							wiz_NetInfo gWIZNETINFO;
+							ctlnetwork(CN_GET_NETINFO, (void*) &gWIZNETINFO);
+							sprintf(dat,"PORT %d,%d,%d,%d,%d,%d\r\n", gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3], (uint8_t)(local_port>>8), (uint8_t)(local_port&0x00ff));
+							send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+							Command.First = f_put;
+
+							gModeActivePassiveflag = 1;
+							break;
+						}
+					}
+					else if(msg_c=='6'){
+						if(ftpc.dsock_mode==PASSIVE_MODE){
+							sprintf(dat,"PASV\r\n");
+							send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+							Command.First = f_get;
+							break;
+						}
+						else{
+							wiz_NetInfo gWIZNETINFO;
+							ctlnetwork(CN_GET_NETINFO, (void*) &gWIZNETINFO);
+							sprintf(dat,"PORT %d,%d,%d,%d,%d,%d\r\n", gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3], (uint8_t)(local_port>>8), (uint8_t)(local_port&0x00ff));
+							send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+							Command.First = f_get;
+
+							gModeActivePassiveflag = 1;
+							break;
+						}
+					}
+					else if(msg_c=='2'){
+#if defined(F_FILESYSTEM)
+						scan_files(ftpc.workingdir, dbuf, (int *)&size);
+						printf("\r\n%s\r\n", dbuf);
+#else
+						if (strncmp(ftpc.workingdir, "/$Recycle.Bin", sizeof("/$Recycle.Bin")) != 0)
+							size = sprintf(dbuf, "drwxr-xr-x 1 ftp ftp 0 Dec 31 2014 $Recycle.Bin\r\n-rwxr-xr-x 1 ftp ftp 512 Dec 31 2014 test.txt\r\n");
+						printf("\r\n%s\r\n", dbuf);
+#endif
+						gMenuStart = 1;
+						break;
+					}
+					else if(msg_c=='3'){
+						printf("1> ASCII\r\n");
+						printf("2> BINARY\r\n");
+						while(1){
+							msg_c=ftp_getc();
+							if(msg_c=='1'){
+								sprintf(dat,"TYPE %c\r\n", TransferAscii);
+								ftpc.type = ASCII_TYPE;
+								send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+								break;
+							}
+							else if(msg_c=='2'){
+								sprintf(dat,"TYPE %c\r\n", TransferBinary);
+								ftpc.type = IMAGE_TYPE;
+								send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+								break;
+							}
+							else{
+								printf("\r\nRetry...\r\n");
+							}
+						}
+						break;
+					}
+					else if(msg_c=='4'){
+						printf("1> ACTIVE\r\n");
+						printf("2> PASSIVE\r\n");
+						while(1){
+							msg_c=ftp_getc();
+							if(msg_c=='1'){
+								ftpc.dsock_mode=ACTIVE_MODE;
+								break;
+							}
+							else if(msg_c=='2'){
+								ftpc.dsock_mode=PASSIVE_MODE;
+								break;
+							}
+							else{
+								printf("\r\nRetry...\r\n");
+							}
+						}
+						gMenuStart = 1;
+						break;
+					}
+#if defined(F_FILESYSTEM)
+					else if(msg_c=='7'){
+						printf(">del filename?");
+						sprintf(ftpc.filename, "/%s\r\n", User_Keyboard_MSG());
+						if (f_unlink((const char *)ftpc.filename) != 0){
+							printf("\r\nCould not delete.\r\n");
+						}
+						else{
+							printf("\r\nDeleted.\r\n");
+						}
+						gMenuStart = 1;
+						break;
+					}
+#endif
+					else{
+						printf("\r\nRetry...\r\n");
+					}
+				}
+			}
+			if(gDataSockReady){
+				gDataSockReady = 0;
+				switch(Command.First){
+					case f_dir:
+						sprintf(dat,"LIST\r\n");
+						send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+						break;
+					case f_put:
+						printf(">put file name?");
+						sprintf(dat,"STOR %s\r\n", User_Keyboard_MSG());
+						send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+						break;
+					case f_get:
+						printf(">get file name?");
+						sprintf(dat,"RETR %s\r\n", User_Keyboard_MSG());
+						send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+						break;
+					default:
+						printf("Command.First = default\r\n");
+						break;
+				}
+			}
+    		if((size = getSn_RX_RSR(CTRL_SOCK)) > 0){ // Don't need to check SOCKERR_BUSY because it doesn't not occur.
+    			memset(dbuf, 0, _MAX_SS);
+    			if(size > _MAX_SS) size = _MAX_SS - 1;
+    			ret = recv(CTRL_SOCK,dbuf,size);
+    			dbuf[ret] = '\0';
+    			if(ret != size)
+    			{
+    				if(ret==SOCK_BUSY) return 0;
+    				if(ret < 0){
+    					printf("%d:recv() error:%ld\r\n",CTRL_SOCK,ret);
+    					close(CTRL_SOCK);
+    					return ret;
+    				}
+    			}
+    			printf("Rcvd Command: %s\r\n", dbuf);
+    			proc_ftpc((char *)dbuf);
+    		}
+    		break;
+    	case SOCK_CLOSE_WAIT :
+    		printf("%d:CloseWait\r\n",CTRL_SOCK);
+    		if((ret=disconnect(CTRL_SOCK)) != SOCK_OK) return ret;
+    		printf("%d:Closed\r\n",CTRL_SOCK);
+    		break;
+    	case SOCK_CLOSED :
+    		printf("%d:FTPStart\r\n",CTRL_SOCK);
+    		if((ret=socket(CTRL_SOCK, Sn_MR_TCP, FTP_destport, 0x0)) != CTRL_SOCK){
+    			printf("%d:socket() error:%ld\r\n", CTRL_SOCK, ret);
+    			close(CTRL_SOCK);
+    			return ret;
+    		}
+    		break;
+    	case SOCK_INIT :
+    		printf("%d:Opened\r\n",CTRL_SOCK);
+			if((ret = connect(CTRL_SOCK, FTP_destip, FTP_destport)) != SOCK_OK){
+				printf("%d:Connect error\r\n",CTRL_SOCK);
+				return ret;
+			}
+			connect_state_control_ftpc = 0;
+			printf("%d:Connectting...\r\n",CTRL_SOCK);
+			break;
+    	default :
+    		break;
+    }
+
+    switch(getSn_SR(DATA_SOCK)){
+    	case SOCK_ESTABLISHED :
+    		if(!connect_state_data_ftpc){
+    			printf("%d:FTP Data socket Connected\r\n", DATA_SOCK);
+    			connect_state_data_ftpc = 1;
+    		}
+			if(gDataPutGetStart){
+				switch(Command.Second){
+				case s_dir:
+					printf("dir waiting...\r\n");
+					if((size = getSn_RX_RSR(DATA_SOCK)) > 0){ // Don't need to check SOCKERR_BUSY because it doesn't not occur.
+						printf("ok\r\n");
+						memset(dbuf, 0, _MAX_SS);
+						if(size > _MAX_SS) size = _MAX_SS - 1;
+						ret = recv(DATA_SOCK,dbuf,size);
+						dbuf[ret] = '\0';
+						if(ret != size){
+							if(ret==SOCK_BUSY) return 0;
+							if(ret < 0){
+								printf("%d:recv() error:%ld\r\n",CTRL_SOCK,ret);
+								close(DATA_SOCK);
+								return ret;
+							}
+						}
+						printf("Rcvd Data:\n\r%s\n\r", dbuf);
+						gDataPutGetStart = 0;
+						Command.Second = s_nocmd;
+					}
+					break;
+				case s_put:
+					printf("put waiting...\r\n");
+					if(strlen(ftpc.workingdir) == 1)
+						sprintf(ftpc.filename, "/%s", (uint8_t *)gMsgBuf);
+					else
+						sprintf(ftpc.filename, "%s/%s", ftpc.workingdir, (uint8_t *)gMsgBuf);
+#if defined(F_FILESYSTEM)
+					ftpc.fr = f_open(&(ftpc.fil), (const char *)ftpc.filename, FA_READ);
+					if(ftpc.fr == FR_OK){
+						remain_filesize = ftpc.fil.fsize;
+						printf("f_open return FR_OK\r\n");
+						do{
+							memset(dbuf, 0, _MAX_SS);
+							if(remain_filesize > _MAX_SS)
+								send_byte = _MAX_SS;
+							else
+								send_byte = remain_filesize;
+							ftpc.fr = f_read(&(ftpc.fil), (void *)dbuf, send_byte , (UINT *)&blocklen);
+							if(ftpc.fr != FR_OK){
+								break;
+							}
+							printf("#");
+							send(DATA_SOCK, dbuf, blocklen);
+							remain_filesize -= blocklen;
+						}while(remain_filesize != 0);
+						printf("\r\nFile read finished\r\n");
+						ftpc.fr = f_close(&(ftpc.fil));
+					}
+					else{
+						printf("File Open Error: %d\r\n", ftpc.fr);
+						ftpc.fr = f_close(&(ftpc.fil));
+					}
+#else
+					remain_filesize = strlen(ftpc.filename);
+					do{
+						memset(dbuf, 0, _MAX_SS);
+						blocklen = sprintf(dbuf, "%s", ftpc.filename);
+						printf("########## dbuf:%s\r\n", dbuf);
+						send(DATA_SOCK, dbuf, blocklen);
+						remain_filesize -= blocklen;
+					}while(remain_filesize != 0);
+#endif
+					gDataPutGetStart = 0;
+					Command.Second = s_nocmd;
+					disconnect(DATA_SOCK);
+					break;
+				case s_get:
+					printf("get waiting...\r\n");
+					if(strlen(ftpc.workingdir) == 1)
+						sprintf(ftpc.filename, "/%s", (uint8_t *)gMsgBuf);
+					else
+						sprintf(ftpc.filename, "%s/%s", ftpc.workingdir, (uint8_t *)gMsgBuf);
+#if defined(F_FILESYSTEM)
+					ftpc.fr = f_open(&(ftpc.fil), (const char *)ftpc.filename, FA_CREATE_ALWAYS | FA_WRITE);
+					if(ftpc.fr == FR_OK){
+						printf("f_open return FR_OK\r\n");
+						while(1){
+							if((remain_datasize = getSn_RX_RSR(DATA_SOCK)) > 0){
+								while(1){
+									memset(dbuf, 0, _MAX_SS);
+									if(remain_datasize > _MAX_SS)	recv_byte = _MAX_SS;
+									else	recv_byte = remain_datasize;
+									ret = recv(DATA_SOCK, dbuf, recv_byte);
+									ftpc.fr = f_write(&(ftpc.fil), (const void *)dbuf, (UINT)ret, (UINT *)&blocklen);
+									remain_datasize -= blocklen;
+									if(ftpc.fr != FR_OK){
+										printf("f_write failed\r\n");
+										break;
+									}
+									if(remain_datasize <= 0)	break;
+								}
+								if(ftpc.fr != FR_OK){
+									printf("f_write failed\r\n");
+									break;
+								}
+								printf("#");
+							}
+							else{
+								if(getSn_SR(DATA_SOCK) != SOCK_ESTABLISHED)	break;
+							}
+						}
+						printf("\r\nFile write finished\r\n");
+						ftpc.fr = f_close(&(ftpc.fil));
+						gDataPutGetStart = 0;
+					}else{
+						printf("File Open Error: %d\r\n", ftpc.fr);
+					}
+#else
+					while(1){
+						if((remain_datasize = getSn_RX_RSR(DATA_SOCK)) > 0){
+							while(1){
+								memset(dbuf, 0, _MAX_SS);
+								if(remain_datasize > _MAX_SS)
+									recv_byte = _MAX_SS;
+								else
+									recv_byte = remain_datasize;
+								ret = recv(DATA_SOCK, dbuf, recv_byte);
+								printf("########## dbuf:%s\r\n", dbuf);
+								remain_datasize -= ret;
+								if(remain_datasize <= 0)
+									break;
+							}
+						}else{
+							if(getSn_SR(DATA_SOCK) != SOCK_ESTABLISHED)
+								break;
+						}
+					}
+					gDataPutGetStart = 0;
+					Command.Second = s_nocmd;
+#endif
+					break;
+				default:
+					printf("Command.Second = default\r\n");
+					break;
+				}
+			}
+    		break;
+   		case SOCK_CLOSE_WAIT :
+   			printf("%d:CloseWait\r\n",DATA_SOCK);
+			if((ret=disconnect(DATA_SOCK)) != SOCK_OK) return ret;
+			printf("%d:Closed\r\n",DATA_SOCK);
+   			break;
+   		case SOCK_CLOSED :
+   			if(ftpc.dsock_state == DATASOCK_READY){
+   				if(ftpc.dsock_mode == PASSIVE_MODE){
+   					printf("%d:FTPDataStart, port : %d\r\n",DATA_SOCK, local_port);
+   					if((ret=socket(DATA_SOCK, Sn_MR_TCP, local_port, 0x0)) != DATA_SOCK){
+   						printf("%d:socket() error:%ld\r\n", DATA_SOCK, ret);
+   						close(DATA_SOCK);
+   						return ret;
+   					}
+   					local_port++;
+   					if(local_port > 50000)
+   						local_port = 35000;
+   				}else{
+   					printf("%d:FTPDataStart, port : %d\r\n",DATA_SOCK, local_port);
+   					if((ret=socket(DATA_SOCK, Sn_MR_TCP, local_port, 0x0)) != DATA_SOCK){
+   						printf("%d:socket() error:%ld\r\n", DATA_SOCK, ret);
+   						close(DATA_SOCK);
+   						return ret;
+   					}
+   					local_port++;
+   					if(local_port > 50000)
+   						local_port = 35000;
+   				}
+   				ftpc.dsock_state = DATASOCK_START;
+   			}
+   			break;
+
+   		case SOCK_INIT :
+   			printf("%d:Opened\r\n",DATA_SOCK);
+   			if(ftpc.dsock_mode == ACTIVE_MODE){
+   				if( (ret = listen(DATA_SOCK)) != SOCK_OK){
+   					printf("%d:Listen error\r\n",DATA_SOCK);
+   					return ret;
+   				}
+   				gDataSockReady = 1;
+   				printf("%d:Listen ok\r\n",DATA_SOCK);
+   			}else{
+   				if((ret = connect(DATA_SOCK, remote_ip.cVal, remote_port)) != SOCK_OK){
+   					printf("%d:Connect error\r\n", DATA_SOCK);
+   					return ret;
+   				}
+   				gDataSockReady = 1;
+   			}
+   			connect_state_data_ftpc = 0;
+   			break;
+   		default :
+   			break;
+    }
+#endif
+    return 0;
+}
+
+char proc_ftpc(char * buf)
+{
+	uint16_t Responses;
+	uint8_t dat[30]={0,};
+
+	Responses =(buf[0]-'0')*100+(buf[1]-'0')*10+(buf[2]-'0');
+
+	switch(Responses){
+		case R_220:	/* Service ready for new user. */
+			printf("\r\nInput your User ID > ");
+			sprintf(dat,"USER %s\r\n", User_Keyboard_MSG());
+			printf("\r\n");
+			send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+			break;
+
+		case R_331:	/* User name okay, need password. */
+			printf("\r\nInput your Password > ");
+			sprintf(dat,"PASS %s\r\n", User_Keyboard_MSG());
+			printf("\r\n");
+			send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+			break;
+		case R_230:	/* User logged in, proceed */
+			printf("\r\nUser logged in, proceed\r\n");
+
+			sprintf(dat,"TYPE %c\r\n", TransferAscii);
+			ftpc.type = ASCII_TYPE;
+			send(CTRL_SOCK, (uint8_t *)dat, strlen(dat));
+			break;
+		case R_200:
+			if((ftpc.dsock_mode==ACTIVE_MODE)&&gModeActivePassiveflag){
+				ftpc.dsock_state = DATASOCK_READY;
+				gModeActivePassiveflag = 0;
+			}
+			else{
+				gMenuStart = 1;
+			}
+			break;
+		case R_150:
+			switch(Command.First){
+			case f_dir:
+				Command.First = f_nocmd;
+				Command.Second = s_dir;
+				gDataPutGetStart = 1;
+				break;
+			case f_get:
+				Command.First = f_nocmd;
+				Command.Second = s_get;
+				gDataPutGetStart = 1;
+				break;
+			case f_put:
+				Command.First = f_nocmd;
+				Command.Second = s_put;
+				gDataPutGetStart = 1;
+				break;
+			default :
+				printf("Command.First = default\r\n");
+				break;
+			}
+			break;
+		case R_226:
+			gMenuStart = 1;
+			break;
+		case R_227:
+			if (pportc(buf) == -1){
+				printf("Bad port syntax\r\n");
+			}
+			else{
+				printf("Go Open Data Sock...\r\n ");
+				ftpc.dsock_mode = PASSIVE_MODE;
+				ftpc.dsock_state = DATASOCK_READY;
+			}
+			break;
+		default:
+			printf("\r\nDefault Status = %d\r\n",(uint16_t)Responses);
+			gDataSockReady = 1;
+			break;
+		}
+	return 1;
+}
+int pportc(char * arg)
+{
+	int i;
+	char* tok=0;
+	strtok(arg,"(");
+	for (i = 0; i < 4; i++)
+	{
+		if(i==0) tok = strtok(NULL,",\r\n");
+		else	 tok = strtok(NULL,",");
+		remote_ip.cVal[i] = (uint8_t)atoi(tok);
+		if (!tok){
+			printf("bad pport : %s\r\n", arg);
+			return -1;
+		}
+	}
+	remote_port = 0;
+	for (i = 0; i < 2; i++){
+		tok = strtok(NULL,",\r\n");
+		remote_port <<= 8;
+		remote_port += atoi(tok);
+		if (!tok){
+			printf("bad pport : %s\r\n", arg);
+			return -1;
+		}
+	}
+	printf("ip : %d.%d.%d.%d, port : %d\r\n", remote_ip.cVal[0], remote_ip.cVal[1], remote_ip.cVal[2], remote_ip.cVal[3], remote_port);
+	return 0;
+}
+uint8_t* User_Keyboard_MSG()
+{
+	uint8_t i=0;
+	do{
+		gMsgBuf[i] = ftp_getc();
+		i++;
+	}while(gMsgBuf[i-1]!=0x0d);
+	gMsgBuf[i-1]=0;
+	return gMsgBuf;
+}

+ 130 - 0
lib/ioLibrary_Driver/Internet/FTPClient/ftpc.h

@@ -0,0 +1,130 @@
+#ifndef _FTPC_H_
+#define _FTPC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "socket.h"
+
+/* If you need this header, use it. */
+//#include "stdio_private.h"
+
+#define F_APP_FTPC
+
+/* If your target support a file system, you have to activate this feature and implement. */
+//#define F_FILESYSTEM
+
+/* Change to your Chipset Uart function, you have to activate this feature and implement.
+ * Change!! -> Board_UARTGetCharBlocking()
+ * Below is an example of a function of lpc_chip library. */
+//#define ftp_getc()	Board_UARTGetCharBlocking()
+
+#ifdef F_FILESYSTEM
+#include "ff.h"
+#endif
+
+#ifndef	ftp_getc()
+#define Need_UARTGetCharBlocking_func
+#else
+/* Change library
+ * Change!! -> board_api.h,
+ * Below is an example of a function of lpc_chip library. */
+#include "board_api.h"
+#endif
+
+
+#define LINELEN		100
+#ifndef F_FILESYSTEM
+#define _MAX_SS		512
+#endif
+
+#define CTRL_SOCK	2
+#define DATA_SOCK	3
+
+/* FTP Responses */
+#define R_150	150		/* File status ok; opening data conn */
+#define R_200	200		/* 'Generic' command ok */
+#define R_220	220		/* Service ready for new user. */
+#define R_226	226		/* Closing data connection.  File transfer/abort successful */
+#define R_227	227		/* Entering passive mode (h1,h2,h3,h4,p1,p2) */
+#define R_230	230		/* User logged in, proceed */
+#define R_331	331		/* User name okay, need password. */
+
+#define TransferAscii		'A'
+#define TransferBinary		'I'
+
+enum ftpc_type {
+	ASCII_TYPE,
+	IMAGE_TYPE,
+};
+
+enum ftpc_datasock_state{
+	DATASOCK_IDLE,
+	DATASOCK_READY,
+	DATASOCK_START
+};
+
+enum ftpc_datasock_mode{
+	PASSIVE_MODE,
+	ACTIVE_MODE
+};
+enum CommandFirst {
+	f_nocmd,
+	f_dir,
+	f_put,
+	f_get,
+};
+enum CommandSecond {
+	s_nocmd,
+	s_dir,
+	s_put,
+	s_get,
+};
+struct Command {
+	enum CommandFirst First;
+	enum CommandSecond Second;
+};
+struct ftpc {
+	uint8_t control;			/* Control stream */
+	uint8_t data;				/* Data stream */
+
+	enum ftpc_type type;		/* Transfer type */
+
+	enum ftpc_datasock_state dsock_state;
+	enum ftpc_datasock_mode dsock_mode;
+
+	char workingdir[LINELEN];
+	char filename[LINELEN];
+
+#ifdef F_FILESYSTEM
+	FIL fil;	// FatFs File objects
+	FRESULT fr;	// FatFs function common result code
+#endif
+};
+
+#ifndef un_I2cval
+typedef union _un_l2cval {
+	uint32_t	lVal;
+	uint8_t		cVal[4];
+}un_l2cval;
+#endif
+
+void ftpc_init(uint8_t * src_ip);
+uint8_t ftpc_run(uint8_t * dbuf);
+char proc_ftpc(char * buf);
+int pportc(char * arg);
+uint8_t* User_Keyboard_MSG();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _FTPC_H_

+ 75 - 0
lib/ioLibrary_Driver/Internet/FTPClient/stdio_private.h

@@ -0,0 +1,75 @@
+/* Copyright (c) 2002, Joerg Wunsch
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+   * Neither the name of the copyright holders nor the names of
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* $Id: stdio_private.h,v 1.6 2003/01/07 22:17:24 joerg_wunsch Exp $ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+
+struct __file {
+	char	*buf;		/* buffer pointer */
+	unsigned char unget;	/* ungetc() buffer */
+	uint8_t	flags;		/* flags, see below */
+#define __SRD	0x0001		/* OK to read */
+#define __SWR	0x0002		/* OK to write */
+#define __SSTR	0x0004		/* this is an sprintf/snprintf string */
+#define __SPGM	0x0008		/* fmt string is in progmem */
+#define __SERR	0x0010		/* found error */
+#define __SEOF	0x0020		/* found EOF */
+#define __SUNGET 0x040		/* ungetc() happened */
+#if 0
+/* possible future extensions, will require uint16_t flags */
+#define __SRW	0x0080		/* open for reading & writing */
+#define __SLBF	0x0100		/* line buffered */
+#define __SNBF	0x0200		/* unbuffered */
+#define __SMBF	0x0400		/* buf is from malloc */
+#endif
+	int	size;		/* size of buffer */
+	int	len;		/* characters read or written so far */
+	int	(*put)(char);	/* function to write one char to device */
+	int	(*get)(void);	/* function to read one char from device */
+};
+
+/* values for PRINTF_LEVEL */
+#define PRINTF_MIN 1
+#define PRINTF_STD 2
+#define PRINTF_FLT 3
+
+/* values for SCANF_LEVEL */
+#define SCANF_MIN 1
+#define SCANF_STD 2
+#define SCANF_FLT 3
+
+#ifdef __cplusplus
+}
+#endif

+ 983 - 0
lib/ioLibrary_Driver/Internet/FTPServer/ftpd.c

@@ -0,0 +1,983 @@
+/*
+* Wiznet.
+* (c) Copyright 2002, Wiznet.
+*
+* Filename	: ftpd.c
+* Version	: 1.0
+* Programmer(s)	: 
+* Created	: 2003/01/28
+* Description   : FTP daemon. (AVR-GCC Compiler)
+*/
+
+
+#include <stdio.h> 
+#include <ctype.h> 
+#include <string.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "socket.h"
+#include "ftpd.h"
+
+/* If you need this header, use it. */
+//#include "stdio_private.h"
+
+/* Command table */
+static char *commands[] = {
+	"user",
+	"acct",
+	"pass",
+	"type",
+	"list",
+	"cwd",
+	"dele",
+	"name",
+	"quit",
+	"retr",
+	"stor",
+	"port",
+	"nlst",
+	"pwd",
+	"xpwd",
+	"mkd",
+	"xmkd",
+	"xrmd",
+	"rmd ",
+	"stru",
+	"mode",
+	"syst",
+	"xmd5",
+	"xcwd",
+	"feat",
+	"pasv",
+	"size",
+	"mlsd",
+	"appe",
+	NULL
+};
+
+#if 0
+/* Response messages */
+char banner[] = "220 %s FTP version %s ready.\r\n";
+char badcmd[] = "500 Unknown command '%s'\r\n";
+char binwarn[] = "100 Warning: type is ASCII and %s appears to be binary\r\n";
+char unsupp[] = "500 Unsupported command or option\r\n";
+char givepass[] = "331 Enter PASS command\r\n";
+char logged[] = "230 Logged in\r\n";
+char typeok[] = "200 Type %s OK\r\n";
+char only8[] = "501 Only logical bytesize 8 supported\r\n";
+char deleok[] = "250 File deleted\r\n";
+char mkdok[] = "200 MKD ok\r\n";
+char delefail[] = "550 Delete failed: %s\r\n";
+char pwdmsg[] = "257 \"%s\" is current directory\r\n";
+char badtype[] = "501 Unknown type \"%s\"\r\n";
+char badport[] = "501 Bad port syntax\r\n";
+char unimp[] = "502 Command does not implemented yet.\r\n";
+char bye[] = "221 Goodbye!\r\n";
+char nodir[] = "553 Can't read directory \"%s\": %s\r\n";
+char cantopen[] = "550 Can't read file \"%s\": %s\r\n";
+char sending[] = "150 Opening data connection for %s (%d.%d.%d.%d,%d)\r\n";
+char cantmake[] = "553 Can't create \"%s\": %s\r\n";
+char writerr[] = "552 Write error: %s\r\n";
+char portok[] = "200 PORT command successful.\r\n";
+char rxok[] = "226 Transfer complete.\r\n";
+char txok[] = "226 Transfer complete.\r\n";
+char noperm[] = "550 Permission denied\r\n";
+char noconn[] = "425 Data connection reset\r\n";
+char lowmem[] = "421 System overloaded, try again later\r\n";
+char notlog[] = "530 Please log in with USER and PASS\r\n";
+char userfirst[] = "503 Login with USER first.\r\n";
+char okay[] = "200 Ok\r\n";
+char syst[] = "215 %s Type: L%d Version: %s\r\n";
+char sizefail[] = "550 File not found\r\n";
+#endif
+
+un_l2cval remote_ip;
+uint16_t  remote_port;
+un_l2cval local_ip;
+uint16_t  local_port;
+uint8_t connect_state_control = 0;
+uint8_t connect_state_data = 0;
+
+struct ftpd ftp;
+
+int current_year = 2014;
+int current_month = 12;
+int current_day = 31;
+int current_hour = 10;
+int current_min = 10;
+int current_sec = 30;
+
+int fsprintf(uint8_t s, const char *format, ...)
+{
+	int i;
+/*
+	char buf[LINELEN];
+	FILE f;
+	va_list ap;
+
+	f.flags = __SWR | __SSTR;
+	f.buf = buf;
+	f.size = INT_MAX;
+	va_start(ap, format);
+	i = vfprintf(&f, format, ap);
+	va_end(ap);
+	buf[f.len] = 0;
+
+	send(s, (uint8_t *)buf, strlen(buf));
+*/
+	return i;
+}
+
+void ftpd_init(uint8_t * src_ip)
+{
+	ftp.state = FTPS_NOT_LOGIN;
+	ftp.current_cmd = NO_CMD;
+	ftp.dsock_mode = ACTIVE_MODE;
+
+	local_ip.cVal[0] = src_ip[0];
+	local_ip.cVal[1] = src_ip[1];
+	local_ip.cVal[2] = src_ip[2];
+	local_ip.cVal[3] = src_ip[3];
+	local_port = 35000;
+	
+	strcpy(ftp.workingdir, "/");
+
+	socket(CTRL_SOCK, Sn_MR_TCP, IPPORT_FTP, 0x0);
+}
+
+uint8_t ftpd_run(uint8_t * dbuf)
+{
+	uint16_t size = 0, i;
+	long ret = 0;
+	uint32_t blocklen, send_byte, recv_byte;
+	uint32_t remain_filesize;
+	uint32_t remain_datasize;
+#if defined(F_FILESYSTEM)
+	//FILINFO fno;
+#endif
+
+	//memset(dbuf, 0, sizeof(_MAX_SS));
+	
+    switch(getSn_SR(CTRL_SOCK))
+    {
+    	case SOCK_ESTABLISHED :
+    		if(!connect_state_control)
+    		{
+#if defined(_FTP_DEBUG_)
+    			printf("%d:FTP Connected\r\n", CTRL_SOCK);
+#endif
+    			//fsprintf(CTRL_SOCK, banner, HOSTNAME, VERSION);
+    			strcpy(ftp.workingdir, "/");
+    			sprintf((char *)dbuf, "220 %s FTP version %s ready.\r\n", HOSTNAME, VERSION);
+    			ret = send(CTRL_SOCK, (uint8_t *)dbuf, strlen((const char *)dbuf));
+    			if(ret < 0)
+    			{
+#if defined(_FTP_DEBUG_)
+    				printf("%d:send() error:%ld\r\n",CTRL_SOCK,ret);
+#endif
+    				close(CTRL_SOCK);
+    				return ret;
+    			}
+    			connect_state_control = 1;
+    		}
+	
+#if defined(_FTP_DEBUG_)
+    		//printf("ftp socket %d\r\n", CTRL_SOCK);
+#endif
+			 
+    		if((size = getSn_RX_RSR(CTRL_SOCK)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
+    		{
+#if defined(_FTP_DEBUG_)
+    			printf("size: %d\r\n", size);
+#endif
+
+    			memset(dbuf, 0, _MAX_SS);
+
+    			if(size > _MAX_SS) size = _MAX_SS - 1;
+
+    			ret = recv(CTRL_SOCK,dbuf,size);
+    			dbuf[ret] = '\0';
+    			if(ret != size)
+    			{
+    				if(ret==SOCK_BUSY) return 0;
+    				if(ret < 0)
+    				{
+#if defined(_FTP_DEBUG_)
+    					printf("%d:recv() error:%ld\r\n",CTRL_SOCK,ret);
+#endif
+    					close(CTRL_SOCK);
+    					return ret;
+    				}
+    			}
+#if defined(_FTP_DEBUG_)
+    			printf("Rcvd Command: %s", dbuf);
+#endif
+    			proc_ftpd((char *)dbuf);
+    		}
+    		break;
+
+    	case SOCK_CLOSE_WAIT :
+#if defined(_FTP_DEBUG_)
+    		printf("%d:CloseWait\r\n",CTRL_SOCK);
+#endif
+    		if((ret=disconnect(CTRL_SOCK)) != SOCK_OK) return ret;
+#if defined(_FTP_DEBUG_)
+    		printf("%d:Closed\r\n",CTRL_SOCK);
+#endif
+    		break;
+
+    	case SOCK_CLOSED :
+#if defined(_FTP_DEBUG_)
+    		printf("%d:FTPStart\r\n",CTRL_SOCK);
+#endif
+    		if((ret=socket(CTRL_SOCK, Sn_MR_TCP, IPPORT_FTP, 0x0)) != CTRL_SOCK)
+    		{
+#if defined(_FTP_DEBUG_)
+    			printf("%d:socket() error:%ld\r\n", CTRL_SOCK, ret);
+#endif
+    			close(CTRL_SOCK);
+    			return ret;
+    		}
+    		break;
+
+    	case SOCK_INIT :
+#if defined(_FTP_DEBUG_)
+    		printf("%d:Opened\r\n",CTRL_SOCK);
+#endif
+    		//strcpy(ftp.workingdir, "/");
+    		if( (ret = listen(CTRL_SOCK)) != SOCK_OK)
+    		{
+#if defined(_FTP_DEBUG_)
+    			printf("%d:Listen error\r\n",CTRL_SOCK);
+#endif
+    			return ret;
+    		}
+			connect_state_control = 0;
+
+#if defined(_FTP_DEBUG_)
+			printf("%d:Listen ok\r\n",CTRL_SOCK);
+#endif
+			break;
+
+    	default :
+    		break;
+    }
+
+#if 1
+    switch(getSn_SR(DATA_SOCK))
+    {
+    	case SOCK_ESTABLISHED :
+    		if(!connect_state_data)
+    		{
+#if defined(_FTP_DEBUG_)
+    			printf("%d:FTP Data socket Connected\r\n", DATA_SOCK);
+#endif
+    			connect_state_data = 1;
+    		}
+	
+    		switch(ftp.current_cmd)
+    		{
+    			case LIST_CMD:
+    			case MLSD_CMD:
+#if defined(_FTP_DEBUG_)
+    				printf("previous size: %d\r\n", size);
+#endif
+#if defined(F_FILESYSTEM)
+    				scan_files(ftp.workingdir, dbuf, (int *)&size);
+#endif
+#if defined(_FTP_DEBUG_)
+    				printf("returned size: %d\r\n", size);
+    				printf("%s\r\n", dbuf);
+#endif
+#if !defined(F_FILESYSTEM)
+    				if (strncmp(ftp.workingdir, "/$Recycle.Bin", sizeof("/$Recycle.Bin")) != 0)
+    					size = sprintf(dbuf, "drwxr-xr-x 1 ftp ftp 0 Dec 31 2014 $Recycle.Bin\r\n-rwxr-xr-x 1 ftp ftp 512 Dec 31 2014 test.txt\r\n");
+#endif
+    				size = strlen(dbuf);
+    				send(DATA_SOCK, dbuf, size);
+    				ftp.current_cmd = NO_CMD;
+    				disconnect(DATA_SOCK);
+    				size = sprintf(dbuf, "226 Successfully transferred \"%s\"\r\n", ftp.workingdir);
+    				send(CTRL_SOCK, dbuf, size);
+    				break;
+
+    			case RETR_CMD:
+#if defined(_FTP_DEBUG_)
+    				printf("filename to retrieve : %s %d\r\n", ftp.filename, strlen(ftp.filename));
+#endif
+#if defined(F_FILESYSTEM)
+    				ftp.fr = f_open(&(ftp.fil), (const char *)ftp.filename, FA_READ);
+    				//print_filedsc(&(ftp.fil));
+    				if(ftp.fr == FR_OK){
+    					remain_filesize = ftp.fil.fsize;
+#if defined(_FTP_DEBUG_)
+    					printf("f_open return FR_OK\r\n");
+#endif
+    					do{
+#if defined(_FTP_DEBUG_)
+    						//printf("remained file size: %d\r\n", ftp.fil.fsize);
+#endif
+    						memset(dbuf, 0, _MAX_SS);
+
+    						if(remain_filesize > _MAX_SS)
+    							send_byte = _MAX_SS;
+    						else
+    							send_byte = remain_filesize;
+
+    						ftp.fr = f_read(&(ftp.fil), dbuf, send_byte , &blocklen);
+    						if(ftp.fr != FR_OK)
+    							break;
+#if defined(_FTP_DEBUG_)
+    						printf("#");
+    						//printf("----->fsize:%d recv:%d len:%d \r\n", remain_filesize, send_byte, blocklen);
+    						//printf("----->fn:%s data:%s \r\n", ftp.filename, dbuf);
+#endif
+    						send(DATA_SOCK, dbuf, blocklen);
+    						remain_filesize -= blocklen;
+    					}while(remain_filesize != 0);
+#if defined(_FTP_DEBUG_)
+    					printf("\r\nFile read finished\r\n");
+#endif
+    					ftp.fr = f_close(&(ftp.fil));
+    				}else{
+#if defined(_FTP_DEBUG_)
+    					printf("File Open Error: %d\r\n", ftp.fr);
+#endif
+    				}
+#else
+					remain_filesize = strlen(ftp.filename);
+
+					do{
+						memset(dbuf, 0, _MAX_SS);
+
+						blocklen = sprintf(dbuf, "%s", ftp.filename);
+
+						printf("########## dbuf:%s\r\n", dbuf);
+
+						send(DATA_SOCK, dbuf, blocklen);
+						remain_filesize -= blocklen;
+					}while(remain_filesize != 0);
+
+#endif
+    				ftp.current_cmd = NO_CMD;
+    				disconnect(DATA_SOCK);
+    				size = sprintf(dbuf, "226 Successfully transferred \"%s\"\r\n", ftp.filename);
+    				send(CTRL_SOCK, dbuf, size);
+    				break;
+
+    			case STOR_CMD:
+#if defined(_FTP_DEBUG_)
+    				printf("filename to store : %s %d\r\n", ftp.filename, strlen(ftp.filename));
+#endif
+#if defined(F_FILESYSTEM)
+    				ftp.fr = f_open(&(ftp.fil), (const char *)ftp.filename, FA_CREATE_ALWAYS | FA_WRITE);
+    				//print_filedsc(&(ftp.fil));
+    				if(ftp.fr == FR_OK){
+#if defined(_FTP_DEBUG_)
+    					printf("f_open return FR_OK\r\n");
+#endif
+    					while(1){
+    						if((remain_datasize = getSn_RX_RSR(DATA_SOCK)) > 0){
+    							while(1){
+    								memset(dbuf, 0, _MAX_SS);
+
+    								if(remain_datasize > _MAX_SS)
+    									recv_byte = _MAX_SS;
+    								else
+    									recv_byte = remain_datasize;
+
+    								ret = recv(DATA_SOCK, dbuf, recv_byte);
+#if defined(_FTP_DEBUG_)
+    								//printf("----->fn:%s data:%s \r\n", ftp.filename, dbuf);
+#endif
+
+    								ftp.fr = f_write(&(ftp.fil), dbuf, (UINT)ret, &blocklen);
+#if defined(_FTP_DEBUG_)
+    								//printf("----->dsize:%d recv:%d len:%d \r\n", remain_datasize, ret, blocklen);
+#endif
+    								remain_datasize -= blocklen;
+
+    								if(ftp.fr != FR_OK){
+#if defined(_FTP_DEBUG_)
+    									printf("f_write failed\r\n");
+#endif
+    									break;
+    								}
+
+    								if(remain_datasize <= 0)
+    									break;
+    							}
+
+    							if(ftp.fr != FR_OK){
+#if defined(_FTP_DEBUG_)
+    								printf("f_write failed\r\n");
+#endif
+    								break;
+    							}
+
+#if defined(_FTP_DEBUG_)
+    							printf("#");
+#endif
+    						}else{
+    							if(getSn_SR(DATA_SOCK) != SOCK_ESTABLISHED)
+    								break;
+    						}
+    					}
+#if defined(_FTP_DEBUG_)
+    					printf("\r\nFile write finished\r\n");
+#endif
+    					ftp.fr = f_close(&(ftp.fil));
+    				}else{
+#if defined(_FTP_DEBUG_)
+    					printf("File Open Error: %d\r\n", ftp.fr);
+#endif
+    				}
+
+    				//fno.fdate = (WORD)(((current_year - 1980) << 9) | (current_month << 5) | current_day);
+    				//fno.ftime = (WORD)((current_hour << 11) | (current_min << 5) | (current_sec >> 1));
+    				//f_utime((const char *)ftp.filename, &fno);
+#else
+					while(1){
+						if((remain_datasize = getSn_RX_RSR(DATA_SOCK)) > 0){
+							while(1){
+								memset(dbuf, 0, _MAX_SS);
+
+								if(remain_datasize > _MAX_SS)
+									recv_byte = _MAX_SS;
+								else
+									recv_byte = remain_datasize;
+
+								ret = recv(DATA_SOCK, dbuf, recv_byte);
+
+								printf("########## dbuf:%s\r\n", dbuf);
+
+								remain_datasize -= ret;
+
+								if(remain_datasize <= 0)
+									break;
+							}
+						}else{
+							if(getSn_SR(DATA_SOCK) != SOCK_ESTABLISHED)
+								break;
+						}
+					}
+#endif
+    				ftp.current_cmd = NO_CMD;
+    				disconnect(DATA_SOCK);
+    				size = sprintf(dbuf, "226 Successfully transferred \"%s\"\r\n", ftp.filename);
+    				send(CTRL_SOCK, dbuf, size);
+    				break;
+
+    			case NO_CMD:
+    			default:
+    				break;
+    		}
+    		break;
+
+   		case SOCK_CLOSE_WAIT :
+#if defined(_FTP_DEBUG_)
+   			printf("%d:CloseWait\r\n",DATA_SOCK);
+#endif
+   			if((ret=disconnect(DATA_SOCK)) != SOCK_OK) return ret;
+#if defined(_FTP_DEBUG_)
+   			printf("%d:Closed\r\n",DATA_SOCK);
+#endif
+   			break;
+
+   		case SOCK_CLOSED :
+   			if(ftp.dsock_state == DATASOCK_READY)
+   			{
+   				if(ftp.dsock_mode == PASSIVE_MODE){
+#if defined(_FTP_DEBUG_)
+   					printf("%d:FTPDataStart, port : %d\r\n",DATA_SOCK, local_port);
+#endif
+   					if((ret=socket(DATA_SOCK, Sn_MR_TCP, local_port, 0x0)) != DATA_SOCK)
+   					{
+#if defined(_FTP_DEBUG_)
+   						printf("%d:socket() error:%ld\r\n", DATA_SOCK, ret);
+#endif
+   						close(DATA_SOCK);
+   						return ret;
+   					}
+
+   					local_port++;
+   					if(local_port > 50000)
+   						local_port = 35000;
+   				}else{
+#if defined(_FTP_DEBUG_)
+   					printf("%d:FTPDataStart, port : %d\r\n",DATA_SOCK, IPPORT_FTPD);
+#endif
+   					if((ret=socket(DATA_SOCK, Sn_MR_TCP, IPPORT_FTPD, 0x0)) != DATA_SOCK)
+   					{
+#if defined(_FTP_DEBUG_)
+   						printf("%d:socket() error:%ld\r\n", DATA_SOCK, ret);
+#endif
+   						close(DATA_SOCK);
+   						return ret;
+   					}
+   				}
+
+   				ftp.dsock_state = DATASOCK_START;
+   			}
+   			break;
+
+   		case SOCK_INIT :
+#if defined(_FTP_DEBUG_)
+   			printf("%d:Opened\r\n",DATA_SOCK);
+#endif
+   			if(ftp.dsock_mode == PASSIVE_MODE){
+   				if( (ret = listen(DATA_SOCK)) != SOCK_OK)
+   				{
+#if defined(_FTP_DEBUG_)
+   					printf("%d:Listen error\r\n",DATA_SOCK);
+#endif
+   					return ret;
+   				}
+
+#if defined(_FTP_DEBUG_)
+   				printf("%d:Listen ok\r\n",DATA_SOCK);
+#endif
+   			}else{
+   				if((ret = connect(DATA_SOCK, remote_ip.cVal, remote_port)) != SOCK_OK){
+#if defined(_FTP_DEBUG_)
+   					printf("%d:Connect error\r\n", DATA_SOCK);
+#endif
+   					return ret;
+   				}
+   			}
+   			connect_state_data = 0;
+   			break;
+
+   		default :
+   			break;
+    }
+#endif
+
+    return 0;
+}
+
+char proc_ftpd(char * buf)
+{
+	char **cmdp, *cp, *arg, *tmpstr;
+	char sendbuf[200];
+	int slen;
+	long ret;
+	
+
+	/* Translate first word to lower case */
+	for (cp = buf; *cp != ' ' && *cp != '\0'; cp++)
+		*cp = tolower(*cp);
+
+	/* Find command in table; if not present, return syntax error */
+	for (cmdp = commands; *cmdp != NULL; cmdp++)
+		if (strncmp(*cmdp, buf, strlen(*cmdp)) == 0)
+			break;
+
+	if (*cmdp == NULL)
+	{
+		//fsprintf(CTRL_SOCK, badcmd, buf);
+		slen = sprintf(sendbuf, "500 Unknown command '%s'\r\n", buf);
+		send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+		return 0;
+	}
+	/* Allow only USER, PASS and QUIT before logging in */
+	if (ftp.state == FTPS_NOT_LOGIN)
+	{
+		switch(cmdp - commands)
+		{
+			case USER_CMD:
+			case PASS_CMD:
+			case QUIT_CMD:
+				break;
+			default:
+				//fsprintf(CTRL_SOCK, notlog);
+				slen = sprintf(sendbuf, "530 Please log in with USER and PASS\r\n");
+				send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+				return 0;
+		}
+	}
+	
+	arg = &buf[strlen(*cmdp)];
+	while(*arg == ' ') arg++;
+
+	/* Execute specific command */
+	switch (cmdp - commands)
+	{
+		case USER_CMD :
+#if defined(_FTP_DEBUG_)
+			printf("USER_CMD : %s", arg);
+#endif
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+			strcpy(ftp.username, arg);
+			//fsprintf(CTRL_SOCK, givepass);
+			slen = sprintf(sendbuf, "331 Enter PASS command\r\n");
+			ret = send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			if(ret < 0)
+			{
+#if defined(_FTP_DEBUG_)
+				printf("%d:send() error:%ld\r\n",CTRL_SOCK,ret);
+#endif
+				close(CTRL_SOCK);
+				return ret;
+			}
+			break;
+
+		case PASS_CMD :
+#if defined(_FTP_DEBUG_)
+			printf("PASS_CMD : %s", arg);
+#endif
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+			ftplogin(arg);
+			break;
+
+		case TYPE_CMD :
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+			switch(arg[0])
+			{
+				case 'A':
+				case 'a':	/* Ascii */
+					ftp.type = ASCII_TYPE;
+					//fsprintf(CTRL_SOCK, typeok, arg);
+					slen = sprintf(sendbuf, "200 Type set to %s\r\n", arg);
+					send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+					break;
+
+				case 'B':
+				case 'b':	/* Binary */
+				case 'I':
+				case 'i':	/* Image */
+					ftp.type = IMAGE_TYPE;
+					//fsprintf(CTRL_SOCK, typeok, arg);
+					slen = sprintf(sendbuf, "200 Type set to %s\r\n", arg);
+					send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+					break;
+
+				default:	/* Invalid */
+					//fsprintf(CTRL_SOCK, badtype, arg);
+					slen = sprintf(sendbuf, "501 Unknown type \"%s\"\r\n", arg);
+					send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+					break;
+			}
+			break;
+
+		case FEAT_CMD :
+			slen = sprintf(sendbuf, "211-Features:\r\n MDTM\r\n REST STREAM\r\n SIZE\r\n MLST size*;type*;create*;modify*;\r\n MLSD\r\n UTF8\r\n CLNT\r\n MFMT\r\n211 END\r\n");
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		case QUIT_CMD :
+#if defined(_FTP_DEBUG_)
+			printf("QUIT_CMD\r\n");
+#endif
+			//fsprintf(CTRL_SOCK, bye);
+			slen = sprintf(sendbuf, "221 Goodbye!\r\n");
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			disconnect(CTRL_SOCK);
+			break;
+
+		case RETR_CMD :
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+#if defined(_FTP_DEBUG_)
+			printf("RETR_CMD\r\n");
+#endif
+			if(strlen(ftp.workingdir) == 1)
+				sprintf(ftp.filename, "/%s", arg);
+			else
+				sprintf(ftp.filename, "%s/%s", ftp.workingdir, arg);
+			slen = sprintf(sendbuf, "150 Opening data channel for file downloand from server of \"%s\"\r\n", ftp.filename);
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			ftp.current_cmd = RETR_CMD;
+			break;
+
+		case APPE_CMD :
+		case STOR_CMD:
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+#if defined(_FTP_DEBUG_)
+			printf("STOR_CMD\r\n");
+#endif
+			if(strlen(ftp.workingdir) == 1)
+				sprintf(ftp.filename, "/%s", arg);
+			else
+				sprintf(ftp.filename, "%s/%s", ftp.workingdir, arg);
+			slen = sprintf(sendbuf, "150 Opening data channel for file upload to server of \"%s\"\r\n", ftp.filename);
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			ftp.current_cmd = STOR_CMD;
+			if((ret = connect(DATA_SOCK, remote_ip.cVal, remote_port)) != SOCK_OK){
+#if defined(_FTP_DEBUG_)
+				printf("%d:Connect error\r\n", DATA_SOCK);
+#endif
+				return ret;
+			}
+   			connect_state_data = 0;
+			break;
+
+		case PORT_CMD:
+#if defined(_FTP_DEBUG_)
+			printf("PORT_CMD\r\n");
+#endif
+			if (pport(arg) == -1){
+				//fsprintf(CTRL_SOCK, badport);
+				slen = sprintf(sendbuf, "501 Bad port syntax\r\n");
+				send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			} else{
+				//fsprintf(CTRL_SOCK, portok);
+				ftp.dsock_mode = ACTIVE_MODE;
+				ftp.dsock_state = DATASOCK_READY;
+				slen = sprintf(sendbuf, "200 PORT command successful.\r\n");
+				send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			}
+			break;
+
+		case MLSD_CMD:
+#if defined(_FTP_DEBUG_)
+			printf("MLSD_CMD\r\n");
+#endif
+			slen = sprintf(sendbuf, "150 Opening data channel for directory listing of \"%s\"\r\n", ftp.workingdir);
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			ftp.current_cmd = MLSD_CMD;
+			break;
+
+		case LIST_CMD:
+#if defined(_FTP_DEBUG_)
+			printf("LIST_CMD\r\n");
+#endif
+			slen = sprintf(sendbuf, "150 Opening data channel for directory listing of \"%s\"\r\n", ftp.workingdir);
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			ftp.current_cmd = LIST_CMD;
+			break;
+
+		case NLST_CMD:
+#if defined(_FTP_DEBUG_)
+			printf("NLST_CMD\r\n");
+#endif
+			break;
+
+		case SYST_CMD:
+			slen = sprintf(sendbuf, "215 UNIX emulated by WIZnet\r\n");
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		case PWD_CMD:
+		case XPWD_CMD:
+			slen = sprintf(sendbuf, "257 \"%s\" is current directory.\r\n", ftp.workingdir);
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		case PASV_CMD:
+			slen = sprintf(sendbuf, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n", local_ip.cVal[0], local_ip.cVal[1], local_ip.cVal[2], local_ip.cVal[3], local_port >> 8, local_port & 0x00ff);
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			disconnect(DATA_SOCK);
+			ftp.dsock_mode = PASSIVE_MODE;
+			ftp.dsock_state = DATASOCK_READY;
+#if defined(_FTP_DEBUG_)
+			printf("PASV port: %d\r\n", local_port);
+#endif
+		break;
+
+		case SIZE_CMD:
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+			if(slen > 3)
+			{
+				tmpstr = strrchr(arg, '/');
+				*tmpstr = 0;
+#if defined(F_FILESYSTEM)
+				slen = get_filesize(arg, tmpstr + 1);
+#else
+				slen = _MAX_SS;
+#endif
+				if(slen > 0)
+					slen = sprintf(sendbuf, "213 %d\r\n", slen);
+				else
+					slen = sprintf(sendbuf, "550 File not Found\r\n");
+			}
+			else
+			{
+				slen = sprintf(sendbuf, "550 File not Found\r\n");
+			}
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		case CWD_CMD:
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+			if(slen > 3)
+			{
+				arg[slen - 3] = 0x00;
+				tmpstr = strrchr(arg, '/');
+				*tmpstr = 0;
+#if defined(F_FILESYSTEM)
+				slen = get_filesize(arg, tmpstr + 1);
+#else
+				slen = 0;
+#endif
+				*tmpstr = '/';
+				if(slen == 0){
+					slen = sprintf(sendbuf, "213 %d\r\n", slen);
+					strcpy(ftp.workingdir, arg);
+					slen = sprintf(sendbuf, "250 CWD successful. \"%s\" is current directory.\r\n", ftp.workingdir);
+				}
+				else
+				{
+					slen = sprintf(sendbuf, "550 CWD failed. \"%s\"\r\n", arg);
+				}
+			}
+			else
+			{
+				strcpy(ftp.workingdir, arg);
+				slen = sprintf(sendbuf, "250 CWD successful. \"%s\" is current directory.\r\n", ftp.workingdir);
+			}
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		case MKD_CMD:
+		case XMKD_CMD:
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+#if defined(F_FILESYSTEM)
+			if (f_mkdir(arg) != 0)
+			{
+				slen = sprintf(sendbuf, "550 Can't create directory. \"%s\"\r\n", arg);
+			}
+			else
+			{
+				slen = sprintf(sendbuf, "257 MKD command successful. \"%s\"\r\n", arg);
+				//strcpy(ftp.workingdir, arg);
+			}
+#else
+			slen = sprintf(sendbuf, "550 Can't create directory. Permission denied\r\n");
+#endif
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		case DELE_CMD:
+			slen = strlen(arg);
+			arg[slen - 1] = 0x00;
+			arg[slen - 2] = 0x00;
+#if defined(F_FILESYSTEM)
+			if (f_unlink(arg) != 0)
+			{
+				slen = sprintf(sendbuf, "550 Could not delete. \"%s\"\r\n", arg);
+			}
+			else
+			{
+				slen = sprintf(sendbuf, "250 Deleted. \"%s\"\r\n", arg);
+			}
+#else
+			slen = sprintf(sendbuf, "550 Could not delete. Permission denied\r\n");
+#endif
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		case XCWD_CMD:
+		case ACCT_CMD:
+		case XRMD_CMD:
+		case RMD_CMD:
+		case STRU_CMD:
+		case MODE_CMD:
+		case XMD5_CMD:
+			//fsprintf(CTRL_SOCK, unimp);
+			slen = sprintf(sendbuf, "502 Command does not implemented yet.\r\n");
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+
+		default:	/* Invalid */
+			//fsprintf(CTRL_SOCK, badcmd, arg);
+			slen = sprintf(sendbuf, "500 Unknown command \'%s\'\r\n", arg);
+			send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+			break;
+	}
+	
+	return 1;
+}
+
+
+char ftplogin(char * pass)
+{
+	char sendbuf[100];
+	int slen = 0;
+	
+	//memset(sendbuf, 0, DATA_BUF_SIZE);
+	
+#if defined(_FTP_DEBUG_)
+	printf("%s logged in\r\n", ftp.username);
+#endif
+	//fsprintf(CTRL_SOCK, logged);
+	slen = sprintf(sendbuf, "230 Logged on\r\n");
+	send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
+	ftp.state = FTPS_LOGIN;
+	
+	return 1;
+}
+
+int pport(char * arg)
+{
+	int i;
+	char* tok=0;
+
+	for (i = 0; i < 4; i++)
+	{
+		if(i==0) tok = strtok(arg,",\r\n");
+		else	 tok = strtok(NULL,",");
+		remote_ip.cVal[i] = (uint8_t)atoi(tok);
+		if (!tok)
+		{
+#if defined(_FTP_DEBUG_)
+			printf("bad pport : %s\r\n", arg);
+#endif
+			return -1;
+		}
+	}
+	remote_port = 0;
+	for (i = 0; i < 2; i++)
+	{
+		tok = strtok(NULL,",\r\n");
+		remote_port <<= 8;
+		remote_port += atoi(tok);
+		if (!tok)
+		{
+#if defined(_FTP_DEBUG_)
+			printf("bad pport : %s\r\n", arg);
+#endif
+			return -1;
+		}
+	}
+#if defined(_FTP_DEBUG_)
+	printf("ip : %d.%d.%d.%d, port : %d\r\n", remote_ip.cVal[0], remote_ip.cVal[1], remote_ip.cVal[2], remote_ip.cVal[3], remote_port);
+#endif
+
+	return 0;
+}
+
+#if defined(F_FILESYSTEM)
+void print_filedsc(FIL *fil)
+{
+#if defined(_FTP_DEBUG_)
+	printf("File System pointer : %08X\r\n", fil->fs);
+	printf("File System mount ID : %d\r\n", fil->id);
+	printf("File status flag : %08X\r\n", fil->flag);
+	printf("File System pads : %08X\r\n", fil->err);
+	printf("File read write pointer : %08X\r\n", fil->fptr);
+	printf("File size : %08X\r\n", fil->fsize);
+	printf("File start cluster : %08X\r\n", fil->sclust);
+	printf("current cluster : %08X\r\n", fil->clust);
+	printf("current data sector : %08X\r\n", fil->dsect);
+	printf("dir entry sector : %08X\r\n", fil->dir_sect);
+	printf("dir entry pointer : %08X\r\n", fil->dir_ptr);
+#endif
+}
+#endif

+ 154 - 0
lib/ioLibrary_Driver/Internet/FTPServer/ftpd.h

@@ -0,0 +1,154 @@
+#ifndef _FTPD_H_
+#define _FTPD_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+* Wiznet.
+* (c) Copyright 2002, Wiznet.
+*
+* Filename	: ftpd.h
+* Version	: 1.0
+* Programmer(s)	: 
+* Created	: 2003/01/28
+* Description   : Header file of FTP daemon. (AVR-GCC Compiler)
+*/
+
+#include <stdint.h>
+
+//#define F_FILESYSTEM // If your target support a file system, you have to activate this feature and implement.
+
+#if defined(F_FILESYSTEM)
+#include "ff.h"
+#endif
+
+#define F_APP_FTP
+#define _FTP_DEBUG_
+
+
+#define LINELEN		100
+//#define DATA_BUF_SIZE	100
+#if !defined(F_FILESYSTEM)
+#define _MAX_SS		512
+#endif
+
+#define CTRL_SOCK	2
+#define DATA_SOCK	3
+
+#define	IPPORT_FTPD	20	/* FTP Data port */
+#define	IPPORT_FTP	21	/* FTP Control port */
+
+#define HOSTNAME	"iinChip"
+#define VERSION		"1.0"
+
+#define FILENAME	"a.txt"
+
+/* FTP commands */
+enum ftp_cmd {
+	USER_CMD,
+	ACCT_CMD,
+	PASS_CMD,
+	TYPE_CMD,
+	LIST_CMD,
+	CWD_CMD,
+	DELE_CMD,
+	NAME_CMD,
+	QUIT_CMD,
+	RETR_CMD,
+	STOR_CMD,
+	PORT_CMD,
+	NLST_CMD,
+	PWD_CMD,
+	XPWD_CMD,
+	MKD_CMD,
+	XMKD_CMD,
+	XRMD_CMD,
+	RMD_CMD,
+	STRU_CMD,
+	MODE_CMD,
+	SYST_CMD,
+	XMD5_CMD,
+	XCWD_CMD,
+	FEAT_CMD,
+	PASV_CMD,
+	SIZE_CMD,
+	MLSD_CMD,
+	APPE_CMD,
+	NO_CMD,
+};
+
+enum ftp_type {
+	ASCII_TYPE,
+	IMAGE_TYPE,
+	LOGICAL_TYPE
+};
+
+enum ftp_state {
+	FTPS_NOT_LOGIN,
+	FTPS_LOGIN
+};
+
+enum datasock_state{
+	DATASOCK_IDLE,
+	DATASOCK_READY,
+	DATASOCK_START
+};
+
+enum datasock_mode{
+	PASSIVE_MODE,
+	ACTIVE_MODE
+};
+
+struct ftpd {
+	uint8_t control;			/* Control stream */
+	uint8_t data;			/* Data stream */
+
+	enum ftp_type type;		/* Transfer type */
+	enum ftp_state state;
+
+	enum ftp_cmd current_cmd;
+
+	enum datasock_state dsock_state;
+	enum datasock_mode dsock_mode;
+
+	char username[LINELEN];		/* Arg to USER command */
+	char workingdir[LINELEN];
+	char filename[LINELEN];
+
+#if defined(F_FILESYSTEM)
+	FIL fil;	// FatFs File objects
+	FRESULT fr;	// FatFs function common result code
+#endif
+
+};
+
+#ifndef un_I2cval
+typedef union _un_l2cval {
+	uint32_t	lVal;
+	uint8_t		cVal[4];
+}un_l2cval;
+#endif
+
+void ftpd_init(uint8_t * src_ip);
+uint8_t ftpd_run(uint8_t * dbuf);
+char proc_ftpd(char * buf);
+char ftplogin(char * pass);
+int pport(char * arg);
+
+int sendit(char * command);
+int recvit(char * command);
+
+long sendfile(uint8_t s, char * command);
+long recvfile(uint8_t s);
+
+#if defined(F_FILESYSTEM)
+void print_filedsc(FIL *fil);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _FTPD_H_

+ 74 - 0
lib/ioLibrary_Driver/Internet/FTPServer/stdio_private.h

@@ -0,0 +1,74 @@
+/* Copyright (c) 2002, Joerg Wunsch
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+   * Neither the name of the copyright holders nor the names of
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* $Id: stdio_private.h,v 1.6 2003/01/07 22:17:24 joerg_wunsch Exp $ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+
+struct __file {
+	char	*buf;		/* buffer pointer */
+	unsigned char unget;	/* ungetc() buffer */
+	uint8_t	flags;		/* flags, see below */
+#define __SRD	0x0001		/* OK to read */
+#define __SWR	0x0002		/* OK to write */
+#define __SSTR	0x0004		/* this is an sprintf/snprintf string */
+#define __SPGM	0x0008		/* fmt string is in progmem */
+#define __SERR	0x0010		/* found error */
+#define __SEOF	0x0020		/* found EOF */
+#define __SUNGET 0x040		/* ungetc() happened */
+#if 0
+/* possible future extensions, will require uint16_t flags */
+#define __SRW	0x0080		/* open for reading & writing */
+#define __SLBF	0x0100		/* line buffered */
+#define __SNBF	0x0200		/* unbuffered */
+#define __SMBF	0x0400		/* buf is from malloc */
+#endif
+	int	size;		/* size of buffer */
+	int	len;		/* characters read or written so far */
+	int	(*put)(char);	/* function to write one char to device */
+	int	(*get)(void);	/* function to read one char from device */
+};
+
+/* values for PRINTF_LEVEL */
+#define PRINTF_MIN 1
+#define PRINTF_STD 2
+#define PRINTF_FLT 3
+
+/* values for SCANF_LEVEL */
+#define SCANF_MIN 1
+#define SCANF_STD 2
+#define SCANF_FLT 3
+
+#ifdef __cplusplus
+}
+#endif

+ 298 - 0
lib/ioLibrary_Driver/Internet/ICMP/ping.c

@@ -0,0 +1,298 @@
+#include "ping.h"
+#include "socket.h"
+#include "w5500.h"
+
+PINGMSGR PingRequest; // Variable for Ping Request
+PINGMSGR PingReply; // Variable for Ping Reply
+static uint16_t RandomID = 0x1234;
+static uint16_t RandomSeqNum = 0x4321;
+uint8_t ping_reply_received = 0;
+uint8_t req = 0;
+uint8_t rep = 0;
+
+extern void ping_wait_ms(int ms);
+
+uint8_t ping_auto(uint8_t s, uint8_t* addr) {
+    uint8_t i;
+    int32_t len = 0;
+    uint8_t cnt = 0;
+    int ret = 0;
+    rep = req = 0;
+    for(i = 0; i <= 3; i++) {
+        uint8_t sr = getSn_SR(s);
+        eth_printf("SR: %02X", sr);
+        switch(sr) {
+        case SOCK_CLOSED:
+            close(s);
+            IINCHIP_WRITE(Sn_PROTO(s), IPPROTO_ICMP); // set ICMP Protocol
+            if((ret = socket(s, Sn_MR_IPRAW, 3000, 0)) !=
+               s) { // open the SOCKET with IPRAW mode, if fail then Error
+                eth_printf("  socket %d fail %d", s, ret);
+#ifdef PING_DEBUG
+                return SOCKET_ERROR;
+#endif
+            }
+            /* Check socket register */
+            while(getSn_SR(s) != SOCK_IPRAW)
+                ;
+            ping_wait_ms(1000); // wait 1000ms
+            ping_wait_ms(1000); // wait 1000ms
+            break;
+        case SOCK_IPRAW:
+            ping_request(s, addr);
+            req++;
+            while(1) {
+                if((len = getSn_RX_RSR(s)) > 0) {
+                    ping_reply(s, addr, len);
+                    rep++;
+                    break;
+                } else if(cnt > 100) {
+                    eth_printf("Request Time out.");
+                    cnt = 0;
+                    break;
+                } else {
+                    cnt++;
+                    ping_wait_ms(50); // wait 50ms
+                }
+                // wait_time for 2 seconds, Break on fail
+            }
+            break;
+        default:
+            break;
+        }
+#ifdef PING_DEBUG
+        if(req >= 3) {
+            eth_printf("Ping Request = %d, PING_Reply = %d", req, rep);
+
+            if(rep == req)
+                return PING_SUCCESS;
+            else
+                return REPLY_ERROR;
+        }
+#endif
+    }
+    return FUNCTION_ERROR;
+}
+
+uint8_t ping_count(uint8_t s, uint16_t pCount, uint8_t* addr) {
+    uint16_t rlen, cnt, i;
+    cnt = 0;
+
+    for(i = 0; i < pCount + 1; i++) {
+        if(i != 0) {
+            /* Output count number */
+            eth_printf("No.%d", (i - 1));
+        }
+
+        uint8_t sr = getSn_SR(s);
+        eth_printf("SR: %d", sr);
+        switch(sr) {
+        case SOCK_CLOSED:
+            close(s);
+            // close the SOCKET
+            /* Create Socket */
+            IINCHIP_WRITE(Sn_PROTO(s), IPPROTO_ICMP); // set ICMP Protocol
+            if(socket(s, Sn_MR_IPRAW, 3000, 0) !=
+               s) { // open the SOCKET with IPRAW mode, if fail then Error
+                eth_printf(" socket %d fail ", (s));
+#ifdef PING_DEBUG
+                return SOCKET_ERROR;
+#endif
+            }
+            /* Check socket register */
+            while(getSn_SR(s) != SOCK_IPRAW)
+                ;
+            ping_wait_ms(1000);
+            break;
+        case SOCK_IPRAW:
+            ping_request(s, addr);
+            req++;
+            while(1) {
+                if((rlen = getSn_RX_RSR(s)) > 0) {
+                    ping_reply(s, addr, rlen);
+                    rep++;
+                    if(ping_reply_received) break;
+                }
+                /* wait_time for 2 seconds, Break on fail*/
+                if((cnt > 100)) {
+                    eth_printf("Request Time out.");
+                    cnt = 0;
+                    break;
+                } else {
+                    cnt++;
+                    ping_wait_ms(20);
+                }
+            }
+            break;
+        default:
+            break;
+        }
+#ifdef PING_DEBUG
+        if(req >= pCount) {
+            eth_printf("Ping Request = %d, PING_Reply = %d", req, rep);
+            if(rep == req)
+                return PING_SUCCESS;
+            else
+                return REPLY_ERROR;
+        }
+#endif
+    }
+    return FUNCTION_ERROR;
+}
+
+uint8_t ping_request(uint8_t s, uint8_t* addr) {
+    uint16_t i;
+
+    //Initailize flag for ping reply
+    ping_reply_received = 0;
+    /* make header of the ping-request  */
+    PingRequest.Type = PING_REQUEST; // Ping-Request
+    PingRequest.Code = CODE_ZERO; // Always '0'
+    PingRequest.ID = htons(RandomID++); // set ping-request's ID to random integer value
+    PingRequest.SeqNum =
+        htons(RandomSeqNum++); // set ping-request's sequence number to ramdom integer value
+    //size = 32;                                 // set Data size
+
+    /* Fill in Data[]  as size of BIF_LEN (Default = 32)*/
+    for(i = 0; i < BUF_LEN; i++) {
+        PingRequest.Data[i] = (i) % 8; //'0'~'8' number into ping-request's data
+    }
+    /* Do checksum of Ping Request */
+    PingRequest.CheckSum =
+        0; // value of checksum before calucating checksum of ping-request packet
+    PingRequest.CheckSum =
+        htons(checksum((uint8_t*)&PingRequest, sizeof(PingRequest))); // Calculate checksum
+
+    /* sendto ping_request to destination */
+    if(sendto(s, (uint8_t*)&PingRequest, sizeof(PingRequest), addr, 3000) ==
+       0) { // Send Ping-Request to the specified peer.
+        eth_printf(" Fail to send ping-reply packet ");
+    } else {
+        eth_printf(
+            "Send Ping Request  to Destination (%d.%d.%d.%d )",
+            (addr[0]),
+            (addr[1]),
+            (addr[2]),
+            (addr[3]));
+        eth_printf(
+            " ID:%x  SeqNum:%x CheckSum:%x",
+            htons(PingRequest.ID),
+            htons(PingRequest.SeqNum),
+            htons(PingRequest.CheckSum));
+    }
+    return 0;
+} // ping request
+
+uint8_t ping_reply(uint8_t s, uint8_t* addr, uint16_t rlen) {
+    uint16_t tmp_checksum;
+    uint16_t len;
+    uint16_t i;
+    uint8_t data_buf[128];
+    uint16_t port = 3000;
+    PINGMSGR PingReply;
+    /* receive data from a destination */
+    len = recvfrom(s, (uint8_t*)data_buf, rlen, addr, &port);
+    if(data_buf[0] == PING_REPLY) {
+        PingReply.Type = data_buf[0];
+        PingReply.Code = data_buf[1];
+        PingReply.CheckSum = (data_buf[3] << 8) + data_buf[2];
+        PingReply.ID = (data_buf[5] << 8) + data_buf[4];
+        PingReply.SeqNum = (data_buf[7] << 8) + data_buf[6];
+
+        for(i = 0; i < len - 8; ++i) {
+            PingReply.Data[i] = data_buf[8 + i];
+        }
+        /* check Checksum of Ping Reply */
+        tmp_checksum = ~checksum(data_buf, len);
+        if(tmp_checksum != 0xffff) {
+            eth_printf("tmp_checksum = %x", tmp_checksum);
+        } else {
+            /*  Output the Destination IP and the size of the Ping Reply Message*/
+            eth_printf(
+                "Reply from %d.%d.%d.%d  ID:%x SeqNum:%x  :data size %d bytes",
+                (addr[0]),
+                (addr[1]),
+                (addr[2]),
+                (addr[3]),
+                htons(PingReply.ID),
+                htons(PingReply.SeqNum),
+                (rlen + 6));
+            /*  SET ping_reply_receiver to '1' and go out the while_loop (waitting for ping reply)*/
+            ping_reply_received = 1;
+        }
+    } else if(data_buf[0] == PING_REQUEST) {
+        PingReply.Code = data_buf[1];
+        PingReply.Type = data_buf[2];
+        PingReply.CheckSum = (data_buf[3] << 8) + data_buf[2];
+        PingReply.ID = (data_buf[5] << 8) + data_buf[4];
+        PingReply.SeqNum = (data_buf[7] << 8) + data_buf[6];
+
+        for(i = 0; i < len - 8; ++i) {
+            PingReply.Data[i] = data_buf[8 + i];
+        }
+        /* check Checksum of Ping Reply */
+        tmp_checksum = PingReply.CheckSum;
+        PingReply.CheckSum = 0;
+        PingReply.CheckSum = htons(checksum((uint8_t*)&PingReply, len));
+
+        if(tmp_checksum != PingReply.CheckSum) {
+            eth_printf(
+                "CheckSum is in correct %x shold be %x",
+                (tmp_checksum),
+                htons(PingReply.CheckSum));
+        } else {
+            eth_printf("Checksum is correct");
+        }
+
+        /*  Output the Destination IP and the size of the Ping Reply Message*/
+        eth_printf(
+            "Request from %d.%d.%d.%d  ID:%x SeqNum:%x  :data size %d bytes",
+            (addr[0]),
+            (addr[1]),
+            (addr[2]),
+            (addr[3]),
+            (PingReply.ID),
+            (PingReply.SeqNum),
+            (rlen + 6));
+        /*  SET ping_reply_receiver to '1' and go out the while_loop (waitting for ping reply)*/
+        ping_reply_received = 1;
+    } else {
+        eth_printf(" Unkonwn msg.");
+    }
+
+    return 0;
+} // ping_reply
+
+uint16_t checksum(uint8_t* data_buf, uint16_t len) {
+    uint16_t sum, tsum, i, j;
+    uint32_t lsum;
+
+    j = len >> 1;
+    lsum = 0;
+    tsum = 0;
+    for(i = 0; i < j; ++i) {
+        tsum = data_buf[i * 2];
+        tsum = tsum << 8;
+        tsum += data_buf[i * 2 + 1];
+        lsum += tsum;
+    }
+    if(len % 2) {
+        tsum = data_buf[i * 2];
+        lsum += (tsum << 8);
+    }
+    sum = (uint16_t)lsum;
+    sum = ~(sum + (lsum >> 16));
+    return sum;
+}
+
+uint16_t htons(uint16_t hostshort) {
+#if 1
+    //#ifdef LITTLE_ENDIAN
+    uint16_t netshort = 0;
+    netshort = (hostshort & 0xFF) << 8;
+    netshort |= ((hostshort >> 8) & 0xFF);
+    return netshort;
+#else
+    return hostshort;
+#endif
+}

+ 38 - 0
lib/ioLibrary_Driver/Internet/ICMP/ping.h

@@ -0,0 +1,38 @@
+#ifndef PING_H
+#define PING_H
+
+#include "wizchip_conf.h"
+
+#define BUF_LEN 32
+#define PING_REQUEST 8
+#define PING_REPLY 0
+#define CODE_ZERO 0
+
+#define SOCKET_ERROR 1
+#define TIMEOUT_ERROR 2
+#define PING_SUCCESS 3
+#define REPLY_ERROR 4
+#define FUNCTION_ERROR 5
+#define PING_DEBUG
+
+typedef struct pingmsg {
+    uint8_t Type; // 0 - Ping Reply, 8 - Ping Request
+    uint8_t Code; // Always 0
+    int16_t CheckSum; // Check sum
+    int16_t ID; // Identification
+    int16_t SeqNum; // Sequence Number
+    int8_t Data[BUF_LEN]; // Ping Data  : 1452 = IP RAW MTU - sizeof(Type+Code+CheckSum+ID+SeqNum)
+} PINGMSGR;
+
+uint8_t ping_auto(uint8_t s, uint8_t* addr);
+uint8_t ping_count(uint8_t s, uint16_t pCount, uint8_t* addr);
+uint8_t ping_request(uint8_t s, uint8_t* addr);
+uint8_t ping_reply(uint8_t s, uint8_t* addr, uint16_t rlen);
+uint16_t checksum(uint8_t* data_buf, uint16_t len);
+uint16_t htons(
+    uint16_t
+        hostshort); /* htons function converts a unsigned short from host to TCP/IP network byte order (which is big-endian).*/
+
+void eth_printf(const char* format, ...);
+
+#endif /* PING_H */

+ 582 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTClient.c

@@ -0,0 +1,582 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+#include "MQTTClient.h"
+
+static void NewMessageData(MessageData* md, MQTTString* aTopicName, MQTTMessage* aMessage) {
+    md->topicName = aTopicName;
+    md->message = aMessage;
+}
+
+
+static int getNextPacketId(MQTTClient *c) {
+    return c->next_packetid = (c->next_packetid == MAX_PACKET_ID) ? 1 : c->next_packetid + 1;
+}
+
+
+static int sendPacket(MQTTClient* c, int length, Timer* timer)
+{
+    int rc = FAILURE,
+        sent = 0;
+
+    while (sent < length && !TimerIsExpired(timer))
+    {
+        rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, TimerLeftMS(timer));
+        if (rc < 0)  // there was an error writing the data
+            break;
+        sent += rc;
+    }
+    if (sent == length)
+    {
+        TimerCountdown(&c->ping_timer, c->keepAliveInterval); // record the fact that we have successfully sent the packet
+        rc = SUCCESSS;
+    }
+    else
+        rc = FAILURE;
+    return rc;
+}
+
+
+void MQTTClientInit(MQTTClient* c, Network* network, unsigned int command_timeout_ms,
+		unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size)
+{
+    int i;
+    c->ipstack = network;
+
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+        c->messageHandlers[i].topicFilter = 0;
+    c->command_timeout_ms = command_timeout_ms;
+    c->buf = sendbuf;
+    c->buf_size = sendbuf_size;
+    c->readbuf = readbuf;
+    c->readbuf_size = readbuf_size;
+    c->isconnected = 0;
+    c->ping_outstanding = 0;
+    c->defaultMessageHandler = NULL;
+	c->next_packetid = 1;
+    TimerInit(&c->ping_timer);
+#if defined(MQTT_TASK)
+	MutexInit(&c->mutex);
+#endif
+}
+
+
+static int decodePacket(MQTTClient* c, int* value, int timeout)
+{
+    unsigned char i;
+    int multiplier = 1;
+    int len = 0;
+    const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
+
+    *value = 0;
+    do
+    {
+        int rc = MQTTPACKET_READ_ERROR;
+
+        if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+        {
+            rc = MQTTPACKET_READ_ERROR; /* bad data */
+            goto exit;
+        }
+        rc = c->ipstack->mqttread(c->ipstack, &i, 1, timeout);
+        if (rc != 1)
+            goto exit;
+        *value += (i & 127) * multiplier;
+        multiplier *= 128;
+    } while ((i & 128) != 0);
+exit:
+    return len;
+}
+
+
+static int readPacket(MQTTClient* c, Timer* timer)
+{
+    int rc = FAILURE;
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    if (c->ipstack->mqttread(c->ipstack, c->readbuf, 1, TimerLeftMS(timer)) != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    decodePacket(c, &rem_len, TimerLeftMS(timer));
+    len += MQTTPacket_encode(c->readbuf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    if (rem_len > 0 && (c->ipstack->mqttread(c->ipstack, c->readbuf + len, rem_len, TimerLeftMS(timer)) != rem_len))
+        goto exit;
+
+    header.byte = c->readbuf[0];
+    rc = header.bits.type;
+exit:
+    return rc;
+}
+
+
+// assume topic filter and name is in correct format
+// # can only be at end
+// + and # can only be next to separator
+static char isTopicMatched(char* topicFilter, MQTTString* topicName)
+{
+    char* curf = topicFilter;
+    char* curn = topicName->lenstring.data;
+    char* curn_end = curn + topicName->lenstring.len;
+
+    while (*curf && curn < curn_end)
+    {
+        if (*curn == '/' && *curf != '/')
+            break;
+        if (*curf != '+' && *curf != '#' && *curf != *curn)
+            break;
+        if (*curf == '+')
+        {   // skip until we meet the next separator, or end of string
+            char* nextpos = curn + 1;
+            while (nextpos < curn_end && *nextpos != '/')
+                nextpos = ++curn + 1;
+        }
+        else if (*curf == '#')
+            curn = curn_end - 1;    // skip until end of string
+        curf++;
+        curn++;
+    };
+
+    return (curn == curn_end) && (*curf == '\0');
+}
+
+
+int deliverMessage(MQTTClient* c, MQTTString* topicName, MQTTMessage* message)
+{
+    int i;
+    int rc = FAILURE;
+
+    // we have to find the right message handler - indexed by topic
+    for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (c->messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(topicName, (char*)c->messageHandlers[i].topicFilter) ||
+                isTopicMatched((char*)c->messageHandlers[i].topicFilter, topicName)))
+        {
+            if (c->messageHandlers[i].fp != NULL)
+            {
+                MessageData md;
+                NewMessageData(&md, topicName, message);
+                c->messageHandlers[i].fp(&md);
+                rc = SUCCESSS;
+            }
+        }
+    }
+
+    if (rc == FAILURE && c->defaultMessageHandler != NULL)
+    {
+        MessageData md;
+        NewMessageData(&md, topicName, message);
+        c->defaultMessageHandler(&md);
+        rc = SUCCESSS;
+    }
+
+    return rc;
+}
+
+
+int keepalive(MQTTClient* c)
+{
+    int rc = FAILURE;
+
+    if (c->keepAliveInterval == 0)
+    {
+        rc = SUCCESSS;
+        goto exit;
+    }
+
+    if (TimerIsExpired(&c->ping_timer))
+    {
+        if (!c->ping_outstanding)
+        {
+            Timer timer;
+            TimerInit(&timer);
+            TimerCountdownMS(&timer, 1000);
+            int len = MQTTSerialize_pingreq(c->buf, c->buf_size);
+            if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESSS) // send the ping packet
+                c->ping_outstanding = 1;
+        }
+    }
+
+exit:
+    return rc;
+}
+
+
+int cycle(MQTTClient* c, Timer* timer)
+{
+    // read the socket, see what work is due
+    unsigned short packet_type = readPacket(c, timer);
+
+    int len = 0,
+        rc = SUCCESSS;
+
+    switch (packet_type)
+    {
+        case CONNACK:
+        case PUBACK:
+        case SUBACK:
+            break;
+        case PUBLISH:
+        {
+            MQTTString topicName;
+            MQTTMessage msg;
+            int intQoS;
+            if (MQTTDeserialize_publish(&msg.dup, &intQoS, &msg.retained, &msg.id, &topicName,
+               (unsigned char**)&msg.payload, (int*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
+                goto exit;
+            msg.qos = (enum QoS)intQoS;
+            deliverMessage(c, &topicName, &msg);
+            if (msg.qos != QOS0)
+            {
+                if (msg.qos == QOS1)
+                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
+                else if (msg.qos == QOS2)
+                    len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
+                if (len <= 0)
+                    rc = FAILURE;
+                else
+                    rc = sendPacket(c, len, timer);
+                if (rc == FAILURE)
+                    goto exit; // there was a problem
+            }
+            break;
+        }
+        case PUBREC:
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+            else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREL, 0, mypacketid)) <= 0)
+                rc = FAILURE;
+            else if ((rc = sendPacket(c, len, timer)) != SUCCESSS) // send the PUBREL packet
+                rc = FAILURE; // there was a problem
+            if (rc == FAILURE)
+                goto exit; // there was a problem
+            break;
+        }
+        case PUBCOMP:
+            break;
+        case PINGRESP:
+            c->ping_outstanding = 0;
+            break;
+    }
+    keepalive(c);
+exit:
+    if (rc == SUCCESSS)
+        rc = packet_type;
+    return rc;
+}
+
+
+int MQTTYield(MQTTClient* c, int timeout_ms)
+{
+    int rc = SUCCESSS;
+    Timer timer;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, timeout_ms);
+
+    if (cycle(c, &timer) == FAILURE)
+    {
+        rc = FAILURE;
+    }
+
+    return rc;
+}
+
+
+void MQTTRun(void* parm)
+{
+	Timer timer;
+	MQTTClient* c = (MQTTClient*)parm;
+
+	TimerInit(&timer);
+
+	while (1)
+	{
+#if defined(MQTT_TASK)
+		MutexLock(&c->mutex);
+#endif
+		TimerCountdownMS(&timer, 500); /* Don't wait too long if no traffic is incoming */
+		cycle(c, &timer);
+#if defined(MQTT_TASK)
+		MutexUnlock(&c->mutex);
+#endif
+	}
+}
+
+
+#if defined(MQTT_TASK)
+int MQTTStartTask(MQTTClient* client)
+{
+	return ThreadStart(&client->thread, &MQTTRun, client);
+}
+#endif
+
+
+int waitfor(MQTTClient* c, int packet_type, Timer* timer)
+{
+    int rc = FAILURE;
+
+    do
+    {
+        if (TimerIsExpired(timer))
+            break; // we timed out
+    }
+    while ((rc = cycle(c, timer)) != packet_type);
+
+    return rc;
+}
+
+
+int MQTTConnect(MQTTClient* c, MQTTPacket_connectData* options)
+{
+    Timer connect_timer;
+    int rc = FAILURE;
+    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	MutexLock(&c->mutex);
+#endif
+	if (c->isconnected) /* don't send connect packet again if we are already connected */
+		goto exit;
+
+    TimerInit(&connect_timer);
+    TimerCountdownMS(&connect_timer, c->command_timeout_ms);
+
+    if (options == 0)
+        options = &default_options; /* set default options if none were supplied */
+
+    c->keepAliveInterval = options->keepAliveInterval;
+    TimerCountdown(&c->ping_timer, c->keepAliveInterval);
+    if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &connect_timer)) != SUCCESSS)  // send the connect packet
+        goto exit; // there was a problem
+
+    // this will be a blocking call, wait for the connack
+    if (waitfor(c, CONNACK, &connect_timer) == CONNACK)
+    {
+        unsigned char connack_rc = 255;
+        unsigned char sessionPresent = 0;
+        if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, c->readbuf, c->readbuf_size) == 1)
+            rc = connack_rc;
+        else
+            rc = FAILURE;
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc == SUCCESSS)
+        c->isconnected = 1;
+
+#if defined(MQTT_TASK)
+	MutexUnlock(&c->mutex);
+#endif
+
+    return rc;
+}
+
+
+int MQTTSubscribe(MQTTClient* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler)
+{
+    int rc = FAILURE;
+    Timer timer;
+    int len = 0;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicFilter;
+    // This was added because enum QoS was previously typed to *int which resulted in HardFault and unaligned integer read.
+    // This coping below makes sure the parameter for MQTTSerialize_subscribe is always char no matter what compiler is using for enums
+    char charQos = (char)qos;
+
+#if defined(MQTT_TASK)
+	MutexLock(&c->mutex);
+#endif
+	if (!c->isconnected)
+		goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, &charQos);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
+        goto exit;             // there was a problem
+
+    if (waitfor(c, SUBACK, &timer) == SUBACK)      // wait for suback
+    {
+        int count = 0, grantedQoS = -1;
+        unsigned short mypacketid;
+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, c->readbuf, c->readbuf_size) == 1)
+            rc = grantedQoS; // 0, 1, 2 or 0x80
+        if (rc != 0x80)
+        {
+            int i;
+            for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+            {
+                if (c->messageHandlers[i].topicFilter == 0)
+                {
+                    c->messageHandlers[i].topicFilter = topicFilter;
+                    c->messageHandlers[i].fp = messageHandler;
+                    rc = 0;
+                    break;
+                }
+            }
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+#if defined(MQTT_TASK)
+	MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTUnsubscribe(MQTTClient* c, const char* topicFilter)
+{
+    int rc = FAILURE;
+    Timer timer;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicFilter;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	MutexLock(&c->mutex);
+#endif
+	if (!c->isconnected)
+		goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
+        goto exit; // there was a problem
+
+    if (waitfor(c, UNSUBACK, &timer) == UNSUBACK)
+    {
+        unsigned short mypacketid;  // should be the same as the packetid above
+        if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1)
+            rc = 0;
+    }
+    else
+        rc = FAILURE;
+
+exit:
+#if defined(MQTT_TASK)
+	MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTPublish(MQTTClient* c, const char* topicName, MQTTMessage* message)
+{
+    int rc = FAILURE;
+    Timer timer;
+    MQTTString topic = MQTTString_initializer;
+    topic.cstring = (char *)topicName;
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	MutexLock(&c->mutex);
+#endif
+	if (!c->isconnected)
+		goto exit;
+
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+    if (message->qos == QOS1 || message->qos == QOS2)
+        message->id = getNextPacketId(c);
+
+    len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id,
+              topic, (unsigned char*)message->payload, message->payloadlen);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
+        goto exit; // there was a problem
+
+    if (message->qos == QOS1)
+    {
+        if (waitfor(c, PUBACK, &timer) == PUBACK)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+        }
+        else
+            rc = FAILURE;
+    }
+    else if (message->qos == QOS2)
+    {
+        if (waitfor(c, PUBCOMP, &timer) == PUBCOMP)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
+                rc = FAILURE;
+        }
+        else
+            rc = FAILURE;
+    }
+
+exit:
+#if defined(MQTT_TASK)
+	MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+
+
+int MQTTDisconnect(MQTTClient* c)
+{
+    int rc = FAILURE;
+    Timer timer;     // we might wait for incomplete incoming publishes to complete
+    int len = 0;
+
+#if defined(MQTT_TASK)
+	MutexLock(&c->mutex);
+#endif
+    TimerInit(&timer);
+    TimerCountdownMS(&timer, c->command_timeout_ms);
+
+	len = MQTTSerialize_disconnect(c->buf, c->buf_size);
+    if (len > 0)
+        rc = sendPacket(c, len, &timer);            // send the disconnect packet
+
+    c->isconnected = 0;
+
+#if defined(MQTT_TASK)
+	MutexUnlock(&c->mutex);
+#endif
+    return rc;
+}
+

+ 182 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTClient.h

@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - documentation and platform specific header
+ *******************************************************************************/
+
+#if !defined(__MQTT_CLIENT_C_)
+#define __MQTT_CLIENT_C_
+
+#if defined(__cplusplus)
+ extern "C" {
+#endif
+
+#if defined(WIN32_DLL) || defined(WIN64_DLL)
+  #define DLLImport __declspec(dllimport)
+  #define DLLExport __declspec(dllexport)
+#elif defined(LINUX_SO)
+  #define DLLImport extern
+  #define DLLExport  __attribute__ ((visibility ("default")))
+#else
+  #define DLLImport
+  #define DLLExport
+#endif
+
+#include "./MQTTPacket/src/MQTTPacket.h"
+#include "stdio.h"
+#include "mqtt_interface.h"
+
+#define MAX_PACKET_ID 65535 /* according to the MQTT specification - do not change! */
+
+#if !defined(MAX_MESSAGE_HANDLERS)
+#define MAX_MESSAGE_HANDLERS 5 /* redefinable - how many subscriptions do you want? */
+#endif
+
+enum QoS { QOS0, QOS1, QOS2 };
+
+/* all failure return codes must be negative */
+enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESSS = 0 };
+
+/* The Platform specific header must define the Network and Timer structures and functions
+ * which operate on them.
+ *
+typedef struct Network
+{
+	int (*mqttread)(Network*, unsigned char* read_buffer, int, int);
+	int (*mqttwrite)(Network*, unsigned char* send_buffer, int, int);
+} Network;*/
+
+/* The Timer structure must be defined in the platform specific header,
+ * and have the following functions to operate on it.  */
+extern void TimerInit(Timer*);
+extern char TimerIsExpired(Timer*);
+extern void TimerCountdownMS(Timer*, unsigned int);
+extern void TimerCountdown(Timer*, unsigned int);
+extern int TimerLeftMS(Timer*);
+
+typedef struct MQTTMessage
+{
+    enum QoS qos;
+    unsigned char retained;
+    unsigned char dup;
+    unsigned short id;
+    void *payload;
+    size_t payloadlen;
+} MQTTMessage;
+
+typedef struct MessageData
+{
+    MQTTMessage* message;
+    MQTTString* topicName;
+} MessageData;
+
+typedef void (*messageHandler)(MessageData*);
+
+typedef struct MQTTClient
+{
+    unsigned int next_packetid,
+      command_timeout_ms;
+    size_t buf_size,
+      readbuf_size;
+    unsigned char *buf,
+      *readbuf;
+    unsigned int keepAliveInterval;
+    char ping_outstanding;
+    int isconnected;
+
+    struct MessageHandlers
+    {
+        const char* topicFilter;
+        void (*fp) (MessageData*);
+    } messageHandlers[MAX_MESSAGE_HANDLERS];      /* Message handlers are indexed by subscription topic */
+
+    void (*defaultMessageHandler) (MessageData*);
+
+    Network* ipstack;
+    Timer ping_timer;
+#if defined(MQTT_TASK)
+	Mutex mutex;
+	Thread thread;
+#endif 
+} MQTTClient;
+
+#define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0}
+
+
+/**
+ * Create an MQTT client object
+ * @param client
+ * @param network
+ * @param command_timeout_ms
+ * @param
+ */
+DLLExport void MQTTClientInit(MQTTClient* client, Network* network, unsigned int command_timeout_ms,
+		unsigned char* sendbuf, size_t sendbuf_size, unsigned char* readbuf, size_t readbuf_size);
+
+/** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+ *  The nework object must be connected to the network endpoint before calling this
+ *  @param options - connect options
+ *  @return success code
+ */
+DLLExport int MQTTConnect(MQTTClient* client, MQTTPacket_connectData* options);
+
+/** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+ *  @param client - the client object to use
+ *  @param topic - the topic to publish to
+ *  @param message - the message to send
+ *  @return success code
+ */
+DLLExport int MQTTPublish(MQTTClient* client, const char*, MQTTMessage*);
+
+/** MQTT Subscribe - send an MQTT subscribe packet and wait for suback before returning.
+ *  @param client - the client object to use
+ *  @param topicFilter - the topic filter to subscribe to
+ *  @param message - the message to send
+ *  @return success code
+ */
+DLLExport int MQTTSubscribe(MQTTClient* client, const char* topicFilter, enum QoS, messageHandler);
+
+/** MQTT Subscribe - send an MQTT unsubscribe packet and wait for unsuback before returning.
+ *  @param client - the client object to use
+ *  @param topicFilter - the topic filter to unsubscribe from
+ *  @return success code
+ */
+DLLExport int MQTTUnsubscribe(MQTTClient* client, const char* topicFilter);
+
+/** MQTT Disconnect - send an MQTT disconnect packet and close the connection
+ *  @param client - the client object to use
+ *  @return success code
+ */
+DLLExport int MQTTDisconnect(MQTTClient* client);
+
+/** MQTT Yield - MQTT background
+ *  @param client - the client object to use
+ *  @param time - the time, in milliseconds, to yield for 
+ *  @return success code
+ */
+DLLExport int MQTTYield(MQTTClient* client, int time);
+
+#if defined(MQTT_TASK)
+/** MQTT start background thread for a client.  After this, MQTTYield should not be called.
+*  @param client - the client object to use
+*  @return success code
+*/
+DLLExport int MQTTStartTask(MQTTClient* client);
+#endif
+
+#if defined(__cplusplus)
+     }
+#endif
+
+#endif

+ 136 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTConnect.h

@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTCONNECT_H_
+#define MQTTCONNECT_H_
+
+#if !defined(DLLImport)
+  #define DLLImport 
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+
+typedef union
+{
+	unsigned char all;	/**< all connect flags */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int username : 1;			/**< 3.1 user name */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int cleansession : 1;	  /**< clean session flag */
+		unsigned int : 1;	  	          /**< unused */
+	} bits;
+#else
+	struct
+	{
+		unsigned int : 1;	     					/**< unused */
+		unsigned int cleansession : 1;	  /**< cleansession flag */
+		unsigned int will : 1;			    /**< will flag */
+		unsigned int willQoS : 2;				/**< will QoS value */
+		unsigned int willRetain : 1;		/**< will retain setting */
+		unsigned int password : 1; 			/**< 3.1 password */
+		unsigned int username : 1;			/**< 3.1 user name */
+	} bits;
+#endif
+} MQTTConnectFlags;	/**< connect flags byte */
+
+
+
+/**
+ * Defines the MQTT "Last Will and Testament" (LWT) settings for
+ * the connect packet.
+ */
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTW. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** The LWT topic to which the LWT message will be published. */
+	MQTTString topicName;
+	/** The LWT payload. */
+	MQTTString message;
+	/**
+      * The retained flag for the LWT message (see MQTTAsync_message.retained).
+      */
+	unsigned char retained;
+	/**
+      * The quality of service setting for the LWT message (see
+      * MQTTAsync_message.qos and @ref qos).
+      */
+	char qos;
+} MQTTPacket_willOptions;
+
+
+#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
+
+
+typedef struct
+{
+	/** The eyecatcher for this structure.  must be MQTC. */
+	char struct_id[4];
+	/** The version number of this structure.  Must be 0 */
+	int struct_version;
+	/** Version of MQTT to be used.  3 = 3.1 4 = 3.1.1
+	  */
+	unsigned char MQTTVersion;
+	MQTTString clientID;
+	unsigned short keepAliveInterval;
+	unsigned char cleansession;
+	unsigned char willFlag;
+	MQTTPacket_willOptions will;
+	MQTTString username;
+	MQTTString password;
+} MQTTPacket_connectData;
+
+typedef union
+{
+	unsigned char all;	/**< all connack flags */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int sessionpresent : 1;    /**< session present flag */
+		unsigned int : 7;	  	          /**< unused */
+	} bits;
+#else
+	struct
+	{
+		unsigned int : 7;	     			/**< unused */
+		unsigned int sessionpresent : 1;    /**< session present flag */
+	} bits;
+#endif
+} MQTTConnackFlags;	/**< connack flags byte */
+
+#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
+		MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
+
+DLLExport int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options);
+DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent);
+DLLExport int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen);
+
+DLLExport int MQTTSerialize_disconnect(unsigned char* buf, int buflen);
+DLLExport int MQTTSerialize_pingreq(unsigned char* buf, int buflen);
+
+#endif /* MQTTCONNECT_H_ */

+ 214 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTConnectClient.c

@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
+  * @param options the options to be used to build the connect packet
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_connectLength(MQTTPacket_connectData* options)
+{
+	int len = 0;
+
+	FUNC_ENTRY;
+
+	if (options->MQTTVersion == 3)
+		len = 12; /* variable depending on MQTT or MQIsdp */
+	else if (options->MQTTVersion == 4)
+		len = 10;
+
+	len += MQTTstrlen(options->clientID)+2;
+	if (options->willFlag)
+		len += MQTTstrlen(options->will.topicName)+2 + MQTTstrlen(options->will.message)+2;
+	if (options->username.cstring || options->username.lenstring.data)
+		len += MQTTstrlen(options->username)+2;
+	if (options->password.cstring || options->password.lenstring.data)
+		len += MQTTstrlen(options->password)+2;
+
+	FUNC_EXIT_RC(len);
+	return len;
+}
+
+
+/**
+  * Serializes the connect options into the buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param len the length in bytes of the supplied buffer
+  * @param options the options to be used to build the connect packet
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options)
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	MQTTConnectFlags flags = {0};
+	int len = 0;
+	int rc = -1;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = CONNECT;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
+
+	if (options->MQTTVersion == 4)
+	{
+		writeCString(&ptr, "MQTT");
+		writeChar(&ptr, (char) 4);
+	}
+	else
+	{
+		writeCString(&ptr, "MQIsdp");
+		writeChar(&ptr, (char) 3);
+	}
+
+	flags.all = 0;
+	flags.bits.cleansession = options->cleansession;
+	flags.bits.will = (options->willFlag) ? 1 : 0;
+	if (flags.bits.will)
+	{
+		flags.bits.willQoS = options->will.qos;
+		flags.bits.willRetain = options->will.retained;
+	}
+
+	if (options->username.cstring || options->username.lenstring.data)
+		flags.bits.username = 1;
+	if (options->password.cstring || options->password.lenstring.data)
+		flags.bits.password = 1;
+
+	writeChar(&ptr, flags.all);
+	writeInt(&ptr, options->keepAliveInterval);
+	writeMQTTString(&ptr, options->clientID);
+	if (options->willFlag)
+	{
+		writeMQTTString(&ptr, options->will.topicName);
+		writeMQTTString(&ptr, options->will.message);
+	}
+	if (flags.bits.username)
+		writeMQTTString(&ptr, options->username);
+	if (flags.bits.password)
+		writeMQTTString(&ptr, options->password);
+
+	rc = ptr - buf;
+
+	exit: FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into connack data - return code
+  * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
+  * @param connack_rc returned integer value of the connack return code
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param len the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+	MQTTConnackFlags flags = {0};
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != CONNACK)
+		goto exit;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+	if (enddata - curdata < 2)
+		goto exit;
+
+	flags.all = readChar(&curdata);
+	*sessionPresent = flags.bits.sessionpresent;
+	*connack_rc = readChar(&curdata);
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @param packettype the message type
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_zero(unsigned char* buf, int buflen, unsigned char packettype)
+{
+	MQTTHeader header = {0};
+	int rc = -1;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = packettype;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_disconnect(unsigned char* buf, int buflen)
+{
+	return MQTTSerialize_zero(buf, buflen, DISCONNECT);
+}
+
+
+/**
+  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pingreq(unsigned char* buf, int buflen)
+{
+	return MQTTSerialize_zero(buf, buflen, PINGREQ);
+}

+ 148 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTConnectServer.c

@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+#include <string.h>
+
+#define min(a, b) ((a < b) ? a : b)
+
+
+/**
+  * Validates MQTT protocol name and version combinations
+  * @param protocol the MQTT protocol name as an MQTTString
+  * @param version the MQTT protocol version number, as in the connect packet
+  * @return correct MQTT combination?  1 is true, 0 is false
+  */
+int MQTTPacket_checkVersion(MQTTString* protocol, int version)
+{
+	int rc = 0;
+
+	if (version == 3 && memcmp(protocol->lenstring.data, "MQIsdp",
+			min(6, protocol->lenstring.len)) == 0)
+		rc = 1;
+	else if (version == 4 && memcmp(protocol->lenstring.data, "MQTT",
+			min(4, protocol->lenstring.len)) == 0)
+		rc = 1;
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into connect data structure
+  * @param data the connect data structure to be filled out
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param len the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len)
+{
+	MQTTHeader header = {0};
+	MQTTConnectFlags flags = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = &buf[len];
+	int rc = 0;
+	MQTTString Protocol;
+	int version;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != CONNECT)
+		goto exit;
+
+	curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
+
+	if (!readMQTTLenString(&Protocol, &curdata, enddata) ||
+		enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+		goto exit;
+
+	version = (int)readChar(&curdata); /* Protocol version */
+	/* If we don't recognize the protocol version, we don't parse the connect packet on the
+	 * basis that we don't know what the format will be.
+	 */
+	if (MQTTPacket_checkVersion(&Protocol, version))
+	{
+		flags.all = readChar(&curdata);
+		data->cleansession = flags.bits.cleansession;
+		data->keepAliveInterval = readInt(&curdata);
+		if (!readMQTTLenString(&data->clientID, &curdata, enddata))
+			goto exit;
+		data->willFlag = flags.bits.will;
+		if (flags.bits.will)
+		{
+			data->will.qos = flags.bits.willQoS;
+			data->will.retained = flags.bits.willRetain;
+			if (!readMQTTLenString(&data->will.topicName, &curdata, enddata) ||
+				  !readMQTTLenString(&data->will.message, &curdata, enddata))
+				goto exit;
+		}
+		if (flags.bits.username)
+		{
+			if (enddata - curdata < 3 || !readMQTTLenString(&data->username, &curdata, enddata))
+				goto exit; /* username flag set, but no username supplied - invalid */
+			if (flags.bits.password &&
+				(enddata - curdata < 3 || !readMQTTLenString(&data->password, &curdata, enddata)))
+				goto exit; /* password flag set, but no password supplied - invalid */
+		}
+		else if (flags.bits.password)
+			goto exit; /* password flag set without username - invalid */
+		rc = 1;
+	}
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the connack packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param connack_rc the integer connack return code to be used 
+  * @param sessionPresent the MQTT 3.1.1 sessionPresent flag
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+	MQTTConnackFlags flags = {0};
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = CONNACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+	flags.all = 0;
+	flags.bits.sessionpresent = sessionPresent;
+	writeChar(&ptr, flags.all); 
+	writeChar(&ptr, connack_rc);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+

+ 107 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTDeserializePublish.c

@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+#include <string.h>
+
+#define min(a, b) ((a < b) ? 1 : 0)
+
+/**
+  * Deserializes the supplied (wire) buffer into publish data
+  * @param dup returned integer - the MQTT dup flag
+  * @param qos returned integer - the MQTT QoS value
+  * @param retained returned integer - the MQTT retained flag
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param topicName returned MQTTString - the MQTT topic in the publish
+  * @param payload returned byte buffer - the MQTT publish payload
+  * @param payloadlen returned integer - the length of the MQTT payload
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success
+  */
+int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+		unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != PUBLISH)
+		goto exit;
+	*dup = header.bits.dup;
+	*qos = header.bits.qos;
+	*retained = header.bits.retain;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	if (!readMQTTLenString(topicName, &curdata, enddata) ||
+		enddata - curdata < 0) /* do we have enough data to read the protocol version byte? */
+		goto exit;
+
+	if (*qos > 0)
+		*packetid = readInt(&curdata);
+
+	*payloadlen = enddata - curdata;
+	*payload = curdata;
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Deserializes the supplied (wire) buffer into an ack
+  * @param packettype returned integer - the MQTT packet type
+  * @param dup returned integer - the MQTT dup flag
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	*dup = header.bits.dup;
+	*packettype = header.bits.type;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	if (enddata - curdata < 2)
+		goto exit;
+	*packetid = readInt(&curdata);
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+

+ 255 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTFormat.c

@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+#include <string.h>
+
+
+const char* MQTTPacket_names[] =
+{
+	"RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL",
+	"PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK",
+	"PINGREQ", "PINGRESP", "DISCONNECT"
+};
+
+
+const char* MQTTPacket_getName(unsigned short packetid)
+{
+	return MQTTPacket_names[packetid];
+}
+
+
+int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data)
+{
+	int strindex = 0;
+
+	strindex = snprintf(strbuf, strbuflen,
+			"CONNECT MQTT version %d, client id %.*s, clean session %d, keep alive %d",
+			(int)data->MQTTVersion, data->clientID.lenstring.len, data->clientID.lenstring.data,
+			(int)data->cleansession, data->keepAliveInterval);
+	if (data->willFlag)
+		strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", will QoS %d, will retain %d, will topic %.*s, will message %.*s",
+				data->will.qos, data->will.retained,
+				data->will.topicName.lenstring.len, data->will.topicName.lenstring.data,
+				data->will.message.lenstring.len, data->will.message.lenstring.data);
+	if (data->username.lenstring.data && data->username.lenstring.len > 0)
+		strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", user name %.*s", data->username.lenstring.len, data->username.lenstring.data);
+	if (data->password.lenstring.data && data->password.lenstring.len > 0)
+		strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
+				", password %.*s", data->password.lenstring.len, data->password.lenstring.data);
+	return strindex;
+}
+
+
+int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent)
+{
+	int strindex = snprintf(strbuf, strbuflen, "CONNACK session present %d, rc %d", sessionPresent, connack_rc);
+	return strindex;
+}
+
+
+int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
+		unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen)
+{
+	int strindex = snprintf(strbuf, strbuflen,
+				"PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %d, payload %.*s",
+				dup, qos, retained, packetid,
+				(topicName.lenstring.len < 20) ? topicName.lenstring.len : 20, topicName.lenstring.data,
+				payloadlen, (payloadlen < 20) ? payloadlen : 20, payload);
+	return strindex;
+}
+
+
+int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid)
+{
+	int strindex = snprintf(strbuf, strbuflen, "%s, packet id %d", MQTTPacket_names[packettype], packetid);
+	if (dup)
+		strindex += snprintf(strbuf + strindex, strbuflen - strindex, ", dup %d", dup);
+	return strindex;
+}
+
+
+int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
+		MQTTString topicFilters[], int requestedQoSs[])
+{
+	return snprintf(strbuf, strbuflen,
+		"SUBSCRIBE dup %d, packet id %d count %d topic %.*s qos %d",
+		dup, packetid, count,
+		topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
+		requestedQoSs[0]);
+}
+
+
+int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs)
+{
+	return snprintf(strbuf, strbuflen,
+		"SUBACK packet id %d count %d granted qos %d", packetid, count, grantedQoSs[0]);
+}
+
+
+int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[])
+{
+	return snprintf(strbuf, strbuflen,
+					"UNSUBSCRIBE dup %d, packet id %d count %d topic %.*s",
+					dup, packetid, count,
+					topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
+}
+
+
+char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
+{
+	int index = 0;
+	int rem_length = 0;
+	MQTTHeader header = {0};
+	header.byte = buf[index++];
+	index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
+
+	switch (header.bits.type)
+	{
+	case CONNACK:
+	{
+		unsigned char sessionPresent, connack_rc;
+		if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1)
+			MQTTStringFormat_connack(strbuf, strbuflen, connack_rc, sessionPresent);
+	}
+	break;
+	case PUBLISH:
+	{
+		unsigned char dup, retained, *payload;
+		unsigned short packetid;
+		int qos, payloadlen;
+		MQTTString topicName = MQTTString_initializer;
+		if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
+				&payload, &payloadlen, buf, buflen) == 1)
+			MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
+					topicName, payload, payloadlen);
+	}
+	break;
+	case PUBACK:
+	case PUBREC:
+	case PUBREL:
+	case PUBCOMP:
+	{
+		unsigned char packettype, dup;
+		unsigned short packetid;
+		if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
+			MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
+	}
+	break;
+	case SUBACK:
+	{
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		int grantedQoSs[1];
+		if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1)
+			MQTTStringFormat_suback(strbuf, strbuflen, packetid, count, grantedQoSs);
+	}
+	break;
+	case UNSUBACK:
+	{
+		unsigned short packetid;
+		if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1)
+			MQTTStringFormat_ack(strbuf, strbuflen, UNSUBACK, 0, packetid);
+	}
+	break;
+	case PINGREQ:
+	case PINGRESP:
+	case DISCONNECT:
+		snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
+		break;
+	}
+	return strbuf;
+}
+
+
+char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen)
+{
+	int index = 0;
+	int rem_length = 0;
+	MQTTHeader header = {0};
+
+	header.byte = buf[index++];
+	index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
+
+	switch (header.bits.type)
+	{
+	case CONNECT:
+	{
+		MQTTPacket_connectData data;
+		int rc;
+		if ((rc = MQTTDeserialize_connect(&data, buf, buflen)) == 1)
+			MQTTStringFormat_connect(strbuf, strbuflen, &data);
+	}
+	break;
+	case PUBLISH:
+	{
+		unsigned char dup, retained, *payload;
+		unsigned short packetid;
+		int qos, payloadlen;
+		MQTTString topicName = MQTTString_initializer;
+		if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
+				&payload, &payloadlen, buf, buflen) == 1)
+			MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, packetid,
+					topicName, payload, payloadlen);
+	}
+	break;
+	case PUBACK:
+	case PUBREC:
+	case PUBREL:
+	case PUBCOMP:
+	{
+		unsigned char packettype, dup;
+		unsigned short packetid;
+		if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
+			MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
+	}
+	break;
+	case SUBSCRIBE:
+	{
+		unsigned char dup;
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		MQTTString topicFilters[1];
+		int requestedQoSs[1];
+		if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
+				topicFilters, requestedQoSs, buf, buflen) == 1)
+			MQTTStringFormat_subscribe(strbuf, strbuflen, dup, packetid, count, topicFilters, requestedQoSs);;
+	}
+	break;
+	case UNSUBSCRIBE:
+	{
+		unsigned char dup;
+		unsigned short packetid;
+		int maxcount = 1, count = 0;
+		MQTTString topicFilters[1];
+		if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1)
+			MQTTStringFormat_unsubscribe(strbuf, strbuflen, dup, packetid, count, topicFilters);
+	}
+	break;
+	case PINGREQ:
+	case PINGRESP:
+	case DISCONNECT:
+		snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
+		break;
+	}
+	strbuf[strbuflen] = '\0';
+	return strbuf;
+}

+ 37 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTFormat.h

@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(MQTTFORMAT_H)
+#define MQTTFORMAT_H
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+const char* MQTTPacket_getName(unsigned short packetid);
+int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data);
+int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent);
+int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained,
+		unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen);
+int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid);
+int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count,
+		MQTTString topicFilters[], int requestedQoSs[]);
+int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs);
+int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[]);
+char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
+char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen);
+
+#endif

+ 410 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTPacket.c

@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Sergio R. Caprile - non-blocking packet read functions for stream transport
+ *******************************************************************************/
+
+#include "StackTrace.h"
+#include "MQTTPacket.h"
+
+#include <string.h>
+
+/**
+ * Encodes the message length according to the MQTT algorithm
+ * @param buf the buffer into which the encoded data is written
+ * @param length the length to be encoded
+ * @return the number of bytes written to buffer
+ */
+int MQTTPacket_encode(unsigned char* buf, int length)
+{
+	int rc = 0;
+
+	FUNC_ENTRY;
+	do
+	{
+		char d = length % 128;
+		length /= 128;
+		/* if there are more digits to encode, set the top bit of this digit */
+		if (length > 0)
+			d |= 0x80;
+		buf[rc++] = d;
+	} while (length > 0);
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+ * Decodes the message length according to the MQTT algorithm
+ * @param getcharfn pointer to function to read the next character from the data source
+ * @param value the decoded length returned
+ * @return the number of bytes read from the socket
+ */
+int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value)
+{
+	unsigned char c;
+	int multiplier = 1;
+	int len = 0;
+#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
+
+	FUNC_ENTRY;
+	*value = 0;
+	do
+	{
+		int rc = MQTTPACKET_READ_ERROR;
+
+		if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+		{
+			rc = MQTTPACKET_READ_ERROR;	/* bad data */
+			goto exit;
+		}
+		rc = (*getcharfn)(&c, 1);
+		if (rc != 1)
+			goto exit;
+		*value += (c & 127) * multiplier;
+		multiplier *= 128;
+	} while ((c & 128) != 0);
+exit:
+	FUNC_EXIT_RC(len);
+	return len;
+}
+
+
+int MQTTPacket_len(int rem_len)
+{
+	rem_len += 1; /* header byte */
+
+	/* now remaining_length field */
+	if (rem_len < 128)
+		rem_len += 1;
+	else if (rem_len < 16384)
+		rem_len += 2;
+	else if (rem_len < 2097151)
+		rem_len += 3;
+	else
+		rem_len += 4;
+	return rem_len;
+}
+
+
+static unsigned char* bufptr;
+
+int bufchar(unsigned char* c, int count)
+{
+	int i;
+
+	for (i = 0; i < count; ++i)
+		*c = *bufptr++;
+	return count;
+}
+
+
+int MQTTPacket_decodeBuf(unsigned char* buf, int* value)
+{
+	bufptr = buf;
+	return MQTTPacket_decode(bufchar, value);
+}
+
+
+/**
+ * Calculates an integer from two bytes read from the input buffer
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the integer value calculated
+ */
+int readInt(unsigned char** pptr)
+{
+	unsigned char* ptr = *pptr;
+	int len = 256*(*ptr) + (*(ptr+1));
+	*pptr += 2;
+	return len;
+}
+
+
+/**
+ * Reads one character from the input buffer.
+ * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
+ * @return the character read
+ */
+char readChar(unsigned char** pptr)
+{
+	char c = **pptr;
+	(*pptr)++;
+	return c;
+}
+
+
+/**
+ * Writes one character to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param c the character to write
+ */
+void writeChar(unsigned char** pptr, char c)
+{
+	**pptr = c;
+	(*pptr)++;
+}
+
+
+/**
+ * Writes an integer as 2 bytes to an output buffer.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param anInt the integer to write
+ */
+void writeInt(unsigned char** pptr, int anInt)
+{
+	**pptr = (unsigned char)(anInt / 256);
+	(*pptr)++;
+	**pptr = (unsigned char)(anInt % 256);
+	(*pptr)++;
+}
+
+
+/**
+ * Writes a "UTF" string to an output buffer.  Converts C string to length-delimited.
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param string the C string to write
+ */
+void writeCString(unsigned char** pptr, const char* string)
+{
+	int len = strlen(string);
+	writeInt(pptr, len);
+	memcpy(*pptr, string, len);
+	*pptr += len;
+}
+
+
+int getLenStringLen(char* ptr)
+{
+	int len = 256*((unsigned char)(*ptr)) + (unsigned char)(*(ptr+1));
+	return len;
+}
+
+
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring)
+{
+	if (mqttstring.lenstring.len > 0)
+	{
+		writeInt(pptr, mqttstring.lenstring.len);
+		memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
+		*pptr += mqttstring.lenstring.len;
+	}
+	else if (mqttstring.cstring)
+		writeCString(pptr, mqttstring.cstring);
+	else
+		writeInt(pptr, 0);
+}
+
+
+/**
+ * @param mqttstring the MQTTString structure into which the data is to be read
+ * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
+ * @param enddata pointer to the end of the data: do not read beyond
+ * @return 1 if successful, 0 if not
+ */
+int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata)
+{
+	int rc = 0;
+
+	FUNC_ENTRY;
+	/* the first two bytes are the length of the string */
+	if (enddata - (*pptr) > 1) /* enough length to read the integer? */
+	{
+		mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
+		if (&(*pptr)[mqttstring->lenstring.len] <= enddata)
+		{
+			mqttstring->lenstring.data = (char*)*pptr;
+			*pptr += mqttstring->lenstring.len;
+			rc = 1;
+		}
+	}
+	mqttstring->cstring = NULL;
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+ * Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
+ * @param mqttstring the string to return the length of
+ * @return the length of the string
+ */
+int MQTTstrlen(MQTTString mqttstring)
+{
+	int rc = 0;
+
+	if (mqttstring.cstring)
+		rc = strlen(mqttstring.cstring);
+	else
+		rc = mqttstring.lenstring.len;
+	return rc;
+}
+
+
+/**
+ * Compares an MQTTString to a C string
+ * @param a the MQTTString to compare
+ * @param bptr the C string to compare
+ * @return boolean - equal or not
+ */
+int MQTTPacket_equals(MQTTString* a, char* bptr)
+{
+	int alen = 0,
+		blen = 0;
+	char *aptr;
+	
+	if (a->cstring)
+	{
+		aptr = a->cstring;
+		alen = strlen(a->cstring);
+	}
+	else
+	{
+		aptr = a->lenstring.data;
+		alen = a->lenstring.len;
+	}
+	blen = strlen(bptr);
+	
+	return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
+}
+
+
+/**
+ * Helper function to read packet data from some source into a buffer
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param getfn pointer to a function which will read any number of bytes from the needed source
+ * @return integer MQTT packet type, or -1 on error
+ * @note  the whole message must fit into the caller's buffer
+ */
+int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int))
+{
+	int rc = -1;
+	MQTTHeader header = {0};
+	int len = 0;
+	int rem_len = 0;
+
+	/* 1. read the header byte.  This has the packet type in it */
+	if ((*getfn)(buf, 1) != 1)
+		goto exit;
+
+	len = 1;
+	/* 2. read the remaining length.  This is variable in itself */
+	MQTTPacket_decode(getfn, &rem_len);
+	len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+	/* 3. read the rest of the buffer using a callback to supply the rest of the data */
+	if((rem_len + len) > buflen)
+		goto exit;
+	if ((*getfn)(buf + len, rem_len) != rem_len)
+		goto exit;
+
+	header.byte = buf[0];
+	rc = header.bits.type;
+exit:
+	return rc;
+}
+
+/**
+ * Decodes the message length according to the MQTT algorithm, non-blocking
+ * @param trp pointer to a transport structure holding what is needed to solve getting data from it
+ * @param value the decoded length returned
+ * @return integer the number of bytes read from the socket, 0 for call again, or -1 on error
+ */
+static int MQTTPacket_decodenb(MQTTTransport *trp)
+{
+	unsigned char c;
+	int rc = MQTTPACKET_READ_ERROR;
+
+	FUNC_ENTRY;
+	if(trp->len == 0){		/* initialize on first call */
+		trp->multiplier = 1;
+		trp->rem_len = 0;
+	}
+	do {
+		int frc;
+		if (++(trp->len) > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+			goto exit;
+		if ((frc=(*trp->getfn)(trp->sck, &c, 1)) == -1)
+			goto exit;
+		if (frc == 0){
+			rc = 0;
+			goto exit;
+		}
+		trp->rem_len += (c & 127) * trp->multiplier;
+		trp->multiplier *= 128;
+	} while ((c & 128) != 0);
+	rc = trp->len;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+/**
+ * Helper function to read packet data from some source into a buffer, non-blocking
+ * @param buf the buffer into which the packet will be serialized
+ * @param buflen the length in bytes of the supplied buffer
+ * @param trp pointer to a transport structure holding what is needed to solve getting data from it
+ * @return integer MQTT packet type, 0 for call again, or -1 on error
+ * @note  the whole message must fit into the caller's buffer
+ */
+int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp)
+{
+	int rc = -1, frc;
+	MQTTHeader header = {0};
+
+	switch(trp->state){
+	default:
+		trp->state = 0;
+		/*FALLTHROUGH*/
+	case 0:
+		/* read the header byte.  This has the packet type in it */
+		if ((frc=(*trp->getfn)(trp->sck, buf, 1)) == -1)
+			goto exit;
+		if (frc == 0)
+			return 0;
+		trp->len = 0;
+		++trp->state;
+		/*FALLTHROUGH*/
+		/* read the remaining length.  This is variable in itself */
+	case 1:
+		if((frc=MQTTPacket_decodenb(trp)) == MQTTPACKET_READ_ERROR)
+			goto exit;
+		if(frc == 0)
+			return 0;
+		trp->len = 1 + MQTTPacket_encode(buf + 1, trp->rem_len); /* put the original remaining length back into the buffer */
+		if((trp->rem_len + trp->len) > buflen)
+			goto exit;
+		++trp->state;
+		/*FALLTHROUGH*/
+	case 2:
+		/* read the rest of the buffer using a callback to supply the rest of the data */
+		if ((frc=(*trp->getfn)(trp->sck, buf + trp->len, trp->rem_len)) == -1)
+			goto exit;
+		if (frc == 0)
+			return 0;
+		trp->rem_len -= frc;
+		trp->len += frc;
+		if(trp->rem_len)
+			return 0;
+
+		header.byte = buf[0];
+		rc = header.bits.type;
+		break;
+	}
+
+exit:
+	trp->state = 0;
+	return rc;
+}
+

+ 133 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTPacket.h

@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTPACKET_H_
+#define MQTTPACKET_H_
+
+#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
+extern "C" {
+#endif
+
+#if defined(WIN32_DLL) || defined(WIN64_DLL)
+  #define DLLImport __declspec(dllimport)
+  #define DLLExport __declspec(dllexport)
+#elif defined(LINUX_SO)
+  #define DLLImport extern
+  #define DLLExport  __attribute__ ((visibility ("default")))
+#else
+  #define DLLImport
+  #define DLLExport  
+#endif
+
+enum errors
+{
+	MQTTPACKET_BUFFER_TOO_SHORT = -2,
+	MQTTPACKET_READ_ERROR = -1,
+	MQTTPACKET_READ_COMPLETE
+};
+
+enum msgTypes
+{
+	CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL,
+	PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK,
+	PINGREQ, PINGRESP, DISCONNECT
+};
+
+/**
+ * Bitfields for the MQTT header byte.
+ */
+typedef union
+{
+	unsigned char byte;	                /**< the whole byte */
+#if defined(REVERSED)
+	struct
+	{
+		unsigned int type : 4;			/**< message type nibble */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int retain : 1;		/**< retained flag bit */
+	} bits;
+#else
+	struct
+	{
+		unsigned int retain : 1;		/**< retained flag bit */
+		unsigned int qos : 2;				/**< QoS value, 0, 1 or 2 */
+		unsigned int dup : 1;				/**< DUP flag bit */
+		unsigned int type : 4;			/**< message type nibble */
+	} bits;
+#endif
+} MQTTHeader;
+
+typedef struct
+{
+	int len;
+	char* data;
+} MQTTLenString;
+
+typedef struct
+{
+	char* cstring;
+	MQTTLenString lenstring;
+} MQTTString;
+
+#define MQTTString_initializer {NULL, {0, NULL}}
+
+int MQTTstrlen(MQTTString mqttstring);
+
+#include "MQTTConnect.h"
+#include "MQTTPublish.h"
+#include "MQTTSubscribe.h"
+#include "MQTTUnsubscribe.h"
+#include "MQTTFormat.h"
+
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char type, unsigned char dup, unsigned short packetid);
+int MQTTDeserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, unsigned char* buf, int buflen);
+
+int MQTTPacket_len(int rem_len);
+int MQTTPacket_equals(MQTTString* a, char* b);
+
+int MQTTPacket_encode(unsigned char* buf, int length);
+int MQTTPacket_decode(int (*getcharfn)(unsigned char*, int), int* value);
+int MQTTPacket_decodeBuf(unsigned char* buf, int* value);
+
+int readInt(unsigned char** pptr);
+char readChar(unsigned char** pptr);
+void writeChar(unsigned char** pptr, char c);
+void writeInt(unsigned char** pptr, int anInt);
+int readMQTTLenString(MQTTString* mqttstring, unsigned char** pptr, unsigned char* enddata);
+void writeCString(unsigned char** pptr, const char* string);
+void writeMQTTString(unsigned char** pptr, MQTTString mqttstring);
+
+DLLExport int MQTTPacket_read(unsigned char* buf, int buflen, int (*getfn)(unsigned char*, int));
+
+typedef struct {
+	int (*getfn)(void *, unsigned char*, int); /* must return -1 for error, 0 for call again, or the number of bytes read */
+	void *sck;	/* pointer to whatever the system may use to identify the transport */
+	int multiplier;
+	int rem_len;
+	int len;
+	char state;
+}MQTTTransport;
+
+int MQTTPacket_readnb(unsigned char* buf, int buflen, MQTTTransport *trp);
+
+#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
+}
+#endif
+
+
+#endif /* MQTTPACKET_H_ */

+ 38 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTPublish.h

@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTPUBLISH_H_
+#define MQTTPUBLISH_H_
+
+#if !defined(DLLImport)
+  #define DLLImport 
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+		MQTTString topicName, unsigned char* payload, int payloadlen);
+
+DLLExport int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
+		unsigned char** payload, int* payloadlen, unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid);
+DLLExport int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid);
+DLLExport int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid);
+
+#endif /* MQTTPUBLISH_H_ */

+ 169 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSerializePublish.c

@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Determines the length of the MQTT publish packet that would be produced using the supplied parameters
+  * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
+  * @param topicName the topic name to be used in the publish  
+  * @param payloadlen the length of the payload to be sent
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_publishLength(int qos, MQTTString topicName, int payloadlen)
+{
+	int len = 0;
+
+	len += 2 + MQTTstrlen(topicName) + payloadlen;
+	if (qos > 0)
+		len += 2; /* packetid */
+	return len;
+}
+
+
+/**
+  * Serializes the supplied publish data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param qos integer - the MQTT QoS value
+  * @param retained integer - the MQTT retained flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param topicName MQTTString - the MQTT topic in the publish
+  * @param payload byte buffer - the MQTT publish payload
+  * @param payloadlen integer - the length of the MQTT payload
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid,
+		MQTTString topicName, unsigned char* payload, int payloadlen)
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.bits.type = PUBLISH;
+	header.bits.dup = dup;
+	header.bits.qos = qos;
+	header.bits.retain = retained;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeMQTTString(&ptr, topicName);
+
+	if (qos > 0)
+		writeInt(&ptr, packetid);
+
+	memcpy(ptr, payload, payloadlen);
+	ptr += payloadlen;
+
+	rc = ptr - buf;
+
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Serializes the ack packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param type the MQTT packet type
+  * @param dup the MQTT dup flag
+  * @param packetid the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 4)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.bits.type = packettype;
+	header.bits.dup = dup;
+	header.bits.qos = (packettype == PUBREL) ? 1 : 0;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+	writeInt(&ptr, packetid);
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes a puback packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBACK, 0, packetid);
+}
+
+
+/**
+  * Serializes a pubrel packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBREL, dup, packetid);
+}
+
+
+/**
+  * Serializes a pubrel packet into the supplied buffer.
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return serialized length, or error if 0
+  */
+int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid);
+}
+
+

+ 39 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSubscribe.h

@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTSUBSCRIBE_H_
+#define MQTTSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+  #define DLLImport
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[], char requestedQoSs[]);
+
+DLLExport int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid,
+		int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs);
+
+DLLExport int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len);
+
+
+#endif /* MQTTSUBSCRIBE_H_ */

+ 137 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSubscribeClient.c

@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
+  * @param count the number of topic filter strings in topicFilters
+  * @param topicFilters the array of topic filter strings to be used in the publish
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_subscribeLength(int count, MQTTString topicFilters[])
+{
+	int i;
+	int len = 2; /* packetid */
+
+	for (i = 0; i < count; ++i)
+		len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */
+	return len;
+}
+
+
+/**
+  * Serializes the supplied subscribe data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied bufferr
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the topicFilters and reqQos arrays
+  * @param topicFilters - array of topic filter names
+  * @param requestedQoSs - array of requested QoS
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count,
+		MQTTString topicFilters[], char requestedQoSs[])
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = 0;
+	int i = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = SUBSCRIBE;
+	header.bits.dup = dup;
+	header.bits.qos = 1;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+	{
+		writeMQTTString(&ptr, topicFilters[i]);
+		writeChar(&ptr, requestedQoSs[i]);
+	}
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+
+/**
+  * Deserializes the supplied (wire) buffer into suback data
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the grantedQoSs array
+  * @param count returned integer - number of members in the grantedQoSs array
+  * @param grantedQoSs returned array of integers - the granted qualities of service
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != SUBACK)
+		goto exit;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+	if (enddata - curdata < 2)
+		goto exit;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (*count > maxcount)
+		{
+			rc = -1;
+			goto exit;
+		}
+		grantedQoSs[(*count)++] = readChar(&curdata);
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+

+ 112 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTSubscribeServer.c

@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Deserializes the supplied (wire) buffer into subscribe data
+  * @param dup integer returned - the MQTT dup flag
+  * @param packetid integer returned - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+  * @param count - number of members in the topicFilters and requestedQoSs arrays
+  * @param topicFilters - array of topic filter names
+  * @param requestedQoSs - array of requested QoS
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+	int requestedQoSs[], unsigned char* buf, int buflen)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = -1;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != SUBSCRIBE)
+		goto exit;
+	*dup = header.bits.dup;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+			goto exit;
+		if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */
+			goto exit;
+		requestedQoSs[*count] = readChar(&curdata);
+		(*count)++;
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the supplied suback data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the grantedQoSs array
+  * @param grantedQoSs - array of granted QoS
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs)
+{
+	MQTTHeader header = {0};
+	int rc = -1;
+	unsigned char *ptr = buf;
+	int i;
+
+	FUNC_ENTRY;
+	if (buflen < 2 + count)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = SUBACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2 + count); /* write remaining length */
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+		writeChar(&ptr, grantedQoSs[i]);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+

+ 38 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTUnsubscribe.h

@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Xiang Rong - 442039 Add makefile to Embedded C client
+ *******************************************************************************/
+
+#ifndef MQTTUNSUBSCRIBE_H_
+#define MQTTUNSUBSCRIBE_H_
+
+#if !defined(DLLImport)
+  #define DLLImport 
+#endif
+#if !defined(DLLExport)
+  #define DLLExport
+#endif
+
+DLLExport int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[]);
+
+DLLExport int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[],
+		unsigned char* buf, int len);
+
+DLLExport int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid);
+
+DLLExport int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len);
+
+#endif /* MQTTUNSUBSCRIBE_H_ */

+ 106 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeClient.c

@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+/**
+  * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
+  * @param count the number of topic filter strings in topicFilters
+  * @param topicFilters the array of topic filter strings to be used in the publish
+  * @return the length of buffer needed to contain the serialized version of the packet
+  */
+int MQTTSerialize_unsubscribeLength(int count, MQTTString topicFilters[])
+{
+	int i;
+	int len = 2; /* packetid */
+
+	for (i = 0; i < count; ++i)
+		len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/
+	return len;
+}
+
+
+/**
+  * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @param dup integer - the MQTT dup flag
+  * @param packetid integer - the MQTT packet identifier
+  * @param count - number of members in the topicFilters array
+  * @param topicFilters - array of topic filter names
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid,
+		int count, MQTTString topicFilters[])
+{
+	unsigned char *ptr = buf;
+	MQTTHeader header = {0};
+	int rem_len = 0;
+	int rc = -1;
+	int i = 0;
+
+	FUNC_ENTRY;
+	if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+
+	header.byte = 0;
+	header.bits.type = UNSUBSCRIBE;
+	header.bits.dup = dup;
+	header.bits.qos = 1;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
+
+	writeInt(&ptr, packetid);
+
+	for (i = 0; i < count; ++i)
+		writeMQTTString(&ptr, topicFilters[i]);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Deserializes the supplied (wire) buffer into unsuback data
+  * @param packetid returned integer - the MQTT packet identifier
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return error code.  1 is success, 0 is failure
+  */
+int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int buflen)
+{
+	unsigned char type = 0;
+	unsigned char dup = 0;
+	int rc = 0;
+
+	FUNC_ENTRY;
+	rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
+	if (type == UNSUBACK)
+		rc = 1;
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+

+ 102 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeServer.c

@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#include "MQTTPacket.h"
+#include "StackTrace.h"
+
+#include <string.h>
+
+
+/**
+  * Deserializes the supplied (wire) buffer into unsubscribe data
+  * @param dup integer returned - the MQTT dup flag
+  * @param packetid integer returned - the MQTT packet identifier
+  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
+  * @param count - number of members in the topicFilters and requestedQoSs arrays
+  * @param topicFilters - array of topic filter names
+  * @param buf the raw buffer data, of the correct length determined by the remaining length field
+  * @param buflen the length in bytes of the data in the supplied buffer
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int maxcount, int* count, MQTTString topicFilters[],
+		unsigned char* buf, int len)
+{
+	MQTTHeader header = {0};
+	unsigned char* curdata = buf;
+	unsigned char* enddata = NULL;
+	int rc = 0;
+	int mylen = 0;
+
+	FUNC_ENTRY;
+	header.byte = readChar(&curdata);
+	if (header.bits.type != UNSUBSCRIBE)
+		goto exit;
+	*dup = header.bits.dup;
+
+	curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
+	enddata = curdata + mylen;
+
+	*packetid = readInt(&curdata);
+
+	*count = 0;
+	while (curdata < enddata)
+	{
+		if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
+			goto exit;
+		(*count)++;
+	}
+
+	rc = 1;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+
+/**
+  * Serializes the supplied unsuback data into the supplied buffer, ready for sending
+  * @param buf the buffer into which the packet will be serialized
+  * @param buflen the length in bytes of the supplied buffer
+  * @param packetid integer - the MQTT packet identifier
+  * @return the length of the serialized data.  <= 0 indicates error
+  */
+int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid)
+{
+	MQTTHeader header = {0};
+	int rc = 0;
+	unsigned char *ptr = buf;
+
+	FUNC_ENTRY;
+	if (buflen < 2)
+	{
+		rc = MQTTPACKET_BUFFER_TOO_SHORT;
+		goto exit;
+	}
+	header.byte = 0;
+	header.bits.type = UNSUBACK;
+	writeChar(&ptr, header.byte); /* write header */
+
+	ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
+
+	writeInt(&ptr, packetid);
+
+	rc = ptr - buf;
+exit:
+	FUNC_EXIT_RC(rc);
+	return rc;
+}
+
+

+ 78 - 0
lib/ioLibrary_Driver/Internet/MQTT/MQTTPacket/src/StackTrace.h

@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - fix for bug #434081
+ *******************************************************************************/
+
+#ifndef STACKTRACE_H_
+#define STACKTRACE_H_
+
+#include <stdio.h>
+#define NOSTACKTRACE 1
+
+#if defined(NOSTACKTRACE)
+#define FUNC_ENTRY
+#define FUNC_ENTRY_NOLOG
+#define FUNC_ENTRY_MED
+#define FUNC_ENTRY_MAX
+#define FUNC_EXIT
+#define FUNC_EXIT_NOLOG
+#define FUNC_EXIT_MED
+#define FUNC_EXIT_MAX
+#define FUNC_EXIT_RC(x)
+#define FUNC_EXIT_MED_RC(x)
+#define FUNC_EXIT_MAX_RC(x)
+
+#else
+
+#if defined(WIN32)
+#define inline __inline
+#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
+#else
+#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
+#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
+#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
+#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
+#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
+#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
+#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
+#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
+#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
+#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
+
+void StackTrace_entry(const char* name, int line, int trace);
+void StackTrace_exit(const char* name, int line, void* return_value, int trace);
+
+void StackTrace_printStack(FILE* dest);
+char* StackTrace_get(unsigned long);
+
+#endif
+
+#endif
+
+
+
+
+#endif /* STACKTRACE_H_ */

+ 182 - 0
lib/ioLibrary_Driver/Internet/MQTT/mqtt_interface.c

@@ -0,0 +1,182 @@
+//*****************************************************************************
+//! \file mqtt_interface.c
+//! \brief Paho MQTT to WIZnet Chip interface implement file.
+//! \details The process of porting an interface to use paho MQTT.
+//! \version 1.0.0
+//! \date 2016/12/06
+//! \par  Revision history
+//!       <2016/12/06> 1st Release
+//!
+//! \author Peter Bang & Justin Kim
+//! \copyright
+//!
+//! Copyright (c)  2016, WIZnet Co., LTD.
+//! All rights reserved.
+//!
+//! Redistribution and use in source and binary forms, with or without
+//! modification, are permitted provided that the following conditions
+//! are met:
+//!
+//!     * Redistributions of source code must retain the above copyright
+//! notice, this list of conditions and the following disclaimer.
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution.
+//!     * Neither the name of the <ORGANIZATION> nor the names of its
+//! contributors may be used to endorse or promote products derived
+//! from this software without specific prior written permission.
+//!
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+#include "mqtt_interface.h"
+#include "wizchip_conf.h"
+#include "socket.h"
+
+unsigned long MilliTimer;
+
+/*
+ * @brief MQTT MilliTimer handler
+ * @note MUST BE register to your system 1m Tick timer handler.
+ */
+void MilliTimer_Handler(void) {
+	MilliTimer++;
+}
+
+/*
+ * @brief Timer Initialize
+ * @param  timer : pointer to a Timer structure
+ *         that contains the configuration information for the Timer.
+ */
+void TimerInit(Timer* timer) {
+	timer->end_time = 0;
+}
+
+/*
+ * @brief expired Timer
+ * @param  timer : pointer to a Timer structure
+ *         that contains the configuration information for the Timer.
+ */
+char TimerIsExpired(Timer* timer) {
+	long left = timer->end_time - MilliTimer;
+	return (left < 0);
+}
+
+/*
+ * @brief Countdown millisecond Timer
+ * @param  timer : pointer to a Timer structure
+ *         that contains the configuration information for the Timer.
+ *         timeout : setting timeout millisecond.
+ */
+void TimerCountdownMS(Timer* timer, unsigned int timeout) {
+	timer->end_time = MilliTimer + timeout;
+}
+
+/*
+ * @brief Countdown second Timer
+ * @param  timer : pointer to a Timer structure
+ *         that contains the configuration information for the Timer.
+ *         timeout : setting timeout millisecond.
+ */
+void TimerCountdown(Timer* timer, unsigned int timeout) {
+	timer->end_time = MilliTimer + (timeout * 1000);
+}
+
+/*
+ * @brief left millisecond Timer
+ * @param  timer : pointer to a Timer structure
+ *         that contains the configuration information for the Timer.
+ */
+int TimerLeftMS(Timer* timer) {
+	long left = timer->end_time - MilliTimer;
+	return (left < 0) ? 0 : left;
+}
+
+/*
+ * @brief New network setting
+ * @param  n : pointer to a Network structure
+ *         that contains the configuration information for the Network.
+ *         sn : socket number where x can be (0..7).
+ * @retval None
+ */
+void NewNetwork(Network* n, int sn) {
+	n->my_socket = sn;
+	n->mqttread = w5x00_read;
+	n->mqttwrite = w5x00_write;
+	n->disconnect = w5x00_disconnect;
+}
+
+/*
+ * @brief read function
+ * @param  n : pointer to a Network structure
+ *         that contains the configuration information for the Network.
+ *         buffer : pointer to a read buffer.
+ *         len : buffer length.
+ * @retval received data length or SOCKERR code
+ */
+int w5x00_read(Network* n, unsigned char* buffer, int len, long time)
+{
+
+	if((getSn_SR(n->my_socket) == SOCK_ESTABLISHED) && (getSn_RX_RSR(n->my_socket)>0))
+		return recv(n->my_socket, buffer, len);
+
+	return SOCK_ERROR;
+}
+
+/*
+ * @brief write function
+ * @param  n : pointer to a Network structure
+ *         that contains the configuration information for the Network.
+ *         buffer : pointer to a read buffer.
+ *         len : buffer length.
+ * @retval length of data sent or SOCKERR code
+ */
+int w5x00_write(Network* n, unsigned char* buffer, int len, long time)
+{
+	if(getSn_SR(n->my_socket) == SOCK_ESTABLISHED)
+		return send(n->my_socket, buffer, len);
+
+	return SOCK_ERROR;
+}
+
+/*
+ * @brief disconnect function
+ * @param  n : pointer to a Network structure
+ *         that contains the configuration information for the Network.
+ */
+void w5x00_disconnect(Network* n)
+{
+	disconnect(n->my_socket);
+}
+
+/*
+ * @brief connect network function
+ * @param  n : pointer to a Network structure
+ *         that contains the configuration information for the Network.
+ *         ip : server iP.
+ *         port : server port.
+ * @retval SOCKOK code or SOCKERR code
+ */
+int ConnectNetwork(Network* n, uint8_t* ip, uint16_t port)
+{
+	uint16_t myport = 12345;
+
+	if(socket(n->my_socket, Sn_MR_TCP, myport, 0) != n->my_socket)
+		return SOCK_ERROR;
+
+	if(connect(n->my_socket, ip, port) != SOCK_OK)
+		return SOCK_ERROR;
+
+	return SOCK_OK;
+}

+ 271 - 0
lib/ioLibrary_Driver/Internet/MQTT/mqtt_interface.h

@@ -0,0 +1,271 @@
+//*****************************************************************************
+//! \file mqtt_interface.h
+//! \brief Paho MQTT to WIZnet Chip interface Header file.
+//! \details The process of porting an interface to use paho MQTT.
+//! \version 1.0.0
+//! \date 2016/12/06
+//! \par  Revision history
+//!       <2016/12/06> 1st Release
+//!
+//! \author Peter Bang & Justin Kim
+//! \copyright
+//!
+//! Copyright (c)  2016, WIZnet Co., LTD.
+//! All rights reserved.
+//!
+//! Redistribution and use in source and binary forms, with or without
+//! modification, are permitted provided that the following conditions
+//! are met:
+//!
+//!     * Redistributions of source code must retain the above copyright
+//! notice, this list of conditions and the following disclaimer.
+//!     * Redistributions in binary form must reproduce the above copyright
+//! notice, this list of conditions and the following disclaimer in the
+//! documentation and/or other materials provided with the distribution.
+//!     * Neither the name of the <ORGANIZATION> nor the names of its
+//! contributors may be used to endorse or promote products derived
+//! from this software without specific prior written permission.
+//!
+//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+//! THE POSSIBILITY OF SUCH DAMAGE.
+//
+//*****************************************************************************
+
+/* MQTT subscribe Example.... W5500 + STM32F103(IoT board)
+//Include: Board configuration
+#include "IoTEVB.h"
+
+//Include: MCU peripheral Library
+#include "stm32f10x_rcc.h"
+#include "stm32f10x.h"
+
+//Include: W5500 iolibrary
+#include "w5500.h"
+#include "wizchip_conf.h"
+#include "misc.h"
+
+//Include: Internet iolibrary
+#include "MQTTClient.h"
+
+//Include: MCU Specific W5500 driver
+#include "W5500HardwareDriver.h"
+
+//Include: Standard IO Library
+#include <stdio.h>
+
+//Socket number defines
+#define TCP_SOCKET	0
+
+//Receive Buffer Size define
+#define BUFFER_SIZE	2048
+
+//Global variables
+unsigned char targetIP[4] = {}; // mqtt server IP
+unsigned int targetPort = 1883; // mqtt server port
+uint8_t mac_address[6] = {};
+wiz_NetInfo gWIZNETINFO = { .mac = {}, //user MAC
+							.ip = {}, //user IP
+							.sn = {},
+							.gw = {},
+							.dns = {},
+							.dhcp = NETINFO_STATIC};
+
+unsigned char tempBuffer[BUFFER_SIZE] = {};
+
+struct opts_struct
+{
+	char* clientid;
+	int nodelimiter;
+	char* delimiter;
+	enum QoS qos;
+	char* username;
+	char* password;
+	char* host;
+	int port;
+	int showtopics;
+} opts ={ (char*)"stdout-subscriber", 0, (char*)"\n", QOS0, NULL, NULL, targetIP, targetPort, 0 };
+
+
+// @brief messageArrived callback function
+void messageArrived(MessageData* md)
+{
+	unsigned char testbuffer[100];
+	MQTTMessage* message = md->message;
+
+	if (opts.showtopics)
+	{
+		memcpy(testbuffer,(char*)message->payload,(int)message->payloadlen);
+		*(testbuffer + (int)message->payloadlen + 1) = "\n";
+		printf("%s\r\n",testbuffer);
+	}
+
+	if (opts.nodelimiter)
+		printf("%.*s", (int)message->payloadlen, (char*)message->payload);
+	else
+		printf("%.*s%s", (int)message->payloadlen, (char*)message->payload, opts.delimiter);
+}
+
+
+// @brief 1 millisecond Tick Timer setting
+void NVIC_configuration(void)
+{
+	NVIC_InitTypeDef NVIC_InitStructure;
+	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
+	SysTick_Config(72000);
+	NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
+	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Highest priority
+	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+	NVIC_Init(&NVIC_InitStructure);
+}
+
+// @brief 1 millisecond Tick Timer Handler setting
+void SysTick_Handler(void)
+{
+	MilliTimer_Handler();
+}
+
+int main(void)
+{
+	led_ctrl led1,led2;
+	int i;
+	int rc = 0;
+	unsigned char buf[100];
+	//Usart initialization for Debug.
+	USART1Initialze();
+		printf("USART initialized.\n\r");
+
+	I2C1Initialize();
+		printf("I2C initialized.\n\r");
+
+	MACEEP_Read(mac_address,0xfa,6);
+
+	printf("Mac address\n\r");
+	for(i = 0 ; i < 6 ; i++)
+	{
+		printf("%02x ",mac_address[i]);
+	}
+	printf("\n\r");
+
+	//LED initialization.
+	led_initialize();
+	led1 = led2 = ON;
+
+	led2Ctrl(led2);
+	led1Ctrl(led1);
+
+	//W5500 initialization.
+	W5500HardwareInitilize();
+		printf("W5500 hardware interface initialized.\n\r");
+
+	W5500Initialze();
+		printf("W5500 IC initialized.\n\r");
+
+	//Set network informations
+	wizchip_setnetinfo(&gWIZNETINFO);
+
+	setSHAR(mac_address);
+
+	print_network_information();
+
+	Network n;
+	MQTTClient c;
+
+	NewNetwork(&n, TCP_SOCKET);
+	ConnectNetwork(&n, targetIP, targetPort);
+	MQTTClientInit(&c,&n,1000,buf,100,tempBuffer,2048);
+
+	MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+	data.willFlag = 0;
+	data.MQTTVersion = 3;
+	data.clientID.cstring = opts.clientid;
+	data.username.cstring = opts.username;
+	data.password.cstring = opts.password;
+
+	data.keepAliveInterval = 60;
+	data.cleansession = 1;
+
+	rc = MQTTConnect(&c, &data);
+	printf("Connected %d\r\n", rc);
+	opts.showtopics = 1;
+
+	printf("Subscribing to %s\r\n", "hello/wiznet");
+	rc = MQTTSubscribe(&c, "hello/wiznet", opts.qos, messageArrived);
+	printf("Subscribed %d\r\n", rc);
+
+    while(1)
+    {
+    	MQTTYield(&c, data.keepAliveInterval);
+    }
+}
+*/
+
+#ifndef __MQTT_INTERFACE_H_
+#define __MQTT_INTERFACE_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * @brief MQTT MilliTimer handler
+ * @note MUST BE register to your system 1m Tick timer handler
+ */
+void MilliTimer_Handler(void);
+
+/*
+ * @brief Timer structure
+ */
+typedef struct Timer Timer;
+struct Timer {
+	unsigned long systick_period;
+	unsigned long end_time;
+};
+
+/*
+ * @brief Network structure
+ */
+typedef struct Network Network;
+struct Network
+{
+	int my_socket;
+	int (*mqttread) (Network*, unsigned char*, int, long);
+	int (*mqttwrite) (Network*, unsigned char*, int, long);
+	void (*disconnect) (Network*);
+};
+
+/*
+ * @brief Timer function
+ */
+void TimerInit(Timer*);
+char TimerIsExpired(Timer*);
+void TimerCountdownMS(Timer*, unsigned int);
+void TimerCountdown(Timer*, unsigned int);
+int TimerLeftMS(Timer*);
+
+/*
+ * @brief Network interface porting
+ */
+int w5x00_read(Network*, unsigned char*, int, long);
+int w5x00_write(Network*, unsigned char*, int, long);
+void w5x00_disconnect(Network*);
+void NewNetwork(Network* n, int sn);
+int ConnectNetwork(Network* n, uint8_t* ip, uint16_t port);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__MQTT_INTERFACE_H_

+ 927 - 0
lib/ioLibrary_Driver/Internet/SNMP/snmp.c

@@ -0,0 +1,927 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>     
+#include <time.h>
+
+#include "socket.h"
+#include "snmp.h"
+#include "snmp_custom.h"
+
+/********************************************************************************************/
+/* SNMP : Functions declaration                                                             */
+/********************************************************************************************/
+// SNMP Parsing functions
+int32_t findEntry(uint8_t *oid, int32_t len);
+int32_t getOID(int32_t id, uint8_t *oid, uint8_t *len);
+int32_t getValue( uint8_t *vptr, int32_t vlen);
+int32_t getEntry(int32_t id, uint8_t *dataType, void *ptr, int32_t *len);
+int32_t setEntry(int32_t id, void *val, int32_t vlen, uint8_t dataType, int32_t index);
+int32_t makeTrapVariableBindings(dataEntryType *oid_data, void *ptr, uint32_t *len);
+
+int32_t parseLength(const uint8_t *msg, int32_t *len);
+int32_t parseTLV(const uint8_t *msg, int32_t index, tlvStructType *tlv);
+void insertRespLen(int32_t reqStart, int32_t respStart, int32_t size);
+int32_t parseVarBind(int32_t reqType, int32_t index);
+int32_t parseSequence(int32_t reqType, int32_t index);
+int32_t parseSequenceOf(int32_t reqType);
+int32_t parseRequest();
+int32_t parseCommunity();
+int32_t parseVersion();
+int32_t parseSNMPMessage();
+
+// Debugging function
+#ifdef _SNMP_DEBUG_
+void dumpCode(uint8_t* header, uint8_t* tail, uint8_t *buff, int32_t len);
+#endif
+
+// Utils
+void ipToByteArray(int8_t *ip, uint8_t *pDes);
+
+/********************************************************************************************/
+/* SNMP : Variable declaration                                                              */
+/********************************************************************************************/
+// SNMP message structures
+struct messageStruct request_msg;
+struct messageStruct response_msg;
+
+// SNMP Time counter
+static time_t startTime = 0;
+volatile uint32_t snmp_tick_10ms = 0; //volatile uint32_t snmp_tick_1ms = 0;
+
+// SNMP Sockets
+static uint8_t SOCK_SNMP_AGENT;
+static uint8_t SOCK_SNMP_TRAP;
+
+uint8_t packet_trap[MAX_TRAPMSG_LEN] = {0,};
+uint8_t errorStatus, errorIndex;
+
+
+/********************************************************************************************/
+/* SNMP : Time handler                                                                      */
+/********************************************************************************************/
+void currentUptime(void *ptr, uint8_t *len)
+{
+	time_t curTime = getSNMPTimeTick();
+
+	//*(uint32_t *)ptr = (uint32_t)(curTime - startTime) / 10; // calculation for 1ms tick
+	*(uint32_t *)ptr = (uint32_t)(curTime - startTime); // calculation for 10ms tick
+	*len = 4;
+}
+
+void SNMP_time_handler(void)
+{
+	//snmp_tick_1ms++;
+	snmp_tick_10ms++;
+}
+
+uint32_t getSNMPTimeTick(void)
+{
+	//return snmp_tick_1ms;
+	return snmp_tick_10ms;
+}
+
+
+/********************************************************************************************/
+/* SNMP : Library Part                                                                      */
+/********************************************************************************************/
+/**
+ * @addtogroup snmp_module
+ * @{
+ */
+
+/**
+ * Initialize SNMP Daemon.
+ * This should be called just one time at first time
+ *
+ * @param none
+ * @return none
+ */
+void snmpd_init(uint8_t * managerIP, uint8_t * agentIP, uint8_t sn_agent, uint8_t sn_trap)
+{
+#ifdef _SNMP_DEBUG_
+    printf("\r\n - SNMP : Start SNMP Agent Daemon\r\n");
+#endif
+    SOCK_SNMP_AGENT = sn_agent;
+    SOCK_SNMP_TRAP = sn_trap;
+
+    if((SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) || (SOCK_SNMP_TRAP > _WIZCHIP_SOCK_NUM_)) return;
+
+    startTime = getSNMPTimeTick(); // Start time (unit: 10ms)
+    initTable(); // Settings for OID entry values
+    
+    initial_Trap(managerIP, agentIP);
+
+/*
+    // Example Codes for SNMP Trap
+    {
+		dataEntryType enterprise_oid = {0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
+    	    									SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\x9b\x19\x10\x00"},	NULL, NULL};
+
+		dataEntryType trap_oid1 = {8, {0x2b, 6, 1, 4, 1, 0, 11, 0}, SNMPDTYPE_OCTET_STRING, 30, {""}, NULL, NULL};
+		dataEntryType trap_oid2 = {8, {0x2b, 6, 1, 4, 1, 0, 12, 0}, SNMPDTYPE_INTEGER, 4, {""}, NULL, NULL};
+
+		strcpy((char *)trap_oid1.u.octetstring, "Alert!!!"); 	// String added
+		trap_oid2.u.intval = 123456;	// Integer value added
+
+		// Generic Trap: warmStart
+		snmp_sendTrap((void *)"192.168.0.214", (void *)"192.168.0.112", (void *)"public", enterprise_oid, SNMPTRAP_WARMSTART, 0, 0);
+
+		// Enterprise-Specific Trap
+		snmp_sendTrap((void *)"192.168.0.214", (void *)"192.168.0.112", (void *)"public", enterprise_oid, 6, 0, 2, &trap_oid1, &trap_oid2);
+	}
+*/
+}
+
+
+/**
+ * SNMP Process Handler.
+ * UDP Socket and SNMP Agent transaction handling.
+ *
+ * @param none
+ * @return none
+ */
+
+int32_t snmpd_run(void)
+{
+    int32_t ret;
+	int32_t len = 0;
+    
+	uint8_t svr_addr[6];
+	uint16_t  svr_port;
+
+	if(SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) return -99;
+    
+	switch(getSn_SR(SOCK_SNMP_AGENT))
+	{
+		case SOCK_UDP :
+			if ( (len = getSn_RX_RSR(SOCK_SNMP_AGENT)) > 0)
+			{
+				request_msg.len= recvfrom(SOCK_SNMP_AGENT, request_msg.buffer, len, svr_addr, &svr_port);
+			}
+			else
+			{
+				request_msg.len = 0;
+			}
+
+			if (request_msg.len > 0)
+			{
+#ifdef _SNMP_DEBUG_
+				dumpCode((void *)"\r\n[Request]\r\n", (void *)"\r\n", request_msg.buffer, request_msg.len);
+#endif
+				// Initialize
+				request_msg.index = 0;
+				response_msg.index = 0;
+				errorStatus = errorIndex = 0;
+				memset(response_msg.buffer, 0x00, MAX_SNMPMSG_LEN);
+
+				// Received message parsing and send response process
+				if (parseSNMPMessage() != -1)
+				{
+					sendto(SOCK_SNMP_AGENT, response_msg.buffer, response_msg.index, svr_addr, svr_port);
+				}
+
+#ifdef _SNMP_DEBUG_
+				dumpCode((void *)"\r\n[Response]\r\n", (void *)"\r\n", response_msg.buffer, response_msg.index);
+#endif
+			}
+			break;
+
+		case SOCK_CLOSED :
+			if((ret = socket(SOCK_SNMP_AGENT, Sn_MR_UDP, PORT_SNMP_AGENT, 0x00)) != SOCK_SNMP_AGENT)
+				return ret;
+#ifdef _SNMP_DEBUG_
+			printf(" - [%d] UDP Socket for SNMP Agent, port [%d]\r\n", SOCK_SNMP_AGENT, PORT_SNMP_AGENT);
+#endif
+			break;
+
+		default :
+			break;
+	}
+
+
+	return 1;
+}
+
+
+int32_t findEntry(uint8_t *oid, int32_t len)
+{
+	int32_t i;
+
+	for (i = 0 ; i < maxData ; i++)
+	{
+		if (len == snmpData[i].oidlen)
+		{
+			if (!memcmp(snmpData[i].oid, oid, len)) return(i);
+		}
+	}
+
+	return OID_NOT_FOUND;
+}
+
+
+int32_t getOID(int32_t id, uint8_t *oid, uint8_t *len)
+{
+	int32_t j;
+
+	if (!((id >= 0) && (id < maxData))) return INVALID_ENTRY_ID;
+
+	*len = snmpData[id].oidlen;
+
+	for (j = 0 ; j < *len ; j++)
+	{
+		oid[j] = snmpData[id].oid[j];
+	}
+
+	return SNMP_SUCCESS;
+}
+
+
+int32_t getValue( uint8_t *vptr, int32_t vlen)
+{
+	int32_t index = 0;
+	int32_t value = 0;
+
+	while (index < vlen)
+	{
+		if (index != 0) value <<= 8;
+		value |= vptr[index++];
+	}
+
+	return value;
+}
+
+
+int32_t getEntry(int32_t id, uint8_t *dataType, void *ptr, int32_t *len)
+{
+	uint8_t * ptr_8;
+	int32_t value;
+
+	uint8_t * string;
+	int32_t j;
+
+	if (!((id >= 0) && (id < maxData))) return INVALID_ENTRY_ID;
+
+	*dataType = snmpData[id].dataType;
+
+	switch(*dataType)
+	{
+	case SNMPDTYPE_OCTET_STRING :
+	case SNMPDTYPE_OBJ_ID :
+		{
+			string = ptr;
+
+			if (snmpData[id].getfunction != NULL)
+			{
+				snmpData[id].getfunction( (void *)&snmpData[id].u.octetstring, &snmpData[id].dataLen );
+			}
+
+			if ( (*dataType)==SNMPDTYPE_OCTET_STRING )
+			{
+				snmpData[id].dataLen = (uint8_t)strlen((char const*)&snmpData[id].u.octetstring);
+			}
+
+			*len = snmpData[id].dataLen;
+			for (j = 0 ; j < *len ; j++)
+			{
+				string[j] = snmpData[id].u.octetstring[j];
+			}
+		}
+		break;
+
+	case SNMPDTYPE_INTEGER :
+	case SNMPDTYPE_TIME_TICKS :
+	case SNMPDTYPE_COUNTER :
+	case SNMPDTYPE_GAUGE :
+		{
+			if (snmpData[id].getfunction != NULL)
+			{
+				snmpData[id].getfunction( (void *)&snmpData[id].u.intval, &snmpData[id].dataLen );
+			}
+
+			if(snmpData[id].dataLen) 	*len = snmpData[id].dataLen;
+			else 						*len = sizeof(uint32_t);
+
+			/*
+			// Original code (IAR, STM32)
+			// This code is not working in NXP+LPCXpresso (32-bit pointer operation error)
+			value = (int32_t *)ptr;
+			*value = HTONL(snmpData[id].u.intval);
+			*/
+
+			ptr_8 = ptr;
+			//value = HTONL(snmpData[id].u.intval); // Endian convert when processing 32bit pointer operation
+			value = snmpData[id].u.intval;
+
+			for (j = 0 ; j < *len ; j++)
+			{
+				ptr_8[j] = (uint8_t)((value >> ((*len-j-1)*8)));
+			}
+		}
+		break;
+
+	default : 
+		return INVALID_DATA_TYPE;
+	}
+
+	return SNMP_SUCCESS;
+}
+
+
+int32_t setEntry(int32_t id, void *val, int32_t vlen, uint8_t dataType, int32_t index)
+{
+
+	int32_t retStatus=OID_NOT_FOUND;
+	int32_t j;
+
+	if (snmpData[id].dataType != dataType)
+	{
+		errorStatus = BAD_VALUE; 
+		errorIndex = index;
+		return INVALID_DATA_TYPE;
+	}
+
+	switch(snmpData[id].dataType)
+	{
+	case SNMPDTYPE_OCTET_STRING :
+	case SNMPDTYPE_OBJ_ID :
+		{
+			uint8_t *string = val;
+			for (j = 0 ; j < vlen ; j++)
+			{
+				snmpData[id].u.octetstring[j] = string[j];
+			}
+			snmpData[id].dataLen = vlen;
+		}
+		retStatus = SNMP_SUCCESS;
+		break;
+
+	case SNMPDTYPE_INTEGER :
+	case SNMPDTYPE_TIME_TICKS :
+	case SNMPDTYPE_COUNTER :
+	case SNMPDTYPE_GAUGE :
+		{
+			snmpData[id].u.intval = getValue( (uint8_t *)val, vlen);
+			snmpData[id].dataLen = vlen;
+
+			if (snmpData[id].setfunction != NULL)
+			{
+				snmpData[id].setfunction(snmpData[id].u.intval);
+			}
+
+		}
+		retStatus = SNMP_SUCCESS;
+		break;
+
+	default : 
+		retStatus = INVALID_DATA_TYPE;
+		break;
+
+	}
+
+	return retStatus;
+}
+
+
+int32_t parseLength(const uint8_t *msg, int32_t *len)
+{
+	int32_t i=1;
+
+	if (msg[0] & 0x80)
+	{
+		int32_t tlen = (msg[0] & 0x7f) - 1;
+		*len = msg[i++];
+
+		while (tlen--)
+		{
+			*len <<= 8;
+			*len |= msg[i++];
+		}
+	}
+	else
+	{
+		*len = msg[0];
+	}
+
+	return i;
+}
+
+
+int32_t parseTLV(const uint8_t *msg, int32_t index, tlvStructType *tlv)
+{
+	int32_t Llen = 0;
+
+	tlv->start = index;
+
+	Llen = parseLength((const uint8_t *)&msg[index+1], &tlv->len );
+
+	tlv->vstart = index + Llen + 1;
+
+	switch (msg[index])
+	{
+	case SNMPDTYPE_SEQUENCE:
+	case GET_REQUEST:
+	case GET_NEXT_REQUEST:
+	case SET_REQUEST:
+		tlv->nstart = tlv->vstart;
+		break;
+	default:
+		tlv->nstart = tlv->vstart + tlv->len;
+		break;
+	}
+
+	return 0;
+}
+
+
+void insertRespLen(int32_t reqStart, int32_t respStart, int32_t size)
+{
+	int32_t indexStart, lenLength;
+	uint32_t mask = 0xff;
+	int32_t shift = 0;
+
+	if (request_msg.buffer[reqStart+1] & 0x80)
+	{
+		lenLength = request_msg.buffer[reqStart+1] & 0x7f;
+		indexStart = respStart+2;
+
+		while (lenLength--)
+		{
+			response_msg.buffer[indexStart+lenLength] = 
+				(uint8_t)((size & mask) >> shift);
+			shift+=8;
+			mask <<= shift;
+		}
+	}
+	else
+	{
+		response_msg.buffer[respStart+1] = (uint8_t)(size & 0xff);
+	}
+}
+
+int32_t parseVarBind(int32_t reqType, int32_t index)
+{
+	int32_t seglen = 0, id;
+	tlvStructType name, value;
+	int32_t size = 0;
+	
+	//extern const int32_t maxData;
+
+	parseTLV(request_msg.buffer, request_msg.index, &name);
+
+	if ( request_msg.buffer[name.start] != SNMPDTYPE_OBJ_ID ) return -1;
+
+	id = findEntry(&request_msg.buffer[name.vstart], name.len);
+
+	if ((reqType == GET_REQUEST) || (reqType == SET_REQUEST))
+	{
+		seglen = name.nstart - name.start;
+		COPY_SEGMENT(name);
+		size = seglen;
+	}
+	else if (reqType == GET_NEXT_REQUEST)
+	{
+		response_msg.buffer[response_msg.index] = request_msg.buffer[name.start];
+
+		if (++id >= maxData)
+		{
+			id = OID_NOT_FOUND;
+			seglen = name.nstart - name.start;
+			COPY_SEGMENT(name);
+			size = seglen;
+		}
+		else
+		{
+			request_msg.index += name.nstart - name.start;
+
+			getOID(id, &response_msg.buffer[response_msg.index+2], &response_msg.buffer[response_msg.index+1]);
+
+			seglen = response_msg.buffer[response_msg.index+1]+2;
+			response_msg.index += seglen ;
+			size = seglen;
+		}
+	}
+
+	parseTLV(request_msg.buffer, request_msg.index, &value);
+
+	if (id != OID_NOT_FOUND)
+	{
+		uint8_t dataType;
+		int32_t len;
+
+		if ((reqType == GET_REQUEST) || (reqType == GET_NEXT_REQUEST))
+		{
+			getEntry(id, &dataType, &response_msg.buffer[response_msg.index+2], &len);
+
+			response_msg.buffer[response_msg.index] = dataType;
+			response_msg.buffer[response_msg.index+1] = len;
+			seglen = (2 + len);
+			response_msg.index += seglen;
+
+			request_msg.index += (value.nstart - value.start);
+
+		}
+		else if (reqType == SET_REQUEST)
+		{
+			setEntry(id, &request_msg.buffer[value.vstart], value.len, request_msg.buffer[value.start], index);
+			seglen = value.nstart - value.start;
+			COPY_SEGMENT(value);
+		}
+	}
+	else
+	{
+		seglen = value.nstart - value.start;
+		COPY_SEGMENT(value);
+
+		errorIndex = index;
+		errorStatus = NO_SUCH_NAME;
+	}
+
+	size += seglen;
+
+	return size;
+}
+
+
+int32_t parseSequence(int32_t reqType, int32_t index)
+{
+	int32_t seglen;
+	tlvStructType seq;
+	int32_t size = 0, respLoc;
+
+	parseTLV(request_msg.buffer, request_msg.index, &seq);
+
+	if ( request_msg.buffer[seq.start] != SNMPDTYPE_SEQUENCE ) return -1;
+
+	seglen = seq.vstart - seq.start;
+	respLoc = response_msg.index;
+	COPY_SEGMENT(seq);
+
+	size = parseVarBind( reqType, index );
+	insertRespLen(seq.start, respLoc, size);
+	size += seglen;
+
+	return size;
+}
+
+
+int32_t parseSequenceOf(int32_t reqType)
+{
+	int32_t seglen;
+	tlvStructType seqof;
+	int32_t size = 0, respLoc;
+	int32_t index = 0;
+
+	parseTLV(request_msg.buffer, request_msg.index, &seqof);
+
+	if ( request_msg.buffer[seqof.start] != SNMPDTYPE_SEQUENCE_OF ) return -1;
+
+	seglen = seqof.vstart - seqof.start;
+	respLoc = response_msg.index;
+	COPY_SEGMENT(seqof);
+
+	while (request_msg.index < request_msg.len)
+	{
+		size += parseSequence( reqType, index++ );
+	}
+
+	insertRespLen(seqof.start, respLoc, size);
+
+	return size;
+}
+
+
+int32_t parseRequest()
+{
+	int32_t ret, seglen;
+	tlvStructType snmpreq, requestid, errStatus, errIndex;
+	int32_t size = 0, respLoc, reqType;
+
+	parseTLV(request_msg.buffer, request_msg.index, &snmpreq);
+
+	reqType = request_msg.buffer[snmpreq.start];
+
+	if ( !VALID_REQUEST(reqType) ) return -1;
+
+	seglen = snmpreq.vstart - snmpreq.start;
+	respLoc = snmpreq.start;
+	size += seglen;
+	COPY_SEGMENT(snmpreq);
+
+	response_msg.buffer[snmpreq.start] = GET_RESPONSE;
+
+	parseTLV(request_msg.buffer, request_msg.index, &requestid);
+	seglen = requestid.nstart - requestid.start;
+	size += seglen;
+	COPY_SEGMENT(requestid);
+
+	parseTLV(request_msg.buffer, request_msg.index, &errStatus);
+	seglen = errStatus.nstart - errStatus.start;
+	size += seglen;
+	COPY_SEGMENT(errStatus);
+
+	parseTLV(request_msg.buffer, request_msg.index, &errIndex);
+	seglen = errIndex.nstart - errIndex.start;
+	size += seglen;
+	COPY_SEGMENT(errIndex);
+
+	ret = parseSequenceOf(reqType);
+	if (ret == -1) return -1;
+	else size += ret;
+
+	insertRespLen(snmpreq.start, respLoc, size);
+
+	if (errorStatus)
+	{
+		response_msg.buffer[errStatus.vstart] = errorStatus;
+		response_msg.buffer[errIndex.vstart] = errorIndex + 1;
+	}
+
+	return size;
+}
+
+
+int32_t parseCommunity()
+{
+	int32_t seglen;
+	tlvStructType community;
+	int32_t size=0;
+
+	parseTLV(request_msg.buffer, request_msg.index, &community);
+
+	if (!((request_msg.buffer[community.start] == SNMPDTYPE_OCTET_STRING) && (community.len == COMMUNITY_SIZE))) 
+	{
+		return -1;
+	}
+
+	if (!memcmp(&request_msg.buffer[community.vstart], (int8_t *)COMMUNITY, COMMUNITY_SIZE))
+	{
+		seglen = community.nstart - community.start;
+		size += seglen;
+		COPY_SEGMENT(community);
+
+		size += parseRequest();
+	}
+	else
+	{
+		return -1;
+	}
+
+	return size;
+}
+
+
+int32_t parseVersion()
+{
+	int32_t size = 0, seglen;
+	tlvStructType tlv;
+
+	size = parseTLV(request_msg.buffer, request_msg.index, &tlv);
+
+	if (!((request_msg.buffer[tlv.start] == SNMPDTYPE_INTEGER) && (request_msg.buffer[tlv.vstart] == SNMP_V1)))
+		return -1;
+
+	seglen = tlv.nstart - tlv.start;
+	size += seglen;
+	COPY_SEGMENT(tlv);
+	size = parseCommunity();
+
+	if (size == -1) return size;
+	else return (size + seglen);
+}
+
+
+int32_t parseSNMPMessage()
+{
+	int32_t size = 0, seglen, respLoc;
+	tlvStructType tlv;
+
+	parseTLV(request_msg.buffer, request_msg.index, &tlv);
+
+	if (request_msg.buffer[tlv.start] != SNMPDTYPE_SEQUENCE_OF) return -1;
+
+	seglen = tlv.vstart - tlv.start;
+	respLoc = tlv.start;
+	COPY_SEGMENT(tlv);
+
+	size = parseVersion();
+
+	if (size == -1) return -1;
+	else size += seglen;
+
+	insertRespLen(tlv.start, respLoc, size);
+
+	return 0;
+}
+
+void ipToByteArray(int8_t *ip, uint8_t *pDes)
+{
+	uint32_t i, ip1=0, ip2=0, ip3=0, ip4=0;
+	int8_t buff[32];
+	uint32_t len = (uint32_t)strlen((char const*)ip);
+	strcpy((char *)buff, (char const*)ip);
+
+	for (i=0; i<len; i++)
+	{
+		if ( buff[i]=='.' )		buff[i] = ' ';
+	}
+
+	sscanf((char const*)buff, "%u %u %u %u", &ip1, &ip2, &ip3, &ip4);
+	pDes[0] = ip1; pDes[1] = ip2; pDes[2] = ip3; pDes[3] = ip4;
+}
+
+
+int32_t makeTrapVariableBindings(dataEntryType *oid_data, void *ptr, uint32_t *len)
+{
+	uint32_t j;
+    
+    ((uint8_t*)ptr)[0] = 0x30;
+	((uint8_t*)ptr)[1] = 0xff;
+	((uint8_t*)ptr)[2] = 0x06;
+	((uint8_t*)ptr)[3] = oid_data->oidlen;
+
+	for (j = 0 ; j < oid_data->oidlen ; j++)
+	{
+		((uint8_t*)ptr)[j+4] = oid_data->oid[j];
+	}
+
+	switch(oid_data->dataType)
+	{
+	case SNMPDTYPE_OCTET_STRING :
+	case SNMPDTYPE_OBJ_ID :
+		{
+			uint8_t *string = &((uint8_t*)ptr)[4+oid_data->oidlen+2];
+
+			if ( oid_data->dataType==SNMPDTYPE_OCTET_STRING )
+			{
+				oid_data->dataLen = (uint8_t)strlen((char const*)&oid_data->u.octetstring);
+			}
+			for (j = 0 ; j < oid_data->dataLen ; j++)
+			{
+				string[j] = oid_data->u.octetstring[j];
+			}
+
+			((uint8_t*)ptr)[4+oid_data->oidlen] = oid_data->dataType;
+			((uint8_t*)ptr)[4+oid_data->oidlen+1] = oid_data->dataLen;
+			((uint8_t*)ptr)[1] = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
+			*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
+		}
+		break;
+
+	case SNMPDTYPE_INTEGER :
+	case SNMPDTYPE_TIME_TICKS :
+	case SNMPDTYPE_COUNTER :
+	case SNMPDTYPE_GAUGE :
+		{
+			oid_data->dataLen = 4;
+
+			*(int32_t*)(&((uint8_t*)ptr)[4+oid_data->oidlen+2]) = HTONL(oid_data->u.intval);
+
+			((uint8_t*)ptr)[4+oid_data->oidlen] = oid_data->dataType;
+			((uint8_t*)ptr)[4+oid_data->oidlen+1] = oid_data->dataLen;
+			((uint8_t*)ptr)[1] = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
+			*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
+		}
+		break;
+
+	default : 
+		return INVALID_DATA_TYPE;
+	}
+
+	return SNMP_SUCCESS;
+}
+
+
+int32_t snmp_sendTrap(uint8_t * managerIP, uint8_t * agentIP, int8_t* community, dataEntryType enterprise_oid, uint32_t genericTrap, uint32_t specificTrap, uint32_t va_count, ...)
+{
+	uint32_t i;
+	int32_t packet_index = 0;
+	int32_t packet_buff1 = 0;
+	int32_t packet_buff2 = 0;
+	int32_t packet_buff3 = 0;
+
+	va_list ap;
+	uint32_t length_var_bindings = 0;
+	uint32_t length_buff = 0;
+
+	//SNMP Trap packet generation
+	packet_trap[packet_index++] = 0x30; // ASN.1 Header
+
+	packet_trap[packet_index] = 0xff; // pdu_length, temp
+	packet_buff1 = packet_index++;
+
+	packet_trap[packet_index++] = 0x02; // Version
+	packet_trap[packet_index++] = 0x01;
+	packet_trap[packet_index++] = 0x00;
+	
+	packet_trap[packet_index++] = 0x04; // Community
+	packet_trap[packet_index++] = (uint8_t)strlen((char const*)community);
+	memcpy(&(packet_trap[packet_index]), community, strlen((char const*)community));
+
+	packet_index = packet_index + (uint8_t)strlen((char const*)community);
+
+	packet_trap[packet_index++] = 0xa4; // trap
+	packet_trap[packet_index] = 0xff; // length, temp
+	packet_buff2 = packet_index++;
+
+	packet_trap[packet_index++] = 0x06; // enterprise_oid
+	packet_trap[packet_index++] = enterprise_oid.oidlen;
+	for (i=0; i<enterprise_oid.oidlen; i++)
+	{
+		packet_trap[packet_index++] = enterprise_oid.oid[i];
+	}
+	
+	packet_trap[packet_index++] = 0x40; // agent ip
+	packet_trap[packet_index++] = 0x04;
+	packet_trap[packet_index++] = agentIP[0];
+	packet_trap[packet_index++] = agentIP[1];
+	packet_trap[packet_index++] = agentIP[2];
+	packet_trap[packet_index++] = agentIP[3];
+
+	packet_trap[packet_index++] = 0x02; // Generic Trap
+	packet_trap[packet_index++] = 0x01;
+	packet_trap[packet_index++] = (uint8_t)genericTrap;
+
+	packet_trap[packet_index++] = 0x02; // Specific Trap
+	packet_trap[packet_index++] = 0x01;
+	packet_trap[packet_index++] = (uint8_t)specificTrap;
+
+	packet_trap[packet_index++] = 0x43; // Timestamp
+	packet_trap[packet_index++] = 0x01;
+	packet_trap[packet_index++] = 0x00;
+
+	packet_trap[packet_index++] = 0x30; // Sequence of variable-bindings
+	packet_trap[packet_index] = 0xff;
+	packet_buff3 = packet_index++;
+	
+	// variable-bindings
+	{
+		va_start (ap, va_count); 
+
+		for (i=0; i<va_count; i++) 
+		{
+			dataEntryType* fff = va_arg(ap, dataEntryType*);
+			makeTrapVariableBindings(fff, &(packet_trap[packet_index]), &length_buff);
+			packet_index = packet_index + length_buff;
+			length_var_bindings = length_var_bindings + length_buff;
+		}
+
+		packet_trap[packet_buff3] = length_var_bindings;
+
+		va_end (ap);
+	}
+
+
+	packet_trap[packet_buff1] = packet_index - 2;
+	packet_trap[packet_buff2] = packet_index - (9 + (uint8_t)strlen((char const*)community));
+
+	// Send SNMP Trap Packet to NMS
+	{
+		socket(SOCK_SNMP_TRAP, Sn_MR_UDP, PORT_SNMP_TRAP, 0);
+		sendto(SOCK_SNMP_TRAP, packet_trap, packet_index, managerIP, PORT_SNMP_TRAP);
+		
+		close(SOCK_SNMP_TRAP);
+		return 0;
+	}
+}
+
+#ifdef _SNMP_DEBUG_
+void dumpCode(uint8_t* header, uint8_t* tail, uint8_t *buff, int32_t len)
+{
+	int i;
+
+	printf((char const*)header);
+
+	for (i=0; i<len; i++)
+	{
+		if ( i%16==0 )	printf("0x%04x : ", i);
+		printf("%02x ",buff[i]);
+
+		if ( i%16-15==0 )
+		{
+			int j;
+			printf("  ");
+			for (j=i-15; j<=i; j++)
+			{
+				if ( isprint(buff[j]) )	printf("%c", buff[j]);
+				else					printf(".");
+			}
+			printf("\r\n");
+		}
+	}
+
+	if ( i%16!=0 )
+	{
+		int j;
+		int spaces=(len-i+16-i%16)*3+2;
+		for (j=0; j<spaces; j++) 	printf(" ");
+		for (j=i-i%16; j<len; j++)
+		{
+			if ( isprint(buff[j]) )	printf("%c", buff[j]);
+			else					printf(".");
+		}
+	}
+	printf((char const*)tail);
+}
+#endif
+

+ 122 - 0
lib/ioLibrary_Driver/Internet/SNMP/snmp.h

@@ -0,0 +1,122 @@
+#ifndef _SNMP_H_
+#define _SNMP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// SNMP Debug Message (dump) Enable
+#define _SNMP_DEBUG_
+
+#define PORT_SNMP_AGENT				161
+#define PORT_SNMP_TRAP				162
+
+#define SNMP_V1						0
+
+#define MAX_OID						12
+#define MAX_STRING					64
+#define MAX_SNMPMSG_LEN				512
+#define MAX_TRAPMSG_LEN				512
+
+// SNMP Error code
+#define SNMP_SUCCESS				0
+#define OID_NOT_FOUND				-1
+#define TABLE_FULL					-2
+#define ILLEGAL_LENGTH				-3
+#define INVALID_ENTRY_ID			-4
+#define INVALID_DATA_TYPE			-5
+
+#define NO_SUCH_NAME				2
+#define BAD_VALUE					3
+
+// SNMPv1 Commands
+#define GET_REQUEST					0xa0
+#define GET_NEXT_REQUEST			0xa1
+#define GET_RESPONSE				0xa2
+#define SET_REQUEST					0xa3
+
+// Macros: SNMPv1 request validation checker
+#define VALID_REQUEST(x)			((x == GET_REQUEST) || (x == GET_NEXT_REQUEST) || (x == SET_REQUEST))
+
+// SNMPv1 Return Types
+#define SNMPDTYPE_INTEGER			0x02
+#define SNMPDTYPE_OCTET_STRING		0x04
+#define SNMPDTYPE_NULL_ITEM			0x05
+#define SNMPDTYPE_OBJ_ID			0x06
+#define SNMPDTYPE_SEQUENCE			0x30
+#define SNMPDTYPE_SEQUENCE_OF		SNMPDTYPE_SEQUENCE
+
+#define SNMPDTYPE_COUNTER			0x41
+#define SNMPDTYPE_GAUGE  			0x42
+#define SNMPDTYPE_TIME_TICKS		0x43
+#define SNMPDTYPE_OPAQUE			0x44
+
+// SNMP Trap: Standard Trap Types (Generic)
+#define SNMPTRAP_COLDSTART			0x00	// Generic trap-type 0: Cold Start
+#define SNMPTRAP_WARMSTART			0x01	// Generic trap-type 1: Warm Start
+#define SNMPTRAP_LINKDOWN			0x02	// Generic trap-type 2: Link Down
+#define SNMPTRAP_LINKUP				0x03	// Generic trap-type 3: Link Up
+#define SNMPTRAP_AUTHENTICATION		0x04	// Generic trap-type 4: Authentication Failure
+#define SNMPTRAP_EGPNEIGHBORLOSS	0x05	// Generic trap-type 5: EGP Neighbor Loss
+
+// Macros
+#define COPY_SEGMENT(x) \
+{ \
+	request_msg.index += seglen; \
+	memcpy(&response_msg.buffer[response_msg.index], &request_msg.buffer[x.start], seglen ); \
+	response_msg.index += seglen; \
+}
+
+#ifndef HTONL
+    #define HTONL(x)                    \
+        ((((x) >> 24) & 0x000000ff) |   \
+         (((x) >>  8) & 0x0000ff00) |   \
+         (((x) <<  8) & 0x00ff0000) |   \
+         (((x) << 24) & 0xff000000))
+#endif
+
+typedef struct {
+	uint8_t oidlen;
+	uint8_t oid[MAX_OID];
+	uint8_t dataType;
+	uint8_t dataLen;
+	union {
+		uint8_t octetstring[MAX_STRING];
+		uint32_t intval;
+	} u;
+	void (*getfunction)(void *, uint8_t *);
+	void (*setfunction)(int32_t);
+} dataEntryType;
+
+struct messageStruct {
+	uint8_t buffer[MAX_SNMPMSG_LEN];
+	int32_t len;
+	int32_t index;
+};
+
+typedef struct {
+	int32_t start;		/* Absolute Index of the TLV */
+	int32_t len;		/* The L value of the TLV */
+	int32_t vstart;		/* Absolute Index of this TLV's Value */
+	int32_t nstart;		/* Absolute Index of the next TLV */
+} tlvStructType;
+
+
+/********************************************************************************************/
+/* SNMP : Functions                                                                         */
+/********************************************************************************************/
+// SNMP Main functions
+void snmpd_init(uint8_t * managerIP, uint8_t * agentIP, uint8_t sn_agent, uint8_t sn_trap);
+int32_t snmpd_run(void);
+int32_t snmp_sendTrap(uint8_t * managerIP, uint8_t * agentIP, int8_t* community, dataEntryType enterprise_oid, uint32_t genericTrap, uint32_t specificTrap, uint32_t va_count, ...);
+
+// SNMP Time handler functions
+void SNMP_time_handler(void);
+uint32_t getSNMPTimeTick(void);
+void currentUptime(void *ptr, uint8_t *len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 147 - 0
lib/ioLibrary_Driver/Internet/SNMP/snmp_custom.c

@@ -0,0 +1,147 @@
+
+/********************************************************************************************
+ * SNMP : User Customization Part
+ *  - OID Registration
+ *  - User defined functions for OID related
+ *  	+ Integer value, String
+ *  	+ I/O control / Chip registers
+ *  	+ Network Informations
+ *  	+ Etc.
+ *
+ *********************************************************************************************/
+#include "snmp_custom.h"
+
+#ifdef _USE_WIZNET_W5500_EVB_
+	#include "board.h"
+#endif
+
+dataEntryType snmpData[] =
+{
+    // System MIB
+	// SysDescr Entry
+	{8, {0x2b, 6, 1, 2, 1, 1, 1, 0},
+	SNMPDTYPE_OCTET_STRING, 30, {"WIZnet Embedded SNMP Agent"},
+	NULL, NULL},
+
+	// SysObjectID Entry
+	{8, {0x2b, 6, 1, 2, 1, 1, 2, 0},
+	SNMPDTYPE_OBJ_ID, 8, {"\x2b\x06\x01\x02\x01\x01\x02\x00"},
+	NULL, NULL},
+
+	// SysUptime Entry
+	{8, {0x2b, 6, 1, 2, 1, 1, 3, 0},
+	SNMPDTYPE_TIME_TICKS, 0, {""},
+	currentUptime, NULL},
+
+	// sysContact Entry
+	{8, {0x2b, 6, 1, 2, 1, 1, 4, 0},
+	SNMPDTYPE_OCTET_STRING, 30, {"http://www.wizwiki.net/forum"},
+	NULL, NULL},
+
+	// sysName Entry
+	{8, {0x2b, 6, 1, 2, 1, 1, 5, 0},
+	SNMPDTYPE_OCTET_STRING, 30, {"http://www.wiznet.co.kr"},
+	NULL, NULL},
+
+	// Location Entry
+	{8, {0x2b, 6, 1, 2, 1, 1, 6, 0},
+	SNMPDTYPE_OCTET_STRING, 30, {"4F Humax Village"},
+	NULL, NULL},
+
+	// SysServices
+	{8, {0x2b, 6, 1, 2, 1, 1, 7, 0},
+	SNMPDTYPE_INTEGER, 4, {""},
+	NULL, NULL},
+
+#ifdef _USE_WIZNET_W5500_EVB_
+	// Get the WIZnet W5500-EVB LED Status
+	{8, {0x2b, 6, 1, 4, 1, 6, 1, 0},
+	SNMPDTYPE_OCTET_STRING, 40, {""},
+	get_LEDStatus_all, NULL},
+
+	// Set the LED_R (RGB LED)
+	{8, {0x2b, 6, 1, 4, 1, 6, 1, 1},
+	SNMPDTYPE_INTEGER, 4, {""},
+	NULL, set_LEDStatus_R},
+
+	// Set the LED_G (RGB LED)
+	{8, {0x2b, 6, 1, 4, 1, 6, 1, 2},
+	SNMPDTYPE_INTEGER, 4, {""},
+	NULL, set_LEDStatus_G},
+
+	// Set the LED_B (RGB LED)
+	{8, {0x2b, 6, 1, 4, 1, 6, 1, 3},
+	SNMPDTYPE_INTEGER, 4, {""},
+	NULL, set_LEDStatus_B},
+#endif
+
+	// OID Test #1 (long-length OID example, 19865)
+	{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
+	SNMPDTYPE_OCTET_STRING, 30, {"long-length OID Test #1"},
+	NULL, NULL},
+
+	// OID Test #2 (long-length OID example, 22210)
+	{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x01, 0x00},
+	SNMPDTYPE_OCTET_STRING, 35, {"long-length OID Test #2"},
+	NULL, NULL},
+
+	// OID Test #2: SysObjectID Entry
+	{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x02, 0x00},
+	SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\xad\x42\x02\x00"},
+	NULL, NULL},
+};
+
+const int32_t maxData = (sizeof(snmpData) / sizeof(dataEntryType));
+
+void initTable()
+{
+	// Example integer value for [OID 1.3.6.1.2.1.1.7.0]
+	snmpData[6].u.intval = -5;
+
+}
+
+
+// W5500-EVB: LED Control ///////////////////////////////////////////////////////////////////////////
+#ifdef _USE_WIZNET_W5500_EVB_
+void get_LEDStatus_all(void *ptr, uint8_t *len)
+{
+	uint8_t led_status[3] = {0, };
+
+	led_status[LED_R] = (uint8_t)Board_LED_Test(LED_R);
+	led_status[LED_G] = (uint8_t)Board_LED_Test(LED_G);
+	led_status[LED_B] = (uint8_t)Board_LED_Test(LED_B);
+
+	*len = sprintf((char *)ptr, "LED R [%s] / G [%s] / B [%s]", led_status[LED_R]?"On":"Off", led_status[LED_G]?"On":"Off", led_status[LED_B]?"On":"Off");
+}
+
+void set_LEDStatus_R(int32_t val)
+{
+	if(val == 0) 	Board_LED_Set(LED_R, false);
+	else 			Board_LED_Set(LED_R, true);
+}
+
+void set_LEDStatus_G(int32_t val)
+{
+	if(val == 0) 	Board_LED_Set(LED_G, false);
+	else 			Board_LED_Set(LED_G, true);
+}
+
+void set_LEDStatus_B(int32_t val)
+{
+	if(val == 0) 	Board_LED_Set(LED_B, false);
+	else 			Board_LED_Set(LED_B, true);
+}
+#endif
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void initial_Trap(uint8_t * managerIP, uint8_t * agentIP)
+{
+	// SNMP Trap: WarmStart(1) Trap
+	{
+		dataEntryType enterprise_oid = {0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
+												SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\x9b\x19\x10\x00"},	NULL, NULL};
+		// Generic Trap: warmStart COMMUNITY
+		snmp_sendTrap(managerIP, agentIP, (void *)COMMUNITY, enterprise_oid, SNMPTRAP_WARMSTART, 0, 0);
+	}
+
+}

+ 41 - 0
lib/ioLibrary_Driver/Internet/SNMP/snmp_custom.h

@@ -0,0 +1,41 @@
+#ifndef _SNMP_CUSTOM_H_
+#define _SNMP_CUSTOM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#include "snmp.h"
+
+extern dataEntryType snmpData[];
+extern const int32_t maxData;
+
+// Define for using W5500-EVB: H/W Dependency (e.g., LEDs...)
+//#define _USE_WIZNET_W5500_EVB_
+
+#define COMMUNITY					"public\0"
+#define COMMUNITY_SIZE				(strlen(COMMUNITY))
+
+/* Predefined function: Response value control */
+void initTable();
+
+/* User defined functions: LED control examples */
+#ifdef _USE_WIZNET_W5500_EVB_
+	void get_LEDStatus_all(void *ptr, uint8_t *len);
+	void set_LEDStatus_R(int32_t val);
+	void set_LEDStatus_G(int32_t val);
+	void set_LEDStatus_B(int32_t val);
+#endif
+/* SNMP Trap: warmStart(1) */
+void initial_Trap(uint8_t * managerIP, uint8_t * agentIP);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 45 - 0
lib/ioLibrary_Driver/Internet/SNMP/tools/OID_Converter/Readme.txt

@@ -0,0 +1,45 @@
+============================================================
+<OID encoding steps for WIZnet SNMP Agent>
+============================================================
+
++ Example OID for convert
+	1.3.6.1.4.1.19865.1.0
+
+(1) Convert Usage
+ 	CMD>>oid 1.3.6.1.4.1.19865.1.0
+ 	=> 06 0A 2B 06 01 04 01 81 9B 19 01 00
+
+	>> TLV(tag-length-value) Example OID
+	(06) Tag
+	(0A) Length
+	[2B] 1(iso).3(identified-organization) (in ASN.1 BER encoding, i.e. 1*40+3 = 0x2b)
+	[06] 6(dod)
+	[01] 1(internet)
+	[04] 4(private)
+	[01] 1(enterprise)
+	[81 9B 19] 19865(Vendor-Specific)
+	...
+
+(2) Add the entry to OID table in source code (DataEntryType, put the converted value to array)
+	{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
+	SNMPDTYPE_OCTET_STRING, 30, {"long-length OID Test"},
+	NULL, NULL},
+
+============================================================
+OID Converter: OID encoder/decoder
+v1.3 - Matthias Gaertner 1999/2001 - Freeware
+============================================================
+
+The OID converter is a handy little tool to convert ASN.1 OIDs from readable dotted decimal notation to binary hexadecimal Distinguished Encoding Rules (DER) representation and vice versa. 
+If you're into x.509 certificates, this may be useful to you, too.
+
+Usage:
+ OID [-c|-C] [-o] {-i|1.2.3.4}
+   converts dotted form to ASCII HEX DER output.
+ OID -x [-o] {-i|hex-digits}
+   decodes ASCII HEX DER and gives dotted form.
+   
+If you need more information, please refer to Matthias Gaertner's page,
+http://www.rtner.de/software/oid.html
+
+===============================================================================================

+ 33 - 0
lib/ioLibrary_Driver/Internet/SNMP/tools/net-snmp-5.7(win32-bin)/snmptrapd.conf

@@ -0,0 +1,33 @@
+#
+# net-snmp (or ucd-snmp) persistent data file.
+#
+############################################################################
+# STOP STOP STOP STOP STOP STOP STOP STOP STOP 
+#
+#          **** DO NOT EDIT THIS FILE ****
+#
+# STOP STOP STOP STOP STOP STOP STOP STOP STOP 
+############################################################################
+#
+# DO NOT STORE CONFIGURATION ENTRIES HERE.
+# Please save normal configuration tokens for snmptrapd in SNMPCONFPATH/snmptrapd.conf.
+# Only "createUser" tokens should be placed here by snmptrapd administrators.
+# (Did I mention: do not edit this file?)
+#
+
+
+authCommunity log,execute,net public
+
+
+
+
+
+
+
+
+
+
+
+
+engineBoots 1
+oldEngineID 0x80001f88803d6f00001ba7934e00000000

+ 450 - 0
lib/ioLibrary_Driver/Internet/SNTP/sntp.c

@@ -0,0 +1,450 @@
+/*
+ * sntp.c
+ *
+ *  Created on: 2014. 12. 15.
+ *      Author: Administrator
+ */
+
+
+#include <string.h>
+
+#include "sntp.h"
+#include "socket.h"
+
+ntpformat NTPformat;
+datetime Nowdatetime;
+uint8_t ntpmessage[48];
+uint8_t *data_buf;
+uint8_t NTP_SOCKET;
+uint8_t time_zone;
+uint16_t ntp_retry_cnt=0; //counting the ntp retry number
+
+/*
+00)UTC-12:00 Baker Island, Howland Island (both uninhabited)
+01) UTC-11:00 American Samoa, Samoa
+02) UTC-10:00 (Summer)French Polynesia (most), United States (Aleutian Islands, Hawaii)
+03) UTC-09:30 Marquesas Islands
+04) UTC-09:00 Gambier Islands;(Summer)United States (most of Alaska)
+05) UTC-08:00 (Summer)Canada (most of British Columbia), Mexico (Baja California)
+06) UTC-08:00 United States (California, most of Nevada, most of Oregon, Washington (state))
+07) UTC-07:00 Mexico (Sonora), United States (Arizona); (Summer)Canada (Alberta)
+08) UTC-07:00 Mexico (Chihuahua), United States (Colorado)
+09) UTC-06:00 Costa Rica, El Salvador, Ecuador (Galapagos Islands), Guatemala, Honduras
+10) UTC-06:00 Mexico (most), Nicaragua;(Summer)Canada (Manitoba, Saskatchewan), United States (Illinois, most of Texas)
+11) UTC-05:00 Colombia, Cuba, Ecuador (continental), Haiti, Jamaica, Panama, Peru
+12) UTC-05:00 (Summer)Canada (most of Ontario, most of Quebec)
+13) UTC-05:00 United States (most of Florida, Georgia, Massachusetts, most of Michigan, New York, North Carolina, Ohio, Washington D.C.)
+14) UTC-04:30 Venezuela
+15) UTC-04:00 Bolivia, Brazil (Amazonas), Chile (continental), Dominican Republic, Canada (Nova Scotia), Paraguay,
+16) UTC-04:00 Puerto Rico, Trinidad and Tobago
+17) UTC-03:30 Canada (Newfoundland)
+18) UTC-03:00 Argentina; (Summer) Brazil (Brasilia, Rio de Janeiro, Sao Paulo), most of Greenland, Uruguay
+19) UTC-02:00 Brazil (Fernando de Noronha), South Georgia and the South Sandwich Islands
+20) UTC-01:00 Portugal (Azores), Cape Verde
+21) UTC&#177;00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira)
+22) UTC&#177;00:00 Spain (Canary Islands), Morocco, United Kingdom
+23) UTC+01:00 Angola, Cameroon, Nigeria, Tunisia; (Summer)Albania, Algeria, Austria, Belgium, Bosnia and Herzegovina,
+24) UTC+01:00 Spain (continental), Croatia, Czech Republic, Denmark, Germany, Hungary, Italy, Kinshasa, Kosovo,
+25) UTC+01:00 Macedonia, France (metropolitan), the Netherlands, Norway, Poland, Serbia, Slovakia, Slovenia, Sweden, Switzerland
+26) UTC+02:00 Libya, Egypt, Malawi, Mozambique, South Africa, Zambia, Zimbabwe, (Summer)Bulgaria, Cyprus, Estonia,
+27) UTC+02:00 Finland, Greece, Israel, Jordan, Latvia, Lebanon, Lithuania, Moldova, Palestine, Romania, Syria, Turkey, Ukraine
+28) UTC+03:00 Belarus, Djibouti, Eritrea, Ethiopia, Iraq, Kenya, Madagascar, Russia (Kaliningrad Oblast), Saudi Arabia,
+29) UTC+03:00 South Sudan, Sudan, Somalia, South Sudan, Tanzania, Uganda, Yemen
+30) UTC+03:30 (Summer)Iran
+31) UTC+04:00 Armenia, Azerbaijan, Georgia, Mauritius, Oman, Russia (European), Seychelles, United Arab Emirates
+32) UTC+04:30 Afghanistan
+33) UTC+05:00 Kazakhstan (West), Maldives, Pakistan, Uzbekistan
+34) UTC+05:30 India, Sri Lanka
+35) UTC+05:45 Nepal
+36) UTC+06:00 Kazakhstan (most), Bangladesh, Russia (Ural: Sverdlovsk Oblast, Chelyabinsk Oblast)
+37) UTC+06:30 Cocos Islands, Myanmar
+38) UTC+07:00 Jakarta, Russia (Novosibirsk Oblast), Thailand, Vietnam
+39) UTC+08:00 China, Hong Kong, Russia (Krasnoyarsk Krai), Malaysia, Philippines, Singapore, Taiwan, most of Mongolia, Western Australia
+40) UTC+09:00 Korea, East Timor, Russia (Irkutsk Oblast), Japan
+41) UTC+09:30 Australia (Northern Territory);(Summer)Australia (South Australia))
+42) UTC+10:00 Russia (Zabaykalsky Krai); (Summer)Australia (New South Wales, Queensland, Tasmania, Victoria)
+43) UTC+10:30 Lord Howe Island
+44) UTC+11:00 New Caledonia, Russia (Primorsky Krai), Solomon Islands
+45) UTC+11:30 Norfolk Island
+46) UTC+12:00 Fiji, Russia (Kamchatka Krai);(Summer)New Zealand
+47) UTC+12:45 (Summer)New Zealand
+48) UTC+13:00 Tonga
+49) UTC+14:00 Kiribati (Line Islands)
+*/
+void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx)
+{
+	tstamp seconds = 0;
+	uint8_t i=0;
+	for (i = 0; i < 4; i++)
+	{
+		seconds = (seconds << 8) | buf[idx + i];
+	}
+	switch (time_zone)
+	{
+	case 0:
+		seconds -=  12*3600;
+		break;
+	case 1:
+		seconds -=  11*3600;
+		break;
+	case 2:
+		seconds -=  10*3600;
+		break;
+	case 3:
+		seconds -=  (9*3600+30*60);
+		break;
+	case 4:
+		seconds -=  9*3600;
+		break;
+	case 5:
+	case 6:
+		seconds -=  8*3600;
+		break;
+	case 7:
+	case 8:
+		seconds -=  7*3600;
+		break;
+	case 9:
+	case 10:
+		seconds -=  6*3600;
+		break;
+	case 11:
+	case 12:
+	case 13:
+		seconds -= 5*3600;
+		break;
+	case 14:
+		seconds -=  (4*3600+30*60);
+		break;
+	case 15:
+	case 16:
+		seconds -=  4*3600;
+		break;
+	case 17:
+		seconds -=  (3*3600+30*60);
+		break;
+	case 18:
+		seconds -=  3*3600;
+		break;
+	case 19:
+		seconds -=  2*3600;
+		break;
+	case 20:
+		seconds -=  1*3600;
+		break;
+	case 21:                            //ï¼?
+	case 22:
+		break;
+	case 23:
+	case 24:
+	case 25:
+		seconds +=  1*3600;
+		break;
+	case 26:
+	case 27:
+		seconds +=  2*3600;
+		break;
+	case 28:
+	case 29:
+		seconds +=  3*3600;
+		break;
+	case 30:
+		seconds +=  (3*3600+30*60);
+		break;
+	case 31:
+		seconds +=  4*3600;
+		break;
+	case 32:
+		seconds +=  (4*3600+30*60);
+		break;
+	case 33:
+		seconds +=  5*3600;
+		break;
+	case 34:
+		seconds +=  (5*3600+30*60);
+		break;
+	case 35:
+		seconds +=  (5*3600+45*60);
+		break;
+	case 36:
+		seconds +=  6*3600;
+		break;
+	case 37:
+		seconds +=  (6*3600+30*60);
+		break;
+	case 38:
+		seconds +=  7*3600;
+		break;
+	case 39:
+		seconds +=  8*3600;
+		break;
+	case 40:
+		seconds +=  9*3600;
+		break;
+	case 41:
+		seconds +=  (9*3600+30*60);
+		break;
+	case 42:
+		seconds +=  10*3600;
+		break;
+	case 43:
+		seconds +=  (10*3600+30*60);
+		break;
+	case 44:
+		seconds +=  11*3600;
+		break;
+	case 45:
+		seconds +=  (11*3600+30*60);
+		break;
+	case 46:
+		seconds +=  12*3600;
+		break;
+	case 47:
+		seconds +=  (12*3600+45*60);
+		break;
+	case 48:
+		seconds +=  13*3600;
+		break;
+	case 49:
+		seconds +=  14*3600;
+		break;
+
+	}
+
+	//calculation for date
+	calcdatetime(seconds);
+}
+
+void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf)
+{
+	NTP_SOCKET = s;
+
+	NTPformat.dstaddr[0] = ntp_server[0];
+	NTPformat.dstaddr[1] = ntp_server[1];
+	NTPformat.dstaddr[2] = ntp_server[2];
+	NTPformat.dstaddr[3] = ntp_server[3];
+
+	time_zone = tz;
+
+	data_buf = buf;
+
+	uint8_t Flag;
+	NTPformat.leap = 0;           /* leap indicator */
+	NTPformat.version = 4;        /* version number */
+	NTPformat.mode = 3;           /* mode */
+	NTPformat.stratum = 0;        /* stratum */
+	NTPformat.poll = 0;           /* poll interval */
+	NTPformat.precision = 0;      /* precision */
+	NTPformat.rootdelay = 0;      /* root delay */
+	NTPformat.rootdisp = 0;       /* root dispersion */
+	NTPformat.refid = 0;          /* reference ID */
+	NTPformat.reftime = 0;        /* reference time */
+	NTPformat.org = 0;            /* origin timestamp */
+	NTPformat.rec = 0;            /* receive timestamp */
+	NTPformat.xmt = 1;            /* transmit timestamp */
+
+	Flag = (NTPformat.leap<<6)+(NTPformat.version<<3)+NTPformat.mode; //one byte Flag
+	memcpy(ntpmessage,(void const*)(&Flag),1);
+}
+
+int8_t SNTP_run(datetime *time)
+{
+	uint16_t RSR_len;
+	uint32_t destip = 0;
+	uint16_t destport;
+	uint16_t startindex = 40; //last 8-byte of data_buf[size is 48 byte] is xmt, so the startindex should be 40
+
+	switch(getSn_SR(NTP_SOCKET))
+	{
+	case SOCK_UDP:
+		if ((RSR_len = getSn_RX_RSR(NTP_SOCKET)) > 0)
+		{
+			if (RSR_len > MAX_SNTP_BUF_SIZE) RSR_len = MAX_SNTP_BUF_SIZE;	// if Rx data size is lager than TX_RX_MAX_BUF_SIZE
+			recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport);
+
+			get_seconds_from_ntp_server(data_buf,startindex);
+			time->yy = Nowdatetime.yy;
+			time->mo = Nowdatetime.mo;
+			time->dd = Nowdatetime.dd;
+			time->hh = Nowdatetime.hh;
+			time->mm = Nowdatetime.mm;
+			time->ss = Nowdatetime.ss;
+
+			ntp_retry_cnt=0;
+			close(NTP_SOCKET);
+
+			return 1;
+		}
+
+		if(ntp_retry_cnt<0xFFFF)
+		{
+			if(ntp_retry_cnt==0)//first send request, no need to wait
+			{
+				sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port);
+				ntp_retry_cnt++;
+			}
+			else // send request again? it should wait for a while
+			{
+				if((ntp_retry_cnt % 0xFFF) == 0) //wait time
+				{
+					sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port);
+#ifdef _SNTP_DEBUG_
+					printf("ntp retry: %d\r\n", ntp_retry_cnt);
+#endif
+					ntp_retry_cnt++;
+				}
+			}
+		}
+		else //ntp retry fail
+		{
+			ntp_retry_cnt=0;
+#ifdef _SNTP_DEBUG_
+			printf("ntp retry failed!\r\n");
+#endif
+			close(NTP_SOCKET);
+		}
+		break;
+	case SOCK_CLOSED:
+		socket(NTP_SOCKET,Sn_MR_UDP,ntp_port,0);
+		break;
+	}
+	// Return value
+	// 0 - failed / 1 - success
+	return 0;
+}
+
+void calcdatetime(tstamp seconds)
+{
+	uint8_t yf=0;
+	tstamp n=0,d=0,total_d=0,rz=0;
+	uint16_t y=0,r=0,yr=0;
+	signed long long yd=0;
+
+	n = seconds;
+	total_d = seconds/(SECS_PERDAY);
+	d=0;
+	uint32_t p_year_total_sec=SECS_PERDAY*365;
+	uint32_t r_year_total_sec=SECS_PERDAY*366;
+	while(n>=p_year_total_sec)
+	{
+		if((EPOCH+r)%400==0 || ((EPOCH+r)%100!=0 && (EPOCH+r)%4==0))
+		{
+			n = n -(r_year_total_sec);
+			d = d + 366;
+		}
+		else
+		{
+			n = n - (p_year_total_sec);
+			d = d + 365;
+		}
+		r+=1;
+		y+=1;
+
+	}
+
+	y += EPOCH;
+
+	Nowdatetime.yy = y;
+
+	yd=0;
+	yd = total_d - d;
+
+	yf=1;
+	while(yd>=28)
+	{
+
+		if(yf==1 || yf==3 || yf==5 || yf==7 || yf==8 || yf==10 || yf==12)
+		{
+			yd -= 31;
+			if(yd<0)break;
+			rz += 31;
+		}
+
+		if (yf==2)
+		{
+			if (y%400==0 || (y%100!=0 && y%4==0))
+			{
+				yd -= 29;
+				if(yd<0)break;
+				rz += 29;
+			}
+			else
+			{
+				yd -= 28;
+				if(yd<0)break;
+				rz += 28;
+			}
+		}
+		if(yf==4 || yf==6 || yf==9 || yf==11 )
+		{
+			yd -= 30;
+			if(yd<0)break;
+			rz += 30;
+		}
+		yf += 1;
+
+	}
+	Nowdatetime.mo=yf;
+	yr = total_d-d-rz;
+
+	yr += 1;
+
+	Nowdatetime.dd=yr;
+
+	//calculation for time
+	seconds = seconds%SECS_PERDAY;
+	Nowdatetime.hh = seconds/3600;
+	Nowdatetime.mm = (seconds%3600)/60;
+	Nowdatetime.ss = (seconds%3600)%60;
+
+}
+
+tstamp changedatetime_to_seconds(void)
+{
+	tstamp seconds=0;
+	uint32_t total_day=0;
+	uint16_t i=0,run_year_cnt=0,l=0;
+
+	l = Nowdatetime.yy;//low
+
+
+	for(i=EPOCH;i<l;i++)
+	{
+		if((i%400==0) || ((i%100!=0) && (i%4==0)))
+		{
+			run_year_cnt += 1;
+		}
+	}
+
+	total_day=(l-EPOCH-run_year_cnt)*365+run_year_cnt*366;
+
+	for(i=1;i<=Nowdatetime.mo;i++)
+	{
+		if(i==5 || i==7 || i==10 || i==12)
+		{
+			total_day += 30;
+		}
+		if (i==3)
+		{
+			if (l%400==0 && l%100!=0 && l%4==0)
+			{
+				total_day += 29;
+			}
+			else
+			{
+				total_day += 28;
+			}
+		}
+		if(i==2 || i==4 || i==6 || i==8 || i==9 || i==11)
+		{
+			total_day += 31;
+		}
+	}
+
+	seconds = (total_day+Nowdatetime.dd-1)*24*3600;
+	seconds += Nowdatetime.ss;//seconds
+	seconds += Nowdatetime.mm*60;//minute
+	seconds += Nowdatetime.hh*3600;//hour
+
+	return seconds;
+}

+ 76 - 0
lib/ioLibrary_Driver/Internet/SNTP/sntp.h

@@ -0,0 +1,76 @@
+/*
+ * sntp.h
+ *
+ *  Created on: 2014. 12. 15.
+ *      Author: Administrator
+ */
+
+#ifndef SNTP_H_
+#define SNTP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/*
+ * @brief Define it for Debug & Monitor DNS processing.
+ * @note If defined, it dependens on <stdio.h>
+ */
+//#define _SNTP_DEBUG_
+
+#define	MAX_SNTP_BUF_SIZE	sizeof(ntpformat)		///< maximum size of DNS buffer. */
+
+/* for ntpclient */
+typedef signed char s_char;
+typedef unsigned long long tstamp;
+typedef unsigned int tdist;
+
+typedef struct _ntpformat
+{
+
+	uint8_t  dstaddr[4];        /* destination (local) address */
+	char    version;        /* version number */
+	char    leap;           /* leap indicator */
+	char    mode;           /* mode */
+	char    stratum;        /* stratum */
+	char    poll;           /* poll interval */
+	s_char  precision;      /* precision */
+	tdist   rootdelay;      /* root delay */
+	tdist   rootdisp;       /* root dispersion */
+	char    refid;          /* reference ID */
+	tstamp  reftime;        /* reference time */
+	tstamp  org;            /* origin timestamp */
+	tstamp  rec;            /* receive timestamp */
+	tstamp  xmt;            /* transmit timestamp */
+
+
+} ntpformat;
+
+typedef struct _datetime
+{
+	uint16_t yy;
+	uint8_t mo;
+	uint8_t dd;
+	uint8_t hh;
+	uint8_t mm;
+	uint8_t ss;
+} datetime;
+
+#define ntp_port		123                     //ntp server port number
+#define SECS_PERDAY		86400UL             	// seconds in a day = 60*60*24
+#define UTC_ADJ_HRS		9              	        // SEOUL : GMT+9
+#define EPOCH			1900                    // NTP start year
+
+void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx);
+void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf);
+int8_t SNTP_run(datetime *time);
+tstamp changedatetime_to_seconds(void);
+void calcdatetime(tstamp seconds);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SNTP_H_ */

+ 158 - 0
lib/ioLibrary_Driver/Internet/TFTP/netutil.c

@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netutil.h"
+
+/**
+ * Convert a 32bit Address into a Dotted Decimal Format string.
+ *
+ * @param addr 32bit address.
+ * @return Dotted Decimal Format string.
+ */
+int8_t* inet_ntoa(uint32_t addr)
+{
+	static int8_t addr_str[16];
+	memset(addr_str,0,16);
+	sprintf((char*)addr_str,"%d.%d.%d.%d",(int32_t)(addr>>24 & 0xFF),(int32_t)(addr>>16 & 0xFF),(int32_t)(addr>>8 & 0xFF),(int32_t)(addr & 0xFF));
+	return addr_str;
+}
+
+/**
+ * Convert a 32bit Address into a Dotted Decimal Format string.
+ * This is differ from inet_ntoa in fixed length.
+ *
+ * @param addr 32bit address.
+ * @return Dotted Decimal Format string.
+ */
+int8_t* inet_ntoa_pad(uint32_t addr)
+{
+	static int8_t addr_str[16];
+	memset(addr_str,0,16);
+	sprintf((char*)addr_str,"%03d.%03d.%03d.%03d",(int32_t)(addr>>24 & 0xFF),(int32_t)(addr>>16 & 0xFF),(int32_t)(addr>>8 & 0xFF),(int32_t)(addr & 0xFF));
+	return addr_str;
+}
+
+/**
+ * Converts a string containing an (Ipv4) Internet Protocol decimal dotted address into a 32bit address.
+ *
+ * @param addr Dotted Decimal Format string.
+ * @return 32bit address.
+ */
+uint32_t inet_addr(uint8_t* addr)
+{
+	int8_t i;
+	uint32_t inetaddr = 0;
+	int8_t taddr[30];
+	int8_t * nexttok;
+	int32_t num;
+	strcpy((char*)taddr,(char*)addr);
+	
+	nexttok = taddr;
+	for(i = 0; i < 4 ; i++)
+	{
+		nexttok = (int8_t*)strtok((char*)nexttok,".");
+		if(nexttok[0] == '0' && nexttok[1] == 'x') num = strtol((char*)nexttok+2, NULL, 16);
+		else num = strtol((char*)nexttok, NULL, 10);
+		inetaddr = inetaddr << 8;		
+		inetaddr |= (num & 0xFF);
+		nexttok = NULL;
+	}
+	return inetaddr;	
+}	
+
+/**
+ * Swap the byte order of 16bit(short) wide variable.
+ *
+ * @param i 16bit value to swap
+ * @return Swapped value
+ */
+uint16_t swaps(uint16_t i)
+{
+	uint16_t ret=0;
+	ret = (i & 0xFF) << 8;
+	ret |= ((i >> 8)& 0xFF);
+	return ret;	
+}
+
+/**
+ * Swap the byte order of 32bit(long) wide variable.
+ *
+ * @param l 32bit value to convert
+ * @return Swapped value
+ */
+uint32_t swapl(uint32_t l)
+{
+	uint32_t ret=0;
+	ret = (l & 0xFF) << 24;
+	ret |= ((l >> 8) & 0xFF) << 16;
+	ret |= ((l >> 16) & 0xFF) << 8;
+	ret |= ((l >> 24) & 0xFF);
+	return ret;
+}
+
+/**
+ * htons function converts a unsigned short from host to TCP/IP network byte order (which is big-endian).
+ *
+ * @param hostshort The value to convert.
+ * @return The value in TCP/IP network byte order.
+ */ 
+uint16_t htons(uint16_t hostshort)
+{
+#ifdef SYSTEM_LITTLE_ENDIAN
+	return swaps(hostshort);
+#else
+	return hostshort;
+#endif		
+}
+
+
+/**
+ * htonl function converts a unsigned long from host to TCP/IP network byte order (which is big-endian).
+ *
+ * @param hostlong The value to convert.
+ * @return The value in TCP/IP network byte order.
+ */ 
+uint32_t htonl(uint32_t hostlong)
+{
+#ifdef SYSTEM_LITTLE_ENDIAN
+	return swapl(hostlong);
+#else
+	return hostlong;
+#endif	
+}
+
+
+/**
+ * ntohs function converts a unsigned short from TCP/IP network byte order
+ * to host byte order (which is little-endian on Intel processors).
+ *
+ * @param netshort The value to convert.
+ * @return A 16-bit number in host byte order
+ */ 
+uint32_t ntohs(uint16_t netshort)
+{
+#ifdef SYSTEM_LITTLE_ENDIAN
+	return htons(netshort);
+#else
+	return netshort;
+#endif		
+}
+
+/**
+ * converts a unsigned long from TCP/IP network byte order to host byte order 
+ * (which is little-endian on Intel processors).
+ *
+ * @param netlong The value to convert.
+ * @return A 16-bit number in host byte order
+ */ 
+uint32_t ntohl(uint32_t netlong)
+{
+#ifdef SYSTEM_LITTLE_ENDIAN
+	return swapl(netlong);
+#else
+	return netlong;
+#endif		
+}
+/**
+ * @}
+ */

+ 27 - 0
lib/ioLibrary_Driver/Internet/TFTP/netutil.h

@@ -0,0 +1,27 @@
+
+#ifndef __NETUTIL_H__
+#define __NETUTIL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define SYSTEM_LITTLE_ENDIAN
+
+int8_t* inet_ntoa(uint32_t addr);
+int8_t* inet_ntoa_pad(uint32_t addr);
+uint32_t inet_addr(uint8_t* addr);
+uint16_t swaps(uint16_t i);
+uint32_t swapl(uint32_t l);
+uint16_t htons(uint16_t hostshort);
+uint32_t htonl(uint32_t hostlong);
+uint32_t ntohs(uint16_t netshort);
+uint32_t ntohl(uint32_t netlong);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 660 - 0
lib/ioLibrary_Driver/Internet/TFTP/tftp.c

@@ -0,0 +1,660 @@
+/**
+ * @file tftp.c
+ * @brief TFTP Source File.
+ * @version 0.1.0
+ * @author Sang-sik Kim
+ */
+
+/* Includes -----------------------------------------------------*/
+#include <string.h>
+#include "tftp.h"
+#include "socket.h"
+#include "netutil.h"
+
+/* define -------------------------------------------------------*/
+
+/* typedef ------------------------------------------------------*/
+
+/* Extern Variable ----------------------------------------------*/
+
+/* Extern Functions ---------------------------------------------*/
+#ifdef F_STORAGE
+extern void save_data(uint8_t *data, uint32_t data_len, uint16_t block_number);
+#endif
+
+/* Global Variable ----------------------------------------------*/
+static int		g_tftp_socket = -1;
+
+static uint8_t g_filename[FILE_NAME_SIZE];
+
+static uint32_t g_server_ip = 0;
+static uint16_t g_server_port = 0;
+static uint16_t g_local_port = 0;
+
+static uint32_t g_tftp_state = STATE_NONE;
+static uint16_t g_block_num = 0;
+
+static uint32_t g_timeout = 5;
+static uint32_t g_resend_flag = 0;
+static uint32_t tftp_time_cnt = 0;
+static uint32_t tftp_retry_cnt = 0;
+
+static uint8_t *g_tftp_rcv_buf = NULL;
+
+static TFTP_OPTION default_tftp_opt = {
+	.code = (uint8_t *)"timeout",
+	.value = (uint8_t *)"5"
+};
+
+uint8_t g_progress_state = TFTP_PROGRESS;
+
+#ifdef __TFTP_DEBUG__
+int dbg_level = (INFO_DBG | ERROR_DBG | IPC_DBG);
+#endif
+
+/* static function define ---------------------------------------*/
+static void set_filename(uint8_t *file, uint32_t file_size)
+{
+	memcpy(g_filename, file, file_size);
+}
+
+static inline void set_server_ip(uint32_t ipaddr)
+{
+	g_server_ip = ipaddr;
+}
+
+static inline uint32_t get_server_ip()
+{
+	return g_server_ip;
+}
+
+static inline void set_server_port(uint16_t port)
+{
+	g_server_port = port;
+}
+
+static inline uint16_t get_server_port()
+{
+	return g_server_port;
+}
+
+static inline void set_local_port(uint16_t port)
+{
+	g_local_port = port;
+}
+
+static inline uint16_t get_local_port()
+{
+	return g_local_port;
+}
+
+static inline uint16_t genernate_port()
+{
+	/* TODO */
+	return 0;
+}
+
+static inline void set_tftp_state(uint32_t state)
+{
+	g_tftp_state = state;
+}
+
+static inline uint32_t get_tftp_state()
+{
+	return g_tftp_state;
+}
+
+static inline void set_tftp_timeout(uint32_t timeout)
+{
+	g_timeout = timeout;
+}
+
+static inline uint32_t get_tftp_timeout()
+{
+	return g_timeout;
+}
+
+static inline void set_block_number(uint16_t block_number)
+{
+	g_block_num = block_number;
+}
+
+static inline uint16_t get_block_number()
+{
+	return g_block_num;
+}
+
+static int open_tftp_socket(uint8_t sock)
+{
+	uint8_t sd, sck_state;
+
+	sd = socket(sock, Sn_MR_UDP, 51000, SF_IO_NONBLOCK);
+	if(sd != sock) {
+		//DBG_PRINT(ERROR_DBG, "[%s] socket error\r\n", __func__);
+		return -1;
+	}
+
+	do {
+		getsockopt(sd , SO_STATUS, &sck_state);
+	} while(sck_state != SOCK_UDP);
+
+	return sd;
+}
+
+static int send_udp_packet(int socket, uint8_t *packet, uint32_t len, uint32_t ip, uint16_t port)
+{
+	int snd_len;
+
+	ip = htonl(ip);
+
+	snd_len = sendto(socket, packet, len, (uint8_t *)&ip, port);
+	if(snd_len != len) {
+		//DBG_PRINT(ERROR_DBG, "[%s] sendto error\r\n", __func__);
+		return -1;
+	}
+
+	return snd_len;
+}
+
+static int recv_udp_packet(int socket, uint8_t *packet, uint32_t len, uint32_t *ip, uint16_t *port)
+{
+	int ret;
+	uint8_t sck_state;
+	uint16_t recv_len;
+
+	/* Receive Packet Process */
+	ret = getsockopt(socket, SO_STATUS, &sck_state);
+	if(ret != SOCK_OK) {
+		//DBG_PRINT(ERROR_DBG, "[%s] getsockopt SO_STATUS error\r\n", __func__);
+		return -1;
+	}
+
+	if(sck_state == SOCK_UDP) {
+		ret = getsockopt(socket, SO_RECVBUF, &recv_len);
+		if(ret != SOCK_OK) {
+			//DBG_PRINT(ERROR_DBG, "[%s] getsockopt SO_RECVBUF error\r\n", __func__);
+			return -1;
+		}
+
+		if(recv_len) {
+			recv_len = recvfrom(socket, packet, len, (uint8_t *)ip, port);
+			if(recv_len < 0) {
+				//DBG_PRINT(ERROR_DBG, "[%s] recvfrom error\r\n", __func__);
+				return -1;
+			}
+
+			*ip = ntohl(*ip);
+
+			return recv_len;
+		}
+	}
+	return -1;
+}
+
+static void close_tftp_socket(int socket)
+{
+	close(socket);
+}
+
+
+static void init_tftp(void)
+{
+	g_filename[0] = 0;
+
+	set_server_ip(0);
+	set_server_port(0);
+	set_local_port(0);
+
+	set_tftp_state(STATE_NONE);
+	set_block_number(0);
+
+	/* timeout flag */
+	g_resend_flag = 0;
+	tftp_retry_cnt = tftp_time_cnt = 0;
+
+	g_progress_state = TFTP_PROGRESS;
+}
+
+static void tftp_cancel_timeout(void)
+{
+	if(g_resend_flag) {
+		g_resend_flag = 0;
+		tftp_retry_cnt = tftp_time_cnt = 0;
+	}
+}
+
+static void tftp_reg_timeout()
+{
+	if(g_resend_flag == 0) {
+		g_resend_flag = 1;
+		tftp_retry_cnt = tftp_time_cnt = 0;
+	}
+}
+
+static void process_tftp_option(uint8_t *msg, uint32_t msg_len)
+{
+	/* TODO Option Process */
+}
+
+static void send_tftp_rrq(uint8_t *filename, uint8_t *mode, TFTP_OPTION *opt, uint8_t opt_len)
+{
+	uint8_t snd_buf[MAX_MTU_SIZE];
+	uint8_t *pkt = snd_buf;
+	uint32_t i, len;
+
+	*((uint16_t *)pkt) = htons(TFTP_RRQ);
+	pkt += 2;
+	strcpy((char *)pkt, (const char *)filename);
+	pkt += strlen((char *)filename) + 1;
+	strcpy((char *)pkt, (const char *)mode);
+	pkt += strlen((char *)mode) + 1;
+
+	for(i = 0 ; i < opt_len ; i++) {
+		strcpy((char *)pkt, (const char *)opt[i].code);
+		pkt += strlen((char *)opt[i].code) + 1;
+		strcpy((char *)pkt, (const char *)opt[i].value);
+		pkt += strlen((char *)opt[i].value) + 1;
+	}
+
+	len = pkt - snd_buf;
+
+	send_udp_packet(g_tftp_socket,  snd_buf, len, get_server_ip(), TFTP_SERVER_PORT);
+	set_tftp_state(STATE_RRQ);
+	set_filename(filename, strlen((char *)filename) + 1);
+	tftp_reg_timeout();
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, ">> TFTP RRQ : FileName(%s), Mode(%s)\r\n", filename, mode);
+#endif
+}
+
+#if 0	// 2014.07.01 sskim
+static void send_tftp_wrq(uint8_t *filename, uint8_t *mode, TFTP_OPTION *opt, uint8_t opt_len)
+{
+	uint8_t snd_buf[MAX_MTU_SIZE];
+	uint8_t *pkt = snd_buf;
+	uint32_t i, len;
+
+	*((uint16_t *)pkt) = htons((uint16_t)TFTP_WRQ);
+	pkt += 2;
+	strcpy((char *)pkt, (const char *)filename);
+	pkt += strlen((char *)filename) + 1;
+	strcpy((char *)pkt, (const char *)mode);
+	pkt += strlen((char *)mode) + 1;
+
+	for(i = 0 ; i < opt_len ; i++) {
+		strcpy((char *)pkt, (const char *)opt[i].code);
+		pkt += strlen((char *)opt[i].code) + 1;
+		strcpy((char *)pkt, (const char *)opt[i].value);
+		pkt += strlen((char *)opt[i].value) + 1;
+	}
+
+	len = pkt - snd_buf;
+
+	send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), TFTP_SERVER_PORT);
+	set_tftp_state(STATE_WRQ);
+	set_filename(filename, strlen((char *)filename) + 1);
+	tftp_reg_timeout();
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, ">> TFTP WRQ : FileName(%s), Mode(%s)\r\n", filename, mode);
+#endif
+}
+#endif
+
+#if 0	// 2014.07.01 sskim
+static void send_tftp_data(uint16_t block_number, uint8_t *data, uint16_t data_len)
+{
+	uint8_t snd_buf[MAX_MTU_SIZE];
+	uint8_t *pkt = snd_buf;
+	uint32_t len;
+
+	*((uint16_t *)pkt) = htons((uint16_t)TFTP_DATA);
+	pkt += 2;
+	*((uint16_t *)pkt) = htons(block_number);
+	pkt += 2;
+	memcpy(pkt, data, data_len);
+	pkt += data_len;
+
+	len = pkt - snd_buf;
+
+	send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), get_server_port());
+	tftp_reg_timeout();
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, ">> TFTP DATA : Block Number(%d), Data Length(%d)\r\n", block_number, data_len);
+#endif
+}
+#endif
+
+static void send_tftp_ack(uint16_t block_number)
+{
+	uint8_t snd_buf[4];
+	uint8_t *pkt = snd_buf;
+
+	*((uint16_t *)pkt) = htons((uint16_t)TFTP_ACK);
+	pkt += 2;
+	*((uint16_t *)pkt) = htons(block_number);
+	pkt += 2;
+
+	send_udp_packet(g_tftp_socket , snd_buf, 4, get_server_ip(), get_server_port());
+	tftp_reg_timeout();
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, ">> TFTP ACK : Block Number(%d)\r\n", block_number);
+#endif
+}
+
+#if 0	// 2014.07.01 sskim
+static void send_tftp_oack(TFTP_OPTION *opt, uint8_t opt_len)
+{
+	uint8_t snd_buf[MAX_MTU_SIZE];
+	uint8_t *pkt = snd_buf;
+	uint32_t i, len;
+
+	*((uint16_t *)pkt) = htons((uint16_t)TFTP_OACK);
+	pkt += 2;
+
+	for(i = 0 ; i < opt_len ; i++) {
+		strcpy((char *)pkt, (const char *)opt[i].code);
+		pkt += strlen((char *)opt[i].code) + 1;
+		strcpy((char *)pkt, (const char *)opt[i].value);
+		pkt += strlen((char *)opt[i].value) + 1;
+	}
+
+	len = pkt - snd_buf;
+
+	send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), get_server_port());
+	tftp_reg_timeout();
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, ">> TFTP OACK \r\n");
+#endif
+}
+#endif
+
+#if 0	// 2014.07.01 sskim
+static void send_tftp_error(uint16_t error_number, uint8_t *error_message)
+{
+	uint8_t snd_buf[MAX_MTU_SIZE];
+	uint8_t *pkt = snd_buf;
+	uint32_t len;
+
+	*((uint16_t *)pkt) = htons((uint16_t)TFTP_ERROR);
+	pkt += 2;
+	*((uint16_t *)pkt) = htons(error_number);
+	pkt += 2;
+	strcpy((char *)pkt, (const char *)error_message);
+	pkt += strlen((char *)error_message) + 1;
+
+	len = pkt - snd_buf;
+
+	send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), get_server_port());
+	tftp_reg_timeout();
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, ">> TFTP ERROR : Error Number(%d)\r\n", error_number);
+#endif
+}
+#endif
+
+static void recv_tftp_rrq(uint8_t *msg, uint32_t msg_len)
+{
+	/* When TFTP Server Mode */
+}
+
+static void recv_tftp_wrq(uint8_t *msg, uint32_t msg_len)
+{
+	/* When TFTP Server Mode */
+}
+
+static void recv_tftp_data(uint8_t *msg, uint32_t msg_len)
+{
+	TFTP_DATA_T *data = (TFTP_DATA_T *)msg;
+
+	data->opcode = ntohs(data->opcode);
+	data->block_num = ntohs(data->block_num);
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, "<< TFTP_DATA : opcode(%d), block_num(%d)\r\n", data->opcode, data->block_num);
+#endif
+
+	switch(get_tftp_state())
+	{
+		case STATE_RRQ :
+		case STATE_OACK :
+			if(data->block_num == 1) {
+				set_tftp_state(STATE_DATA);
+				set_block_number(data->block_num);
+#ifdef F_STORAGE
+				save_data(data->data, msg_len - 4, data->block_num);
+#endif
+				tftp_cancel_timeout();
+			}
+			send_tftp_ack(data->block_num);
+
+			if((msg_len - 4) < TFTP_BLK_SIZE) {
+				init_tftp();
+				g_progress_state = TFTP_SUCCESS;
+			}
+
+			break;
+			
+		case STATE_DATA :
+			if(data->block_num == (get_block_number() + 1)) {
+				set_block_number(data->block_num);
+#ifdef F_STORAGE
+				save_data(data->data, msg_len - 4, data->block_num);
+#endif
+				tftp_cancel_timeout();
+			}
+			send_tftp_ack(data->block_num);
+
+			if((msg_len - 4) < TFTP_BLK_SIZE) {
+				init_tftp();
+				g_progress_state = TFTP_SUCCESS;
+			}
+
+			break;
+
+		default :
+			/* invalid message */
+			break;
+	}
+}
+
+static void recv_tftp_ack(uint8_t *msg, uint32_t msg_len)
+{
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, "<< TFTP_ACK : \r\n");
+#endif
+
+	switch(get_tftp_state())
+	{
+		case STATE_WRQ :
+			break;
+
+		case STATE_ACK :
+			break;
+
+		default :
+			/* invalid message */
+			break;
+	}
+}
+
+static void recv_tftp_oack(uint8_t *msg, uint32_t msg_len)
+{
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, "<< TFTP_OACK : \r\n");
+#endif
+
+	switch(get_tftp_state())
+	{
+		case STATE_RRQ :
+			process_tftp_option(msg, msg_len);	
+			set_tftp_state(STATE_OACK);
+			tftp_cancel_timeout();
+			send_tftp_ack(0);
+			break;
+
+		case STATE_WRQ :
+			process_tftp_option(msg, msg_len);	
+			set_tftp_state(STATE_ACK);
+			tftp_cancel_timeout();
+
+			/* TODO DATA Transfer */
+			//send_tftp_data(...);
+			break;
+
+		default :
+			/* invalid message */
+			break;
+	}
+}
+
+static void recv_tftp_error(uint8_t *msg, uint32_t msg_len)
+{
+	TFTP_ERROR_T *data= (TFTP_ERROR_T *)msg;
+
+	data->opcode = ntohs(data->opcode);
+	data->error_code = ntohs(data->error_code);
+
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(IPC_DBG, "<< TFTP_ERROR : %d (%s)\r\n", data->error_code, data->error_msg);
+	DBG_PRINT(ERROR_DBG, "[%s] Error Code : %d (%s)\r\n", __func__, data->error_code, data->error_msg);
+#endif
+	init_tftp();
+	g_progress_state = TFTP_FAIL;
+}
+
+static void recv_tftp_packet(uint8_t *packet, uint32_t packet_len, uint32_t from_ip, uint16_t from_port)
+{
+	uint16_t opcode;
+
+	/* Verify Server IP */
+	if(from_ip != get_server_ip()) {
+#ifdef __TFTP_DEBUG__
+		DBG_PRINT(ERROR_DBG, "[%s] Server IP faults\r\n", __func__);
+		DBG_PRINT(ERROR_DBG, "from IP : %08x, Server IP : %08x\r\n", from_ip, get_server_ip());
+#endif
+		return;
+	}
+
+	opcode = ntohs(*((uint16_t *)packet));
+
+	/* Set Server Port */
+	if((get_tftp_state() == STATE_WRQ) || (get_tftp_state() == STATE_RRQ)) {
+		set_server_port(from_port);
+#ifdef __TFTP_DEBUG__
+		DBG_PRINT(INFO_DBG, "[%s] Set Server Port : %d\r\n", __func__, from_port);
+#endif
+	}
+
+	switch(opcode)
+	{
+		case TFTP_RRQ :						/* When Server */
+			recv_tftp_rrq(packet, packet_len);
+			break;
+		case TFTP_WRQ :						/* When Server */
+			recv_tftp_wrq(packet, packet_len);
+			break;
+		case TFTP_DATA :
+			recv_tftp_data(packet, packet_len);
+			break;
+		case TFTP_ACK :
+			recv_tftp_ack(packet, packet_len);
+			break;
+		case TFTP_OACK :
+			recv_tftp_oack(packet, packet_len);
+			break;
+		case TFTP_ERROR :
+			recv_tftp_error(packet, packet_len);
+			break;
+
+		default :
+			// Unknown Mesage
+			break;
+	}
+}
+
+/* Functions ----------------------------------------------------*/
+void TFTP_init(uint8_t socket, uint8_t *buf)
+{
+	init_tftp();
+
+	g_tftp_socket = open_tftp_socket(socket);
+	g_tftp_rcv_buf = buf;
+}
+
+void TFTP_exit(void)
+{
+	init_tftp();
+
+	close_tftp_socket(g_tftp_socket);
+	g_tftp_socket = -1;
+
+	g_tftp_rcv_buf = NULL;
+}
+
+int TFTP_run(void)
+{
+	uint16_t len, from_port;
+	uint32_t from_ip;
+
+	/* Timeout Process */
+	if(g_resend_flag) {
+		if(tftp_time_cnt >= g_timeout) {
+			switch(get_tftp_state()) {
+			case STATE_WRQ:						// 미구현
+				break;
+
+			case STATE_RRQ:
+				send_tftp_rrq(g_filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
+				break;
+
+			case STATE_OACK:
+			case STATE_DATA:
+				send_tftp_ack(get_block_number());
+				break;
+
+			case STATE_ACK:						// 미구현
+				break;
+
+			default:
+				break;
+			}
+
+			tftp_time_cnt = 0;
+			tftp_retry_cnt++;
+
+			if(tftp_retry_cnt >= 5) {
+				init_tftp();
+				g_progress_state = TFTP_FAIL;
+			}
+		}
+	}
+
+	/* Receive Packet Process */
+	len = recv_udp_packet(g_tftp_socket, g_tftp_rcv_buf, MAX_MTU_SIZE, &from_ip, &from_port);
+	if(len < 0) {
+#ifdef __TFTP_DEBUG__
+		DBG_PRINT(ERROR_DBG, "[%s] recv_udp_packet error\r\n", __func__);
+#endif
+		return g_progress_state;
+	}
+
+	recv_tftp_packet(g_tftp_rcv_buf, len, from_ip, from_port);
+
+	return g_progress_state;
+}
+
+void TFTP_read_request(uint32_t server_ip, uint8_t *filename)
+{
+	set_server_ip(server_ip);
+#ifdef __TFTP_DEBUG__
+	DBG_PRINT(INFO_DBG, "[%s] Set Tftp Server : %x\r\n", __func__, server_ip);
+#endif
+
+	g_progress_state = TFTP_PROGRESS;
+	send_tftp_rrq(filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
+}
+
+void tftp_timeout_handler(void)
+{
+	if(g_resend_flag) 
+		tftp_time_cnt++;
+}

+ 101 - 0
lib/ioLibrary_Driver/Internet/TFTP/tftp.h

@@ -0,0 +1,101 @@
+/**
+ * @file tftp.h
+ * @brief TFTP Header File.
+ * @version 0.1.0
+ * @author Sang-sik Kim
+ */
+#ifndef __TFTP_H__
+#define __TFTP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define F_APP_TFTP
+#define __TFTP_DEBUG__
+
+#define F_STORAGE // If your target support a storage, you have to activate this feature and implement.
+
+#define SOCK_TFTP		1
+
+#define INFO_DBG		0x01
+#define ERROR_DBG		0x02
+#define DEBUG_DBG		0x04
+#define IPC_DBG			0x08
+
+#define DBG_PRINT(level, format, args...)		{ \
+											if(dbg_level & level) \
+												printf(format, ##args); \
+										}
+
+#define NORMAL_MODE		0
+#define TFTP_MODE		1
+
+extern int dbg_level;
+
+/* tftp message */
+#define TFTP_RRQ		1
+#define TFTP_WRQ		2
+#define TFTP_DATA		3
+#define TFTP_ACK		4
+#define TFTP_ERROR		5
+#define TFTP_OACK		6
+
+/* tftp state */
+#define STATE_NONE		0
+#define STATE_RRQ		1
+#define STATE_WRQ		2
+#define STATE_DATA		3
+#define STATE_ACK		4
+#define STATE_OACK		5
+
+/* tftp transfer mode */
+#define TRANS_ASCII		"netascii"
+#define TRANS_BINARY	"octet"
+
+/* tftp progress state */
+#define TFTP_PROGRESS	0
+#define TFTP_FAIL		1
+#define TFTP_SUCCESS	2
+
+/* define */
+#define TFTP_SERVER_PORT		69
+#define TFTP_TEMP_PORT			51000
+#define TFTP_BLK_SIZE			512
+#define MAX_MTU_SIZE			1514
+#define FILE_NAME_SIZE			20
+
+//#define __TFTP_DEBUG__
+
+/* typedef */ 
+typedef struct tftp_data {
+	uint16_t opcode;
+	uint16_t block_num;
+	uint8_t data[0];
+} TFTP_DATA_T;
+
+typedef struct tftp_error {
+	uint16_t opcode;
+	uint16_t error_code;
+	uint8_t error_msg[0];
+} TFTP_ERROR_T;
+
+typedef struct tftp_option {
+	uint8_t *code;
+	uint8_t *value;
+} TFTP_OPTION;
+
+/* Functions */
+void TFTP_init(uint8_t socket, uint8_t *buf);
+void TFTP_exit(void);
+int TFTP_run(void);
+void TFTP_read_request(uint32_t server_ip, uint8_t *filename);
+void tftp_timeout_handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/*__TFTP_H__ */

+ 402 - 0
lib/ioLibrary_Driver/Internet/httpServer/httpParser.c

@@ -0,0 +1,402 @@
+/**
+ @file		httpd.c
+ @brief 		functions associated http processing
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "socket.h"
+#include "httpParser.h"
+
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+//uint8_t BUFPUB[2048];
+uint8_t BUFPUB[256];
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+static void replacetochar(uint8_t * str, uint8_t oldchar, uint8_t newchar); 	/* Replace old character with new character in the string */
+static uint8_t C2D(uint8_t c); 												/* Convert a character to HEX */
+
+/**
+ @brief	convert escape characters(%XX) to ASCII character
+ */ 
+void unescape_http_url(
+	char * url	/**< pointer to be converted ( escape characters )*/
+	)
+{
+	int x, y;
+
+	for (x = 0, y = 0; url[y]; ++x, ++y) {
+		if ((url[x] = url[y]) == '%') {
+			url[x] = C2D(url[y+1])*0x10+C2D(url[y+2]);
+			y+=2;
+		}
+	}
+	url[x] = '\0';
+}
+
+
+/**
+ @brief	make response header such as html, gif, jpeg,etc.
+ */ 
+void make_http_response_head(
+	char * buf, 	/**< pointer to response header to be made */
+	char type, 	/**< response type */
+	uint32_t len	/**< size of response header */
+	)
+{
+	char * head;
+	char tmp[10];
+			
+	/*  file type*/
+	if 	(type == PTYPE_HTML) 		head = RES_HTMLHEAD_OK;
+	else if (type == PTYPE_GIF)		head = RES_GIFHEAD_OK;
+	else if (type == PTYPE_TEXT)	head = RES_TEXTHEAD_OK;
+	else if (type == PTYPE_JPEG)	head = RES_JPEGHEAD_OK;
+	else if (type == PTYPE_FLASH)	head = RES_FLASHHEAD_OK;
+	else if (type == PTYPE_XML) 	head =  RES_XMLHEAD_OK;
+	else if (type == PTYPE_CSS) 	head = RES_CSSHEAD_OK;
+	else if (type == PTYPE_JSON)	head = RES_JSONHEAD_OK;
+	else if (type == PTYPE_JS)		head = RES_JSHEAD_OK;
+	else if (type == PTYPE_CGI)		head = RES_CGIHEAD_OK;
+	else if (type == PTYPE_PNG)		head = RES_PNGHEAD_OK;
+	else if (type == PTYPE_ICO)		head = RES_ICOHEAD_OK;
+	else if (type == PTYPE_TTF)		head = RES_TTFHEAD_OK;
+	else if (type == PTYPE_OTF)		head = RES_OTFHEAD_OK;
+	else if (type == PTYPE_WOFF)	head = RES_WOFFHEAD_OK;
+	else if (type == PTYPE_EOT)		head = RES_EOTHEAD_OK;
+	else if (type == PTYPE_SVG)		head = RES_SVGHEAD_OK;
+#ifdef _HTTPPARSER_DEBUG_
+	else
+	{
+		head = NULL;
+		printf("\r\n\r\n-MAKE HEAD UNKNOWN-\r\n");
+	}
+#else
+	else head = NULL;
+#endif	
+
+	sprintf(tmp, "%ld", len);
+	strcpy(buf, head);
+	strcat(buf, tmp);
+	strcat(buf, "\r\n\r\n");
+}
+
+
+/**
+ @brief	find MIME type of a file
+ */ 
+void find_http_uri_type(
+	uint8_t * type, 	/**< type to be returned */
+	uint8_t * buff		/**< file name */
+	) 
+{
+	/* Decide type according to extension*/
+
+	char * buf;
+	buf = (char *)buff;
+
+	if 	(strstr(buf, ".htm")	|| strstr(buf, ".html"))	*type = PTYPE_HTML;
+	else if (strstr(buf, ".gif"))							*type = PTYPE_GIF;
+	else if (strstr(buf, ".text") 	|| strstr(buf,".txt"))	*type = PTYPE_TEXT;
+	else if (strstr(buf, ".jpeg") 	|| strstr(buf,".jpg"))	*type = PTYPE_JPEG;
+	else if (strstr(buf, ".swf")) 							*type = PTYPE_FLASH;
+	else if (strstr(buf, ".cgi") 	|| strstr(buf,".CGI"))	*type = PTYPE_CGI;
+	else if (strstr(buf, ".json") 	|| strstr(buf,".JSON"))	*type = PTYPE_JSON;
+	else if (strstr(buf, ".js") 	|| strstr(buf,".JS"))	*type = PTYPE_JS;
+	else if (strstr(buf, ".CGI") 	|| strstr(buf,".cgi"))	*type = PTYPE_CGI;
+	else if (strstr(buf, ".xml") 	|| strstr(buf,".XML"))	*type = PTYPE_XML;
+	else if (strstr(buf, ".css") 	|| strstr(buf,".CSS"))	*type = PTYPE_CSS;
+	else if (strstr(buf, ".png") 	|| strstr(buf,".PNG"))	*type = PTYPE_PNG;
+	else if (strstr(buf, ".ico") 	|| strstr(buf,".ICO"))	*type = PTYPE_ICO;
+	else if (strstr(buf, ".ttf") 	|| strstr(buf,".TTF"))	*type = PTYPE_TTF;
+	else if (strstr(buf, ".otf") 	|| strstr(buf,".OTF"))	*type = PTYPE_OTF;
+	else if (strstr(buf, ".woff") 	|| strstr(buf,".WOFF"))	*type = PTYPE_WOFF;
+	else if (strstr(buf, ".eot") 	|| strstr(buf,".EOT"))	*type = PTYPE_EOT;
+	else if (strstr(buf, ".svg") 	|| strstr(buf,".SVG"))	*type = PTYPE_SVG;
+	else 													*type = PTYPE_ERR;
+}
+
+
+/**
+ @brief	parse http request from a peer
+ */ 
+void parse_http_request(
+	st_http_request * request, 	/**< request to be returned */
+	uint8_t * buf				/**< pointer to be parsed */
+	)
+{
+  char * nexttok;
+  nexttok = strtok((char*)buf," ");
+  if(!nexttok)
+  {
+    request->METHOD = METHOD_ERR;
+    return;
+  }
+  if(!strcmp(nexttok, "GET") || !strcmp(nexttok,"get"))
+  {
+    request->METHOD = METHOD_GET;
+    nexttok = strtok(NULL," ");
+
+  }
+  else if (!strcmp(nexttok, "HEAD") || !strcmp(nexttok,"head"))
+  {
+    request->METHOD = METHOD_HEAD;
+    nexttok = strtok(NULL," ");
+
+  }
+  else if (!strcmp(nexttok, "POST") || !strcmp(nexttok,"post"))
+  {
+    nexttok = strtok(NULL,"\0");
+    request->METHOD = METHOD_POST;
+  }
+  else
+  {
+    request->METHOD = METHOD_ERR;
+  }
+
+  if(!nexttok)
+  {
+    request->METHOD = METHOD_ERR;
+    return;
+  }
+  strcpy((char *)request->URI, nexttok);
+}
+
+#ifdef _OLD_
+/**
+ @brief	get next parameter value in the request
+ */
+uint8_t * get_http_param_value(
+	char* uri, 
+	char* param_name
+	)
+{
+	char tempURI[MAX_URI_SIZE];
+	uint8_t * name = 0;
+	
+
+	if(!uri || !param_name) return 0;
+	
+	strcpy((char*)tempURI,uri);
+	if((name = (uint8_t*)strstr(tempURI, param_name)))
+	{
+		name += strlen(param_name) + 1; // strlen(para_name) + strlen("=")
+		if((name = (uint8_t*)strtok((char *)name,"& \r\n\t\0")))
+		{
+			unescape_http_url((char *)name);
+			replacetochar(name, '+', ' ');
+		}
+	}
+#ifdef _HTTPPARSER_DEBUG_
+	printf("  %s=%s",param_name,name);
+#endif	
+
+	return name;
+}
+#else
+/**
+ @brief	get next parameter value in the request
+ */
+uint8_t * get_http_param_value(char* uri, char* param_name)
+{
+
+	uint8_t * name = 0;
+	uint8_t * ret = BUFPUB;
+	uint8_t * pos2;
+	uint16_t len = 0, content_len = 0;
+	uint8_t tmp_buf[10]={0x00, };
+
+	if(!uri || !param_name) return 0;
+
+	/***************/
+	mid(uri, "Content-Length: ", "\r\n", (char *)tmp_buf);
+	content_len = ATOI(tmp_buf, 10);
+	uri = strstr(uri, "\r\n\r\n");
+	uri += 4;
+	uri[content_len] = 0;
+	/***************/
+
+	if((name = (uint8_t *)strstr(uri, param_name)))
+	{
+		name += strlen(param_name) + 1;
+		pos2 = (uint8_t*)strstr((char*)name, "&");
+		if(!pos2)
+		{
+			pos2 = name + strlen((char*)name);
+		}
+		len = pos2 - name;
+
+		if(len)
+		{
+			ret[len] = 0;
+			strncpy((char*)ret,(char*)name, len);
+			unescape_http_url((char *)ret);
+			replacetochar(ret, '+' ,' ');
+			//ret[len] = 0;
+			//ret[strlen((int8*)ret)] = 0;
+			//printf("len=%d\r\n",len);
+		}
+		else
+		{
+			ret[0] = 0;
+		}
+	}
+	else
+	{
+		return 0;
+	}
+#ifdef _HTTPPARSER_DEBUG_
+	printf("  %s=%s\r\n", param_name, ret);
+#endif
+	return ret;
+}
+#endif
+
+#ifdef _OLD_
+uint8_t * get_http_uri_name(uint8_t * uri)
+{
+	char tempURI[MAX_URI_SIZE];
+	uint8_t * uri_name;
+
+	if(!uri) return 0;
+
+	strcpy(tempURI, (char *)uri);
+
+	uri_name = (uint8_t *)strtok(tempURI, " ?");
+
+	if(strcmp((char *)uri_name,"/")) uri_name++;
+
+#ifdef _HTTPPARSER_DEBUG_
+	printf("  uri_name = %s\r\n", uri_name);
+#endif	
+
+	return uri_name;
+}
+#else
+
+uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf)
+{
+	uint8_t * uri_ptr;
+	if(!uri) return 0;
+
+	strcpy((char *)uri_buf, (char *)uri);
+
+	uri_ptr = (uint8_t *)strtok((char *)uri_buf, " ?");
+
+	if(strcmp((char *)uri_ptr,"/")) uri_ptr++;
+	strcpy((char *)uri_buf, (char *)uri_ptr);
+
+#ifdef _HTTPPARSER_DEBUG_
+	printf("  uri_name = %s\r\n", uri_buf);
+#endif
+
+	return 1;
+}
+
+#endif
+
+void inet_addr_(uint8_t * addr, uint8_t *ip)
+{
+	uint8_t i;
+	uint8_t taddr[30];
+	uint8_t * nexttok;
+	uint8_t num;
+
+	strcpy((char *)taddr, (char *)addr);
+
+	nexttok = taddr;
+	for(i = 0; i < 4 ; i++)
+	{
+		nexttok = (uint8_t *)strtok((char *)nexttok, ".");
+		if(nexttok[0] == '0' && nexttok[1] == 'x') num = ATOI(nexttok+2,0x10);
+		else num = ATOI(nexttok,10);
+		ip[i] = num;
+		nexttok = NULL;
+	}
+}
+
+
+/**
+@brief	CONVERT STRING INTO INTEGER
+@return	a integer number
+*/
+uint16_t ATOI(
+	uint8_t * str,	/**< is a pointer to convert */
+	uint8_t base	/**< is a base value (must be in the range 2 - 16) */
+	)
+{
+        unsigned int num = 0;
+// debug_2013_11_25
+//        while (*str !=0)
+        while ((*str !=0) && (*str != 0x20)) // not include the space(0x020)
+                num = num * base + C2D(*str++);
+	return num;
+}
+
+/**
+ * @brief Check strings and then execute callback function by each string.
+ * @param src The information of URI
+ * @param s1 The start string to be researched
+ * @param s2 The end string to be researched
+ * @param sub The string between s1 and s2
+ * @return The length value atfer working
+ */
+void mid(char* src, char* s1, char* s2, char* sub)
+{
+	char* sub1;
+	char* sub2;
+	uint16_t n;
+
+	sub1=strstr((char*)src,(char*)s1);
+	sub1+=strlen((char*)s1);
+	sub2=strstr((char*)sub1,(char*)s2);
+
+	n=sub2-sub1;
+	strncpy((char*)sub,(char*)sub1,n);
+	sub[n]='\0';
+}
+
+////////////////////////////////////////////////////////////////////
+// Static functions
+////////////////////////////////////////////////////////////////////
+
+/**
+@brief	replace the specified character in a string with new character
+*/
+static void replacetochar(
+		uint8_t * str, 		/**< pointer to be replaced */
+		uint8_t oldchar, 	/**< old character */
+		uint8_t newchar	/**< new character */
+	)
+{
+	int x;
+	for (x = 0; str[x]; x++)
+		if (str[x] == oldchar) str[x] = newchar;
+}
+
+/**
+@brief	CONVERT CHAR INTO HEX
+@return	HEX
+
+This function converts HEX(0-F) to a character
+*/
+static uint8_t C2D(
+		uint8_t c	/**< is a character('0'-'F') to convert to HEX */
+	)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return 10 + c -'a';
+	if (c >= 'A' && c <= 'F')
+		return 10 + c -'A';
+
+	return (char)c;
+}
+
+
+

+ 158 - 0
lib/ioLibrary_Driver/Internet/httpServer/httpParser.h

@@ -0,0 +1,158 @@
+/**
+ @file		httpd.h
+ @brief 		Define Constants and fucntions associated with HTTP protocol.
+ */
+
+#include <stdint.h>
+
+#ifndef	__HTTPPARSER_H__
+#define	__HTTPPARSER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define _HTTPPARSER_DEBUG_
+
+#define HTTP_SERVER_PORT		80		/**< HTTP server well-known port number */
+
+/* HTTP Method */
+#define		METHOD_ERR		0		/**< Error Method. */
+#define		METHOD_GET		1		/**< GET Method.   */
+#define		METHOD_HEAD		2		/**< HEAD Method.  */
+#define		METHOD_POST		3		/**< POST Method.  */
+
+/* HTTP GET Method */
+#define		PTYPE_ERR		0		/**< Error file. */
+#define		PTYPE_HTML		1		/**< HTML file.  */
+#define		PTYPE_GIF		2		/**< GIF file.   */
+#define		PTYPE_TEXT		3		/**< TEXT file.  */
+#define		PTYPE_JPEG		4		/**< JPEG file.  */
+#define		PTYPE_FLASH		5		/**< FLASH file. */
+#define		PTYPE_MPEG		6		/**< MPEG file.  */
+#define		PTYPE_PDF		7		/**< PDF file.   */
+#define 	PTYPE_CGI		8		/**< CGI file.   */
+#define     PTYPE_XML       9       /**< XML file.   */ 
+#define     PTYPE_CSS       10      /**< CSS file.   */
+#define		PTYPE_JS		11		/**< JavaScript file.	*/
+#define		PTYPE_JSON		12		/**< JSON (JavaScript Standard Object Notation) file.	*/
+#define		PTYPE_PNG		13		/**< PNG file. 	*/
+#define		PTYPE_ICO		14		/**< ICON file. */
+
+#define		PTYPE_TTF		20		/**< Font type: TTF file. */
+#define		PTYPE_OTF		21		/**< Font type: OTF file. */
+#define		PTYPE_WOFF		22		/**< Font type: WOFF file. */
+#define		PTYPE_EOT		23		/**< Font type: EOT file. */
+#define		PTYPE_SVG		24		/**< Font type: SVG file. */
+
+
+/* HTTP response */
+#define		STATUS_OK			200
+#define		STATUS_CREATED		201
+#define		STATUS_ACCEPTED		202
+#define		STATUS_NO_CONTENT	204
+#define		STATUS_MV_PERM		301
+#define		STATUS_MV_TEMP		302
+#define		STATUS_NOT_MODIF	304
+#define		STATUS_BAD_REQ		400
+#define		STATUS_UNAUTH		401
+#define		STATUS_FORBIDDEN	403
+#define		STATUS_NOT_FOUND	404
+#define		STATUS_INT_SERR		500
+#define		STATUS_NOT_IMPL		501
+#define		STATUS_BAD_GATEWAY	502
+#define		STATUS_SERV_UNAVAIL	503
+
+/* HTML Doc. for ERROR */
+static const char  	ERROR_HTML_PAGE[] = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nContent-Length: 78\r\n\r\n<HTML>\r\n<BODY>\r\nSorry, the page you requested was not found.\r\n</BODY>\r\n</HTML>\r\n\0";
+static const char 	ERROR_REQUEST_PAGE[] = "HTTP/1.1 400 OK\r\nContent-Type: text/html\r\nContent-Length: 50\r\n\r\n<HTML>\r\n<BODY>\r\nInvalid request.\r\n</BODY>\r\n</HTML>\r\n\0";
+
+/* HTML Doc. for CGI result  */
+#define HTML_HEADER "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
+
+/* Response header for HTML*/
+#define RES_HTMLHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: "
+
+/* Response head for TEXT */
+#define RES_TEXTHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: "
+
+/* Response head for GIF */
+#define RES_GIFHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: image/gif\r\nContent-Length: "
+
+/* Response head for JPEG */
+#define RES_JPEGHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: "
+
+/* Response head for PNG */
+#define RES_PNGHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: image/png\r\nContent-Length: "
+
+/* Response head for FLASH */
+#define RES_FLASHHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-shockwave-flash\r\nContent-Length: "
+
+/* Response head for XML */
+#define RES_XMLHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\nConnection: keep-alive\r\nContent-Length: "
+
+/* Response head for CSS */
+#define RES_CSSHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: text/css\r\nContent-Length: "		
+
+/* Response head for JavaScript */
+#define RES_JSHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: application/javascript\r\nContent-Length: "
+
+/* Response head for JSON */
+#define RES_JSONHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: "
+
+/* Response head for ICO */
+#define RES_ICOHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: image/x-icon\r\nContent-Length: "
+
+/* Response head for CGI */
+#define RES_CGIHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
+
+/* Response head for TTF, Font */
+#define RES_TTFHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: application/x-font-truetype\r\nContent-Length: "
+
+/* Response head for OTF, Font */
+#define RES_OTFHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: application/x-font-opentype\r\nContent-Length: "
+
+/* Response head for WOFF, Font */
+#define RES_WOFFHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: application/font-woff\r\nContent-Length: "
+
+/* Response head for EOT, Font */
+#define RES_EOTHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: application/vnd.ms-fontobject\r\nContent-Length: "
+
+/* Response head for SVG, Font */
+#define RES_SVGHEAD_OK	"HTTP/1.1 200 OK\r\nContent-Type: image/svg+xml\r\nContent-Length: "
+
+/**
+ @brief 	Structure of HTTP REQUEST 
+ */
+
+//#define MAX_URI_SIZE	1461
+#define MAX_URI_SIZE	512
+
+typedef struct _st_http_request
+{
+	uint8_t	METHOD;						/**< request method(METHOD_GET...). */
+	uint8_t	TYPE;						/**< request type(PTYPE_HTML...).   */
+	uint8_t	URI[MAX_URI_SIZE];			/**< request file name.             */
+}st_http_request;
+
+// HTTP Parsing functions
+void unescape_http_url(char * url);								/* convert escape character to ascii */
+void parse_http_request(st_http_request *, uint8_t *);			/* parse request from peer */
+void find_http_uri_type(uint8_t *, uint8_t *);					/* find MIME type of a file */
+void make_http_response_head(char *, char, uint32_t);			/* make response header */
+uint8_t * get_http_param_value(char* uri, char* param_name);	/* get the user-specific parameter value */
+uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf);	/* get the requested URI name */
+#ifdef _OLD_
+uint8_t * get_http_uri_name(uint8_t * uri);
+#endif
+
+// Utility functions
+uint16_t ATOI(uint8_t * str, uint8_t base);
+void mid(char* src, char* s1, char* s2, char* sub);
+void inet_addr_(uint8_t * addr, uint8_t * ip);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* end of __HTTPPARSER_H__ */

+ 749 - 0
lib/ioLibrary_Driver/Internet/httpServer/httpServer.c

@@ -0,0 +1,749 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "socket.h"
+#include "wizchip_conf.h"
+
+#include "httpServer.h"
+#include "httpParser.h"
+#include "httpUtil.h"
+
+#ifdef	_USE_SDCARD_
+#include "ff.h" 	// header file for FatFs library (FAT file system)
+#endif
+
+#ifndef DATA_BUF_SIZE
+	#define DATA_BUF_SIZE		2048
+#endif
+
+/*****************************************************************************
+ * Private types/enumerations/variables
+ ****************************************************************************/
+static uint8_t HTTPSock_Num[_WIZCHIP_SOCK_NUM_] = {0, };
+static st_http_request * http_request;				/**< Pointer to received HTTP request */
+static st_http_request * parsed_http_request;		/**< Pointer to parsed HTTP request */
+static uint8_t * http_response;						/**< Pointer to HTTP response */
+
+// ## For Debugging
+//static uint8_t uri_buf[128];
+
+// Number of registered web content in code flash memory
+static uint16_t total_content_cnt = 0;
+/*****************************************************************************
+ * Public types/enumerations/variables
+ ****************************************************************************/
+uint8_t * pHTTP_TX;
+uint8_t * pHTTP_RX;
+
+volatile uint32_t httpServer_tick_1s = 0;
+st_http_socket HTTPSock_Status[_WIZCHIP_SOCK_NUM_] = { {STATE_HTTP_IDLE, }, };
+httpServer_webContent web_content[MAX_CONTENT_CALLBACK];
+
+#ifdef	_USE_SDCARD_
+FIL fs;		// FatFs: File object
+FRESULT fr;	// FatFs: File function return code
+#endif
+
+/*****************************************************************************
+ * Private functions
+ ****************************************************************************/
+void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist);
+static uint8_t getHTTPSocketNum(uint8_t seqnum);
+static int8_t getHTTPSequenceNum(uint8_t socket);
+static int8_t http_disconnect(uint8_t sn);
+
+static void http_process_handler(uint8_t s, st_http_request * p_http_request);
+static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status);
+static void send_http_response_body(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len);
+static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len);
+
+/*****************************************************************************
+ * Public functions
+ ****************************************************************************/
+// Callback functions definition: MCU Reset / WDT Reset
+void default_mcu_reset(void) {;}
+void default_wdt_reset(void) {;}
+void (*HTTPServer_ReStart)(void) = default_mcu_reset;
+void (*HTTPServer_WDT_Reset)(void) = default_wdt_reset;
+
+void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist)
+{
+	uint8_t i;
+
+	for(i = 0; i < cnt; i++)
+	{
+		// Mapping the H/W socket numbers to the sequential index numbers
+		HTTPSock_Num[i] = socklist[i];
+	}
+}
+
+static uint8_t getHTTPSocketNum(uint8_t seqnum)
+{
+	// Return the 'H/W socket number' corresponding to the index number
+	return HTTPSock_Num[seqnum];
+}
+
+static int8_t getHTTPSequenceNum(uint8_t socket)
+{
+	uint8_t i;
+
+	for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++)
+		if(HTTPSock_Num[i] == socket) return i;
+
+	return -1;
+}
+
+void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist)
+{
+	// User's shared buffer
+	pHTTP_TX = tx_buf;
+	pHTTP_RX = rx_buf;
+
+	// H/W Socket number mapping
+	httpServer_Sockinit(cnt, socklist);
+}
+
+
+/* Register the call back functions for HTTP Server */
+void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void))
+{
+	// Callback: HW Reset and WDT reset function for each MCU platforms
+	if(mcu_reset) HTTPServer_ReStart = mcu_reset;
+	if(wdt_reset) HTTPServer_WDT_Reset = wdt_reset;
+}
+
+
+void httpServer_run(uint8_t seqnum)
+{
+	uint8_t s;	// socket number
+	uint16_t len;
+	uint32_t gettime = 0;
+
+#ifdef _HTTPSERVER_DEBUG_
+	uint8_t destip[4] = {0, };
+	uint16_t destport = 0;
+#endif
+
+	http_request = (st_http_request *)pHTTP_RX;		// Structure of HTTP Request
+	parsed_http_request = (st_http_request *)pHTTP_TX;
+
+	// Get the H/W socket number
+	s = getHTTPSocketNum(seqnum);
+
+	/* HTTP Service Start */
+	switch(getSn_SR(s))
+	{
+		case SOCK_ESTABLISHED:
+			// Interrupt clear
+			if(getSn_IR(s) & Sn_IR_CON)
+			{
+				setSn_IR(s, Sn_IR_CON);
+			}
+
+			// HTTP Process states
+			switch(HTTPSock_Status[seqnum].sock_status)
+			{
+
+				case STATE_HTTP_IDLE :
+					if ((len = getSn_RX_RSR(s)) > 0)
+					{
+						if (len > DATA_BUF_SIZE) len = DATA_BUF_SIZE;
+						len = recv(s, (uint8_t *)http_request, len);
+
+						*(((uint8_t *)http_request) + len) = '\0';
+
+						parse_http_request(parsed_http_request, (uint8_t *)http_request);
+#ifdef _HTTPSERVER_DEBUG_
+						getSn_DIPR(s, destip);
+						destport = getSn_DPORT(s);
+						printf("\r\n");
+						printf("> HTTPSocket[%d] : HTTP Request received ", s);
+						printf("from %d.%d.%d.%d : %d\r\n", destip[0], destip[1], destip[2], destip[3], destport);
+#endif
+#ifdef _HTTPSERVER_DEBUG_
+						printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE\r\n", s);
+#endif
+						// HTTP 'response' handler; includes send_http_response_header / body function
+						http_process_handler(s, parsed_http_request);
+
+						gettime = get_httpServer_timecount();
+						// Check the TX socket buffer for End of HTTP response sends
+						while(getSn_TX_FSR(s) != (getSn_TxMAX(s)))
+						{
+							if((get_httpServer_timecount() - gettime) > 3)
+							{
+#ifdef _HTTPSERVER_DEBUG_
+								printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE: TX Buffer clear timeout\r\n", s);
+#endif
+								break;
+							}
+						}
+
+						if(HTTPSock_Status[seqnum].file_len > 0) HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_INPROC;
+						else HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE; // Send the 'HTTP response' end
+					}
+					break;
+
+				case STATE_HTTP_RES_INPROC :
+					/* Repeat: Send the remain parts of HTTP responses */
+#ifdef _HTTPSERVER_DEBUG_
+					printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_INPROC\r\n", s);
+#endif
+					// Repeatedly send remaining data to client
+					send_http_response_body(s, 0, http_response, 0, 0);
+
+					if(HTTPSock_Status[seqnum].file_len == 0) HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE;
+					break;
+
+				case STATE_HTTP_RES_DONE :
+#ifdef _HTTPSERVER_DEBUG_
+					printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_DONE\r\n", s);
+#endif
+					// Socket file info structure re-initialize
+					HTTPSock_Status[seqnum].file_len = 0;
+					HTTPSock_Status[seqnum].file_offset = 0;
+					HTTPSock_Status[seqnum].file_start = 0;
+					HTTPSock_Status[seqnum].sock_status = STATE_HTTP_IDLE;
+
+//#ifdef _USE_SDCARD_
+//					f_close(&fs);
+//#endif
+#ifdef _USE_WATCHDOG_
+					HTTPServer_WDT_Reset();
+#endif
+					http_disconnect(s);
+					break;
+
+				default :
+					break;
+			}
+			break;
+
+		case SOCK_CLOSE_WAIT:
+#ifdef _HTTPSERVER_DEBUG_
+		printf("> HTTPSocket[%d] : ClOSE_WAIT\r\n", s);	// if a peer requests to close the current connection
+#endif
+			disconnect(s);
+			break;
+
+		case SOCK_CLOSED:
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : CLOSED\r\n", s);
+#endif
+			if(socket(s, Sn_MR_TCP, HTTP_SERVER_PORT, 0x00) == s)    /* Reinitialize the socket */
+			{
+#ifdef _HTTPSERVER_DEBUG_
+				printf("> HTTPSocket[%d] : OPEN\r\n", s);
+#endif
+			}
+			break;
+
+		case SOCK_INIT:
+			listen(s);
+			break;
+
+		case SOCK_LISTEN:
+			break;
+
+		default :
+			break;
+
+	} // end of switch
+
+#ifdef _USE_WATCHDOG_
+	HTTPServer_WDT_Reset();
+#endif
+}
+
+////////////////////////////////////////////
+// Private Functions
+////////////////////////////////////////////
+static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status)
+{
+	switch(http_status)
+	{
+		case STATUS_OK: 		// HTTP/1.1 200 OK
+			if((content_type != PTYPE_CGI) && (content_type != PTYPE_XML)) // CGI/XML type request does not respond HTTP header
+			{
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_OK\r\n", s);
+#endif
+				make_http_response_head((char*)http_response, content_type, body_len);
+			}
+			else
+			{
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response Header - NONE / CGI or XML\r\n", s);
+#endif
+				// CGI/XML type request does not respond HTTP header to client
+				http_status = 0;
+			}
+			break;
+		case STATUS_BAD_REQ: 	// HTTP/1.1 400 OK
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_BAD_REQ\r\n", s);
+#endif
+			memcpy(http_response, ERROR_REQUEST_PAGE, sizeof(ERROR_REQUEST_PAGE));
+			break;
+		case STATUS_NOT_FOUND:	// HTTP/1.1 404 Not Found
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_NOT_FOUND\r\n", s);
+#endif
+			memcpy(http_response, ERROR_HTML_PAGE, sizeof(ERROR_HTML_PAGE));
+			break;
+		default:
+			break;
+	}
+
+	// Send the HTTP Response 'header'
+	if(http_status)
+	{
+#ifdef _HTTPSERVER_DEBUG_
+		printf("> HTTPSocket[%d] : [Send] HTTP Response Header [ %d ]byte\r\n", s, (uint16_t)strlen((char *)http_response));
+#endif
+		send(s, http_response, strlen((char *)http_response));
+	}
+}
+
+static void send_http_response_body(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len)
+{
+	int8_t get_seqnum;
+	uint32_t send_len;
+
+	uint8_t flag_datasend_end = 0;
+
+#ifdef _USE_SDCARD_
+	uint16_t blocklen;
+#endif
+#ifdef _USE_FLASH_
+	uint32_t addr = 0;
+#endif
+
+	if((get_seqnum = getHTTPSequenceNum(s)) == -1) return; // exception handling; invalid number
+
+	// Send the HTTP Response 'body'; requested file
+	if(!HTTPSock_Status[get_seqnum].file_len) // ### Send HTTP response body: First part ###
+	{
+		if (file_len > DATA_BUF_SIZE - 1)
+		{
+			HTTPSock_Status[get_seqnum].file_start = start_addr;
+			HTTPSock_Status[get_seqnum].file_len = file_len;
+			send_len = DATA_BUF_SIZE - 1;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
+			memset(HTTPSock_Status[get_seqnum].file_name, 0x00, MAX_CONTENT_NAME_LEN);
+			strcpy((char *)HTTPSock_Status[get_seqnum].file_name, (char *)uri_name);
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response body - file name [ %s ]\r\n", s, HTTPSock_Status[get_seqnum].file_name);
+#endif
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response body - file len [ %ld ]byte\r\n", s, file_len);
+#endif
+		}
+		else
+		{
+			// Send process end
+			send_len = file_len;
+
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response end - file len [ %ld ]byte\r\n", s, send_len);
+#endif
+		}
+#ifdef _USE_FLASH_
+		if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH) addr = start_addr;
+#endif
+	}
+	else // remained parts
+	{
+#ifdef _USE_FLASH_
+		if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH)
+		{
+			addr = HTTPSock_Status[get_seqnum].file_start + HTTPSock_Status[get_seqnum].file_offset;
+		}
+#endif
+		send_len = HTTPSock_Status[get_seqnum].file_len - HTTPSock_Status[get_seqnum].file_offset;
+
+		if(send_len > DATA_BUF_SIZE - 1)
+		{
+			send_len = DATA_BUF_SIZE - 1;
+			//HTTPSock_Status[get_seqnum]->file_offset += send_len;
+		}
+		else
+		{
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response end - file len [ %ld ]byte\r\n", s, HTTPSock_Status[get_seqnum].file_len);
+#endif
+			// Send process end
+			flag_datasend_end = 1;
+		}
+#ifdef _HTTPSERVER_DEBUG_
+			printf("> HTTPSocket[%d] : HTTP Response body - send len [ %ld ]byte\r\n", s, send_len);
+#endif
+	}
+
+/*****************************************************/
+	//HTTPSock_Status[get_seqnum]->storage_type == NONE
+	//HTTPSock_Status[get_seqnum]->storage_type == CODEFLASH
+	//HTTPSock_Status[get_seqnum]->storage_type == SDCARD
+	//HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH
+/*****************************************************/
+
+	if(HTTPSock_Status[get_seqnum].storage_type == CODEFLASH)
+	{
+		if(HTTPSock_Status[get_seqnum].file_len) start_addr = HTTPSock_Status[get_seqnum].file_start;
+		read_userReg_webContent(start_addr, &buf[0], HTTPSock_Status[get_seqnum].file_offset, send_len);
+	}
+#ifdef _USE_SDCARD_
+	else if(HTTPSock_Status[get_seqnum].storage_type == SDCARD)
+	{
+		// Data read from SD Card
+		fr = f_read(&fs, &buf[0], send_len, (void *)&blocklen);
+		if(fr != FR_OK)
+		{
+			send_len = 0;
+#ifdef _HTTPSERVER_DEBUG_
+		printf("> HTTPSocket[%d] : [FatFs] Error code return: %d (File Read) / HTTP Send Failed - %s\r\n", s, fr, HTTPSock_Status[get_seqnum].file_name);
+#endif
+		}
+		else
+		{
+			*(buf+send_len+1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
+		}
+	}
+#endif
+
+#ifdef _USE_FLASH_
+	else if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH)
+	{
+		// Data read from external data flash memory
+		read_from_flashbuf(addr, &buf[0], send_len);
+		*(buf+send_len+1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
+	}
+#endif
+	else
+	{
+		send_len = 0;
+	}
+	// Requested content send to HTTP client
+#ifdef _HTTPSERVER_DEBUG_
+	printf("> HTTPSocket[%d] : [Send] HTTP Response body [ %ld ]byte\r\n", s, send_len);
+#endif
+
+	if(send_len) send(s, buf, send_len);
+	else flag_datasend_end = 1;
+
+	if(flag_datasend_end)
+	{
+		HTTPSock_Status[get_seqnum].file_start = 0;
+		HTTPSock_Status[get_seqnum].file_len = 0;
+		HTTPSock_Status[get_seqnum].file_offset = 0;
+		flag_datasend_end = 0;
+	}
+	else
+	{
+		HTTPSock_Status[get_seqnum].file_offset += send_len;
+#ifdef _HTTPSERVER_DEBUG_
+		printf("> HTTPSocket[%d] : HTTP Response body - offset [ %ld ]\r\n", s, HTTPSock_Status[get_seqnum].file_offset);
+#endif
+	}
+
+// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
+#ifdef _USE_SDCARD_
+	f_close(&fs);
+#endif
+// ## 20141219 added end
+}
+
+static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len)
+{
+	uint16_t send_len = 0;
+
+#ifdef _HTTPSERVER_DEBUG_
+	printf("> HTTPSocket[%d] : HTTP Response Header + Body - CGI\r\n", s);
+#endif
+	send_len = sprintf((char *)buf, "%s%d\r\n\r\n%s", RES_CGIHEAD_OK, file_len, http_body);
+#ifdef _HTTPSERVER_DEBUG_
+	printf("> HTTPSocket[%d] : HTTP Response Header + Body - send len [ %d ]byte\r\n", s, send_len);
+#endif
+
+	send(s, buf, send_len);
+}
+
+
+static int8_t http_disconnect(uint8_t sn)
+{
+	setSn_CR(sn,Sn_CR_DISCON);
+	/* wait to process the command... */
+	while(getSn_CR(sn));
+
+	return SOCK_OK;
+}
+
+
+static void http_process_handler(uint8_t s, st_http_request * p_http_request)
+{
+	uint8_t * uri_name;
+	uint32_t content_addr = 0;
+	uint16_t content_num = 0;
+	uint32_t file_len = 0;
+
+	uint8_t uri_buf[MAX_URI_SIZE]={0x00, };
+
+	uint16_t http_status;
+	int8_t get_seqnum;
+	uint8_t content_found;
+
+	if((get_seqnum = getHTTPSequenceNum(s)) == -1) return; // exception handling; invalid number
+
+	http_status = 0;
+	http_response = pHTTP_RX;
+	file_len = 0;
+
+	//method Analyze
+	switch (p_http_request->METHOD)
+	{
+		case METHOD_ERR :
+			http_status = STATUS_BAD_REQ;
+			send_http_response_header(s, 0, 0, http_status);
+			break;
+
+		case METHOD_HEAD :
+		case METHOD_GET :
+			get_http_uri_name(p_http_request->URI, uri_buf);
+			uri_name = uri_buf;
+
+			if (!strcmp((char *)uri_name, "/")) strcpy((char *)uri_name, INITIAL_WEBPAGE);	// If URI is "/", respond by index.html
+			if (!strcmp((char *)uri_name, "m")) strcpy((char *)uri_name, M_INITIAL_WEBPAGE);
+			if (!strcmp((char *)uri_name, "mobile")) strcpy((char *)uri_name, MOBILE_INITIAL_WEBPAGE);
+			find_http_uri_type(&p_http_request->TYPE, uri_name);	// Checking requested file types (HTML, TEXT, GIF, JPEG and Etc. are included)
+
+#ifdef _HTTPSERVER_DEBUG_
+			printf("\r\n> HTTPSocket[%d] : HTTP Method GET\r\n", s);
+			printf("> HTTPSocket[%d] : Request Type = %d\r\n", s, p_http_request->TYPE);
+			printf("> HTTPSocket[%d] : Request URI = %s\r\n", s, uri_name);
+#endif
+
+			if(p_http_request->TYPE == PTYPE_CGI)
+			{
+				content_found = http_get_cgi_handler(uri_name, pHTTP_TX, &file_len);
+				if(content_found && (file_len <= (DATA_BUF_SIZE-(strlen(RES_CGIHEAD_OK)+8))))
+				{
+					send_http_response_cgi(s, http_response, pHTTP_TX, (uint16_t)file_len);
+				}
+				else
+				{
+					send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
+				}
+			}
+			else
+			{
+				// Find the User registered index for web content
+				if(find_userReg_webContent(uri_buf, &content_num, &file_len))
+				{
+					content_found = 1; // Web content found in code flash memory
+					content_addr = (uint32_t)content_num;
+					HTTPSock_Status[get_seqnum].storage_type = CODEFLASH;
+				}
+				// Not CGI request, Web content in 'SD card' or 'Data flash' requested
+#ifdef _USE_SDCARD_
+#ifdef _HTTPSERVER_DEBUG_
+				printf("\r\n> HTTPSocket[%d] : Searching the requested content\r\n", s);
+#endif
+				if((fr = f_open(&fs, (const char *)uri_name, FA_READ)) == 0)
+				{
+					content_found = 1; // file open succeed
+
+					file_len = fs.fsize;
+					content_addr = fs.sclust;
+					HTTPSock_Status[get_seqnum].storage_type = SDCARD;
+				}
+#elif _USE_FLASH_
+				else if(/* Read content from Dataflash */)
+				{
+					content_found = 1;
+					HTTPSock_Status[get_seqnum]->storage_type = DATAFLASH;
+					; // To do
+				}
+#endif
+				else
+				{
+					content_found = 0; // fail to find content
+				}
+
+				if(!content_found)
+				{
+#ifdef _HTTPSERVER_DEBUG_
+					printf("> HTTPSocket[%d] : Unknown Page Request\r\n", s);
+#endif
+					http_status = STATUS_NOT_FOUND;
+				}
+				else
+				{
+#ifdef _HTTPSERVER_DEBUG_
+					printf("> HTTPSocket[%d] : Find Content [%s] ok - Start [%ld] len [ %ld ]byte\r\n", s, uri_name, content_addr, file_len);
+#endif
+					http_status = STATUS_OK;
+				}
+
+				// Send HTTP header
+				if(http_status)
+				{
+#ifdef _HTTPSERVER_DEBUG_
+					printf("> HTTPSocket[%d] : Requested content len = [ %ld ]byte\r\n", s, file_len);
+#endif
+					send_http_response_header(s, p_http_request->TYPE, file_len, http_status);
+				}
+
+				// Send HTTP body (content)
+				if(http_status == STATUS_OK)
+				{
+					send_http_response_body(s, uri_name, http_response, content_addr, file_len);
+				}
+			}
+			break;
+
+		case METHOD_POST :
+			mid((char *)p_http_request->URI, "/", " HTTP", (char *)uri_buf);
+			uri_name = uri_buf;
+			find_http_uri_type(&p_http_request->TYPE, uri_name);	// Check file type (HTML, TEXT, GIF, JPEG are included)
+
+#ifdef _HTTPSERVER_DEBUG_
+			printf("\r\n> HTTPSocket[%d] : HTTP Method POST\r\n", s);
+			printf("> HTTPSocket[%d] : Request URI = %s ", s, uri_name);
+			printf("Type = %d\r\n", p_http_request->TYPE);
+#endif
+
+			if(p_http_request->TYPE == PTYPE_CGI)	// HTTP POST Method; CGI Process
+			{
+				content_found = http_post_cgi_handler(uri_name, p_http_request, http_response, &file_len);
+#ifdef _HTTPSERVER_DEBUG_
+				printf("> HTTPSocket[%d] : [CGI: %s] / Response len [ %ld ]byte\r\n", s, content_found?"Content found":"Content not found", file_len);
+#endif
+				if(content_found && (file_len <= (DATA_BUF_SIZE-(strlen(RES_CGIHEAD_OK)+8))))
+				{
+					send_http_response_cgi(s, pHTTP_TX, http_response, (uint16_t)file_len);
+
+					// Reset the H/W for apply to the change configuration information
+					if(content_found == HTTP_RESET) HTTPServer_ReStart();
+				}
+				else
+				{
+					send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
+				}
+			}
+			else	// HTTP POST Method; Content not found
+			{
+				send_http_response_header(s, 0, 0, STATUS_NOT_FOUND);
+			}
+			break;
+
+		default :
+			http_status = STATUS_BAD_REQ;
+			send_http_response_header(s, 0, 0, http_status);
+			break;
+	}
+}
+
+void httpServer_time_handler(void)
+{
+	httpServer_tick_1s++;
+}
+
+uint32_t get_httpServer_timecount(void)
+{
+	return httpServer_tick_1s;
+}
+
+void reg_httpServer_webContent(uint8_t * content_name, uint8_t * content)
+{
+	uint16_t name_len;
+	uint32_t content_len;
+
+	if(content_name == NULL || content == NULL)
+	{
+		return;
+	}
+	else if(total_content_cnt >= MAX_CONTENT_CALLBACK)
+	{
+		return;
+	}
+
+	name_len = strlen((char *)content_name);
+	content_len = strlen((char *)content);
+
+	web_content[total_content_cnt].content_name = malloc(name_len+1);
+	strcpy((char *)web_content[total_content_cnt].content_name, (const char *)content_name);
+	web_content[total_content_cnt].content_len = content_len;
+	web_content[total_content_cnt].content = content;
+
+	total_content_cnt++;
+}
+
+uint8_t display_reg_webContent_list(void)
+{
+	uint16_t i;
+	uint8_t ret;
+
+	if(total_content_cnt == 0)
+	{
+		printf(">> Web content file not found\r\n");
+		ret = 0;
+	}
+	else
+	{
+		printf("\r\n=== List of Web content in code flash ===\r\n");
+		for(i = 0; i < total_content_cnt; i++)
+		{
+			printf(" [%d] ", i+1);
+			printf("%s, ", web_content[i].content_name);
+			printf("%ld byte, ", web_content[i].content_len);
+
+			if(web_content[i].content_len < 30) printf("[%s]\r\n", web_content[i].content);
+			else printf("[ ... ]\r\n");
+		}
+		printf("=========================================\r\n\r\n");
+		ret = 1;
+	}
+
+	return ret;
+}
+
+uint8_t find_userReg_webContent(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len)
+{
+	uint16_t i;
+	uint8_t ret = 0; // '0' means 'File Not Found'
+
+	for(i = 0; i < total_content_cnt; i++)
+	{
+		if(!strcmp((char *)content_name, (char *)web_content[i].content_name))
+		{
+			*file_len = web_content[i].content_len;
+			*content_num = i;
+			ret = 1; // If the requested content found, ret set to '1' (Found)
+			break;
+		}
+	}
+	return ret;
+}
+
+
+uint16_t read_userReg_webContent(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size)
+{
+	uint16_t ret = 0;
+	uint8_t * ptr;
+
+	if(content_num > total_content_cnt) return 0;
+
+	ptr = web_content[content_num].content;
+	if(offset) ptr += offset;
+
+	strncpy((char *)buf, (char *)ptr, size);
+	*(buf+size) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
+
+	ret = strlen((void *)buf);
+	return ret;
+}

+ 111 - 0
lib/ioLibrary_Driver/Internet/httpServer/httpServer.h

@@ -0,0 +1,111 @@
+/**
+ @file		httpServer.h
+ @brief 	Define constants and functions related HTTP Web server.
+ */
+
+#include <stdint.h>
+
+#ifndef	__HTTPSERVER_H__
+#define	__HTTPSERVER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// HTTP Server debug message enable
+#define _HTTPSERVER_DEBUG_
+
+#define INITIAL_WEBPAGE				"index.html"
+#define M_INITIAL_WEBPAGE			"m/index.html"
+#define MOBILE_INITIAL_WEBPAGE		"mobile/index.html"
+
+/* Web Server Content Storage Select */
+//#define _USE_SDCARD_
+#ifndef _USE_SDCARD_
+//#define _USE_FLASH_
+#endif
+
+#if !defined(_USE_SDCARD_) && !defined(_USE_FLASH_)
+#define _NOTUSED_STORAGE_
+#endif
+
+
+/* Watchdog timer */
+//#define _USE_WATCHDOG_
+
+/*********************************************
+* HTTP Process states list
+*********************************************/
+#define STATE_HTTP_IDLE             0           /* IDLE, Waiting for data received (TCP established) */
+#define STATE_HTTP_REQ_INPROC  		1           /* Received HTTP request from HTTP client */
+#define STATE_HTTP_REQ_DONE    		2           /* The end of HTTP request parse */
+#define STATE_HTTP_RES_INPROC  		3           /* Sending the HTTP response to HTTP client (in progress) */
+#define STATE_HTTP_RES_DONE    		4           /* The end of HTTP response send (HTTP transaction ended) */
+
+/*********************************************
+* HTTP Simple Return Value
+*********************************************/
+#define HTTP_FAILED					0
+#define HTTP_OK						1
+#define HTTP_RESET					2
+
+/*********************************************
+* HTTP Content NAME length
+*********************************************/
+#define MAX_CONTENT_NAME_LEN		128
+
+/*********************************************
+* HTTP Timeout
+*********************************************/
+#define HTTP_MAX_TIMEOUT_SEC		3			// Sec.
+
+typedef enum
+{
+   NONE,		///< Web storage none
+   CODEFLASH,	///< Code flash memory
+   SDCARD,    	///< SD card
+   DATAFLASH	///< External data flash memory
+}StorageType;
+
+typedef struct _st_http_socket
+{
+	uint8_t			sock_status;
+	uint8_t			file_name[MAX_CONTENT_NAME_LEN];
+	uint32_t 		file_start;
+	uint32_t 		file_len;
+	uint32_t 		file_offset; // (start addr + sent size...)
+	uint8_t			storage_type; // Storage type; Code flash, SDcard, Data flash ...
+}st_http_socket;
+
+// Web content structure for file in code flash memory
+#define MAX_CONTENT_CALLBACK		20
+
+typedef struct _httpServer_webContent
+{
+	uint8_t	*	content_name;
+	uint32_t	content_len;
+	uint8_t * 	content;
+}httpServer_webContent;
+
+
+void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist);
+void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void));
+void httpServer_run(uint8_t seqnum);
+
+void reg_httpServer_webContent(uint8_t * content_name, uint8_t * content);
+uint8_t find_userReg_webContent(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len);
+uint16_t read_userReg_webContent(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size);
+uint8_t display_reg_webContent_list(void);
+
+/*
+ * @brief HTTP Server 1sec Tick Timer handler
+ * @note SHOULD BE register to your system 1s Tick timer handler
+ */
+void httpServer_time_handler(void);
+uint32_t get_httpServer_timecount(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 75 - 0
lib/ioLibrary_Driver/Internet/httpServer/httpUtil.c

@@ -0,0 +1,75 @@
+/**
+ * @file	httpUtil.c
+ * @brief	HTTP Server Utilities	
+ * @version 1.0
+ * @date	2014/07/15
+ * @par Revision
+ *			2014/07/15 - 1.0 Release
+ * @author	
+ * \n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "httpUtil.h"
+
+uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len)
+{
+	uint8_t ret = HTTP_OK;
+	uint16_t len = 0;
+
+	if(predefined_get_cgi_processor(uri_name, buf, &len))
+	{
+		;
+	}
+	else if(strcmp((const char *)uri_name, "example.cgi") == 0)
+	{
+		// To do
+		;
+	}
+	else
+	{
+		// CGI file not found
+		ret = HTTP_FAILED;
+	}
+
+	if(ret)	*file_len = len;
+	return ret;
+}
+
+uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len)
+{
+	uint8_t ret = HTTP_OK;
+	uint16_t len = 0;
+	uint8_t val = 0;
+
+	if(predefined_set_cgi_processor(uri_name, p_http_request->URI, buf, &len))
+	{
+		;
+	}
+	else if(strcmp((const char *)uri_name, "example.cgi") == 0)
+	{
+		// To do
+		val = 1;
+		len = sprintf((char *)buf, "%d", val);
+	}
+	else
+	{
+		// CGI file not found
+		ret = HTTP_FAILED;
+	}
+
+	if(ret)	*file_len = len;
+	return ret;
+}
+
+uint8_t predefined_get_cgi_processor(uint8_t * uri_name, uint8_t * buf, uint16_t * len)
+{
+	;
+}
+
+uint8_t predefined_set_cgi_processor(uint8_t * uri_name, uint8_t * uri, uint8_t * buf, uint16_t * en)
+{
+	;
+}

+ 32 - 0
lib/ioLibrary_Driver/Internet/httpServer/httpUtil.h

@@ -0,0 +1,32 @@
+/**
+ * @file	httpUtil.h
+ * @brief	Header File for HTTP Server Utilities
+ * @version 1.0
+ * @date	2014/07/15
+ * @par Revision
+ *			2014/07/15 - 1.0 Release
+ * @author	
+ * \n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
+ */
+
+#ifndef	__HTTPUTIL_H__
+#define	__HTTPUTIL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "httpServer.h"
+#include "httpParser.h"
+
+uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len);
+uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len);
+
+uint8_t predefined_get_cgi_processor(uint8_t * uri_name, uint8_t * buf, uint16_t * len);
+uint8_t predefined_set_cgi_processor(uint8_t * uri_name, uint8_t * uri, uint8_t * buf, uint16_t * len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 58 - 0
lib/ioLibrary_Driver/README.md

@@ -0,0 +1,58 @@
+# ioLibrary Driver
+The ioLibrary means “Internet Offload Library” for WIZnet chip. It includes drivers and application protocols.
+The driver (ioLibrary) can be used for the application design of WIZnet TCP/IP chips as [W5500](http://wizwiki.net/wiki/doku.php?id=products:w5500:start), W5300, W5200, W5100 [W5100S](http://wizwiki.net/wiki/doku.php?id=products:w5100s:start).
+
+## ioLibrary
+This driver provides the Berkeley Socket type APIs.
+- Directory Structure
+<!-- ioLibrary pic -->
+![ioLibrary](http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:iolibrary_bsd.jpg "ioLibrary")
+
+- Ethernet : SOCKET APIs like BSD & WIZCHIP([W5500](http://wizwiki.net/wiki/doku.php?id=products:w5500:start) / W5300 /  W5200 / W5100 / [W5100S](http://wizwiki.net/wiki/doku.php?id=products:w5100s:start)) Driver
+- Internet :
+  - DHCP client
+  - DNS client
+  - FTP client
+  - FTP server
+  - SNMP agent/trap
+  - SNTP client
+  - TFTP client
+  - HTTP server
+  - MQTT Client
+  - Others will be added.
+
+## How to add an ioLibrary in project through github site.
+  - Example, refer to https://www.youtube.com/watch?v=mt815RBGdsA
+  - [ioLibrary Doxygen doument](https://github.com/Wiznet/ioLibrary_Driver/blob/master/Ethernet/Socket_APIs_V3.0.3.chm) : Refer to **TODO** in this document
+    - Define what chip is used in **wizchip_conf.h**
+    - Define what Host I/F mode is used in **wizchip_conf.h**
+
+## Revision History
+  * ioLibrary V4.0.0 Released : 29, MAR, 2018
+    * New features added: Library for W5100S added.
+  * ioLibrary V3.1.1 Released : 14, Dec, 2016
+    * Bug fixed : In Socket.c Fixed MACraw & IPraw sendto function.
+  * ioLibrary V3.1.0 Released : 05, Dec, 2016
+    * Internet application protocol add to MQTT Client (using paho MQTT 3.11)
+  * ioLibrary V3.0.3 Released : 03, May, 2016
+    * In W5300, Fixed some compile errors in close(). Refer to M20160503
+    * In close(), replace socket() with some command sequences.
+  * ioLibrary V3.0.2 Released : 26, April, 2016
+    * Applied the erratum #1 in close() of socket.c (Refer to A20160426)
+  * ioLibrary V3.0.1 Released : 15, July, 2015
+    * Bug fixed : In W5100, Fixed CS control problem in read/write buffer with SPI. Refer to M20150715.
+  * ioLibrary V3.0 Released : 01, June, 2015
+    * Add to W5300
+    * Typing Error in comments
+    * Refer to 20150601 in sources.
+
+  * Type casting error Fixed : 09, April. 2015
+    In socket.c, send() : Refer to M20150409
+
+  * ioLibrary V2.0 released : April. 2015
+    * Added to W5100, W5200
+    * Correct to some typing error
+    * Fixed the warning of type casting.
+
+  * Last release : Nov. 2014
+

TEMPAT SAMPAH
lib/ioLibrary_Driver/iolibrary.chm


+ 22 - 0
lib/ioLibrary_Driver/license.txt

@@ -0,0 +1,22 @@
+
+Copyright (c) 2014 WIZnet Co.,Ltd.
+Copyright (c) WIZnet ioLibrary Project.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.