KL25 driver for Tango Control System

Dependencies:   mbed

Committer:
jskl
Date:
Thu Aug 28 07:50:06 2014 +0000
Revision:
2:9fe6f1e273b4
Parent:
0:5d27c333afa6
Fixed bugs in JSON format replies

Who changed what in which revision?

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