W5500 driver for mbed OS 5

Dependents:   http-webserver-example mbed-os-example-sockets

Fork of W5500Interface by Sergei G

Committer:
Bongjun
Date:
Fri Aug 10 08:51:31 2018 +0000
Revision:
9:351e20cf7d05
Parent:
6:e2ab76b2be07
add comment on DHCPClient files

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bongjun 9:351e20cf7d05 1 /*
Bongjun 9:351e20cf7d05 2 * DHCPClient.cpp
Bongjun 9:351e20cf7d05 3 * Mbed OS5 support added by Sergei G <https://os.mbed.com/users/sgnezdov/>
Bongjun 9:351e20cf7d05 4 * Ported here on Aug/09/2018
Bongjun 9:351e20cf7d05 5 *
Bongjun 9:351e20cf7d05 6 */
Bongjun 9:351e20cf7d05 7
Bongjun 6:e2ab76b2be07 8 // DHCPClient.cpp 2013/4/10
Bongjun 6:e2ab76b2be07 9 #include "mbed.h"
Bongjun 6:e2ab76b2be07 10 #include "mbed_debug.h"
Bongjun 6:e2ab76b2be07 11 #include "UDPSocket.h"
Bongjun 6:e2ab76b2be07 12 #include "DHCPClient.h"
Bongjun 6:e2ab76b2be07 13
Bongjun 6:e2ab76b2be07 14 #define DBG_DHCP 0
Bongjun 6:e2ab76b2be07 15
Bongjun 6:e2ab76b2be07 16 #if DBG_DHCP
Bongjun 6:e2ab76b2be07 17 #define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0);
Bongjun 6:e2ab76b2be07 18 #define DBG_HEX(A,B) do{debug("[%s:%d]\r\n", __PRETTY_FUNCTION__,__LINE__);debug_hex(A,B);} while(0);
Bongjun 6:e2ab76b2be07 19 #else
Bongjun 6:e2ab76b2be07 20 #define DBG(...) while(0);
Bongjun 6:e2ab76b2be07 21 #define DBG_HEX(A,B) while(0);
Bongjun 6:e2ab76b2be07 22 #endif
Bongjun 6:e2ab76b2be07 23
Bongjun 6:e2ab76b2be07 24 int DHCPClient::discover()
Bongjun 6:e2ab76b2be07 25 {
Bongjun 6:e2ab76b2be07 26 m_pos = 0;
Bongjun 6:e2ab76b2be07 27 const uint8_t header[] = {0x01,0x01,0x06,0x00};
Bongjun 6:e2ab76b2be07 28 add_buf((uint8_t*)header, sizeof(header));
Bongjun 6:e2ab76b2be07 29 uint32_t x = time(NULL) + rand();
Bongjun 6:e2ab76b2be07 30 xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x;
Bongjun 6:e2ab76b2be07 31 add_buf(xid, 4);
Bongjun 6:e2ab76b2be07 32 fill_buf(20, 0x00);
Bongjun 6:e2ab76b2be07 33 add_buf(chaddr, 6);
Bongjun 6:e2ab76b2be07 34 fill_buf(10+192, 0x00);
Bongjun 6:e2ab76b2be07 35 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
Bongjun 6:e2ab76b2be07 36 53,1,DHCPDISCOVER, // DHCP option 53: DHCP Discover
Bongjun 6:e2ab76b2be07 37 55,4,1,3,15,6,
Bongjun 6:e2ab76b2be07 38 255};
Bongjun 6:e2ab76b2be07 39 add_buf((uint8_t*)options, sizeof(options));
Bongjun 6:e2ab76b2be07 40 return m_pos;
Bongjun 6:e2ab76b2be07 41 }
Bongjun 6:e2ab76b2be07 42
Bongjun 6:e2ab76b2be07 43 int DHCPClient::request()
Bongjun 6:e2ab76b2be07 44 {
Bongjun 6:e2ab76b2be07 45 m_pos = 0;
Bongjun 6:e2ab76b2be07 46 const uint8_t header[] = {0x01,0x01,0x06,0x00};
Bongjun 6:e2ab76b2be07 47 add_buf((uint8_t*)header, sizeof(header));
Bongjun 6:e2ab76b2be07 48 add_buf(xid, 4);
Bongjun 6:e2ab76b2be07 49 fill_buf(12, 0x00);
Bongjun 6:e2ab76b2be07 50 add_buf(siaddr, 4);
Bongjun 6:e2ab76b2be07 51 fill_buf(4, 0x00); // giaddr
Bongjun 6:e2ab76b2be07 52 add_buf(chaddr, 6);
Bongjun 6:e2ab76b2be07 53 fill_buf(10+192, 0x00);
Bongjun 6:e2ab76b2be07 54 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
Bongjun 6:e2ab76b2be07 55 53,1,DHCPREQUEST, // DHCP option 53: DHCP Request
Bongjun 6:e2ab76b2be07 56 55,4,1,3,15,6, // DHCP option 55:
Bongjun 6:e2ab76b2be07 57 };
Bongjun 6:e2ab76b2be07 58 add_buf((uint8_t*)options, sizeof(options));
Bongjun 6:e2ab76b2be07 59 add_option(50, yiaddr, 4);
Bongjun 6:e2ab76b2be07 60 add_option(54, siaddr, 4);
Bongjun 6:e2ab76b2be07 61 add_option(255);
Bongjun 6:e2ab76b2be07 62 return m_pos;
Bongjun 6:e2ab76b2be07 63 }
Bongjun 6:e2ab76b2be07 64
Bongjun 6:e2ab76b2be07 65 int DHCPClient::offer(uint8_t buf[], int size) {
Bongjun 6:e2ab76b2be07 66 memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4);
Bongjun 6:e2ab76b2be07 67 memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4);
Bongjun 6:e2ab76b2be07 68 uint8_t *p;
Bongjun 6:e2ab76b2be07 69 int msg_type = -1;
Bongjun 6:e2ab76b2be07 70 p = buf + DHCP_OFFSET_OPTIONS;
Bongjun 6:e2ab76b2be07 71 while(*p != 255 && p < (buf+size)) {
Bongjun 6:e2ab76b2be07 72 uint8_t code = *p++;
Bongjun 6:e2ab76b2be07 73 if (code == 0) { // Pad Option
Bongjun 6:e2ab76b2be07 74 continue;
Bongjun 6:e2ab76b2be07 75 }
Bongjun 6:e2ab76b2be07 76 int len = *p++;
Bongjun 6:e2ab76b2be07 77
Bongjun 6:e2ab76b2be07 78 DBG("DHCP option: %d\r\n", code);
Bongjun 6:e2ab76b2be07 79 DBG_HEX(p, len);
Bongjun 6:e2ab76b2be07 80
Bongjun 6:e2ab76b2be07 81 switch(code) {
Bongjun 6:e2ab76b2be07 82 case 53:
Bongjun 6:e2ab76b2be07 83 msg_type = *p;
Bongjun 6:e2ab76b2be07 84 break;
Bongjun 6:e2ab76b2be07 85 case 1:
Bongjun 6:e2ab76b2be07 86 memcpy(netmask, p, 4); // Subnet mask address
Bongjun 6:e2ab76b2be07 87 break;
Bongjun 6:e2ab76b2be07 88 case 3:
Bongjun 6:e2ab76b2be07 89 memcpy(gateway, p, 4); // Gateway IP address
Bongjun 6:e2ab76b2be07 90 break;
Bongjun 6:e2ab76b2be07 91 case 6: // DNS server
Bongjun 6:e2ab76b2be07 92 memcpy(dnsaddr, p, 4);
Bongjun 6:e2ab76b2be07 93 break;
Bongjun 6:e2ab76b2be07 94 case 51: // IP lease time
Bongjun 6:e2ab76b2be07 95 break;
Bongjun 6:e2ab76b2be07 96 case 54: // DHCP server
Bongjun 6:e2ab76b2be07 97 memcpy(siaddr, p, 4);
Bongjun 6:e2ab76b2be07 98 break;
Bongjun 6:e2ab76b2be07 99 }
Bongjun 6:e2ab76b2be07 100 p += len;
Bongjun 6:e2ab76b2be07 101 }
Bongjun 6:e2ab76b2be07 102 return msg_type;
Bongjun 6:e2ab76b2be07 103 }
Bongjun 6:e2ab76b2be07 104
Bongjun 6:e2ab76b2be07 105 bool DHCPClient::verify(uint8_t buf[], int len) {
Bongjun 6:e2ab76b2be07 106 if (len < DHCP_OFFSET_OPTIONS) {
Bongjun 6:e2ab76b2be07 107 return false;
Bongjun 6:e2ab76b2be07 108 }
Bongjun 6:e2ab76b2be07 109 if (buf[DHCP_OFFSET_OP] != 0x02) {
Bongjun 6:e2ab76b2be07 110 return false;
Bongjun 6:e2ab76b2be07 111 }
Bongjun 6:e2ab76b2be07 112 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) {
Bongjun 6:e2ab76b2be07 113 return false;
Bongjun 6:e2ab76b2be07 114 }
Bongjun 6:e2ab76b2be07 115 return true;
Bongjun 6:e2ab76b2be07 116 }
Bongjun 6:e2ab76b2be07 117
Bongjun 6:e2ab76b2be07 118 void DHCPClient::callback()
Bongjun 6:e2ab76b2be07 119 {
Bongjun 6:e2ab76b2be07 120 DBG("DHCPClient callback\n");
Bongjun 6:e2ab76b2be07 121 SocketAddress host;
Bongjun 6:e2ab76b2be07 122 int recv_len = m_udp->recvfrom(&host, (char*)m_buf, sizeof(m_buf));
Bongjun 6:e2ab76b2be07 123 if (recv_len < 0) {
Bongjun 6:e2ab76b2be07 124 return;
Bongjun 6:e2ab76b2be07 125 }
Bongjun 6:e2ab76b2be07 126 if (!verify(m_buf, recv_len)) {
Bongjun 6:e2ab76b2be07 127 return;
Bongjun 6:e2ab76b2be07 128 }
Bongjun 6:e2ab76b2be07 129 int r = offer(m_buf, recv_len);
Bongjun 6:e2ab76b2be07 130 if (r == DHCPOFFER) {
Bongjun 6:e2ab76b2be07 131 int send_size = request();
Bongjun 6:e2ab76b2be07 132 m_udp->sendto(m_server, (char*)m_buf, send_size);
Bongjun 6:e2ab76b2be07 133 } else if (r == DHCPACK) {
Bongjun 6:e2ab76b2be07 134 exit_flag = true;
Bongjun 6:e2ab76b2be07 135 }
Bongjun 6:e2ab76b2be07 136 }
Bongjun 6:e2ab76b2be07 137
Bongjun 6:e2ab76b2be07 138 void DHCPClient::add_buf(uint8_t c)
Bongjun 6:e2ab76b2be07 139 {
Bongjun 6:e2ab76b2be07 140 m_buf[m_pos++] = c;
Bongjun 6:e2ab76b2be07 141 }
Bongjun 6:e2ab76b2be07 142
Bongjun 6:e2ab76b2be07 143 void DHCPClient::add_buf(uint8_t* buf, int len)
Bongjun 6:e2ab76b2be07 144 {
Bongjun 6:e2ab76b2be07 145 for(int i = 0; i < len; i++) {
Bongjun 6:e2ab76b2be07 146 add_buf(buf[i]);
Bongjun 6:e2ab76b2be07 147 }
Bongjun 6:e2ab76b2be07 148 }
Bongjun 6:e2ab76b2be07 149
Bongjun 6:e2ab76b2be07 150 void DHCPClient::fill_buf(int len, uint8_t data)
Bongjun 6:e2ab76b2be07 151 {
Bongjun 6:e2ab76b2be07 152 while(len-- > 0) {
Bongjun 6:e2ab76b2be07 153 add_buf(data);
Bongjun 6:e2ab76b2be07 154 }
Bongjun 6:e2ab76b2be07 155 }
Bongjun 6:e2ab76b2be07 156
Bongjun 6:e2ab76b2be07 157 void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len)
Bongjun 6:e2ab76b2be07 158 {
Bongjun 6:e2ab76b2be07 159 add_buf(code);
Bongjun 6:e2ab76b2be07 160 if (len > 0) {
Bongjun 6:e2ab76b2be07 161 add_buf((uint8_t)len);
Bongjun 6:e2ab76b2be07 162 add_buf(buf, len);
Bongjun 6:e2ab76b2be07 163 }
Bongjun 6:e2ab76b2be07 164 }
Bongjun 6:e2ab76b2be07 165
Bongjun 6:e2ab76b2be07 166 int DHCPClient::setup(NetworkStack *ns, uint8_t mac_addr[6], int timeout_ms)
Bongjun 6:e2ab76b2be07 167 {
Bongjun 6:e2ab76b2be07 168 memcpy(chaddr, mac_addr, 6);
Bongjun 6:e2ab76b2be07 169
Bongjun 6:e2ab76b2be07 170 int interval_ms = 5*1000; // 5000msec
Bongjun 6:e2ab76b2be07 171 if (timeout_ms < interval_ms) {
Bongjun 6:e2ab76b2be07 172 interval_ms = timeout_ms;
Bongjun 6:e2ab76b2be07 173 }
Bongjun 6:e2ab76b2be07 174
Bongjun 6:e2ab76b2be07 175 UDPSocket udp_sock;
Bongjun 6:e2ab76b2be07 176 m_udp = &udp_sock;
Bongjun 6:e2ab76b2be07 177 {
Bongjun 6:e2ab76b2be07 178 nsapi_error_t err = udp_sock.open(ns);
Bongjun 6:e2ab76b2be07 179 if (err) {
Bongjun 6:e2ab76b2be07 180 DBG("setup failed to open UDP socket.");
Bongjun 6:e2ab76b2be07 181 return err;
Bongjun 6:e2ab76b2be07 182 }
Bongjun 6:e2ab76b2be07 183 udp_sock.set_blocking(false);
Bongjun 6:e2ab76b2be07 184 err = udp_sock.bind(68); // local port
Bongjun 6:e2ab76b2be07 185 if (err) {
Bongjun 6:e2ab76b2be07 186 DBG("setup failed in bind: %d", err);
Bongjun 6:e2ab76b2be07 187 return err;
Bongjun 6:e2ab76b2be07 188 }
Bongjun 6:e2ab76b2be07 189 }
Bongjun 6:e2ab76b2be07 190
Bongjun 6:e2ab76b2be07 191 m_server.set_ip_address("255.255.255.255"); // DHCP broadcast
Bongjun 6:e2ab76b2be07 192 m_server.set_port(67); // DHCP broadcast
Bongjun 6:e2ab76b2be07 193 exit_flag = false;
Bongjun 6:e2ab76b2be07 194 int err = 0;
Bongjun 6:e2ab76b2be07 195 int seq = 0;
Bongjun 6:e2ab76b2be07 196 int send_size;
Bongjun 6:e2ab76b2be07 197 while(!exit_flag) {
Bongjun 6:e2ab76b2be07 198 switch(seq) {
Bongjun 6:e2ab76b2be07 199 case 0:
Bongjun 6:e2ab76b2be07 200 m_retry = 0;
Bongjun 6:e2ab76b2be07 201 seq++;
Bongjun 6:e2ab76b2be07 202 break;
Bongjun 6:e2ab76b2be07 203 case 1:
Bongjun 6:e2ab76b2be07 204 send_size = discover();
Bongjun 6:e2ab76b2be07 205 nsapi_size_or_error_t err2 = udp_sock.sendto(m_server, (char*)m_buf, send_size);
Bongjun 6:e2ab76b2be07 206 if (err2 < 0) {
Bongjun 6:e2ab76b2be07 207 DBG("setup sendto error: %d\n", err2);
Bongjun 6:e2ab76b2be07 208 return err2;
Bongjun 6:e2ab76b2be07 209 }
Bongjun 6:e2ab76b2be07 210 m_interval.reset();
Bongjun 6:e2ab76b2be07 211 m_interval.start();
Bongjun 6:e2ab76b2be07 212 seq++;
Bongjun 6:e2ab76b2be07 213 break;
Bongjun 6:e2ab76b2be07 214 case 2:
Bongjun 6:e2ab76b2be07 215 callback();
Bongjun 6:e2ab76b2be07 216 if (m_interval.read_ms() > interval_ms) {
Bongjun 6:e2ab76b2be07 217 DBG("m_retry: %d\n", m_retry);
Bongjun 6:e2ab76b2be07 218 if (++m_retry >= (timeout_ms/interval_ms)) {
Bongjun 6:e2ab76b2be07 219 err = -1;
Bongjun 6:e2ab76b2be07 220 exit_flag = true;
Bongjun 6:e2ab76b2be07 221 }
Bongjun 6:e2ab76b2be07 222 seq--;
Bongjun 6:e2ab76b2be07 223 }
Bongjun 6:e2ab76b2be07 224 break;
Bongjun 6:e2ab76b2be07 225 }
Bongjun 6:e2ab76b2be07 226 }
Bongjun 6:e2ab76b2be07 227 DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms());
Bongjun 6:e2ab76b2be07 228 return err;
Bongjun 6:e2ab76b2be07 229 }
Bongjun 6:e2ab76b2be07 230
Bongjun 6:e2ab76b2be07 231 DHCPClient::DHCPClient() {
Bongjun 6:e2ab76b2be07 232 }