├── Application ├── Application.h └── loopback │ ├── loopback.c │ └── loopback.h ├── Doxygen ├── Doxyfile.dox ├── Main_page.txt ├── doc │ └── io6Library.chm └── img │ ├── Berkeley_SOCKET.jpg │ ├── SocketStatus.png │ ├── WIZnet_SOCKET.jpg │ ├── io6Library.png │ ├── io6Library_logo.png │ ├── io6Library_logo_big.png │ ├── w5100_w5200_w5500.gif │ ├── w5100_w5200_w5500.jpg │ ├── w5200_w5500.jpg │ └── w6100.png ├── Ethernet ├── W6100 │ ├── w6100.c │ └── w6100.h ├── socket.c ├── socket.h ├── wizchip_conf.c └── wizchip_conf.h ├── Internet ├── DHCP4 │ ├── dhcpv4.c │ └── dhcpv4.h ├── DHCP6 │ ├── dhcpv6.c │ └── dhcpv6.h ├── DNS │ ├── dns.c │ └── dns.h └── SNTP │ ├── sntp.c │ └── sntp.h ├── LICENSE └── README.md /Application/Application.h: -------------------------------------------------------------------------------- 1 | #ifndef _APPLICATION_H_ 2 | #define _APPLICATION_H_ 3 | 4 | #include 5 | 6 | 7 | #define SOCK_TCP4 (Sn_MR_TCP) 8 | #define SOCK_TCP6 (Sn_MR_TCP6) 9 | #define SOCK_TCPD (Sn_MR_TCPD) 10 | 11 | #define SOCK_UDP4 (Sn_MR_UDP4) 12 | #define SOCK_UDP6 (Sn_MR_UDP6) 13 | #define SOCK_UDPD (Sn_MR_UDPD) 14 | 15 | #define AS_IPV4 2 16 | #define AS_IPV6 23 17 | #define AS_IPDUAL 11 18 | #endif 19 | -------------------------------------------------------------------------------- /Application/loopback/loopback.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "loopback.h" 3 | #include "socket.h" 4 | #include "wizchip_conf.h" 5 | #include "stdlib.h" 6 | 7 | #if LOOPBACK_MODE == LOOPBACK_MAIN_NOBLCOK 8 | 9 | //static uint16_t j=0; 10 | static uint16_t any_port = 50000; 11 | static uint8_t curr_state[8] = {0,}; 12 | static uint8_t sock_state[8] = {0,}; 13 | uint8_t* msg_v4 = "IPv4 mode"; 14 | uint8_t* msg_v6 = "IPv6 mode"; 15 | uint8_t* msg_dual = "Dual IP mode"; 16 | 17 | int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port, uint8_t loopback_mode) 18 | { 19 | int32_t ret; 20 | datasize_t sentsize=0; 21 | int8_t status,inter; 22 | uint8_t tmp = 0; 23 | datasize_t received_size; 24 | uint8_t arg_tmp8; 25 | uint8_t* mode_msg; 26 | 27 | if(loopback_mode == AS_IPV4) 28 | { 29 | mode_msg = msg_v4; 30 | }else if(loopback_mode == AS_IPV6) 31 | { 32 | mode_msg = msg_v6; 33 | }else 34 | { 35 | mode_msg = msg_dual; 36 | } 37 | #ifdef _LOOPBACK_DEBUG_ 38 | uint8_t dst_ip[16], ext_status; 39 | uint16_t dst_port; 40 | #endif 41 | getsockopt(sn, SO_STATUS, &status); 42 | switch(status) 43 | { 44 | case SOCK_ESTABLISHED : 45 | ctlsocket(sn,CS_GET_INTERRUPT,&inter); 46 | if(inter & Sn_IR_CON) 47 | { 48 | #ifdef _LOOPBACK_DEBUG_ 49 | getsockopt(sn,SO_DESTIP,dst_ip); 50 | getsockopt(sn,SO_EXTSTATUS, &ext_status); 51 | if(ext_status & TCPSOCK_MODE){ 52 | //IPv6 53 | printf("%d:Peer IP : %04X:%04X", sn, ((uint16_t)dst_ip[0] << 8) | ((uint16_t)dst_ip[1]), 54 | ((uint16_t)dst_ip[2] << 8) | ((uint16_t)dst_ip[3])); 55 | printf(":%04X:%04X", ((uint16_t)dst_ip[4] << 8) | ((uint16_t)dst_ip[5]), 56 | ((uint16_t)dst_ip[6] << 8) | ((uint16_t)dst_ip[7])); 57 | printf(":%04X:%04X", ((uint16_t)dst_ip[8] << 8) | ((uint16_t)dst_ip[9]), 58 | ((uint16_t)dst_ip[10] << 8) | ((uint16_t)dst_ip[11])); 59 | printf(":%04X:%04X, ", ((uint16_t)dst_ip[12] << 8) | ((uint16_t)dst_ip[13]), 60 | ((uint16_t)dst_ip[14] << 8) | ((uint16_t)dst_ip[15])); 61 | }else 62 | { 63 | //IPv4 64 | //getSn_DIPR(sn,dst_ip); 65 | printf("%d:Peer IP : %.3d.%.3d.%.3d.%.3d, ", 66 | sn, dst_ip[0], dst_ip[1], dst_ip[2], dst_ip[3]); 67 | } 68 | getsockopt(sn,SO_DESTPORT,&dst_port); 69 | printf("Peer Port : %d\r\n", dst_port); 70 | #endif 71 | arg_tmp8 = Sn_IR_CON; 72 | ctlsocket(sn,CS_CLR_INTERRUPT,&arg_tmp8); 73 | } 74 | getsockopt(sn,SO_RECVBUF,&received_size); 75 | 76 | if(received_size > 0){ 77 | if(received_size > DATA_BUF_SIZE) received_size = DATA_BUF_SIZE; 78 | ret = recv(sn, buf, received_size); 79 | 80 | if(ret <= 0) return ret; // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY. 81 | received_size = (uint16_t) ret; 82 | sentsize = 0; 83 | 84 | while(received_size != sentsize) 85 | { 86 | ret = send(sn, buf+sentsize, received_size-sentsize); 87 | if(ret < 0) 88 | { 89 | close(sn); 90 | return ret; 91 | } 92 | sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. 93 | } 94 | } 95 | break; 96 | case SOCK_CLOSE_WAIT : 97 | #ifdef _LOOPBACK_DEBUG_ 98 | printf("%d:CloseWait\r\n",sn); 99 | #endif 100 | getsockopt(sn, SO_RECVBUF, &received_size); 101 | if(received_size > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur. 102 | { 103 | if(received_size > DATA_BUF_SIZE) received_size = DATA_BUF_SIZE; 104 | ret = recv(sn, buf, received_size); 105 | 106 | if(ret <= 0) return ret; // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY. 107 | received_size = (uint16_t) ret; 108 | sentsize = 0; 109 | 110 | while(received_size != sentsize) 111 | { 112 | ret = send(sn, buf+sentsize, received_size-sentsize); 113 | if(ret < 0) 114 | { 115 | close(sn); 116 | return ret; 117 | } 118 | sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. 119 | } 120 | } 121 | 122 | if((ret = disconnect(sn)) != SOCK_OK) return ret; 123 | #ifdef _LOOPBACK_DEBUG_ 124 | printf("%d:Socket Closed\r\n", sn); 125 | #endif 126 | break; 127 | case SOCK_INIT : 128 | if( (ret = listen(sn)) != SOCK_OK) return ret; 129 | #ifdef _LOOPBACK_DEBUG_ 130 | printf("%d:Listen, TCP server loopback, port [%d] as %s\r\n", sn, port, mode_msg); 131 | #endif 132 | printf("%d:Listen, TCP server loopback, port [%d] as %s\r\n", sn, port, mode_msg); 133 | break; 134 | case SOCK_CLOSED: 135 | #ifdef _LOOPBACK_DEBUG_ 136 | printf("%d:TCP server loopback start\r\n",sn); 137 | #endif 138 | switch(loopback_mode) 139 | { 140 | case AS_IPV4: 141 | tmp = socket(sn, Sn_MR_TCP4, port, SOCK_IO_NONBLOCK); 142 | break; 143 | case AS_IPV6: 144 | tmp = socket(sn, Sn_MR_TCP6, port, SOCK_IO_NONBLOCK); 145 | break; 146 | case AS_IPDUAL: 147 | tmp = socket(sn, Sn_MR_TCPD, port, SOCK_IO_NONBLOCK); 148 | break; 149 | default: 150 | break; 151 | } 152 | if(tmp != sn) /* reinitialize the socket */ 153 | { 154 | #ifdef _LOOPBACK_DEBUG_ 155 | printf("%d : Fail to create socket.\r\n",sn); 156 | #endif 157 | return SOCKERR_SOCKNUM; 158 | } 159 | #ifdef _LOOPBACK_DEBUG_ 160 | printf("%d:Socket opened[%d]\r\n",sn, getSn_SR(sn)); 161 | sock_state[sn] = 1; 162 | #endif 163 | break; 164 | default: 165 | break; 166 | } 167 | return 1; 168 | } 169 | 170 | 171 | int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport, uint8_t loopback_mode) 172 | { 173 | 174 | int32_t ret; // return value for SOCK_ERRORs 175 | datasize_t sentsize=0; 176 | uint8_t status,inter,addr_len; 177 | datasize_t received_size; 178 | uint8_t tmp = 0; 179 | uint8_t arg_tmp8; 180 | wiz_IPAddress destinfo; 181 | 182 | 183 | // Socket Status Transitions 184 | // Check the W6100 Socket n status register (Sn_SR, The 'Sn_SR' controlled by Sn_CR command or Packet send/recv status) 185 | getsockopt(sn,SO_STATUS,&status); 186 | switch(status) 187 | { 188 | case SOCK_ESTABLISHED : 189 | ctlsocket(sn,CS_GET_INTERRUPT,&inter); 190 | if(inter & Sn_IR_CON) // Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful 191 | { 192 | #ifdef _LOOPBACK_DEBUG_ 193 | printf("%d:Connected to - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport); 194 | #endif 195 | arg_tmp8 = Sn_IR_CON; 196 | ctlsocket(sn,CS_CLR_INTERRUPT,&arg_tmp8);// this interrupt should be write the bit cleared to '1' 197 | } 198 | 199 | ////////////////////////////////////////////////////////////////////////////////////////////// 200 | // Data Transaction Parts; Handle the [data receive and send] process 201 | ////////////////////////////////////////////////////////////////////////////////////////////// 202 | getsockopt(sn, SO_RECVBUF, &received_size); 203 | 204 | if(received_size > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length 205 | { 206 | if(received_size > DATA_BUF_SIZE) received_size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array) 207 | ret = recv(sn, buf, received_size); // Data Receive process (H/W Rx socket buffer -> User's buffer) 208 | 209 | if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end 210 | received_size = (uint16_t) ret; 211 | sentsize = 0; 212 | 213 | // Data sentsize control 214 | while(received_size != sentsize) 215 | { 216 | ret = send(sn, buf+sentsize, received_size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer) 217 | if(ret < 0) // Send Error occurred (sent data length < 0) 218 | { 219 | close(sn); // socket close 220 | return ret; 221 | } 222 | sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. 223 | } 224 | } 225 | ////////////////////////////////////////////////////////////////////////////////////////////// 226 | break; 227 | 228 | case SOCK_CLOSE_WAIT : 229 | #ifdef _LOOPBACK_DEBUG_ 230 | printf("%d:CloseWait\r\n",sn); 231 | #endif 232 | getsockopt(sn, SO_RECVBUF, &received_size); 233 | 234 | if((received_size = getSn_RX_RSR(sn)) > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length 235 | { 236 | if(received_size > DATA_BUF_SIZE) received_size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array) 237 | ret = recv(sn, buf, received_size); // Data Receive process (H/W Rx socket buffer -> User's buffer) 238 | 239 | if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end 240 | received_size = (uint16_t) ret; 241 | sentsize = 0; 242 | 243 | // Data sentsize control 244 | while(received_size != sentsize) 245 | { 246 | ret = send(sn, buf+sentsize, received_size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer) 247 | if(ret < 0) // Send Error occurred (sent data length < 0) 248 | { 249 | close(sn); // socket close 250 | return ret; 251 | } 252 | sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. 253 | } 254 | } 255 | if((ret=disconnect(sn)) != SOCK_OK) return ret; 256 | #ifdef _LOOPBACK_DEBUG_ 257 | printf("%d:Socket Closed\r\n", sn); 258 | #endif 259 | break; 260 | 261 | case SOCK_INIT : 262 | #ifdef _LOOPBACK_DEBUG_ 263 | if(loopback_mode == AS_IPV4) 264 | printf("%d:Try to connect to the %d.%d.%d.%d, %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport); 265 | else if(loopback_mode == AS_IPV6) 266 | { 267 | printf("%d:Try to connect to the %04X:%04X", sn, ((uint16_t)destip[0] << 8) | ((uint16_t)destip[1]), 268 | ((uint16_t)destip[2] << 8) | ((uint16_t)destip[3])); 269 | printf(":%04X:%04X", ((uint16_t)destip[4] << 8) | ((uint16_t)destip[5]), 270 | ((uint16_t)destip[6] << 8) | ((uint16_t)destip[7])); 271 | printf(":%04X:%04X", ((uint16_t)destip[8] << 8) | ((uint16_t)destip[9]), 272 | ((uint16_t)destip[10] << 8) | ((uint16_t)destip[11])); 273 | printf(":%04X:%04X,", ((uint16_t)destip[12] << 8) | ((uint16_t)destip[13]), 274 | ((uint16_t)destip[14] << 8) | ((uint16_t)destip[15])); 275 | printf("%d\r\n", destport); 276 | } 277 | #endif 278 | 279 | if(loopback_mode == AS_IPV4) 280 | ret = connect(sn, destip, destport, 4); /* Try to connect to TCP server(Socket, DestIP, DestPort) */ 281 | else if(loopback_mode == AS_IPV6) 282 | ret = connect(sn, destip, destport, 16); /* Try to connect to TCP server(Socket, DestIP, DestPort) */ 283 | 284 | printf("SOCK Status: %d\r\n", ret); 285 | 286 | if( ret != SOCK_OK) return ret; // Try to TCP connect to the TCP server (destination) 287 | break; 288 | 289 | case SOCK_CLOSED: 290 | switch(loopback_mode) 291 | { 292 | case AS_IPV4: 293 | tmp = socket(sn, Sn_MR_TCP4, any_port++, SOCK_IO_NONBLOCK); 294 | break; 295 | case AS_IPV6: 296 | tmp = socket(sn, Sn_MR_TCP6, any_port++, SOCK_IO_NONBLOCK); 297 | break; 298 | case AS_IPDUAL: 299 | tmp = socket(sn, Sn_MR_TCPD, any_port++, SOCK_IO_NONBLOCK); 300 | break; 301 | default: 302 | break; 303 | } 304 | 305 | if(tmp != sn){ /* reinitialize the socket */ 306 | #ifdef _LOOPBACK_DEBUG_ 307 | printf("%d : Fail to create socket.\r\n",sn); 308 | #endif 309 | return SOCKERR_SOCKNUM; 310 | } 311 | printf("%d:Socket opened[%d]\r\n",sn, getSn_SR(sn)); 312 | sock_state[sn] = 1; 313 | 314 | break; 315 | default: 316 | break; 317 | } 318 | return 1; 319 | } 320 | 321 | int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port, uint8_t loopback_mode) 322 | { 323 | uint8_t status; 324 | static uint8_t destip[16] = {0,}; 325 | static uint16_t destport; 326 | uint8_t pack_info; 327 | uint8_t addr_len; 328 | datasize_t ret; 329 | datasize_t received_size; 330 | uint16_t size, sentsize; 331 | uint8_t* mode_msg; 332 | 333 | if(loopback_mode == AS_IPV4) 334 | { 335 | mode_msg = msg_v4; 336 | }else if(loopback_mode == AS_IPV6) 337 | { 338 | mode_msg = msg_v6; 339 | }else 340 | { 341 | mode_msg = msg_dual; 342 | } 343 | 344 | getsockopt(sn, SO_STATUS,&status); 345 | switch(status) 346 | { 347 | case SOCK_UDP: 348 | getsockopt(sn, SO_RECVBUF, &received_size); 349 | if(received_size > DATA_BUF_SIZE) received_size = DATA_BUF_SIZE; 350 | if(received_size>0) 351 | { 352 | ret = recvfrom(sn, buf, received_size, (uint8_t*)&destip, (uint16_t*)&destport, &addr_len); 353 | 354 | if(ret <= 0) 355 | return ret; 356 | received_size = (uint16_t) ret; 357 | sentsize = 0; 358 | while(sentsize != received_size){ 359 | ret = sendto(sn, buf+sentsize, received_size-sentsize, destip, destport, addr_len); 360 | 361 | if(ret < 0) return ret; 362 | 363 | sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. 364 | } 365 | } 366 | break; 367 | case SOCK_CLOSED: 368 | 369 | switch(loopback_mode) 370 | { 371 | case AS_IPV4: 372 | socket(sn,Sn_MR_UDP4, port, SOCK_IO_NONBLOCK); 373 | break; 374 | case AS_IPV6: 375 | socket(sn,Sn_MR_UDP6, port, SOCK_IO_NONBLOCK); 376 | break; 377 | case AS_IPDUAL: 378 | socket(sn,Sn_MR_UDPD, port, SOCK_IO_NONBLOCK); 379 | break; 380 | } 381 | printf("%d:Opened, UDP loopback, port [%d] as %s\r\n", sn, port, mode_msg); 382 | 383 | } 384 | 385 | return 0; 386 | } 387 | 388 | #endif 389 | -------------------------------------------------------------------------------- /Application/loopback/loopback.h: -------------------------------------------------------------------------------- 1 | #ifndef _LOOPBACK_H_ 2 | #define _LOOPBACK_H_ 3 | 4 | #include 5 | 6 | /* Loopback test debug message printout enable */ 7 | //#define _LOOPBACK_DEBUG_ 8 | 9 | /* DATA_BUF_SIZE define for Loopback example */ 10 | #ifndef DATA_BUF_SIZE 11 | #define DATA_BUF_SIZE 2048 12 | #endif 13 | 14 | int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port, uint8_t loopback_mode); 15 | int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port, uint8_t loopback_mode); 16 | int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport, uint8_t loopback_mode); 17 | 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Doxygen/Main_page.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * \mainpage io6Library 3 | * 4 | * 5 | *
@image html io6Library_logo_big.png
6 | * 7 | *

Overview

8 | * 9 | * 10 | * io6Library provides a useful library in order to integrate user application program with WIZnet dual stack chips such as @b W6100. \n 11 | * It is easy to change the enhanced WIZnet chips, so user can migrate and integrate easily user application.\n\n 12 | * Enjoy io6Library!!! \n\n 13 | * 14 | *

Contents

15 | * 16 | * This document contains two register groups, the dependent chip I/O functions, and the integrated chip control functions. 17 | * - Register Group 18 | * - W6100 : @ref WIZCHIP_register_W6100 19 | * - Common register Group : @ref Common_register_group_W6100 20 | * - SOCKET register Group : @ref Socket_register_group_W6100 21 | * - The dependent chip I/O functions 22 | * - W6100 : @ref WIZCHIP_IO_Functions_W6100 23 | * - Basic IO function : @ref Basic_IO_function_W6100, 24 | * - Common register access function : @ref Common_register_access_function_W6100 25 | * - Socket register access function : @ref Socket_register_group_W6100 26 | * - The integrated chip control function 27 | * - WIZnet SOCKET APIs : @ref WIZnet_socket_APIs 28 | * - WIZnet Extra function : @ref extra_functions \n\n 29 | * 30 | * 31 | *

Todo : How to use io6Library

32 | * 33 | * As belows should be defined or implemented by user becase they are dependent on user HOST MCU. 34 | * - @ref _WIZCHIP_ : Select a dual stack TCP/Ip chips. 35 | * - @ref _WIZCHIP_IO_MODE_ : Define your HOST interface. 36 | * - @ref _WIZCHIP_IO_BASE_ : Define the address map of WIZnet chip as your system memory address map when you use a parallel BUS interface. Otherwize, it should be zero. 37 | * - @ref _WIZCHIP_T_ : Make your basic io function and Register them to @ref _WIZCHIP_T_. 38 | * - @ref _WIZCHIP_T_::CRIS : Criticail Section function 39 | * - Make your critcial section functions to protect @ref _WIZCHIP_ IO access against interference such like as interrupt or task switching. 40 | * - Register them by calling @ref reg_wizchip_cris_cbfunc() 41 | * - @ref _WIZCHIP_T_::CS : WIZnet chip select 42 | * - Make your chip selection or deselection functions when you want to use another host interface than parallel BUS interface. 43 | * - Register them by calling @ref reg_wizchip_cs_cbfunc() 44 | * - @ref _WIZCHIP_T_::IF : Basic IO functions (@ref _WIZCHIP_T_::_IF::BUS or @ref _WIZCHIP_T_::_IF::SPI) 45 | * - Make your basic IO functions to read or write @ref _WIZCHIP_ chip register. When you use parallel BUS interface, the unit is @ref iodata_t. Otherwize, the unit is byte(uint8_t) 46 | * - Register them by calling @ref reg_wizchip_bus_cbfunc() in the parallel BUS interface, or by calling @ref reg_wizchip_spi_cbfunc() in the serial BUS interface. \n\n 47 | * 48 | * 49 | *

WIZnet Extra funcion

50 | * 51 | * WIZnet Extra fucnions(@ref extra_functions) makes your applications easy to use and ease to integrate regardless of @ref _WIZCHIP_. \n 52 | * But, they increases the code size of io6Library. If you want to use lightweight io6Library, they may be removed or not called. 53 | * Because they can all be replaced with the dependent chip I/O functions as mentioned the above. \n\n 54 | * 55 | *

Available WIZCHIP product

56 | * 57 | * 58 | *
@image html w6100.png
59 | * 60 | * - W6100 \n\n 61 | * 62 | * 63 | *

Release Notes

64 | * - 2019/01/15 65 | * - First Released V1.0.0 66 | * 67 | * 68 | */ -------------------------------------------------------------------------------- /Doxygen/doc/io6Library.chm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/doc/io6Library.chm -------------------------------------------------------------------------------- /Doxygen/img/Berkeley_SOCKET.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/Berkeley_SOCKET.jpg -------------------------------------------------------------------------------- /Doxygen/img/SocketStatus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/SocketStatus.png -------------------------------------------------------------------------------- /Doxygen/img/WIZnet_SOCKET.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/WIZnet_SOCKET.jpg -------------------------------------------------------------------------------- /Doxygen/img/io6Library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/io6Library.png -------------------------------------------------------------------------------- /Doxygen/img/io6Library_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/io6Library_logo.png -------------------------------------------------------------------------------- /Doxygen/img/io6Library_logo_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/io6Library_logo_big.png -------------------------------------------------------------------------------- /Doxygen/img/w5100_w5200_w5500.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/w5100_w5200_w5500.gif -------------------------------------------------------------------------------- /Doxygen/img/w5100_w5200_w5500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/w5100_w5200_w5500.jpg -------------------------------------------------------------------------------- /Doxygen/img/w5200_w5500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/w5200_w5500.jpg -------------------------------------------------------------------------------- /Doxygen/img/w6100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wiznet/io6Library/8ac15e2537593998d49a369d4f9b59ac9f9ab72e/Doxygen/img/w6100.png -------------------------------------------------------------------------------- /Ethernet/W6100/w6100.c: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | //! \file w6100.c 4 | //! \brief W6100 HAL Implements file. 5 | //! \version 1.0.0 6 | //! \date 2019/01/01 7 | //! \par Revision history 8 | //! <2019/01/01> 1st Release 9 | //! \author MidnightCow 10 | //! \copyright 11 | //! 12 | //! Copyright (c) 2019, WIZnet Co., LTD. 13 | //! 14 | //! Permission is hereby granted, free of charge, to any person obtaining a copy 15 | //! of this software and associated documentation files (the "Software"), to deal 16 | //! in the Software without restriction, including without limitation the rights 17 | //! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | //! copies of the Software, and to permit persons to whom the Software is 19 | //! furnished to do so, subject to the following conditions: 20 | //! 21 | //! The above copyright notice and this permission notice shall be included in 22 | //! all copies or substantial portions of the Software. 23 | //! 24 | //! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | //! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | //! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | //! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | //! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | //! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | //! SOFTWARE. 31 | //! 32 | //***************************************************************************** 33 | 34 | #include "w6100.h" 35 | 36 | 37 | 38 | #define _WIZCHIP_SPI_VDM_OP_ 0x00 39 | #define _WIZCHIP_SPI_FDM_LEN1_ 0x01 40 | #define _WIZCHIP_SPI_FDM_LEN2_ 0x02 41 | #define _WIZCHIP_SPI_FDM_LEN4_ 0x03 42 | // 43 | // If you want to use SPI FDM mode, Feel free contact to WIZnet. 44 | // http://forum.wiznet.io 45 | // 46 | 47 | #if _WIZCHIP_ == 6100 48 | //////////////////////////////////////////////////////////////////////////////////////// 49 | 50 | 51 | #define _W6100_SPI_OP_ _WIZCHIP_SPI_VDM_OP_ 52 | 53 | ////////////////////////////////////////////////// 54 | void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) 55 | { 56 | uint8_t tAD[4]; 57 | tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16); 58 | tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8); 59 | tAD[2] = (uint8_t)(AddrSel & 0x000000ff); 60 | tAD[3] = wb; 61 | 62 | WIZCHIP_CRITICAL_ENTER(); 63 | WIZCHIP.CS._s_e_l_e_c_t_(); 64 | 65 | #if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_)) 66 | tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_); 67 | WIZCHIP.IF.SPI._write_byte_buf(tAD, 4); 68 | 69 | #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) 70 | WIZCHIP.IF.BUS._write_data_buf(IDM_AR0, tAD, 4, 1); 71 | #else 72 | #error "Unknown _WIZCHIP_IO_MODE_ in W5100. !!!" 73 | #endif 74 | 75 | WIZCHIP.CS._d_e_s_e_l_e_c_t_(); 76 | WIZCHIP_CRITICAL_EXIT(); 77 | } 78 | 79 | uint8_t WIZCHIP_READ(uint32_t AddrSel) 80 | { 81 | uint8_t ret; 82 | uint8_t tAD[3]; 83 | tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16); 84 | tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8); 85 | tAD[2] = (uint8_t)(AddrSel & 0x000000ff); 86 | 87 | WIZCHIP_CRITICAL_ENTER(); 88 | WIZCHIP.CS._s_e_l_e_c_t_(); 89 | 90 | #if( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_)) 91 | tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_); 92 | WIZCHIP.IF.SPI._write_byte_buf(tAD, 3); 93 | ret = WIZCHIP.IF.SPI._read_byte(); 94 | #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) 95 | WIZCHIP.IF.BUS._write_data_buf(IDM_AR0,tAD,3,1); 96 | ret = WIZCHIP.IF.BUS._read_data(IDM_DR); 97 | #else 98 | #error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!" 99 | #endif 100 | 101 | WIZCHIP.CS._d_e_s_e_l_e_c_t_(); 102 | WIZCHIP_CRITICAL_EXIT(); 103 | return ret; 104 | } 105 | 106 | void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, datasize_t len) 107 | { 108 | uint8_t tAD[3]; 109 | tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16); 110 | tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8); 111 | tAD[2] = (uint8_t)(AddrSel & 0x000000ff); 112 | 113 | 114 | WIZCHIP_CRITICAL_ENTER(); 115 | WIZCHIP.CS._s_e_l_e_c_t_(); 116 | 117 | #if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_)) 118 | tAD[2] |= (_W6100_SPI_WRITE_ | _W6100_SPI_OP_); 119 | 120 | WIZCHIP.IF.SPI._write_byte_buf(tAD, 3); 121 | WIZCHIP.IF.SPI._write_byte_buf(pBuf, len); 122 | 123 | #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) 124 | WIZCHIP.IF.BUS._write_data_buf(IDM_AR0,tAD, 3, 1); 125 | WIZCHIP.IF.BUS._write_data_buf(IDM_DR,pBuf,len, 0); 126 | #else 127 | #error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!" 128 | #endif 129 | 130 | WIZCHIP.CS._d_e_s_e_l_e_c_t_(); 131 | WIZCHIP_CRITICAL_EXIT(); 132 | } 133 | 134 | void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, datasize_t len) 135 | { 136 | uint8_t tAD[3]; 137 | tAD[0] = (uint8_t)((AddrSel & 0x00FF0000) >> 16); 138 | tAD[1] = (uint8_t)((AddrSel & 0x0000FF00) >> 8); 139 | tAD[2] = (uint8_t)(AddrSel & 0x000000ff); 140 | 141 | WIZCHIP_CRITICAL_ENTER(); 142 | WIZCHIP.CS._s_e_l_e_c_t_(); 143 | 144 | #if((_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_)) 145 | tAD[2] |= (_W6100_SPI_READ_ | _W6100_SPI_OP_); 146 | WIZCHIP.IF.SPI._write_byte_buf(tAD,3); 147 | WIZCHIP.IF.SPI._read_byte_buf(pBuf, len); 148 | #elif ( (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_) ) 149 | WIZCHIP.IF.BUS._write_data_buf(IDM_AR0,tAD,3,1); 150 | WIZCHIP.IF.BUS._read_data_buf(IDM_DR,pBuf,len,0); 151 | #else 152 | #error "Unknown _WIZCHIP_IO_MODE_ in W6100. !!!!" 153 | #endif 154 | WIZCHIP.CS._d_e_s_e_l_e_c_t_(); 155 | WIZCHIP_CRITICAL_EXIT(); 156 | } 157 | 158 | datasize_t getSn_TX_FSR(uint8_t sn) 159 | { 160 | datasize_t prev_val=-1,val=0; 161 | do 162 | { 163 | prev_val = val; 164 | val = WIZCHIP_READ(_Sn_TX_FSR_(sn)); 165 | val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_Sn_TX_FSR_(sn),1)); 166 | }while (val != prev_val); 167 | return val; 168 | } 169 | 170 | datasize_t getSn_RX_RSR(uint8_t sn) 171 | { 172 | datasize_t prev_val=-1,val=0; 173 | do 174 | { 175 | prev_val = val; 176 | val = WIZCHIP_READ(_Sn_RX_RSR_(sn)); 177 | val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(_Sn_RX_RSR_(sn),1)); 178 | }while (val != prev_val); 179 | return val; 180 | } 181 | 182 | void wiz_send_data(uint8_t sn, uint8_t *wizdata, datasize_t len) 183 | { 184 | datasize_t ptr = 0; 185 | uint32_t addrsel = 0; 186 | ptr = getSn_TX_WR(sn); 187 | addrsel = ((uint32_t)ptr << 8) + WIZCHIP_TXBUF_BLOCK(sn); 188 | WIZCHIP_WRITE_BUF(addrsel,wizdata, len); 189 | ptr += len; 190 | setSn_TX_WR(sn,ptr); 191 | } 192 | 193 | void wiz_recv_data(uint8_t sn, uint8_t *wizdata, datasize_t len) 194 | { 195 | datasize_t ptr = 0; 196 | uint32_t addrsel = 0; 197 | if(len == 0) return; 198 | ptr = getSn_RX_RD(sn); 199 | addrsel = ((uint32_t)ptr << 8) + WIZCHIP_RXBUF_BLOCK(sn); 200 | WIZCHIP_READ_BUF(addrsel, wizdata, len); 201 | ptr += len; 202 | setSn_RX_RD(sn,ptr); 203 | } 204 | 205 | void wiz_recv_ignore(uint8_t sn, datasize_t len) 206 | { 207 | setSn_RX_RD(sn,getSn_RX_RD(sn)+len); 208 | } 209 | 210 | 211 | /// @cond DOXY_APPLY_CODE 212 | #if (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_) 213 | /// @endcond 214 | void wiz_mdio_write(uint8_t phyregaddr, uint16_t var) 215 | { 216 | setPHYRAR(phyregaddr); 217 | setPHYDIR(var); 218 | setPHYACR(PHYACR_WRITE); 219 | while(getPHYACR()); //wait for command complete 220 | } 221 | 222 | uint16_t wiz_mdio_read(uint8_t phyregaddr) 223 | { 224 | setPHYRAR(phyregaddr); 225 | setPHYACR(PHYACR_READ); 226 | while(getPHYACR()); //wait for command complete 227 | return getPHYDOR(); 228 | } 229 | /// @cond DOXY_APPLY_CODE 230 | #endif 231 | /// @endcond 232 | 233 | //////////////////////////////////////////////////////////////////////////////////////// 234 | #endif 235 | -------------------------------------------------------------------------------- /Ethernet/socket.c: -------------------------------------------------------------------------------- 1 | //* **************************************************************************** 2 | //! \file socket.c 3 | //! \brief SOCKET APIs Implements file. 4 | //! \details SOCKET APIs like as Berkeley Socket APIs. 5 | //! \version 1.0.1 6 | //! \date 2020/04/27 7 | //! \par Revision history 8 | //! <2020/04/27> V1.0.1 Modify default value of tcmd to Sn_CR_SEND to send data 9 | //! in macrawmode and the condition of the if()when setting 10 | //! the destination port number. 11 | //! <2019/01/01> 1st Release 12 | //! \author MidnightCow 13 | //! \copyright 14 | //! 15 | //! Copyright (c) 2019, WIZnet Co., LTD. 16 | //! 17 | //! Permission is hereby granted, free of charge, to any person obtaining a copy 18 | //! of this software and associated documentation files (the "Software"), to deal 19 | //! in the Software without restriction, including without limitation the rights 20 | //! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | //! copies of the Software, and to permit persons to whom the Software is 22 | //! furnished to do so, subject to the following conditions: 23 | //! 24 | //! The above copyright notice and this permission notice shall be included in 25 | //! all copies or substantial portions of the Software. 26 | //! 27 | //! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | //! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | //! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | //! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | //! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | //! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | //! SOFTWARE. 34 | //! 35 | //***************************************************************************** 36 | 37 | #include 38 | #include "socket.h" 39 | #include "w6100.h" 40 | 41 | #define SOCK_ANY_PORT_NUM 0x0400 42 | 43 | static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; 44 | static uint16_t sock_io_mode = 0; 45 | static uint16_t sock_is_sending = 0; 46 | static datasize_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; 47 | static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; 48 | 49 | 50 | #define CHECK_SOCKNUM() \ 51 | do{ \ 52 | if(sn >= _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ 53 | }while(0); 54 | 55 | #define CHECK_SOCKMODE(mode) \ 56 | do{ \ 57 | if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ 58 | }while(0); 59 | 60 | #define CHECK_TCPMODE() \ 61 | do{ \ 62 | if((getSn_MR(sn) & 0x03) != 0x01) return SOCKERR_SOCKMODE; \ 63 | }while(0); 64 | 65 | #define CHECK_UDPMODE() \ 66 | do{ \ 67 | if((getSn_MR(sn) & 0x03) != 0x02) return SOCKERR_SOCKMODE; \ 68 | }while(0); 69 | 70 | #define CHECK_IPMODE() \ 71 | do{ \ 72 | if((getSn_MR(sn) & 0x07) != 0x03) return SOCKERR_SOCKMODE; \ 73 | }while(0); 74 | 75 | #define CHECK_DGRAMMODE() \ 76 | do{ \ 77 | if(getSn_MR(sn) == Sn_MR_CLOSED) return SOCKERR_SOCKMODE; \ 78 | if((getSn_MR(sn) & 0x03) == 0x01) return SOCKERR_SOCKMODE; \ 79 | }while(0); 80 | 81 | 82 | #define CHECK_SOCKINIT() \ 83 | do{ \ 84 | if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ 85 | }while(0); 86 | 87 | #define CHECK_SOCKDATA() \ 88 | do{ \ 89 | if(len == 0) return SOCKERR_DATALEN; \ 90 | }while(0); 91 | 92 | #define CHECK_IPZERO(addr, addrlen) \ 93 | do{ \ 94 | uint16_t ipzero= 0; \ 95 | for(uint8_t i=0; i>3)) << sn); 176 | sock_is_sending &= ~(1< freesize) len = freesize; // check size not to exceed MAX size. 302 | while(1) 303 | { 304 | freesize = (datasize_t)getSn_TX_FSR(sn); 305 | tmp = getSn_SR(sn); 306 | if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) 307 | { 308 | if(tmp == SOCK_CLOSED) close(sn); 309 | return SOCKERR_SOCKSTATUS; 310 | } 311 | if(len <= freesize) break; 312 | if( sock_io_mode & (1< freesize) len = freesize; // check size not to exceed MAX size. 411 | 412 | while(1) 413 | { 414 | freesize = getSn_TX_FSR(sn); 415 | if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; 416 | if(len <= freesize) break; 417 | if( sock_io_mode & (1< 1514) 492 | { 493 | close(sn); 494 | return SOCKFATAL_PACKLEN; 495 | } 496 | break; 497 | default: 498 | return SOCKERR_SOCKMODE; 499 | break; 500 | } 501 | sock_remained_size[sn] = pack_len; 502 | sock_pack_info[sn] |= PACK_FIRST; 503 | if((getSn_MR(sn) & 0x03) == 0x02) // Sn_MR_UDP4(0010), Sn_MR_UDP6(1010), Sn_MR_UDPD(1110) 504 | { 505 | /* Read port number of PACKET INFO in SOCKETn RX buffer */ 506 | if(port==0) return SOCKERR_ARG; 507 | wiz_recv_data(sn, head, 2); 508 | *port = ( ((((uint16_t)head[0])) << 8) + head[1] ); 509 | setSn_CR(sn,Sn_CR_RECV); 510 | while(getSn_CR(sn)); 511 | } 512 | } 513 | 514 | if (len < sock_remained_size[sn]) pack_len = len; 515 | else pack_len = sock_remained_size[sn]; 516 | wiz_recv_data(sn, buf, pack_len); 517 | setSn_CR(sn,Sn_CR_RECV); 518 | /* wait to process the command... */ 519 | while(getSn_CR(sn)) ; 520 | 521 | sock_remained_size[sn] -= pack_len; 522 | if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED; 523 | else sock_pack_info[sn] |= PACK_COMPLETED; 524 | 525 | return pack_len; 526 | } 527 | 528 | int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg) 529 | { 530 | uint8_t tmp = 0; 531 | CHECK_SOCKNUM(); 532 | tmp = *((uint8_t*)arg); 533 | switch(cstype) 534 | { 535 | case CS_SET_IOMODE: 536 | if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1<> sn) & 0x0001); 542 | break; 543 | case CS_GET_MAXTXBUF: 544 | *((datasize_t*)arg) = getSn_TxMAX(sn); 545 | break; 546 | case CS_GET_MAXRXBUF: 547 | *((datasize_t*)arg) = getSn_RxMAX(sn); 548 | break; 549 | case CS_CLR_INTERRUPT: 550 | if( tmp > SIK_ALL) return SOCKERR_ARG; 551 | setSn_IRCLR(sn,tmp); 552 | break; 553 | case CS_GET_INTERRUPT: 554 | *((uint8_t*)arg) = getSn_IR(sn); 555 | break; 556 | case CS_SET_INTMASK: 557 | if( tmp > SIK_ALL) return SOCKERR_ARG; 558 | setSn_IMR(sn,tmp); 559 | break; 560 | case CS_GET_INTMASK: 561 | *((uint8_t*)arg) = getSn_IMR(sn); 562 | break; 563 | case CS_SET_PREFER: 564 | if((tmp & 0x03) == 0x01) return SOCKERR_ARG; 565 | setSn_PSR(sn, tmp); 566 | break; 567 | case CS_GET_PREFER: 568 | *(uint8_t*) arg = getSn_PSR(sn); 569 | break; 570 | default: 571 | return SOCKERR_ARG; 572 | } 573 | return SOCK_OK; 574 | } 575 | 576 | int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg) 577 | { 578 | CHECK_SOCKNUM(); 579 | switch(sotype) 580 | { 581 | case SO_TTL: 582 | setSn_TTLR(sn,*(uint8_t*)arg); 583 | break; 584 | case SO_TOS: 585 | setSn_TOSR(sn,*(uint8_t*)arg); 586 | break; 587 | case SO_MSS: 588 | setSn_MSSR(sn,*(uint16_t*)arg); 589 | break; 590 | case SO_DESTIP: 591 | if(((wiz_IPAddress*)arg)->len == 16) setSn_DIP6R(sn, ((wiz_IPAddress*)arg)->ip); 592 | else setSn_DIPR(sn, ((wiz_IPAddress*)arg)->ip); 593 | break; 594 | case SO_DESTPORT: 595 | setSn_DPORTR(sn, *(uint16_t*)arg); 596 | break; 597 | case SO_KEEPALIVESEND: 598 | CHECK_TCPMODE(); 599 | if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; 600 | setSn_CR(sn,Sn_CR_SEND_KEEP); 601 | while(getSn_CR(sn) != 0) 602 | { 603 | if (getSn_IR(sn) & Sn_IR_TIMEOUT) 604 | { 605 | setSn_IRCLR(sn, Sn_IR_TIMEOUT); 606 | return SOCKERR_TIMEOUT; 607 | } 608 | } 609 | break; 610 | case SO_KEEPALIVEAUTO: 611 | CHECK_TCPMODE(); 612 | setSn_KPALVTR(sn,*(uint8_t*)arg); 613 | break; 614 | default: 615 | return SOCKERR_ARG; 616 | } 617 | return SOCK_OK; 618 | } 619 | 620 | int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg) 621 | { 622 | CHECK_SOCKNUM(); 623 | switch(sotype) 624 | { 625 | case SO_FLAG: 626 | *(uint8_t*)arg = (getSn_MR(sn) & 0xF0) | (getSn_MR2(sn)) | ((uint8_t)(((sock_io_mode >> sn) & 0x0001) << 3)); 627 | break; 628 | case SO_TTL: 629 | *(uint8_t*) arg = getSn_TTLR(sn); 630 | break; 631 | case SO_TOS: 632 | *(uint8_t*) arg = getSn_TOSR(sn); 633 | break; 634 | case SO_MSS: 635 | *(uint16_t*) arg = getSn_MSSR(sn); 636 | break; 637 | case SO_DESTIP: 638 | CHECK_TCPMODE(); 639 | if(getSn_ESR(sn) & TCPSOCK_MODE) //IPv6 ? 640 | { 641 | getSn_DIP6R(sn, ((wiz_IPAddress*)arg)->ip); 642 | ((wiz_IPAddress*)arg)->len = 16; 643 | } 644 | else 645 | { 646 | getSn_DIPR(sn, ((wiz_IPAddress*)arg)->ip); 647 | ((wiz_IPAddress*)arg)->len = 4; 648 | } 649 | break; 650 | case SO_DESTPORT: 651 | *(uint16_t*) arg = getSn_DPORTR(sn); 652 | break; 653 | case SO_KEEPALIVEAUTO: 654 | CHECK_TCPMODE(); 655 | *(uint16_t*) arg = getSn_KPALVTR(sn); 656 | break; 657 | case SO_SENDBUF: 658 | *(datasize_t*) arg = getSn_TX_FSR(sn); 659 | break; 660 | case SO_RECVBUF: 661 | *(datasize_t*) arg = getSn_RX_RSR(sn); 662 | break; 663 | case SO_STATUS: 664 | *(uint8_t*) arg = getSn_SR(sn); 665 | break; 666 | case SO_EXTSTATUS: 667 | CHECK_TCPMODE(); 668 | *(uint8_t*) arg = getSn_ESR(sn) & 0x07; 669 | break; 670 | case SO_REMAINSIZE: 671 | if(getSn_MR(sn)==SOCK_CLOSED) return SOCKERR_SOCKSTATUS; 672 | if(getSn_MR(sn) & 0x01) *(uint16_t*)arg = getSn_RX_RSR(sn); 673 | else *(uint16_t*)arg = sock_remained_size[sn]; 674 | break; 675 | case SO_PACKINFO: 676 | if(getSn_MR(sn)==SOCK_CLOSED) return SOCKERR_SOCKSTATUS; 677 | if(getSn_MR(sn) & 0x01) return SOCKERR_SOCKMODE; 678 | else *(uint8_t*)arg = sock_pack_info[sn]; 679 | break; 680 | case SO_MODE: 681 | *(uint8_t*) arg = 0x0F & getSn_MR(sn); 682 | break; 683 | default: 684 | return SOCKERR_SOCKOPT; 685 | } 686 | return SOCK_OK; 687 | } 688 | 689 | int16_t peeksockmsg(uint8_t sn, uint8_t* submsg, uint16_t subsize) 690 | { 691 | uint32_t rx_ptr = 0; 692 | uint16_t i = 0, sub_idx = 0; 693 | 694 | if( (getSn_RX_RSR(sn) > 0) && (subsize > 0) ) 695 | { 696 | rx_ptr = ((uint32_t)getSn_RX_RD(sn) << 8) + WIZCHIP_RXBUF_BLOCK(sn); 697 | sub_idx = 0; 698 | for(i = 0; i < getSn_RX_RSR(sn) ; i++) 699 | { 700 | if(WIZCHIP_READ(rx_ptr) == submsg[sub_idx]) 701 | { 702 | sub_idx++; 703 | if(sub_idx == subsize) return (i + 1 - sub_idx); 704 | } 705 | else sub_idx = 0; 706 | rx_ptr = WIZCHIP_OFFSET_INC(rx_ptr,1); 707 | } 708 | } 709 | return -1; 710 | } 711 | -------------------------------------------------------------------------------- /Ethernet/socket.h: -------------------------------------------------------------------------------- 1 | //* **************************************************************************** 2 | //! \file socket.h 3 | //! \brief SOCKET APIs Header File. 4 | //! \version 1.0.0 5 | //! \date 2019/01/01 6 | //! \par Revision history 7 | //! <2019/01/01> 1st Release 8 | //! \author MidnightCow 9 | //! \copyright 10 | //! 11 | //! Copyright (c) 2019, WIZnet Co., LTD. 12 | //! 13 | //! Permission is hereby granted, free of charge, to any person obtaining a copy 14 | //! of this software and associated documentation files (the "Software"), to deal 15 | //! in the Software without restriction, including without limitation the rights 16 | //! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | //! copies of the Software, and to permit persons to whom the Software is 18 | //! furnished to do so, subject to the following conditions: 19 | //! 20 | //! The above copyright notice and this permission notice shall be included in 21 | //! all copies or substantial portions of the Software. 22 | //! 23 | //! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | //! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | //! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | //! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | //! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | //! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | //! SOFTWARE. 30 | //! 31 | //***************************************************************************** 32 | 33 | /** 34 | * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs 35 | * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. 36 | * But there is a little bit of difference. 37 | * @details 38 | * Comparison between WIZnet and Berkeley SOCKET APIs 39 | * 40 | * 41 | * 42 | * 43 | * 44 | * 45 | * 46 | * 47 | * 48 | * 49 | * 50 | * 51 | *
API WIZnet Berkeley
socket() O O
bind() X O
listen() O O
connect() O O
accept() X O
recv() O O
send() O O
recvfrom() O O
sendto() O O
closesocket() O
close() & disconnect()
O
52 | * There are bind() and accept() functions in Berkeley SOCKET API but, not in WIZnet SOCKET API. \n 53 | * Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, \n 54 | * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n 55 | * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. \n 56 | * When the listen SOCKET accepts a connection request from a client, it keeps listening. \n 57 | * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n 58 | * Following figure shows network flow diagram by Berkeley SOCKET API. \n 59 | * 60 | * 61 | *
@image html Berkeley_SOCKET.jpg ""
62 | * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n 63 | * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, \n 64 | * it is changed in order to communicate with the client.\n 65 | * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n 66 | * If there're many listen SOCKET with same listen port number and a client requests a connection, \n 67 | * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n 68 | * Following figure shows network flow diagram by WIZnet SOCKET API. 69 | * 70 | * 71 | *
@image html WIZnet_SOCKET.jpg ""
72 | */ 73 | 74 | #ifndef _SOCKET_H_ 75 | #define _SOCKET_H_ 76 | 77 | #include "stdint.h" 78 | #include "wizchip_conf.h" 79 | 80 | #define SOCKET uint8_t ///< SOCKET type define for legacy driver 81 | 82 | #define SOCK_OK 1 ///< Result is OK about socket process. 83 | #define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. 84 | #define SOCK_FATAL (-1000) ///< Result is fatal error about socket process. 85 | 86 | #define SOCK_ERROR 0 87 | #define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number 88 | #define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option 89 | #define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized or SIPR is Zero IP address when Sn_MR_TCP 90 | #define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. 91 | #define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. 92 | #define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag 93 | #define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. 94 | #define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. 95 | #define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero 96 | #define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid source or destination IP address 97 | #define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred 98 | #define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Invalid data length 99 | #define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. 100 | //#define SOCKERR_IPvMISMATCH (SOCK_ERROR - 16) ///< Socket IP version invalid 101 | //#define SOCKERR_IPLENINVALID (SOCK_ERROR - 17) ///< Socket IP version invalid 102 | 103 | #define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. 104 | 105 | /* 106 | * - @ref Sn_MR_MULTI : Support UDP Multicasting 107 | * - @ref Sn_MR_MF : Support MAC Filter Enable 108 | * - @ref Sn_MR_BRDB : Broadcast Block 109 | * - @ref Sn_MR_FPSH : Force PSH flag 110 | * - @ref Sn_MR_ND : No Delay ACK flag 111 | * - @ref Sn_MR_MC : IGMP ver2, ver1 112 | * - @ref Sn_MR_SMB : Solicited Multicast Block 113 | * - @ref Sn_MR_MMB : IPv4 Multicast block 114 | * - @ref Sn_MR_UNIB : Unicast Block 115 | * - @ref Sn_MR_MMB6 : IPv6 UDP Multicast Block 116 | 117 | * - @ref Sn_MR2_DHAM : @ref Sn_MR2_DHAM_AUTO, @ref Sn_MR2_DHAM_MANUAL 118 | * - @ref Sn_MR_FARP 119 | */ 120 | 121 | /* 122 | * SOCKET FLAG 123 | */ 124 | /** 125 | * @brief In UDP mode such as @ref Sn_MR_UDP4 and @ref Sn_MR_UDP6, @ref Sn_MR_UDP6, Enable multicast mode. When @ref Sn_MR_UDP6, Enable only IPv6 Multicating. 126 | */ 127 | #define SF_MULTI_ENABLE (Sn_MR_MULTI) 128 | #define SF_ETHER_OWN (Sn_MR_MF) ///< In MACRAW mode such as @ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet 129 | 130 | /** 131 | * @brief In UDP mode such as @ref Sn_MR_UDP4, @ref Sn_MR_UDP6 and @ref Sn_MR_UDPD, or In MACRAW mode sucha as @ref Sn_MR_MACRAW, Block a broadcast packet. 132 | */ 133 | #define SF_BROAD_BLOCK (Sn_MR_BRDB) 134 | #define SF_TCP_FPSH (Sn_MR_FPSH) ///< In TCP mode such as @ref Sn_MR_TCP4, @ref Sn_MR_TCP6 and @ref Sn_MR_TCPD, Use to forced push flag. 135 | 136 | #define SF_TCP_NODELAY (Sn_MR_ND) ///< In TCP mode such as @ref Sn_MR_TCP4, @ref Sn_MR_TCP6 and @ref Sn_MR_TCPD, Use to nodelayed ack. 137 | #define SF_IGMP_VER2 (Sn_MR_MC) ///< In UDP mode such as @ref Sn_MR_UDP4 with @ref SF_MULTI_ENABLE, Select IGMP version 2. 138 | #define SF_SOLICIT_BLOCK (Sn_MR_SMB) ///< In UDP mode such as @ref Sn_MR_UDP6 and @ref Sn_MR_UDPD, Block a solicited mutlicast packet. 139 | #define SF_ETHER_MULTI4B (Sn_MR_MMB4) ///< In MACRAW mode such as @ref Sn_MR_MACRAW with @ref SF_MULTI_ENABLE, Block a IPv4 multicast packet. 140 | 141 | #define SF_UNI_BLOCK (Sn_MR_UNIB) ///< In UDP mdoe such as @ref Sn_MR_UDP4, @ref Sn_MR_UDP6 and @ref Sn_MR_UDPD with @ref SF_MULTI_ENABLE, Block a unicast packet. 142 | #define SF_ETHER_MULIT6B (Sn_MR_MMB6) ///< In MACRAW mode such as @ref Sn_MR_MACRAW with @ref SF_MULTI_ENABLE, Block a IPv6 multicast packet. 143 | 144 | /** 145 | * @brief Force to APR. 146 | * @details In datagram mode such as @ref Sn_MR_IPRAW4, @ref Sn_MR_IPRAW6, @ref Sn_MR_UDP4, @ref Sn_MR_UDP6, and @ref Sn_MR_UDPD, 147 | * Force to request ARP before a packet is sent to a destination.\n 148 | * In TCP mode such as @ref Sn_MR_TCP4, @ref Sn_MR_TCP6, and @ref Sn_MR_TCPD and TCP SERVER operation mode, 149 | * Force to request ARP before SYN/ACK packet is sent to a TCP CLIENT. \n 150 | * When @ref SF_DHA_MANUAL is set, the ARP is process but the destination hardware address is fixed by user. 151 | */ 152 | #define SF_FORCE_ARP (Sn_MR2_FARP) 153 | 154 | /** 155 | * @brief The destination hardware address of packet to be transmitted is set by user through @ref _Sn_DHAR_. It is invalid in MACRAW mode such as @ref Sn_MR_MACRAW. 156 | */ 157 | #define SF_DHA_MANUAL (Sn_MR2_DHAM) 158 | 159 | #define SF_IO_NONBLOCK (0x01 << 3) ///< Socket nonblock io mode. It used parameter in @ref socket(). 160 | 161 | /* 162 | * UDP, IPRAW, MACRAW Packet Infomation 163 | */ 164 | #define PACK_IPv6 (1<<7) ///< It indicates the destination IP address of the received packet is IPv6 or IPv4. 165 | #define PACK_IPV6_ALLNODE (PACK_IPv6 | (1<<6)) ///< It indicates the destination IP address of the received packet is allnode multicast(broadcast) address or not. 166 | #define PACK_IPV6_MULTI (PACK_IPv6 | (1<<5)) ///< It indicates the destination IP address of the received packet is multicast address or not. 167 | #define PACK_IPV6_LLA (PACK_IPv6 | (1<<4)) ///< It indicates the destination IP address of the received packet is lla or gua. 168 | #define PACK_COMPLETED (1<<3) ///< It indicates the read data is last in the received packet. 169 | #define PACK_REMAINED (1<<2) ///< It indicates to remain data in the received packet 170 | #define PACK_FIRST (1<<1) ///< It indicates the read data is first in the received packet. 171 | #define PACK_NONE (0x00) ///< It indicates no information of a packet 172 | 173 | #define SRCV6_PREFER_AUTO (PSR_AUTO) ///< Soruce IPv6 address is preferred to auto-selection. Refer to @ref _Sn_PSR_ 174 | #define SRCV6_PREFER_LLA (PSR_LLA) ///< Soruce IPv6 address is preferred to link local address. Refer to @ref _Sn_PSR_ 175 | #define SRCV6_PREFER_GUA (PSR_GUA) ///< Soruce IPv6 address is preferred to global unique address. Refer to @ref _Sn_PSR_ 176 | 177 | #define TCPSOCK_MODE (Sn_ESR_TCPM) ///< It indicates the IP version when SOCKETn is opened as TCP6 or TCPD mode.(0 - IPv4 , 1 - IPv6) 178 | #define TCPSOCK_OP (Sn_ESR_TCPOP) ///< It indicates the operation mode when SOCKETn is connected.(0 - TCP CLIENT , 1 - TCP SERVER) 179 | #define TCPSOCK_SIP (Sn_ESR_IP6T) ///< It indicates the source ip address type when SOCKET is connected. (0 - Link Local, 1 - Global Unique) 180 | 181 | ///////////////////////////// 182 | // SOCKET CONTROL & OPTION // 183 | ///////////////////////////// 184 | #define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). 185 | #define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). 186 | 187 | 188 | /** 189 | * @ingroup WIZnet_socket_APIs 190 | * @brief Open a socket. 191 | * @details Initializes the SOCKET have the sn number open it. 192 | * 193 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 194 | * @param protocol Protocol type to operate such as TCP, UDP IPRAW, and MACRAW. \n 195 | * - TCP : @ref Sn_MR_TCP(= @ref Sn_MR_TCP4), @ref Sn_MR_TCP6, and @ref Sn_MR_TCPD 196 | * - UDP : @ref Sn_MR_UDP(= @ref Sn_MR_UDP4), @ref Sn_MR_UDP6, and @ref Sn_MR_UDPD 197 | * - IPRAW : @ref Sn_MR_IPRAW(= @ref Sn_MR_IPRAW4) and @ref Sn_MR_IPRAW6 198 | * - MACRAW : @ref Sn_MR_MACRAW 199 | * @param port Source port number to be binded. 200 | * @param flag SOCKET flags are as following. It is used together with OR operation. 201 | * - @ref SF_MULTI_ENABLE 202 | * - @ref SF_ETHER_OWN 203 | * - @ref SF_BROAD_BLOCK 204 | * - @ref SF_TCP_FPSH 205 | * - @ref SF_TCP_NODELAY 206 | * - @ref SF_IGMP_VER2 207 | * - @ref SF_SOLICIT_BLOCK 208 | * - @ref SF_ETHER_MULTI4B 209 | * - @ref SF_UNI_BLOCK 210 | * - @ref SF_ETHER_MULIT6B 211 | * - @ref SF_DHA_MANUAL 212 | * - @ref SF_FORCE_ARP 213 | * - @ref SF_IO_NONBLOCK 214 | * @return Success : The SOCKET number sn passed as parameter\n 215 | * Fail :\n @ref SOCKERR_SOCKNUM - Invalid SOCKETn, sn\n 216 | * @ref SOCKERR_SOCKMODE - Invalid SOCKETn mode\n 217 | * @ref SOCKERR_SOCKFLAG - Invaild SOCKETn flag. 218 | * @sa _Sn_MR_, _Sn_MR2_ 219 | */ 220 | int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); 221 | 222 | /** 223 | * @ingroup WIZnet_socket_APIs 224 | * @brief Close a SOCKET. 225 | * @details It closes the SOCKET with 'sn' passed as parameter. 226 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 227 | * @return Success : @ref SOCK_OK \n 228 | * Fail : @ref SOCKERR_SOCKNUM - Invalid SOCKET number 229 | */ 230 | int8_t close(uint8_t sn); 231 | 232 | /** 233 | * @ingroup WIZnet_socket_APIs 234 | * @brief Listen to a connection request from a TCP CLIENT. 235 | * @details It is listening to a connection request from a client. 236 | * If connection request is accepted successfully, the connection is established. \n 237 | * SOCKET sn is used as passive(TCP SERVER) mode. 238 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 239 | * @return Success : @ref SOCK_OK \n 240 | * Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n 241 | * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. 242 | */ 243 | int8_t listen(uint8_t sn); 244 | 245 | /** 246 | * @ingroup WIZnet_socket_APIs 247 | * @brief Try to connect to a TCP SERVER. 248 | * @details It sends a connection-reqeust message to the server with destination IP address and port number passed as parameter.\n 249 | * SOCKET sn is used as active(TCP CLIENT) mode. 250 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 251 | * @param addr Pointer variable of destination IPv6 or IPv4 address. 252 | * @param port Destination port number. 253 | * @param addrlen the length of addr. \n 254 | * If addr is IPv6 address it should be 16,else if addr is IPv4 address it should be 4. Otherwize, return @ref SOCKERR_IPINVALID. 255 | * @return Success : @ref SOCK_OK \n 256 | * Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n 257 | * @ref SOCKERR_SOCKMODE - Invalid socket mode\n 258 | * @ref SOCKERR_SOCKINIT - Socket is not initialized\n 259 | * @ref SOCKERR_IPINVALID - Wrong server IP address\n 260 | * @ref SOCKERR_PORTZERO - Server port zero\n 261 | * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n 262 | * @ref SOCK_BUSY - In non-block io mode, it returns immediately\n 263 | * @note It is valid only in TCP client mode. \n 264 | * In block io mode, it does not return until connection is completed. \n 265 | * In Non-block io mode(@ref SF_IO_NONBLOCK), it returns @ref SOCK_BUSY immediately. 266 | */ 267 | int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port, uint8_t addrlen); 268 | 269 | 270 | /** 271 | * @ingroup WIZnet_socket_APIs 272 | * @brief Try to disconnect to the connected peer. 273 | * @details It sends disconnect-request message to the connected peer which is TCP SERVER or TCP CLIENT. 274 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 275 | * @return Success : @ref SOCK_OK \n 276 | * Fail :\n @ref SOCKERR_SOCKNUM - Invalid SOCKET number \n 277 | * @ref SOCKERR_SOCKMODE - Invalid operation in the SOCKET \n 278 | * @ref SOCKERR_TIMEOUT - Timeout occurred \n 279 | * @ref SOCK_BUSY - In non-block io mode, it returns immediately. 280 | * @note It is valid only in TCP mode such as @ref Sn_MR_TCP4, @ref Sn_MR_TCP6, and @ref Sn_MR_TCPD. \n 281 | * In block io mode, it does not return until disconnection is completed. \n 282 | * In Non-block io mode(@ref SF_IO_NONBLOCK), it returns @ref SOCK_BUSY immediately. \n 283 | */ 284 | int8_t disconnect(uint8_t sn); 285 | 286 | /** 287 | * @ingroup WIZnet_socket_APIs 288 | * @brief Send data to the connected peer. 289 | * @details It sends data to the connected peer by using TCP mode SOCKET sn. 290 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 291 | * @param buf Pointer of data buffer to be sent. 292 | * @param len The byte length of data in buf. 293 | * @return Success : The real sent data size. It may be equal to len or small. \n 294 | * Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid SOCKET status for SOCKET operation \n 295 | * @ref SOCKERR_TIMEOUT - Timeout occurred \n 296 | * @ref SOCKERR_SOCKMODE - Invalid operation in the SOCKET \n 297 | * @ref SOCKERR_SOCKNUM - Invalid SOCKET number \n 298 | * @ref SOCK_BUSY - SOCKET is busy. 299 | * @note It is valid only in TCP mode such as @ref Sn_MR_TCP4, Sn_MR_TCP6, and Sn_MR_TCPD. \n 300 | * It can send data as many as SOCKET TX buffer size if data is greater than SOCKET TX buffer size. \n 301 | * In block io mode, It doesn't return until data sending is completed when SOCKET transmittable buffer size is greater than data. \n 302 | * In non-block io mode(@ref SF_IO_NONBLOCK), It return @ref SOCK_BUSY immediately when SOCKET transmittable buffer size is not enough or the previous sent data is not completed. \n 303 | */ 304 | datasize_t send(uint8_t sn, uint8_t * buf, datasize_t len); 305 | 306 | 307 | /** 308 | * @ingroup WIZnet_socket_APIs 309 | * @brief Receive data from the connected peer. 310 | * @details It can read data received from the connected peer by using TCP mode SOCKET sn.\n 311 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 312 | * @param buf Pointer buffer to read the received data. 313 | * @param len The max data length of data in buf. 314 | * @return Success : The real received data size. It may be equal to len or small. \n 315 | * Fail :\n 316 | * @ref SOCKERR_SOCKSTATUS - Invalid SOCKET status for SOCKET operation \n 317 | * @ref SOCKERR_SOCKMODE - Invalid operation in the SOCKET \n 318 | * @ref SOCKERR_SOCKNUM - Invalid SOCKET number \n 319 | * @ref SOCK_BUSY - SOCKET is busy. 320 | * @note It is valid only in TCP SERVER or TCP CLIENT mode. \n 321 | * It can read data as many as SOCKET RX buffer size if data is greater than SOCKET RX buffer size. \n 322 | * In block io mode, it doesn't return until data reception is completed. that is, it waits until any data is received in SOCKET RX buffer. \n 323 | * In non-block io mode(@ref SF_IO_NONBLOCK), it return @ref SOCK_BUSY immediately when SOCKET RX buffer is empty. \n 324 | * 325 | */ 326 | datasize_t recv(uint8_t sn, uint8_t * buf, datasize_t len); 327 | 328 | 329 | /** 330 | * @ingroup WIZnet_socket_APIs 331 | * @brief Send datagram to the peer specifed by destination IP address and port number passed as parameter. 332 | * @details It sends datagram data by using UDP,IPRAW, or MACRAW mode SOCKET. 333 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 334 | * @param buf Pointer of data buffer to be sent. 335 | * @param len The byte length of data in buf. 336 | * @param addr Pointer variable of destination IPv6 or IPv4 address. 337 | * @param port Destination port number. 338 | * @param addrlen the length of addr. \n 339 | * If addr is IPv6 address it should be 16,else if addr is IPv4 address it should be 4. Otherwize, return @ref SOCKERR_IPINVALID. 340 | * @return Success : The real sent data size. It may be equal to len or small.\n 341 | * Fail :\n @ref SOCKERR_SOCKNUM - Invalid SOCKET number \n 342 | * @ref SOCKERR_SOCKMODE - Invalid operation in the SOCKET \n 343 | * @ref SOCKERR_SOCKSTATUS - Invalid SOCKET status for SOCKET operation \n 344 | * @ref SOCKERR_IPINVALID - Invalid IP address\n 345 | * @ref SOCKERR_PORTZERO - Destination port number is zero\n 346 | * @ref SOCKERR_DATALEN - Invalid data length \n 347 | * @ref SOCKERR_SOCKCLOSED - SOCKET unexpectedly closed \n 348 | * @ref SOCKERR_TIMEOUT - Timeout occurred \n 349 | * @ref SOCK_BUSY - SOCKET is busy. 350 | * @note It is valid only in @ref Sn_MR_UDP4, @ref Sn_MR_UDP6, @ref Sn_MR_UDPD, @ref Sn_MR_IPRAW4, @ref Sn_MR_IPRAW6, and @ref Sn_MR_MACRAW. \n 351 | * In UDP mode, It can send data as many as SOCKET RX buffer size if data is greater than SOCKET TX buffer size. \n 352 | * In IPRAW and MACRAW mode, It should send data as many as MTU(maxium transmission unit) if data is greater than MTU. That is, len can't exceed to MTU. 353 | * In block io mode, It doesn't return until data send is completed. 354 | * In non-block io mode(@ref SF_IO_NONBLOCK), It return @ref SOCK_BUSY immediately when SOCKET transimttable buffer size is not enough. 355 | */ 356 | datasize_t sendto(uint8_t sn, uint8_t * buf, datasize_t len, uint8_t * addr, uint16_t port, uint8_t addrlen); 357 | 358 | /** 359 | * @ingroup WIZnet_socket_APIs 360 | * @brief Receive datagram from a peer 361 | * @details It can read a data received from a peer by using UDP, IPRAW, or MACRAW mode SOCKET. 362 | * @param sn SOCKET number. It should be 0 ~ @ref _WIZCHIP_SOCK_NUM_. 363 | * @param buf Pointer buffer to be saved the received data. 364 | * @param len The max read data length. \n 365 | * When the received packet size <= len, it can read data as many as the packet size. \n 366 | * When others, it can read data as many as len and remain to the rest data of the packet. 367 | * @param addr Pointer variable of destination IP address.\n 368 | * It is valid only when @ref recvfrom() is first called for receiving the datagram packet. 369 | * You can check it valid or not through @ref PACK_FIRST. You can get it through @ref getsockopt(sn, @ref SO_PACKINFO, &packinfo).\n 370 | * In UDP4, IPRAW mode SOCKET, it should be allocated over 4bytes. \n 371 | * In UDP6, UDPD mode SOCKET, it should be allocated over 16bytes. 372 | * @param port Pointer variable of destination port number. \n 373 | * It is valid only when @ref recvfrom() is first called for receiving the datagram packet, same as port case. 374 | * @param addrlen The byte length of destination IP address. \n 375 | * It is valid only when @ref recvfrom() is first called for receiving the datagram packet, same as port case.\n 376 | * When the destination has a IPv4 address, it is set to 4. \n 377 | * when the destination has a IPv6 address, it is set to 16. 378 | * @return Success : The real received data size. It may be equal to len or small.\n 379 | * Fail : @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n 380 | * @ref SOCKERR_SOCKNUM - Invalid socket number \n 381 | * @ref SOCKERR_ARG - Invalid parameter such as addr, port 382 | * @ref SOCK_BUSY - SOCKET is busy. 383 | * @note It is valid only in @ref Sn_MR_UDP4, @ref Sn_MR_UDP6, @ref Sn_MR_UDPD, @ref Sn_MR_IPRAW4, @ref Sn_MR_IPRAW6, and @ref Sn_MR_MACRAW. \n 384 | * When SOCKET is opened with @ref Sn_MR_MACRAW or When it reads the the remained data of the previous datagram packet, 385 | * the parameters such as addr, port, addrlen is ignored. \n 386 | * Also, It can read data as many as the received datagram packet size if len is greater than the datagram packet size. \n 387 | * In block io mode, it doesn't return until data reception is completed. that is, it waits until any datagram packet is received in SOCKET RX buffer. \n 388 | * In non-block io mode(@ref SF_IO_NONBLOCK), it return @ref SOCK_BUSY immediately when SOCKET RX buffer is empty. \n 389 | */ 390 | datasize_t recvfrom(uint8_t sn, uint8_t * buf, datasize_t len, uint8_t * addr, uint16_t *port, uint8_t *addrlen); 391 | 392 | 393 | 394 | /** 395 | * @defgroup DATA_TYPE DATA TYPE 396 | */ 397 | 398 | /** 399 | * @ingroup DATA_TYPE 400 | * @brief The kind of SOCKET Interrupt. 401 | * @sa _Sn_IR_, _Sn_IMR_, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() 402 | */ 403 | typedef enum 404 | { 405 | SIK_CONNECTED = (1 << 0), ///< connected 406 | SIK_DISCONNECTED = (1 << 1), ///< disconnected 407 | SIK_RECEIVED = (1 << 2), ///< data received 408 | SIK_TIMEOUT = (1 << 3), ///< timeout occurred 409 | SIK_SENT = (1 << 4), ///< send ok 410 | SIK_ALL = 0x1F ///< all interrupt 411 | }sockint_kind; 412 | 413 | /** 414 | * @ingroup DATA_TYPE 415 | * @brief The type of @ref ctlsocket(). 416 | */ 417 | typedef enum 418 | { 419 | CS_SET_IOMODE, ///< set SOCKET IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK 420 | CS_GET_IOMODE, ///< get SOCKET IO mode 421 | CS_GET_MAXTXBUF, ///< get the size of SOCKET TX buffer allocated in TX memory 422 | CS_GET_MAXRXBUF, ///< get the size of SOCKET RX buffer allocated in RX memory 423 | CS_CLR_INTERRUPT, ///< clear the interrupt of SOCKET with @ref sockint_kind. 424 | CS_GET_INTERRUPT, ///< get the SOCKET interrupt. refer to @ref sockint_kind. 425 | CS_SET_INTMASK, ///< set the interrupt mask of SOCKET with @ref sockint_kind. 426 | CS_GET_INTMASK, ///< get the masked interrupt of SOCKET. refer to @ref sockint_kind. 427 | CS_SET_PREFER, ///< set the preferred source IPv6 address of transmission packet.\n Refer to @ref SRCV6_PREFER_AUTO, @ref SRCV6_PREFER_LLA and @ref SRCV6_PREFER_GUA. 428 | CS_GET_PREFER, ///< get the preferred source IPv6 address of transmission packet.\n Refer to @ref SRCV6_PREFER_AUTO, @ref SRCV6_PREFER_LLA and @ref SRCV6_PREFER_GUA. 429 | }ctlsock_type; 430 | 431 | 432 | /** 433 | * @ingroup DATA_TYPE 434 | * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() 435 | */ 436 | typedef enum 437 | { 438 | SO_FLAG, ///< Valid only in @ref getsockopt(), For set flag of socket refer to flag in @ref socket(). \n 439 | SO_TTL, ///< Set/Get TTL. ( @ref setSn_TTLR(), @ref getSn_TTLR() ) \n 440 | SO_TOS, ///< Set/Get TOS. ( @ref setSn_TOSR(), @ref getSn_TOSR() ) 441 | SO_MSS, ///< Set/Get MSS. ( @ref setSn_MSSR(), @ref getSn_MSSR() ) 442 | SO_DESTIP, ///< Set/Get the destination IP address with argument @ref wiz_IPAddress. To get it, SOCKETn should be TCP mode. 443 | SO_DESTPORT, ///< Set/Get the destination Port number. To get it, SOCKETn should be TCP mode. 444 | SO_KEEPALIVESEND, ///< Valid only in @ref setsockopt(). Manually send keep-alive packet in TCP mode. 445 | SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode 446 | SO_SENDBUF, ///< Valid only in @ref getsockopt(). Get the free data size of SOCKETn TX buffer. @ref getSn_TX_FSR() 447 | SO_RECVBUF, ///< Valid only in @ref getsockopt(). Get the received data size in SOCKETn RX buffer. @ref getSn_RX_RSR() 448 | SO_STATUS, ///< Valid only in @ref getsockopt(). Get the SOCKETn status. @ref getSn_SR() 449 | SO_EXTSTATUS, ///< Valid only in @ref getsockopt(). Get the extended TCP SOCKETn status. @ref getSn_ESR() 450 | SO_REMAINSIZE, ///< Valid only in @ref getsockopt(). Get the remained packet size in non-TCP mode. 451 | SO_MODE, 452 | SO_PACKINFO ///< Valid only in @ref getsockopt(). Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and etc. 453 | }sockopt_type; 454 | 455 | /** 456 | * @ingroup WIZnet_socket_APIs 457 | * @brief Control SOCKETn. 458 | * @details Control IO mode, Interrupt & Mask of SOCKETn and get the SOCKETn buffer information. 459 | * Refer to @ref ctlsock_type. 460 | * @param sn socket number 461 | * @param cstype type of control SOCKETn. refer to @ref ctlsock_type. 462 | * @param arg Data type and value is determined according to @ref ctlsock_type. \n 463 | * 464 | * 465 | * 466 | * 467 | * 468 | * 469 | * 470 | * 471 | * 472 | * 473 | * < /tr> 474 | *
@b cstype @b arg type@b value
@ref CS_SET_IOMODE \n @ref CS_GET_IOMODE uint8_t @ref SOCK_IO_BLOCK, @ref SOCK_IO_NONBLOCK
@ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF datasize_t 0,1,2,4,8,16 KB
@ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK @ref sockint_kind @ref SIK_CONNECTED, etc.
@ref CS_SET_PREFER \n @ref CS_GET_PREFER uint8_t @ref SRCV6_PREFER_AUTO, @ref SRCV6_PREFER_LLA, @ref SRCV6_PREFER_GUA
475 | * @return Success @ref SOCK_OK \n 476 | * Fail : \n 477 | * - @ref SOCKERR_ARG - Invalid argument\n 478 | * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n 479 | */ 480 | int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg); 481 | 482 | /** 483 | * @ingroup WIZnet_socket_APIs 484 | * @brief Set SOCKETn options 485 | * @details Set SOCKETn option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. 486 | * 487 | * @param sn SOCKET number 488 | * @param sotype SOCKET option type. refer to @ref sockopt_type 489 | * @param arg Data type and value is determined according to sotype. \n 490 | * 491 | * 492 | * 493 | * 494 | * 495 | * 496 | * 497 | * 498 | * 499 | *
@b sotype @b >arg type@b value
@ref SO_TTL uint8_t 0 ~ 255
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP @ref wiz_IPAddress
@ref SO_DESTPORT uint16_t 1 ~ 65535
@ref SO_KEEPALIVESEND null null
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
500 | * @return 501 | * - Success : @ref SOCK_OK \n 502 | * - Fail 503 | * - @ref SOCKERR_SOCKNUM - Invalid SOCKET number \n 504 | * - @ref SOCKERR_SOCKMODE - Invalid SOCKET mode \n 505 | * - @ref SOCKERR_SOCKOPT - Invalid SOCKET option or its value \n 506 | * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet 507 | */ 508 | int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg); 509 | 510 | /** 511 | * @ingroup WIZnet_socket_APIs 512 | * @brief get SOCKETn options 513 | * @details Get SOCKETn option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type 514 | * @param sn SOCKET number 515 | * @param sotype SOCKET option type. refer to @ref sockopt_type 516 | * @param arg Data type and value is determined according to sotype. 517 | * 518 | * 519 | * 520 | * 521 | * 522 | * 523 | * 524 | * 525 | * 526 | * 527 | * 528 | * 529 | * 530 | * 531 | *
@b sotype @b arg type @b value
@ref SO_FLAG uint8_t @ref SF_ETHER_OWN, etc...
@ref SO_TOS uint8_t 0 ~ 255
@ref SO_MSS uint16_t 0 ~ 65535
@ref SO_DESTIP @ref wiz_IPAddress
@ref SO_DESTPORT uint16_t 1 ~ 65535
@ref SO_KEEPALIVEAUTO uint8_t 0 ~ 255
@ref SO_SENDBUF @ref datasize_t 0 ~
@ref SO_RECVBUF @ref datasize_t 0 ~
@ref SO_STATUS uint8_t @ref SOCK_ESTABLISHED, etc.
@ref SO_EXTSTATUS uint8_t @ref TCPSOCK_MODE, @ref TCPSOCK_OP, @ref TCPSOCK_SIP
@ref SO_REMAINSIZE @ref datasize_t 0~
@ref SO_PACKINFO uint8_t @ref PACK_FIRST, etc.
532 | * @return 533 | * - Success : @ref SOCK_OK \n 534 | * - Fail 535 | * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n 536 | * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n 537 | * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n 538 | * @note 539 | * The option as @ref PACK_REMAINED of @ref SO_PACKINFO is valid only in NON-TCP mode. 540 | */ 541 | int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg); 542 | 543 | /** 544 | * @ingroup WIZnet_socket_APIs 545 | * @brief Peeks a sub-message in SOCKETn RX buffer 546 | * @details It peeks the incoming message of SOCKETn RX buffer. \n 547 | * It can find the specified sub-message in the incoming message and 548 | * return the length of incoming message before the sub-message. \n 549 | * It is useful when you need to read each messages from multiple message in SOCKET RX buffer. 550 | * @param sn SOCKET number 551 | * @param submsg sub-message pointer to find 552 | * @param subsize the length of submsg 553 | * @return 554 | * - Success : the length of incoming message length before the submsg \n 555 | * - Fail : -1 556 | * @note 557 | * It is just return the length of incoming message before the found sub-message. It does not receive the message.\n 558 | * So, after calling peeksockmsg, @ref _Sn_RX_RD_ is not changed. 559 | */ 560 | int16_t peeksockmsg(uint8_t sn, uint8_t* submsg, uint16_t subsize); 561 | 562 | #endif // _SOCKET_H_ 563 | -------------------------------------------------------------------------------- /Ethernet/wizchip_conf.c: -------------------------------------------------------------------------------- 1 | //* **************************************************************************** 2 | //! \file wizchip_conf.c 3 | //! \brief WIZCHIP Config Implements file. 4 | //! \version 1.0.0 5 | //! \date 2019/01/01 6 | //! \par Revision history 7 | //! <2019/01/01> 1st Release 8 | //! \author MidnightCow 9 | //! \copyright 10 | //! 11 | //! Copyright (c) 2019, WIZnet Co., LTD. 12 | //! 13 | //! Permission is hereby granted, free of charge, to any person obtaining a copy 14 | //! of this software and associated documentation files (the "Software"), to deal 15 | //! in the Software without restriction, including without limitation the rights 16 | //! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | //! copies of the Software, and to permit persons to whom the Software is 18 | //! furnished to do so, subject to the following conditions: 19 | //! 20 | //! The above copyright notice and this permission notice shall be included in 21 | //! all copies or substantial portions of the Software. 22 | //! 23 | //! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | //! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | //! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | //! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | //! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | //! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | //! SOFTWARE. 30 | //! 31 | //***************************************************************************** 32 | 33 | #include // for use the type - ptrdiff_t 34 | 35 | 36 | #include "wizchip_conf.h" 37 | 38 | /** 39 | * @brief Default function to enter the critical section for @ref _WIZCHIP_. 40 | * @details @ref wizchip_cris_enter() provides the default protection while @ref _WIZCHIP_ is accessed. \n 41 | * but it is null function. 42 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_cris_cbfunc(). 43 | * @sa wizchip_cris_exit() 44 | */ 45 | void wizchip_cris_enter(void) {} 46 | 47 | /** 48 | * @brief Default function to exit the critical section for @ref _WIZCHIP_. 49 | * @details @ref wizchip_cris_exit provides the default protection while @ref _WIZCHIP_ is accessed\n 50 | * but it is null function. 51 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_cris_cbfunc(). 52 | * @sa wizchip_cris_enter() 53 | */ 54 | void wizchip_cris_exit(void) {} 55 | 56 | /** 57 | * @brief Default function to select @ref _WIZCHIP_. 58 | * @details @ref wizchip_cs_select() provides the default selection @ref _WIZCHIP_,\n 59 | * but it is null function. 60 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_cs_cbfunc(). 61 | * @sa wizchip_cs_deselect() 62 | */ 63 | void wizchip_cs_select(void) {} 64 | 65 | /** 66 | * @brief Default function to de-select @ref _WIZCHIP_. 67 | * @details @ref wizchip_cs_deselect() provides the default de-selection @ref _WIZCHIP_, \n 68 | * but it is null function. 69 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_cs_cbfunc(). 70 | * @sa wizchip_cs_select() 71 | */ 72 | void wizchip_cs_deselect(void) {} 73 | 74 | 75 | /// @cond DOXY_APPLY_CODE 76 | #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) 77 | /// @endcond 78 | 79 | /** 80 | * @brief Default function to read one @ref iodata_t data by using BUS interface 81 | * @details @ref wizchip_bus_read() provides the default read one @ref iodata_t data from BUS of @ref _WIZCHIP_. 82 | * @param AddrSel It specifies the address of register to be read. 83 | * @return @ref iodata_t 84 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_bus_cbfunc(). 85 | * @sa wizchip_bus_write() 86 | */ 87 | iodata_t wizchip_bus_read(uint32_t AddrSel) { return * ((volatile iodata_t *)((ptrdiff_t) AddrSel)); } 88 | 89 | /** 90 | * @brief Default function to write one @ref iodata_t data by using BUS interface. 91 | * @details @ref wizchip_bus_write() provides the default write one @ref iodata_t data to BUS of @ref _WIZCHIP_. 92 | * @param AddrSel It specifies the address of register to be written. 93 | * @param wb @ref iodata_t data to be written 94 | * @return void 95 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_bus_cbfunc(). 96 | * @sa wizchip_bus_read() 97 | */ 98 | void wizchip_bus_write(uint32_t AddrSel, iodata_t wb) { *((volatile iodata_t*)((ptrdiff_t)AddrSel)) = wb; } 99 | 100 | /** 101 | * @brief Default function to read @ref iodata_t buffer by using BUS interface 102 | * @details @ref wizchip_bus_read_buf() provides the default read @ref iodata_t data as many as len from BUS of @ref _WIZCHIP_. 103 | * @param AddrSel It specifies the address of register to be read. 104 | * @param buf It specifies your buffer pointer to be saved the read data from @ref _WIZCHIP_. 105 | * @param len It specifies the data length to be read from @ref _WIZCHIP_. 106 | * @param addrinc It specifies whether the address is increased by every read operation or not.\n 107 | * 0 : Not Increased \n 108 | * 1 : Increased 109 | * @return void 110 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_bus_cbfunc(). 111 | * @sa wizchip_bus_write_buf() 112 | */ 113 | void wizchip_bus_read_buf(uint32_t AddrSel, iodata_t* buf, datasize_t len, uint8_t addrinc) 114 | { 115 | datasize_t i; 116 | if(addrinc) addrinc = sizeof(iodata_t); 117 | for ( i = 0; i < len; i++) 118 | { 119 | *buf++ = WIZCHIP.IF.BUS._read_data(AddrSel); 120 | AddrSel += (uint32_t) addrinc; 121 | } 122 | } 123 | 124 | /** 125 | * @brief Default function to write @ref iodata_t buffer by using BUS interface. 126 | * @details @ref wizchip_bus_write_buf() provides the default write @ref iodata_t data as many as len to BUS of @ref _WIZCHIP_. 127 | * @param AddrSel It specifies the address of register to be written. 128 | * @param buf It specifies your buffer pointer to be written to @ref _WIZCHIP_. 129 | * @param len It specifies the data length to be written to @ref _WIZCHIP_. 130 | * @param addrinc It specifies whether the address is increased by every write operation or not.\n 131 | * 0 : Not Increased \n 132 | * 1 : Increased 133 | * @return void 134 | * @note It can be overwritten with your function or register your functions by calling @ref reg_wizchip_bus_cbfunc(). 135 | * @sa wizchip_bus_read_buf() 136 | */ 137 | void wizchip_bus_write_buf(uint32_t AddrSel, iodata_t* buf, datasize_t len, uint8_t addrinc) 138 | { 139 | datasize_t i; 140 | if(addrinc) addrinc = sizeof(iodata_t); 141 | for( i = 0; i < len ; i++) 142 | { 143 | WIZCHIP.IF.BUS._write_data(AddrSel,*buf++); 144 | AddrSel += (uint32_t)addrinc; 145 | } 146 | 147 | } 148 | 149 | /// @cond DOXY_APPLY_CODE 150 | #endif 151 | /// @endcond 152 | 153 | 154 | /// @cond DOXY_APPLY_CODE 155 | #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) 156 | /// @endcond 157 | 158 | /** 159 | * @brief Default function to read one byte by using SPI interface. 160 | * @details @ref wizchip_spi_read() provides the default read one byte data from SPI of @ref _WIZCHIP_,\n 161 | * but it is null function. 162 | * @return uint8_t 163 | * @todo It should be overwritten with your function or register your functions by calling @ref reg_wizchip_spi_cbfunc(). 164 | */ 165 | uint8_t wizchip_spi_read(void) {return 0;} 166 | 167 | /** 168 | * @brief Default function to write one byte by using SPI interface. 169 | * @details @ref wizchip_spi_write() provides the default write one byte data to SPI of @ref _WIZCHIP_,\n 170 | * but it is null function. 171 | * @param wb uint8_t data to be written 172 | * @return void 173 | * @todo It should be overwritten with your function or register your functions by calling @ref reg_wizchip_spi_cbfunc(). 174 | */ 175 | void wizchip_spi_write(uint8_t wb) {} 176 | 177 | /** 178 | * @brief Default function to read buffer by using SPI interface. 179 | * @details @ref wizchip_spi_read_buf() provides the default read byte buffer as many as len from SPI of @ref _WIZCHIP_. 180 | * @param buf It specifies your buffer pointer to be saved the read data from @ref _WIZCHIP_. 181 | * @param len It specifies the data length to be read from @ref _WIZCHIP_. 182 | * @return void 183 | * @note It is use @ref wizchip_spi_read() as default. \n 184 | * It can be overwritten with your function or register your functions by calling @ref reg_wizchip_spi_cbfunc(). 185 | */ 186 | void wizchip_spi_read_buf(uint8_t* buf, datasize_t len) 187 | { 188 | for(datasize_t i=0; i < len; i++) *buf++ = WIZCHIP.IF.SPI._read_byte(); 189 | } 190 | 191 | /** 192 | * @brief Default function to write buffer by using SPI interface. 193 | * @details @ref wizchip_spi_write_buf() provides the default write byte buffer as many as len to SPI of @ref _WIZCHIP_. 194 | * @param buf It specifies your buffer pointer to be written to @ref _WIZCHIP_. 195 | * @param len It specifies the data length to be write from @ref _WIZCHIP_. 196 | * @return void 197 | * @note It is use @ref wizchip_spi_write() as default. \n 198 | * It can be overwritten with your function or register your functions by calling @ref reg_wizchip_spi_cbfunc(). 199 | */ 200 | void wizchip_spi_write_buf(uint8_t* buf, datasize_t len) 201 | { 202 | for(datasize_t i=0; i < len; i++) WIZCHIP.IF.SPI._write_byte(*buf++); 203 | } 204 | 205 | /// @cond DOXY_APPLY_CODE 206 | #endif 207 | /// @endcond 208 | 209 | 210 | /** 211 | * @brief @ref _WIZCHIP_T_ instance 212 | * @details It provides the call-back function set for accessing to @ref _WIZCHIP_ 213 | */ 214 | _WIZCHIP_T_ WIZCHIP = 215 | { 216 | _WIZCHIP_IO_MODE_, 217 | _WIZCHIP_ID_ , 218 | { 219 | wizchip_cris_enter, 220 | wizchip_cris_exit 221 | }, 222 | { 223 | wizchip_cs_select, 224 | wizchip_cs_deselect 225 | }, 226 | #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) 227 | { 228 | .BUS = 229 | { 230 | wizchip_bus_read, 231 | wizchip_bus_write, 232 | wizchip_bus_read_buf, 233 | wizchip_bus_write_buf 234 | } 235 | } 236 | #elif (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) 237 | { 238 | .SPI = 239 | { 240 | wizchip_spi_read, 241 | wizchip_spi_write, 242 | wizchip_spi_read_buf, 243 | wizchip_spi_write_buf 244 | } 245 | } 246 | #else 247 | #error "Undefined _WIZCHIP_IO_MODE_. You should define it" 248 | #endif 249 | }; 250 | 251 | 252 | static uint8_t _DNS_[4]; ///< DNS server IPv4 address 253 | static uint8_t _DNS6_[16]; ///< DSN server IPv6 address 254 | static ipconf_mode _IPMODE_; ///< IP configuration mode 255 | 256 | void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) 257 | { 258 | if(!cris_en) WIZCHIP.CRIS._e_n_t_e_r_ = wizchip_cris_enter; 259 | else WIZCHIP.CRIS._e_n_t_e_r_ = cris_en; 260 | if(!cris_ex) WIZCHIP.CRIS._e_x_i_t_ = wizchip_cris_exit; 261 | else WIZCHIP.CRIS._e_x_i_t_ = cris_ex; 262 | } 263 | 264 | void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) 265 | { 266 | if(!cs_sel) WIZCHIP.CS._s_e_l_e_c_t_ = wizchip_cs_select; 267 | else WIZCHIP.CS._s_e_l_e_c_t_ = cs_sel; 268 | if(!cs_desel) WIZCHIP.CS._d_e_s_e_l_e_c_t_ = wizchip_cs_deselect; 269 | else WIZCHIP.CS._d_e_s_e_l_e_c_t_ = cs_desel; 270 | } 271 | 272 | #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_) 273 | void reg_wizchip_bus_cbfunc( iodata_t(*bus_rd)(uint32_t addr), 274 | void (*bus_wd)(uint32_t addr, iodata_t wb), 275 | void (*bus_rbuf)(uint32_t AddrSel, uint8_t* buf, datasize_t len, uint8_t inc), 276 | void (*bus_wbuf)(uint32_t AddrSel, uint8_t* buf, datasize_t len, uint8_t inc) ) 277 | { 278 | while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_)); 279 | if(!bus_rd) WIZCHIP.IF.BUS._read_data = wizchip_bus_read; 280 | else WIZCHIP.IF.BUS._read_data = bus_rd; 281 | if(!bus_wd) WIZCHIP.IF.BUS._write_data = wizchip_bus_write; 282 | else WIZCHIP.IF.BUS._write_data = bus_wd; 283 | 284 | if(!bus_rbuf) WIZCHIP.IF.BUS._read_data_buf = wizchip_bus_read_buf; 285 | else WIZCHIP.IF.BUS._read_data_buf = bus_rbuf; 286 | if(!bus_wbuf) WIZCHIP.IF.BUS._write_data_buf = wizchip_bus_write_buf; 287 | else WIZCHIP.IF.BUS._write_data_buf = bus_wbuf; 288 | } 289 | #endif 290 | 291 | 292 | 293 | #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_) 294 | void reg_wizchip_spi_cbfunc( uint8_t (*spi_rb)(void), 295 | void (*spi_wb)(uint8_t wb), 296 | void (*spi_rbuf)(uint8_t* buf, datasize_t len), 297 | void (*spi_wbuf)(uint8_t* buf, datasize_t len) ) 298 | { 299 | while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); 300 | 301 | if(!spi_rb) WIZCHIP.IF.SPI._read_byte = wizchip_spi_read; 302 | else WIZCHIP.IF.SPI._read_byte = spi_rb; 303 | if(!spi_wb) WIZCHIP.IF.SPI._write_byte = wizchip_spi_write; 304 | else WIZCHIP.IF.SPI._write_byte = spi_wb; 305 | 306 | if(!spi_rbuf) WIZCHIP.IF.SPI._read_byte_buf = wizchip_spi_read_buf; 307 | else WIZCHIP.IF.SPI._read_byte_buf = spi_rbuf; 308 | if(!spi_wbuf) WIZCHIP.IF.SPI._write_byte_buf = wizchip_spi_write_buf; 309 | else WIZCHIP.IF.SPI._write_byte_buf = spi_wbuf; 310 | } 311 | #endif 312 | 313 | int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) 314 | { 315 | uint8_t tmp = *(uint8_t*) arg; 316 | 317 | uint8_t* ptmp[2] = {0,0}; 318 | switch(cwtype) 319 | { 320 | case CW_SYS_LOCK: 321 | if(tmp & SYS_CHIP_LOCK) CHIPLOCK(); 322 | if(tmp & SYS_NET_LOCK) NETLOCK(); 323 | if(tmp & SYS_PHY_LOCK) PHYLOCK(); 324 | break; 325 | case CW_SYS_UNLOCK: 326 | if(tmp & SYS_CHIP_LOCK) CHIPUNLOCK(); 327 | if(tmp & SYS_NET_LOCK) NETUNLOCK(); 328 | if(tmp & SYS_PHY_LOCK) PHYUNLOCK(); 329 | break; 330 | case CW_GET_SYSLOCK: 331 | *(uint8_t*)arg = getSYSR() >> 5; 332 | break; 333 | case CW_RESET_WIZCHIP: 334 | wizchip_sw_reset(); 335 | break; 336 | case CW_INIT_WIZCHIP: 337 | if(arg != 0) 338 | { 339 | ptmp[0] = (uint8_t*)arg; 340 | ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; 341 | } 342 | return wizchip_init(ptmp[0], ptmp[1]); 343 | case CW_GET_INTERRUPT: 344 | *(intr_kind*)arg = wizchip_getinterrupt(); 345 | break; 346 | case CW_CLR_INTERRUPT: 347 | wizchip_clrinterrupt(*(intr_kind*)arg); 348 | break; 349 | case CW_SET_INTRMASK: 350 | wizchip_setinterruptmask(*(intr_kind*)arg); 351 | break; 352 | case CW_GET_INTRMASK: 353 | *(intr_kind*)arg = wizchip_getinterruptmask(); 354 | break; 355 | case CW_SET_INTRTIME: 356 | setINTPTMR(*(uint16_t*)arg); 357 | break; 358 | case CW_GET_INTRTIME: 359 | *(uint16_t*)arg = getINTPTMR(); 360 | break; 361 | case CW_SET_IEN: 362 | tmp = getSYCR1(); 363 | if(*(uint8_t*)arg == 1) setSYCR1(tmp | SYCR1_IEN); 364 | else setSYCR1(tmp & ~SYCR1_IEN); 365 | break; 366 | case CW_GET_IEN: 367 | *((uint8_t*)arg) = getSYCR1() >> 7; 368 | break; 369 | case CW_GET_ID: 370 | ((uint8_t*)arg)[0] = WIZCHIP.id[0]; 371 | ((uint8_t*)arg)[1] = WIZCHIP.id[1]; 372 | ((uint8_t*)arg)[2] = WIZCHIP.id[2]; 373 | ((uint8_t*)arg)[3] = WIZCHIP.id[3]; 374 | ((uint8_t*)arg)[4] = WIZCHIP.id[4]; 375 | ((uint8_t*)arg)[5] = 0; 376 | break; 377 | case CW_GET_VER: 378 | *(uint16_t*)arg = getVER(); 379 | break; 380 | case CW_SET_SYSCLK: 381 | tmp = getSYCR1(); 382 | if(*(uint8_t*)arg == SYSCLK_100MHZ) setSYCR1(tmp & ~SYCR1_CLKSEL); 383 | else if(*(uint8_t*)arg == SYSCLK_25MHZ) setSYCR1(tmp | SYCR1_CLKSEL); 384 | break; 385 | case CW_GET_SYSCLK: 386 | *(uint8_t*)arg = (getSYCR1() & SYCR1_CLKSEL); 387 | break; 388 | case CW_RESET_PHY: 389 | wizphy_reset(); 390 | break; 391 | case CW_SET_PHYCONF: 392 | wizphy_setphyconf((wiz_PhyConf*)arg); 393 | break; 394 | case CW_GET_PHYCONF: 395 | wizphy_getphyconf((wiz_PhyConf*)arg); 396 | break; 397 | case CW_GET_PHYSTATUS: 398 | wizphy_getphystatus((wiz_PhyConf*)arg); 399 | break; 400 | case CW_SET_PHYPOWMODE: 401 | wizphy_setphypmode(tmp); 402 | break; 403 | case CW_GET_PHYPOWMODE: 404 | *(uint8_t*)arg = wizphy_getphypmode(); 405 | break; 406 | case CW_GET_PHYLINK: 407 | *(uint8_t*)arg = wizphy_getphylink(); 408 | break; 409 | default: 410 | return -1; 411 | } 412 | return 0; 413 | } 414 | 415 | int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) 416 | { 417 | switch(cntype) 418 | { 419 | case CN_SET_NETINFO: 420 | wizchip_setnetinfo((wiz_NetInfo*)arg); 421 | break; 422 | case CN_GET_NETINFO: 423 | wizchip_getnetinfo((wiz_NetInfo*)arg); 424 | break; 425 | case CN_SET_NETMODE: 426 | wizchip_setnetmode(*(netmode_type*)arg); 427 | break; 428 | case CN_GET_NETMODE: 429 | *(netmode_type*)arg = wizchip_getnetmode(); 430 | break; 431 | case CN_SET_TIMEOUT: 432 | wizchip_settimeout((wiz_NetTimeout*)arg); 433 | break; 434 | case CN_GET_TIMEOUT: 435 | wizchip_gettimeout((wiz_NetTimeout*)arg); 436 | break; 437 | case CN_SET_PREFER: 438 | setSLPSR(*(uint8_t*)arg); 439 | break; 440 | case CN_GET_PREFER: 441 | *(uint8_t*)arg= getSLPSR(); 442 | break; 443 | default: 444 | return -1; 445 | } 446 | return 0; 447 | } 448 | 449 | int8_t ctlnetservice(ctlnetservice_type cnstype, void* arg) 450 | { 451 | switch(cnstype) 452 | { 453 | case CNS_ARP: 454 | return wizchip_arp((wiz_ARP*)arg); 455 | case CNS_PING: 456 | return wizchip_ping((wiz_PING*)arg); 457 | case CNS_DAD: 458 | return wizchip_dad((uint8_t*)arg); 459 | case CNS_SLAAC: 460 | return wizchip_slaac((wiz_Prefix*)arg); 461 | case CNS_UNSOL_NA: 462 | return wizchip_unsolicited(); 463 | case CNS_GET_PREFIX: 464 | return wizchip_getprefix((wiz_Prefix*)arg); 465 | default: 466 | return -1; 467 | break; 468 | } 469 | } 470 | 471 | void wizchip_sw_reset(void) 472 | { 473 | uint8_t gw[4], sn[4], sip[4], gw6[16], sn6[16], lla[16], gua[16]; 474 | uint8_t mac[6]; 475 | uint8_t islock = getSYSR(); 476 | 477 | CHIPUNLOCK(); 478 | 479 | getSHAR(mac); 480 | getGAR(gw); getSUBR(sn); getSIPR(sip); getGA6R(gw6); getSUB6R(sn6); getLLAR(lla); getGUAR(gua); 481 | setSYCR0(SYCR0_RST); 482 | getSYCR0(); // for delay 483 | 484 | NETUNLOCK(); 485 | 486 | setSHAR(mac); 487 | setGAR(gw); 488 | setSUBR(sn); 489 | setSIPR(sip); 490 | setGA6R(gw6); 491 | setSUB6R(sn6); 492 | setLLAR(lla); 493 | setGUAR(gua); 494 | if(islock & SYSR_CHPL) CHIPLOCK(); 495 | if(islock & SYSR_NETL) NETLOCK(); 496 | } 497 | 498 | int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) 499 | { 500 | int8_t i; 501 | int8_t tmp = 0; 502 | wizchip_sw_reset(); 503 | if(txsize) 504 | { 505 | tmp = 0; 506 | for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) 507 | { 508 | tmp += txsize[i]; 509 | if(tmp > 2*_WIZCHIP_SOCK_NUM_) return -1; 510 | } 511 | for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) setSn_TXBUF_SIZE(i, txsize[i]); 512 | } 513 | if(rxsize) 514 | { 515 | tmp = 0; 516 | for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) 517 | { 518 | tmp += rxsize[i]; 519 | if(tmp > 2*_WIZCHIP_SOCK_NUM_) return -1; 520 | } 521 | for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) setSn_RXBUF_SIZE(i, rxsize[i]); 522 | } 523 | return 0; 524 | } 525 | 526 | void wizchip_clrinterrupt(intr_kind intr) 527 | { 528 | int i; 529 | uint8_t ir = (uint8_t)intr; 530 | uint8_t sir = (uint8_t)((uint32_t)intr >> 8); 531 | uint8_t slir = (uint8_t)((uint32_t)intr >> 16); 532 | setIRCLR(ir); 533 | for(i=0; i<_WIZCHIP_SOCK_NUM_; i++) 534 | { 535 | if(sir&(1<> 8); 551 | uint8_t slimr = (uint8_t)((uint32_t)intr >> 16); 552 | setIMR(imr); 553 | setSIMR(simr); 554 | setSLIMR(slimr); 555 | } 556 | 557 | intr_kind wizchip_getinterruptmask(void) 558 | { 559 | uint32_t ret; 560 | ret = (((uint32_t)getSLIMR())<<16) | (((uint32_t)getSIMR())<<8) | (((uint32_t)getIMR())); 561 | return (intr_kind)ret; 562 | } 563 | 564 | int8_t wizphy_getphylink(void) 565 | { 566 | #if (_PHY_IO_MODE_ == _PHY_IO_MODE_PHYCR_) 567 | return (getPHYSR() & PHYSR_LNK); 568 | #elif (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_) 569 | if(wiz_mdio_read(PHYRAR_BMSR) & BMSR_LINK_STATUS) return PHY_LINK_ON; 570 | return PHY_LINK_OFF; 571 | #endif 572 | } 573 | 574 | void wizphy_reset(void) 575 | { 576 | #if (_PHY_IO_MODE_ == _PHY_IO_MODE_PHYCR_) 577 | uint8_t tmp = getPHYCR1() | PHYCR1_RST; 578 | PHYUNLOCK(); 579 | setPHYCR1(tmp); 580 | PHYLOCK(); 581 | #elif (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_) 582 | wiz_mdio_write(PHYRAR_BMCR, wiz_mdio_read(PHYRAR_BMCR) | BMCR_RST); 583 | while(wiz_mdio_read(PHYRAR_BMCR) & BMCR_RST); 584 | #endif 585 | } 586 | 587 | void wizphy_setphyconf(wiz_PhyConf* phyconf) 588 | { 589 | #if (_PHY_IO_MODE_ == _PHY_IO_MODE_PHYCR_) 590 | uint8_t tmp = 0; 591 | if(phyconf->mode == PHY_MODE_TE) 592 | { 593 | setPHYCR1(getPHYCR1() | PHYCR1_TE); 594 | tmp = PHYCR0_AUTO; 595 | } 596 | else 597 | { 598 | setPHYCR1(getPHYCR1() & ~PHYCR1_TE); 599 | if(phyconf->mode == PHY_MODE_AUTONEGO) tmp = PHYCR0_AUTO; 600 | else 601 | { 602 | tmp |= 0x04; 603 | if(phyconf->speed == PHY_SPEED_10) tmp |= 0x02; 604 | if(phyconf->duplex == PHY_DUPLEX_HALF) tmp |= 0x01; 605 | } 606 | } 607 | setPHYCR0(tmp); 608 | #elif (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_) 609 | uint16_t tmp = wiz_mdio_read(PHYRAR_BMCR); 610 | if(phyconf->mode == PHY_MODE_TE) 611 | { 612 | setPHYCR1(getPHYC1R() | PHYCR1_TE); 613 | setPHYCR0(PHYCR0_AUTO); 614 | } 615 | else 616 | { 617 | setPHYCR1(getPHYC1R() & ~PHYCR1_TE); 618 | if(phyconf->mode == PHY_MODE_AUTONEGO) tmp |= BMCR_ANE; 619 | else 620 | { 621 | tmp &= ~(BMCR_ANE|BMCR_DPX|BMCR_SPD); 622 | if(phyconf->duplex == PHY_DUPLEX_FULL) tmp |= BMCR_DPX; 623 | if(phyconf->speed == PHY_SPEED_100) tmp |= BMCR_SPD; 624 | } 625 | wiz_mdio_write(PHYRAR_BMCR, tmp); 626 | } 627 | #endif 628 | } 629 | 630 | void wizphy_getphyconf(wiz_PhyConf* phyconf) 631 | { 632 | #if (_PHY_IO_MODE_ == _PHY_IO_MODE_PHYCR_) 633 | uint8_t tmp = 0; 634 | tmp = getPHYSR(); 635 | if(getPHYCR1() & PHYCR1_TE) phyconf->mode = PHY_MODE_TE; 636 | else phyconf->mode = (tmp & (1<<5)) ? PHY_MODE_MANUAL : PHY_MODE_AUTONEGO ; 637 | phyconf->speed = (tmp & (1<<4)) ? PHY_SPEED_10 : PHY_SPEED_100; 638 | phyconf->duplex = (tmp & (1<<3)) ? PHY_DUPLEX_HALF : PHY_DUPLEX_FULL; 639 | #elif (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_) 640 | uint16_t tmp = 0; 641 | tmp = wiz_mdio_read(PHYRAR_BMCR); 642 | if(getPHYCR1() & PHYCR1_TE) phyconf->mode = PHY_MODE_TE; 643 | else phyconf->mode = (tmp & BMCR_ANE) ? PHY_MODE_AUTONEGO : PHY_MODE_MANUAL; 644 | phyconf->duplex = (tmp & BMCR_DPX) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; 645 | phyconf->speed = (tmp & BMCR_SPD) ? PHY_SPEED_100 : PHY_SPEED_10; 646 | #endif 647 | } 648 | 649 | void wizphy_getphystatus(wiz_PhyConf* phyconf) 650 | { 651 | uint8_t tmp = 0; 652 | tmp = getPHYSR(); 653 | if(getPHYCR1() & PHYCR1_TE) phyconf->mode = PHY_MODE_TE; 654 | else phyconf->mode = (tmp & (1<<5)) ? PHY_MODE_MANUAL : PHY_MODE_AUTONEGO ; 655 | phyconf->speed = (tmp & PHYSR_SPD) ? PHY_SPEED_10 : PHY_SPEED_100; 656 | phyconf->duplex = (tmp & PHYSR_DPX) ? PHY_DUPLEX_HALF : PHY_DUPLEX_FULL; 657 | } 658 | 659 | void wizphy_setphypmode(uint8_t pmode) 660 | { 661 | #if (_PHY_IO_MODE_ == _PHY_IO_MODE_PHYCR_) 662 | uint8_t tmp = getPHYCR1(); 663 | if (pmode == PHY_POWER_DOWN) tmp |= PHYCR1_PWDN; 664 | else tmp &= ~PHYCR1_PWDN; 665 | setPHYCR1(tmp); 666 | #elif (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_) 667 | uint16_t tmp = 0; 668 | tmp = wiz_mdio_read(PHYRAR_BMCR); 669 | if (pmode == PHY_POWER_DOWN) tmp |= BMCR_PWDN; 670 | else tmp &= ~BMCR_PWDN; 671 | wiz_mdio_write(PHYRAR_BMCR, tmp); 672 | #endif 673 | } 674 | 675 | int8_t wizphy_getphypmode(void) 676 | { 677 | #if (_PHY_IO_MODE_ == _PHY_IO_MODE_PHYCR_) 678 | if (getPHYCR1() & PHYCR1_PWDN) return PHY_POWER_DOWN; 679 | #elif (_PHY_IO_MODE_ == _PHY_IO_MODE_MII_) 680 | if (wiz_mdio_read(PHYRAR_BMCR) & BMCR_PWDN) return PHY_POWER_DOWN; 681 | #endif 682 | return PHY_POWER_NORM; 683 | } 684 | 685 | void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) 686 | { 687 | uint8_t i=0; 688 | setSHAR(pnetinfo->mac); 689 | setGAR(pnetinfo->gw); 690 | setSUBR(pnetinfo->sn); 691 | setSIPR(pnetinfo->ip); 692 | setGA6R(pnetinfo->gw6); 693 | setSUB6R(pnetinfo->sn6); 694 | setLLAR(pnetinfo->lla); 695 | setGUAR(pnetinfo->gua); 696 | 697 | for(i=0; i<4; i++) _DNS_[i] = pnetinfo->dns[i]; 698 | for(i=0; i<16; i++) _DNS6_[i] = pnetinfo->dns6[i]; 699 | 700 | _IPMODE_ = pnetinfo->ipmode; 701 | } 702 | 703 | void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) 704 | { 705 | uint8_t i = 0; 706 | getSHAR(pnetinfo->mac); 707 | 708 | getGAR(pnetinfo->gw); 709 | getSUBR(pnetinfo->sn); 710 | getSIPR(pnetinfo->ip); 711 | 712 | getGA6R(pnetinfo->gw6); 713 | getSUB6R(pnetinfo->sn6); 714 | getLLAR(pnetinfo->lla); 715 | getGUAR(pnetinfo->gua); 716 | for(i=0; i<4; i++) pnetinfo->dns[i] = _DNS_[i]; 717 | for(i=0; i<16; i++) pnetinfo->dns6[i] = _DNS6_[i]; 718 | 719 | pnetinfo->ipmode = _IPMODE_; 720 | } 721 | 722 | void wizchip_setnetmode(netmode_type netmode) 723 | { 724 | uint32_t tmp = (uint32_t) netmode; 725 | setNETMR ((uint8_t)tmp); 726 | setNETMR2((uint8_t)(tmp>>8)); 727 | setNET4MR((uint8_t)(tmp>>16)); 728 | setNET6MR((uint8_t)(tmp>>24)); 729 | } 730 | 731 | netmode_type wizchip_getnetmode(void) 732 | { 733 | uint32_t ret = 0; 734 | ret = getNETMR(); 735 | ret = (ret << 8) + getNETMR2(); 736 | ret = (ret << 16) + getNET4MR(); 737 | ret = (ret << 24) + getNET6MR(); 738 | return (netmode_type)ret; 739 | } 740 | 741 | void wizchip_settimeout(wiz_NetTimeout* nettime) 742 | { 743 | setRCR(nettime->s_retry_cnt); 744 | setRTR(nettime->s_time_100us); 745 | setSLRCR(nettime->sl_retry_cnt); 746 | setSLRTR(nettime->sl_time_100us); 747 | } 748 | 749 | void wizchip_gettimeout(wiz_NetTimeout* nettime) 750 | { 751 | nettime->s_retry_cnt = getRCR(); 752 | nettime->s_time_100us = getRTR(); 753 | nettime->sl_retry_cnt = getSLRCR(); 754 | nettime->sl_time_100us = getSLRTR(); 755 | } 756 | 757 | int8_t wizchip_arp(wiz_ARP* arp) 758 | { 759 | uint8_t tmp; 760 | if(arp->destinfo.len == 16) 761 | { 762 | setSLDIP6R(arp->destinfo.ip); 763 | setSLCR(SLCR_ARP6); 764 | } 765 | else 766 | { 767 | setSLDIP4R(arp->destinfo.ip); 768 | setSLCR(SLCR_ARP4); 769 | } 770 | while(getSLCR()); 771 | while((tmp = getSLIR()) == 0x00); 772 | setSLIRCLR(~SLIR_RA); 773 | if(tmp & (SLIR_ARP4 | SLIR_ARP6)) 774 | { 775 | getSLDHAR(arp->dha); 776 | return 0; 777 | } 778 | return -1; 779 | } 780 | 781 | int8_t wizchip_ping(wiz_PING* ping) 782 | { 783 | uint8_t tmp; 784 | setPINGIDR(ping->id); 785 | setPINGSEQR(ping->seq); 786 | if(ping->destinfo.len == 16) 787 | { 788 | setSLDIP6R(ping->destinfo.ip); 789 | setSLCR(SLCR_PING6); 790 | } 791 | else 792 | { 793 | setSLDIP4R(ping->destinfo.ip); 794 | setSLCR(SLCR_PING4); 795 | } 796 | while(getSLCR()); 797 | while((tmp = getSLIR()) == 0x00); 798 | setSLIRCLR(~SLIR_RA); 799 | if(tmp & (SLIR_PING4 | SLIR_PING6)) return 0; 800 | return -1; 801 | } 802 | 803 | int8_t wizchip_dad(uint8_t* ipv6) 804 | { 805 | uint8_t tmp; 806 | setSLDIP6R(ipv6); 807 | setSLCR(SLCR_NS); 808 | while(getSLCR()); 809 | while((tmp = getSLIR()) == 0x00); 810 | setSLIRCLR(~SLIR_RA); 811 | if(tmp & SLIR_TOUT) return 0; 812 | return -1; 813 | } 814 | 815 | int8_t wizchip_slaac(wiz_Prefix* prefix) 816 | { 817 | uint8_t tmp; 818 | setSLCR(SLCR_RS); 819 | while(getSLCR()); 820 | while((tmp = getSLIR()) == 0x00); 821 | setSLIRCLR(~SLIR_RA); 822 | if(tmp & SLIR_RS) 823 | { 824 | prefix->len = getPLR(); 825 | prefix->flag = getPFR(); 826 | prefix->valid_lifetime = getVLTR(); 827 | prefix->preferred_lifetime = getPLTR(); 828 | getPAR(prefix->prefix); 829 | return 0; 830 | } 831 | return -1; 832 | } 833 | 834 | int8_t wizchip_unsolicited(void) 835 | { 836 | uint8_t tmp; 837 | setSLCR(SLCR_UNA); 838 | while(getSLCR()); 839 | while((tmp = getSLIR()) == 0x00); 840 | setSLIRCLR(~SLIR_RA); 841 | if(tmp & SLIR_TOUT) return 0; 842 | return -1; 843 | } 844 | 845 | int8_t wizchip_getprefix(wiz_Prefix * prefix) 846 | { 847 | if(getSLIR() & SLIR_RA) 848 | { 849 | prefix->len = getPLR(); 850 | prefix->flag = getPFR(); 851 | prefix->valid_lifetime = getVLTR(); 852 | prefix->preferred_lifetime = getPLTR(); 853 | getPAR(prefix->prefix); 854 | setSLIRCLR(SLIR_RA); 855 | } 856 | return -1; 857 | } 858 | -------------------------------------------------------------------------------- /Internet/DHCP4/dhcpv4.c: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | //! \file dhcpv4.c 4 | //! \brief DHCP APIs implement file. 5 | //! \details Processing DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. 6 | //! \version 1.1.1 7 | //! \date 2019/10/08 8 | //! \par Revision history 9 | //! <2019/10/08> compare DHCP server ip address 10 | //! <2013/11/18> 1st Release 11 | //! <2012/12/20> V1.1.0 12 | //! 1. Optimize code 13 | //! 2. Add reg_dhcpv4_cbfunc() 14 | //! 3. Add DHCPv4_stop() 15 | //! 4. Integrate check_DHCPv4_state() & DHCPv4_run() to DHCPv4_run() 16 | //! 5. Don't care system endian 17 | //! 6. Add comments 18 | //! <2012/12/26> V1.1.1 19 | //! 1. Modify variable declaration: dhcpv4_tick_1s is declared volatile for code optimization 20 | //! \author Eric Jung & MidnightCow 21 | //! \copyright 22 | //! 23 | //! Copyright (c) 2013, WIZnet Co., LTD. 24 | //! All rights reserved. 25 | //! 26 | //! Redistribution and use in source and binary forms, with or without 27 | //! modification, are permitted provided that the following conditions 28 | //! are met: 29 | //! 30 | //! * Redistributions of source code must retain the above copyright 31 | //! notice, this list of conditions and the following disclaimer. 32 | //! * Redistributions in binary form must reproduce the above copyright 33 | //! notice, this list of conditions and the following disclaimer in the 34 | //! documentation and/or other materials provided with the distribution. 35 | //! * Neither the name of the nor the names of its 36 | //! contributors may be used to endorse or promote products derived 37 | //! from this software without specific prior written permission. 38 | //! 39 | //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 40 | //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 | //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 42 | //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 43 | //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 44 | //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 45 | //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 46 | //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 47 | //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48 | //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 49 | //! THE POSSIBILITY OF SUCH DAMAGE. 50 | // 51 | //***************************************************************************** 52 | 53 | #include "socket.h" 54 | #include "dhcpv4.h" 55 | 56 | /* If you want to display debug & processing message, Define _DHCPV4_DEBUG_ in dhcp.h */ 57 | 58 | #ifdef _DHCPV4_DEBUG_ 59 | #include 60 | #endif 61 | 62 | /* DHCP state machine. */ 63 | #define STATE_DHCPV4_INIT 0 ///< Initialize 64 | #define STATE_DHCPV4_DISCOVER 1 ///< send DISCOVER and wait OFFER 65 | #define STATE_DHCPV4_REQUEST 2 ///< send REQEUST and wait ACK or NACK 66 | #define STATE_DHCPV4_LEASED 3 ///< ReceiveD ACK and IP leased 67 | #define STATE_DHCPV4_REREQUEST 4 ///< send REQUEST for maintaining leased IP 68 | #define STATE_DHCPV4_RELEASE 5 ///< No use 69 | #define STATE_DHCPV4_STOP 6 ///< Stop processing DHCP 70 | 71 | #define DHCPV4_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG 72 | #define DHCPV4_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG 73 | 74 | /* DHCP message OP code */ 75 | #define DHCPV4_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG 76 | #define DHCPV4_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG 77 | 78 | /* DHCP message type */ 79 | #define DHCPV4_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG 80 | #define DHCPV4_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG 81 | #define DHCPV4_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG 82 | #define DHCPV4_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG 83 | #define DHCPV4_ACK 5 ///< ACK message in OPT of @ref RIP_MSG 84 | #define DHCPV4_NAK 6 ///< NACK message in OPT of @ref RIP_MSG 85 | #define DHCPV4_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use 86 | #define DHCPV4_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use 87 | 88 | #define DHCPV4_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG 89 | #define DHCPV4_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG 90 | 91 | #define DHCPV4_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG 92 | #define DHCPV4_HOPS 0 ///< Used in hops of @ref RIP_MSG 93 | #define DHCPV4_SECS 0 ///< Used in secs of @ref RIP_MSG 94 | 95 | #define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time 96 | 97 | #define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG 98 | #define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG 99 | 100 | /* 101 | * @brief DHCP option and value (cf. RFC1533) 102 | */ 103 | enum 104 | { 105 | padOption = 0, 106 | subnetMask = 1, 107 | timerOffset = 2, 108 | routersOnSubnet = 3, 109 | timeServer = 4, 110 | nameServer = 5, 111 | dns = 6, 112 | logServer = 7, 113 | cookieServer = 8, 114 | lprServer = 9, 115 | impressServer = 10, 116 | resourceLocationServer = 11, 117 | hostName = 12, 118 | bootFileSize = 13, 119 | meritDumpFile = 14, 120 | domainName = 15, 121 | swapServer = 16, 122 | rootPath = 17, 123 | extentionsPath = 18, 124 | IPforwarding = 19, 125 | nonLocalSourceRouting = 20, 126 | policyFilter = 21, 127 | maxDgramReasmSize = 22, 128 | defaultIPTTL = 23, 129 | pathMTUagingTimeout = 24, 130 | pathMTUplateauTable = 25, 131 | ifMTU = 26, 132 | allSubnetsLocal = 27, 133 | broadcastAddr = 28, 134 | performMaskDiscovery = 29, 135 | maskSupplier = 30, 136 | performRouterDiscovery = 31, 137 | routerSolicitationAddr = 32, 138 | staticRoute = 33, 139 | trailerEncapsulation = 34, 140 | arpCacheTimeout = 35, 141 | ethernetEncapsulation = 36, 142 | tcpDefaultTTL = 37, 143 | tcpKeepaliveInterval = 38, 144 | tcpKeepaliveGarbage = 39, 145 | nisDomainName = 40, 146 | nisServers = 41, 147 | ntpServers = 42, 148 | vendorSpecificInfo = 43, 149 | netBIOSnameServer = 44, 150 | netBIOSdgramDistServer = 45, 151 | netBIOSnodeType = 46, 152 | netBIOSscope = 47, 153 | xFontServer = 48, 154 | xDisplayManager = 49, 155 | dhcpRequestedIPaddr = 50, 156 | dhcpIPaddrLeaseTime = 51, 157 | dhcpOptionOverload = 52, 158 | dhcpMessageType = 53, 159 | dhcpServerIdentifier = 54, 160 | dhcpParamRequest = 55, 161 | dhcpMsg = 56, 162 | dhcpMaxMsgSize = 57, 163 | dhcpT1value = 58, 164 | dhcpT2value = 59, 165 | dhcpClassIdentifier = 60, 166 | dhcpClientIdentifier = 61, 167 | endOption = 255 168 | }; 169 | 170 | /* 171 | * @brief DHCP message format 172 | */ 173 | typedef struct { 174 | uint8_t op; ///< @ref DHCPV4_BOOTREQUEST or @ref DHCPV4_BOOTREPLY 175 | uint8_t htype; ///< @ref DHCPV4_HTYPE10MB or @ref DHCPV4_HTYPE100MB 176 | uint8_t hlen; ///< @ref DHCPV4_HLENETHERNET 177 | uint8_t hops; ///< @ref DHCPV4_HOPS 178 | uint32_t xid; ///< @ref DHCPV4_XID This increase one every DHCP transaction. 179 | uint16_t secs; ///< @ref DHCPV4_SECS 180 | uint16_t flags; ///< @ref DHCPV4_FLAGSBROADCAST or @ref DHCPV4_FLAGSUNICAST 181 | uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever 182 | uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server 183 | uint8_t siaddr[4]; ///< No use 184 | uint8_t giaddr[4]; ///< No use 185 | uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero 186 | uint8_t sname[64]; ///< No use 187 | uint8_t file[128]; ///< No use 188 | uint8_t OPT[OPT_SIZE]; ///< Option 189 | } RIP_MSG; 190 | 191 | 192 | 193 | uint8_t DHCPV4_SOCKET; // Socket number for DHCP 194 | 195 | uint8_t DHCPV4_SIP[4]; // DHCP Server IP address 196 | uint8_t DHCPV4_REAL_SIP[4]; // For extract my DHCP server in a few DHCP server 197 | 198 | // Network information from DHCP Server 199 | uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address 200 | uint8_t DHCPv4_allocated_ip[4] = {0, }; // IP address from DHCP 201 | uint8_t DHCPv4_allocated_gw[4] = {0, }; // Gateway address from DHCP 202 | uint8_t DHCPv4_allocated_sn[4] = {0, }; // Subnet mask from DHCP 203 | uint8_t DHCPv4_allocated_dns[4] = {0, }; // DNS address from DHCP 204 | 205 | 206 | int8_t dhcpv4_state = STATE_DHCPV4_INIT; // DHCP state 207 | int8_t dhcpv4_retry_count = 0; 208 | 209 | uint32_t dhcpv4_lease_time = INFINITE_LEASETIME; 210 | volatile uint32_t dhcpv4_tick_1s = 0; // unit 1 second 211 | uint32_t dhcpv4_tick_next = DHCPV4_WAIT_TIME ; 212 | 213 | uint32_t DHCPV4_XID; // Any number 214 | 215 | RIP_MSG* pDHCPv4MSG; // Buffer pointer for DHCP processing 216 | 217 | uint8_t HOST_NAMEv4[] = DCHPV4_HOST_NAME; 218 | 219 | uint8_t DHCPv4_CHADDR[6]; // DHCP Client MAC address. 220 | 221 | /* The default callback function */ 222 | void default_ipv4_assign(void); 223 | void default_ipv4_update(void); 224 | void default_ipv4_conflict(void); 225 | 226 | /* Callback handler */ 227 | void (*dhcp_ipv4_assign)(void) = default_ipv4_assign; /* handler to be called when the IP address from DHCP server is first assigned */ 228 | void (*dhcp_ipv4_update)(void) = default_ipv4_update; /* handler to be called when the IP address from DHCP server is updated */ 229 | void (*dhcp_ipv4_conflict)(void) = default_ipv4_conflict; /* handler to be called when the IP address from DHCP server is conflict */ 230 | 231 | void reg_dhcpv4_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); 232 | 233 | char NibbleToHex(uint8_t nibble); 234 | 235 | /* send DISCOVER message to DHCP server */ 236 | void send_DHCPv4_DISCOVER(void); 237 | 238 | /* send REQEUST message to DHCP server */ 239 | void send_DHCPv4_REQUEST(void); 240 | 241 | /* send DECLINE message to DHCP server */ 242 | void send_DHCPv4_DECLINE(void); 243 | 244 | /* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ 245 | int8_t check_DHCPv4_leasedIP(void); 246 | 247 | /* check the timeout in DHCP process */ 248 | uint8_t check_DHCPv4_timeout(void); 249 | 250 | /* Initialize to timeout process. */ 251 | void reset_DHCPv4_timeout(void); 252 | 253 | /* Parse message as OFFER and ACK and NACK from DHCP server.*/ 254 | int8_t parseDHCPCMSG(void); 255 | 256 | /* The default handler of ip assign first */ 257 | void default_ipv4_assign(void) 258 | { 259 | setSIPR(DHCPv4_allocated_ip); 260 | setSUBR(DHCPv4_allocated_sn); 261 | setGAR (DHCPv4_allocated_gw); 262 | } 263 | 264 | /* The default handler of ip changed */ 265 | void default_ipv4_update(void) 266 | { 267 | /* WIZchip Software Reset */ 268 | setSYCR0(SYCR0_RST); 269 | getSYCR0(); // for delay 270 | default_ipv4_assign(); 271 | setSHAR(DHCPv4_CHADDR); 272 | } 273 | 274 | /* The default handler of ip changed */ 275 | void default_ipv4_conflict(void) 276 | { 277 | // WIZchip Software Reset 278 | setSYCR0(SYCR0_RST); 279 | getSYCR0(); // for delay 280 | setSHAR(DHCPv4_CHADDR); 281 | } 282 | 283 | /* register the call back func. */ 284 | void reg_dhcpv4_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) 285 | { 286 | dhcp_ipv4_assign = default_ipv4_assign; 287 | dhcp_ipv4_update = default_ipv4_update; 288 | dhcp_ipv4_conflict = default_ipv4_conflict; 289 | if(ip_assign) dhcp_ipv4_assign = ip_assign; 290 | if(ip_update) dhcp_ipv4_update = ip_update; 291 | if(ip_conflict) dhcp_ipv4_conflict = ip_conflict; 292 | } 293 | 294 | /* make the common DHCP message */ 295 | void makeDHCPV4MSG(void) 296 | { 297 | uint8_t bk_mac[6]; 298 | uint8_t* ptmp; 299 | uint8_t i; 300 | getSHAR(bk_mac); 301 | pDHCPv4MSG->op = DHCPV4_BOOTREQUEST; 302 | pDHCPv4MSG->htype = DHCPV4_HTYPE10MB; 303 | pDHCPv4MSG->hlen = DHCPV4_HLENETHERNET; 304 | pDHCPv4MSG->hops = DHCPV4_HOPS; 305 | ptmp = (uint8_t*)(&pDHCPv4MSG->xid); 306 | *(ptmp+0) = (uint8_t)((DHCPV4_XID & 0xFF000000) >> 24); 307 | *(ptmp+1) = (uint8_t)((DHCPV4_XID & 0x00FF0000) >> 16); 308 | *(ptmp+2) = (uint8_t)((DHCPV4_XID & 0x0000FF00) >> 8); 309 | *(ptmp+3) = (uint8_t)((DHCPV4_XID & 0x000000FF) >> 0); 310 | pDHCPv4MSG->secs = DHCPV4_SECS; 311 | ptmp = (uint8_t*)(&pDHCPv4MSG->flags); 312 | *(ptmp+0) = (uint8_t)((DHCPV4_FLAGSBROADCAST & 0xFF00) >> 8); 313 | *(ptmp+1) = (uint8_t)((DHCPV4_FLAGSBROADCAST & 0x00FF) >> 0); 314 | 315 | pDHCPv4MSG->ciaddr[0] = 0; 316 | pDHCPv4MSG->ciaddr[1] = 0; 317 | pDHCPv4MSG->ciaddr[2] = 0; 318 | pDHCPv4MSG->ciaddr[3] = 0; 319 | 320 | pDHCPv4MSG->yiaddr[0] = 0; 321 | pDHCPv4MSG->yiaddr[1] = 0; 322 | pDHCPv4MSG->yiaddr[2] = 0; 323 | pDHCPv4MSG->yiaddr[3] = 0; 324 | 325 | pDHCPv4MSG->siaddr[0] = 0; 326 | pDHCPv4MSG->siaddr[1] = 0; 327 | pDHCPv4MSG->siaddr[2] = 0; 328 | pDHCPv4MSG->siaddr[3] = 0; 329 | 330 | pDHCPv4MSG->giaddr[0] = 0; 331 | pDHCPv4MSG->giaddr[1] = 0; 332 | pDHCPv4MSG->giaddr[2] = 0; 333 | pDHCPv4MSG->giaddr[3] = 0; 334 | 335 | pDHCPv4MSG->chaddr[0] = DHCPv4_CHADDR[0]; 336 | pDHCPv4MSG->chaddr[1] = DHCPv4_CHADDR[1]; 337 | pDHCPv4MSG->chaddr[2] = DHCPv4_CHADDR[2]; 338 | pDHCPv4MSG->chaddr[3] = DHCPv4_CHADDR[3]; 339 | pDHCPv4MSG->chaddr[4] = DHCPv4_CHADDR[4]; 340 | pDHCPv4MSG->chaddr[5] = DHCPv4_CHADDR[5]; 341 | 342 | for (i = 6; i < 16; i++) pDHCPv4MSG->chaddr[i] = 0; 343 | for (i = 0; i < 64; i++) pDHCPv4MSG->sname[i] = 0; 344 | for (i = 0; i < 128; i++) pDHCPv4MSG->file[i] = 0; 345 | 346 | // MAGIC_COOKIE 347 | pDHCPv4MSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); 348 | pDHCPv4MSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); 349 | pDHCPv4MSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8); 350 | pDHCPv4MSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0; 351 | } 352 | 353 | /* SEND DHCP DISCOVER */ 354 | void send_DHCPv4_DISCOVER(void) 355 | { 356 | uint16_t i; 357 | uint8_t ip[4]; 358 | uint16_t k = 0; 359 | 360 | makeDHCPV4MSG(); 361 | DHCPV4_SIP[0]=0; 362 | DHCPV4_SIP[1]=0; 363 | DHCPV4_SIP[2]=0; 364 | DHCPV4_SIP[3]=0; 365 | DHCPV4_REAL_SIP[0]=0; 366 | DHCPV4_REAL_SIP[1]=0; 367 | DHCPV4_REAL_SIP[2]=0; 368 | DHCPV4_REAL_SIP[3]=0; 369 | 370 | k = 4; // because MAGIC_COOKIE already made by makeDHCPV4MSG() 371 | 372 | // Option Request Param 373 | pDHCPv4MSG->OPT[k++] = dhcpMessageType; 374 | pDHCPv4MSG->OPT[k++] = 0x01; 375 | pDHCPv4MSG->OPT[k++] = DHCPV4_DISCOVER; 376 | 377 | // Client identifier 378 | pDHCPv4MSG->OPT[k++] = dhcpClientIdentifier; 379 | pDHCPv4MSG->OPT[k++] = 0x07; 380 | pDHCPv4MSG->OPT[k++] = 0x01; 381 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[0]; 382 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[1]; 383 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[2]; 384 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[3]; 385 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[4]; 386 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[5]; 387 | 388 | // host name 389 | pDHCPv4MSG->OPT[k++] = hostName; 390 | pDHCPv4MSG->OPT[k++] = 0; // fill zero length of hostname 391 | for(i = 0 ; HOST_NAMEv4[i] != 0; i++) 392 | pDHCPv4MSG->OPT[k++] = HOST_NAMEv4[i]; 393 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[3] >> 4); 394 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[3]); 395 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[4] >> 4); 396 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[4]); 397 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[5] >> 4); 398 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[5]); 399 | pDHCPv4MSG->OPT[k - (i+6+1)] = i+6; // length of hostname 400 | 401 | pDHCPv4MSG->OPT[k++] = dhcpParamRequest; 402 | pDHCPv4MSG->OPT[k++] = 0x06; // length of request 403 | pDHCPv4MSG->OPT[k++] = subnetMask; 404 | pDHCPv4MSG->OPT[k++] = routersOnSubnet; 405 | pDHCPv4MSG->OPT[k++] = dns; 406 | pDHCPv4MSG->OPT[k++] = domainName; 407 | pDHCPv4MSG->OPT[k++] = dhcpT1value; 408 | pDHCPv4MSG->OPT[k++] = dhcpT2value; 409 | pDHCPv4MSG->OPT[k++] = endOption; 410 | 411 | for (i = k; i < OPT_SIZE; i++) pDHCPv4MSG->OPT[i] = 0; 412 | 413 | // send broadcasting packet 414 | ip[0] = 255; 415 | ip[1] = 255; 416 | ip[2] = 255; 417 | ip[3] = 255; 418 | 419 | #ifdef _DHCPV4_DEBUG_ 420 | printf("> Send DHCP_DISCOVER\r\n"); 421 | #endif 422 | 423 | sendto(DHCPV4_SOCKET, (uint8_t *)pDHCPv4MSG, RIP_MSG_SIZE, ip, DHCPV4_SERVER_PORT, 4); 424 | } 425 | 426 | /* SEND DHCP REQUEST */ 427 | void send_DHCPv4_REQUEST(void) 428 | { 429 | int i; 430 | uint8_t ip[4]; 431 | uint16_t k = 0; 432 | 433 | makeDHCPV4MSG(); 434 | 435 | if(dhcpv4_state == STATE_DHCPV4_LEASED || dhcpv4_state == STATE_DHCPV4_REREQUEST) 436 | { 437 | *((uint8_t*)(&pDHCPv4MSG->flags)) = ((DHCPV4_FLAGSUNICAST & 0xFF00)>> 8); 438 | *((uint8_t*)(&pDHCPv4MSG->flags)+1) = (DHCPV4_FLAGSUNICAST & 0x00FF); 439 | pDHCPv4MSG->ciaddr[0] = DHCPv4_allocated_ip[0]; 440 | pDHCPv4MSG->ciaddr[1] = DHCPv4_allocated_ip[1]; 441 | pDHCPv4MSG->ciaddr[2] = DHCPv4_allocated_ip[2]; 442 | pDHCPv4MSG->ciaddr[3] = DHCPv4_allocated_ip[3]; 443 | ip[0] = DHCPV4_SIP[0]; 444 | ip[1] = DHCPV4_SIP[1]; 445 | ip[2] = DHCPV4_SIP[2]; 446 | ip[3] = DHCPV4_SIP[3]; 447 | } 448 | else 449 | { 450 | ip[0] = 255; 451 | ip[1] = 255; 452 | ip[2] = 255; 453 | ip[3] = 255; 454 | } 455 | 456 | k = 4; // because MAGIC_COOKIE already made by makeDHCPV4MSG() 457 | 458 | // Option Request Param. 459 | pDHCPv4MSG->OPT[k++] = dhcpMessageType; 460 | pDHCPv4MSG->OPT[k++] = 0x01; 461 | pDHCPv4MSG->OPT[k++] = DHCPV4_REQUEST; 462 | 463 | pDHCPv4MSG->OPT[k++] = dhcpClientIdentifier; 464 | pDHCPv4MSG->OPT[k++] = 0x07; 465 | pDHCPv4MSG->OPT[k++] = 0x01; 466 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[0]; 467 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[1]; 468 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[2]; 469 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[3]; 470 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[4]; 471 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[5]; 472 | 473 | if(ip[3] == 255) // if(dchp_state == STATE_DHCPV4_LEASED || dchp_state == DHCP_REREQUEST_STATE) 474 | { 475 | pDHCPv4MSG->OPT[k++] = dhcpRequestedIPaddr; 476 | pDHCPv4MSG->OPT[k++] = 0x04; 477 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[0]; 478 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[1]; 479 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[2]; 480 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[3]; 481 | 482 | pDHCPv4MSG->OPT[k++] = dhcpServerIdentifier; 483 | pDHCPv4MSG->OPT[k++] = 0x04; 484 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[0]; 485 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[1]; 486 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[2]; 487 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[3]; 488 | } 489 | 490 | // host name 491 | pDHCPv4MSG->OPT[k++] = hostName; 492 | pDHCPv4MSG->OPT[k++] = 0; // length of hostname 493 | for(i = 0 ; HOST_NAMEv4[i] != 0; i++) 494 | pDHCPv4MSG->OPT[k++] = HOST_NAMEv4[i]; 495 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[3] >> 4); 496 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[3]); 497 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[4] >> 4); 498 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[4]); 499 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[5] >> 4); 500 | pDHCPv4MSG->OPT[k++] = NibbleToHex(DHCPv4_CHADDR[5]); 501 | pDHCPv4MSG->OPT[k - (i+6+1)] = i+6; // length of hostname 502 | 503 | pDHCPv4MSG->OPT[k++] = dhcpParamRequest; 504 | pDHCPv4MSG->OPT[k++] = 0x08; 505 | pDHCPv4MSG->OPT[k++] = subnetMask; 506 | pDHCPv4MSG->OPT[k++] = routersOnSubnet; 507 | pDHCPv4MSG->OPT[k++] = dns; 508 | pDHCPv4MSG->OPT[k++] = domainName; 509 | pDHCPv4MSG->OPT[k++] = dhcpT1value; 510 | pDHCPv4MSG->OPT[k++] = dhcpT2value; 511 | pDHCPv4MSG->OPT[k++] = performRouterDiscovery; 512 | pDHCPv4MSG->OPT[k++] = staticRoute; 513 | pDHCPv4MSG->OPT[k++] = endOption; 514 | 515 | for (i = k; i < OPT_SIZE; i++) pDHCPv4MSG->OPT[i] = 0; 516 | 517 | #ifdef _DHCPV4_DEBUG_ 518 | printf("> Send DHCP_REQUEST\r\n"); 519 | #endif 520 | 521 | sendto(DHCPV4_SOCKET, (uint8_t *)pDHCPv4MSG, RIP_MSG_SIZE, ip, DHCPV4_SERVER_PORT, 4); 522 | 523 | } 524 | 525 | /* SEND DHCP DHCPDECLINE */ 526 | void send_DHCPv4_DECLINE(void) 527 | { 528 | int i; 529 | uint8_t ip[4]; 530 | uint16_t k = 0; 531 | 532 | makeDHCPV4MSG(); 533 | 534 | k = 4; // because MAGIC_COOKIE already made by makeDHCPV4MSG() 535 | 536 | *((uint8_t*)(&pDHCPv4MSG->flags)) = ((DHCPV4_FLAGSUNICAST & 0xFF00)>> 8); 537 | *((uint8_t*)(&pDHCPv4MSG->flags)+1) = (DHCPV4_FLAGSUNICAST & 0x00FF); 538 | 539 | // Option Request Param. 540 | pDHCPv4MSG->OPT[k++] = dhcpMessageType; 541 | pDHCPv4MSG->OPT[k++] = 0x01; 542 | pDHCPv4MSG->OPT[k++] = DHCPV4_DECLINE; 543 | 544 | pDHCPv4MSG->OPT[k++] = dhcpClientIdentifier; 545 | pDHCPv4MSG->OPT[k++] = 0x07; 546 | pDHCPv4MSG->OPT[k++] = 0x01; 547 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[0]; 548 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[1]; 549 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[2]; 550 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[3]; 551 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[4]; 552 | pDHCPv4MSG->OPT[k++] = DHCPv4_CHADDR[5]; 553 | 554 | pDHCPv4MSG->OPT[k++] = dhcpRequestedIPaddr; 555 | pDHCPv4MSG->OPT[k++] = 0x04; 556 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[0]; 557 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[1]; 558 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[2]; 559 | pDHCPv4MSG->OPT[k++] = DHCPv4_allocated_ip[3]; 560 | 561 | pDHCPv4MSG->OPT[k++] = dhcpServerIdentifier; 562 | pDHCPv4MSG->OPT[k++] = 0x04; 563 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[0]; 564 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[1]; 565 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[2]; 566 | pDHCPv4MSG->OPT[k++] = DHCPV4_SIP[3]; 567 | 568 | pDHCPv4MSG->OPT[k++] = endOption; 569 | 570 | for (i = k; i < OPT_SIZE; i++) pDHCPv4MSG->OPT[i] = 0; 571 | 572 | //send broadcasting packet 573 | ip[0] = 0xFF; 574 | ip[1] = 0xFF; 575 | ip[2] = 0xFF; 576 | ip[3] = 0xFF; 577 | 578 | #ifdef _DHCPV4_DEBUG_ 579 | printf("\r\n> Send DHCPV4_DECLINE\r\n"); 580 | #endif 581 | 582 | sendto(DHCPV4_SOCKET, (uint8_t *)pDHCPv4MSG, RIP_MSG_SIZE, ip, DHCPV4_SERVER_PORT, 4); 583 | } 584 | 585 | /* PARSE REPLY pDHCPv4MSG */ 586 | int8_t parseDHCPv4MSG(void) 587 | { 588 | uint8_t svr_addr[6]; 589 | uint16_t svr_port; 590 | uint16_t len; 591 | 592 | uint8_t * p; 593 | uint8_t * e; 594 | uint8_t type = 0; 595 | uint8_t opt_len; 596 | uint8_t addr_len; 597 | 598 | if((len = getSn_RX_RSR(DHCPV4_SOCKET)) > 0) 599 | { 600 | len = recvfrom(DHCPV4_SOCKET, (uint8_t *)pDHCPv4MSG, len, svr_addr, &svr_port, &addr_len); 601 | #ifdef _DHCPV4_DEBUG_ 602 | printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len); 603 | #endif 604 | } 605 | else return 0; 606 | if (svr_port == DHCPV4_SERVER_PORT) { 607 | // compare mac address 608 | if ( (pDHCPv4MSG->chaddr[0] != DHCPv4_CHADDR[0]) || (pDHCPv4MSG->chaddr[1] != DHCPv4_CHADDR[1]) || 609 | (pDHCPv4MSG->chaddr[2] != DHCPv4_CHADDR[2]) || (pDHCPv4MSG->chaddr[3] != DHCPv4_CHADDR[3]) || 610 | (pDHCPv4MSG->chaddr[4] != DHCPv4_CHADDR[4]) || (pDHCPv4MSG->chaddr[5] != DHCPv4_CHADDR[5]) ) 611 | { 612 | #ifdef _DHCPV4_DEBUG_ 613 | printf("No My DHCP Message. This message is ignored.\r\n"); 614 | #endif 615 | return 0; 616 | } 617 | //compare DHCP server ip address 618 | if((DHCPV4_SIP[0]!=0) || (DHCPV4_SIP[1]!=0) || (DHCPV4_SIP[2]!=0) || (DHCPV4_SIP[3]!=0)){ 619 | if( ((svr_addr[0]!=DHCPV4_SIP[0])|| (svr_addr[1]!=DHCPV4_SIP[1])|| (svr_addr[2]!=DHCPV4_SIP[2])|| (svr_addr[3]!=DHCPV4_SIP[3])) && 620 | ((svr_addr[0]!=DHCPV4_REAL_SIP[0])|| (svr_addr[1]!=DHCPV4_REAL_SIP[1])|| (svr_addr[2]!=DHCPV4_REAL_SIP[2])|| (svr_addr[3]!=DHCPV4_REAL_SIP[3])) ) 621 | { 622 | #ifdef _DHCPV4_DEBUG_ 623 | printf("Another DHCP sever send a response message. This is ignored.\r\n"); 624 | #endif 625 | return 0; 626 | } 627 | } 628 | p = (uint8_t *)(&pDHCPv4MSG->op); 629 | p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) 630 | e = p + (len - 240); 631 | 632 | while ( p < e ) { 633 | 634 | switch ( *p ) { 635 | 636 | case endOption : 637 | p = e; // for break while(p < e) 638 | break; 639 | case padOption : 640 | p++; 641 | break; 642 | case dhcpMessageType : 643 | p++; 644 | p++; 645 | type = *p++; 646 | break; 647 | case subnetMask : 648 | p++; 649 | p++; 650 | DHCPv4_allocated_sn[0] = *p++; 651 | DHCPv4_allocated_sn[1] = *p++; 652 | DHCPv4_allocated_sn[2] = *p++; 653 | DHCPv4_allocated_sn[3] = *p++; 654 | break; 655 | case routersOnSubnet : 656 | p++; 657 | opt_len = *p++; 658 | DHCPv4_allocated_gw[0] = *p++; 659 | DHCPv4_allocated_gw[1] = *p++; 660 | DHCPv4_allocated_gw[2] = *p++; 661 | DHCPv4_allocated_gw[3] = *p++; 662 | p = p + (opt_len - 4); 663 | break; 664 | case dns : 665 | p++; 666 | opt_len = *p++; 667 | DHCPv4_allocated_dns[0] = *p++; 668 | DHCPv4_allocated_dns[1] = *p++; 669 | DHCPv4_allocated_dns[2] = *p++; 670 | DHCPv4_allocated_dns[3] = *p++; 671 | p = p + (opt_len - 4); 672 | break; 673 | case dhcpIPaddrLeaseTime : 674 | p++; 675 | opt_len = *p++; 676 | dhcpv4_lease_time = *p++; 677 | dhcpv4_lease_time = (dhcpv4_lease_time << 8) + *p++; 678 | dhcpv4_lease_time = (dhcpv4_lease_time << 8) + *p++; 679 | dhcpv4_lease_time = (dhcpv4_lease_time << 8) + *p++; 680 | #ifdef _DHCPV4_DEBUG_ 681 | dhcpv4_lease_time = 10; 682 | #endif 683 | break; 684 | case dhcpServerIdentifier : 685 | p++; 686 | opt_len = *p++; 687 | DHCPV4_SIP[0] = *p++; 688 | DHCPV4_SIP[1] = *p++; 689 | DHCPV4_SIP[2] = *p++; 690 | DHCPV4_SIP[3] = *p++; 691 | DHCPV4_REAL_SIP[0]=svr_addr[0]; 692 | DHCPV4_REAL_SIP[1]=svr_addr[1]; 693 | DHCPV4_REAL_SIP[2]=svr_addr[2]; 694 | DHCPV4_REAL_SIP[3]=svr_addr[3]; 695 | break; 696 | default : 697 | p++; 698 | opt_len = *p++; 699 | p += opt_len; 700 | break; 701 | } // switch 702 | } // while 703 | } // if 704 | return type; 705 | } 706 | 707 | uint8_t DHCPv4_run(void) 708 | { 709 | uint8_t type; 710 | uint8_t ret; 711 | 712 | if(dhcpv4_state == STATE_DHCPV4_STOP) return DHCPV4_STOPPED; 713 | 714 | if(getSn_SR(DHCPV4_SOCKET) != SOCK_UDP) 715 | socket(DHCPV4_SOCKET, Sn_MR_UDP, DHCPV4_CLIENT_PORT, 0x00); 716 | 717 | ret = DHCPV4_RUNNING; 718 | type = parseDHCPv4MSG(); 719 | 720 | 721 | switch ( dhcpv4_state ) { 722 | case STATE_DHCPV4_INIT : 723 | DHCPv4_allocated_ip[0] = 0; 724 | DHCPv4_allocated_ip[1] = 0; 725 | DHCPv4_allocated_ip[2] = 0; 726 | DHCPv4_allocated_ip[3] = 0; 727 | send_DHCPv4_DISCOVER(); 728 | dhcpv4_state = STATE_DHCPV4_DISCOVER; 729 | break; 730 | case STATE_DHCPV4_DISCOVER : 731 | if (type == DHCPV4_OFFER){ 732 | #ifdef _DHCPV4_DEBUG_ 733 | printf("> Receive DHCP_OFFER\r\n"); 734 | #endif 735 | DHCPv4_allocated_ip[0] = pDHCPv4MSG->yiaddr[0]; 736 | DHCPv4_allocated_ip[1] = pDHCPv4MSG->yiaddr[1]; 737 | DHCPv4_allocated_ip[2] = pDHCPv4MSG->yiaddr[2]; 738 | DHCPv4_allocated_ip[3] = pDHCPv4MSG->yiaddr[3]; 739 | 740 | send_DHCPv4_REQUEST(); 741 | dhcpv4_state = STATE_DHCPV4_REQUEST; 742 | } else ret = check_DHCPv4_timeout(); 743 | break; 744 | 745 | case STATE_DHCPV4_REQUEST : 746 | if (type == DHCPV4_ACK) { 747 | 748 | #ifdef _DHCPV4_DEBUG_ 749 | printf("> Receive DHCP_ACK\r\n"); 750 | #endif 751 | if (check_DHCPv4_leasedIP()) { 752 | // Network info assignment from DHCP 753 | dhcp_ipv4_assign(); 754 | reset_DHCPv4_timeout(); 755 | 756 | dhcpv4_state = STATE_DHCPV4_LEASED; 757 | } else { 758 | // IP address conflict occurred 759 | reset_DHCPv4_timeout(); 760 | dhcp_ipv4_conflict(); 761 | dhcpv4_state = STATE_DHCPV4_INIT; 762 | } 763 | } else if (type == DHCPV4_NAK) { 764 | 765 | #ifdef _DHCPV4_DEBUG_ 766 | printf("> Receive DHCP_NACK\r\n"); 767 | #endif 768 | 769 | reset_DHCPv4_timeout(); 770 | 771 | dhcpv4_state = STATE_DHCPV4_DISCOVER; 772 | } else ret = check_DHCPv4_timeout(); 773 | break; 774 | 775 | case STATE_DHCPV4_LEASED : 776 | ret = DHCP_IPV4_LEASED; 777 | if ((dhcpv4_lease_time != INFINITE_LEASETIME) && ((dhcpv4_lease_time/2) < dhcpv4_tick_1s)) { 778 | 779 | #ifdef _DHCPV4_DEBUG_ 780 | printf("> Maintains the IP address \r\n"); 781 | #endif 782 | 783 | type = 0; 784 | OLD_allocated_ip[0] = DHCPv4_allocated_ip[0]; 785 | OLD_allocated_ip[1] = DHCPv4_allocated_ip[1]; 786 | OLD_allocated_ip[2] = DHCPv4_allocated_ip[2]; 787 | OLD_allocated_ip[3] = DHCPv4_allocated_ip[3]; 788 | 789 | DHCPV4_XID++; 790 | 791 | send_DHCPv4_REQUEST(); 792 | 793 | reset_DHCPv4_timeout(); 794 | 795 | dhcpv4_state = STATE_DHCPV4_REREQUEST; 796 | } 797 | break; 798 | 799 | case STATE_DHCPV4_REREQUEST : 800 | ret = DHCP_IPV4_LEASED; 801 | if (type == DHCPV4_ACK) { 802 | dhcpv4_retry_count = 0; 803 | if (OLD_allocated_ip[0] != DHCPv4_allocated_ip[0] || 804 | OLD_allocated_ip[1] != DHCPv4_allocated_ip[1] || 805 | OLD_allocated_ip[2] != DHCPv4_allocated_ip[2] || 806 | OLD_allocated_ip[3] != DHCPv4_allocated_ip[3]) 807 | { 808 | ret = DHCP_IPV4_CHANGED; 809 | dhcp_ipv4_update(); 810 | #ifdef _DHCPV4_DEBUG_ 811 | printf(">IP changed.\r\n"); 812 | #endif 813 | 814 | } 815 | #ifdef _DHCPV4_DEBUG_ 816 | else printf(">IP is continued.\r\n"); 817 | #endif 818 | reset_DHCPv4_timeout(); 819 | dhcpv4_state = STATE_DHCPV4_LEASED; 820 | } else if (type == DHCPV4_NAK) { 821 | 822 | #ifdef _DHCPV4_DEBUG_ 823 | printf("> Receive DHCP_NACK, Failed to maintain ip\r\n"); 824 | #endif 825 | 826 | reset_DHCPv4_timeout(); 827 | 828 | dhcpv4_state = STATE_DHCPV4_DISCOVER; 829 | } else ret = check_DHCPv4_timeout(); 830 | break; 831 | default : 832 | break; 833 | } 834 | 835 | return ret; 836 | } 837 | 838 | void DHCPv4_stop(void) 839 | { 840 | close(DHCPV4_SOCKET); 841 | dhcpv4_state = STATE_DHCPV4_STOP; 842 | } 843 | 844 | uint8_t check_DHCPv4_timeout(void) 845 | { 846 | uint8_t ret = DHCPV4_RUNNING; 847 | 848 | if (dhcpv4_retry_count < MAX_DHCPV4_RETRY) { 849 | if (dhcpv4_tick_next < dhcpv4_tick_1s) { 850 | 851 | switch ( dhcpv4_state ) { 852 | case STATE_DHCPV4_DISCOVER : 853 | // printf("<> state : STATE_DHCPV4_DISCOVER\r\n"); 854 | send_DHCPv4_DISCOVER(); 855 | break; 856 | 857 | case STATE_DHCPV4_REQUEST : 858 | // printf("<> state : STATE_DHCPV4_REQUEST\r\n"); 859 | 860 | send_DHCPv4_REQUEST(); 861 | break; 862 | 863 | case STATE_DHCPV4_REREQUEST : 864 | // printf("<> state : STATE_DHCPV4_REREQUEST\r\n"); 865 | 866 | send_DHCPv4_REQUEST(); 867 | break; 868 | 869 | default : 870 | break; 871 | } 872 | 873 | dhcpv4_tick_1s = 0; 874 | dhcpv4_tick_next = dhcpv4_tick_1s + DHCPV4_WAIT_TIME; 875 | dhcpv4_retry_count++; 876 | } 877 | } else { // timeout occurred 878 | 879 | switch(dhcpv4_state) { 880 | case STATE_DHCPV4_DISCOVER: 881 | dhcpv4_state = STATE_DHCPV4_INIT; 882 | ret = DHCPV4_FAILED; 883 | break; 884 | case STATE_DHCPV4_REQUEST: 885 | case STATE_DHCPV4_REREQUEST: 886 | send_DHCPv4_DISCOVER(); 887 | dhcpv4_state = STATE_DHCPV4_DISCOVER; 888 | break; 889 | default : 890 | break; 891 | } 892 | reset_DHCPv4_timeout(); 893 | } 894 | return ret; 895 | } 896 | 897 | int8_t check_DHCPv4_leasedIP(void) 898 | { 899 | uint8_t tmp; 900 | int32_t ret; 901 | 902 | //WIZchip RCR value changed for ARP Timeout count control 903 | tmp = getRCR(); 904 | setRCR(0x03); 905 | 906 | // IP conflict detection : ARP request - ARP reply 907 | // Broadcasting ARP Request for check the IP conflict using UDP sendto() function 908 | ret = sendto(DHCPV4_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCPv4_allocated_ip, 5000, 4); 909 | 910 | // RCR value restore 911 | setRCR(tmp); 912 | 913 | if(ret == SOCKERR_TIMEOUT) { 914 | // UDP send Timeout occurred : allocated IP address is unique, DHCP Success 915 | 916 | #ifdef _DHCPV4_DEBUG_ 917 | printf("\r\n> Check leased IP - OK\r\n"); 918 | #endif 919 | 920 | return 1; 921 | } else { 922 | // Received ARP reply or etc : IP address conflict occur, DHCP Failed 923 | send_DHCPv4_DECLINE(); 924 | 925 | ret = dhcpv4_tick_1s; 926 | while((dhcpv4_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message; 927 | 928 | return 0; 929 | } 930 | } 931 | 932 | void DHCPv4_init(uint8_t s, uint8_t * buf) 933 | { 934 | uint8_t zeroip[4] = {0,0,0,0}; 935 | getSHAR(DHCPv4_CHADDR); 936 | if((DHCPv4_CHADDR[0] | DHCPv4_CHADDR[1] | DHCPv4_CHADDR[2] | DHCPv4_CHADDR[3] | DHCPv4_CHADDR[4] | DHCPv4_CHADDR[5]) == 0x00) 937 | { 938 | // assigning temporary mac address, you should be set SHAR before call this function. 939 | DHCPv4_CHADDR[0] = 0x00; 940 | DHCPv4_CHADDR[1] = 0x08; 941 | DHCPv4_CHADDR[2] = 0xdc; 942 | DHCPv4_CHADDR[3] = 0x00; 943 | DHCPv4_CHADDR[4] = 0x00; 944 | DHCPv4_CHADDR[5] = 0x00; 945 | setSHAR(DHCPv4_CHADDR); 946 | } 947 | 948 | DHCPV4_SOCKET = s; // SOCK_DHCP 949 | pDHCPv4MSG = (RIP_MSG*)buf; 950 | DHCPV4_XID = 0x12345678; 951 | 952 | // WIZchip Netinfo Clear 953 | setSIPR(zeroip); 954 | setGAR(zeroip); 955 | 956 | reset_DHCPv4_timeout(); 957 | dhcpv4_state = STATE_DHCPV4_INIT; 958 | } 959 | 960 | 961 | /* Reset the DHCP timeout count and retry count. */ 962 | void reset_DHCPv4_timeout(void) 963 | { 964 | dhcpv4_tick_1s = 0; 965 | dhcpv4_tick_next = DHCPV4_WAIT_TIME; 966 | dhcpv4_retry_count = 0; 967 | } 968 | 969 | void DHCPv4_time_handler(void) 970 | { 971 | dhcpv4_tick_1s++; 972 | } 973 | 974 | void getIPfromDHCPv4(uint8_t* ip) 975 | { 976 | ip[0] = DHCPv4_allocated_ip[0]; 977 | ip[1] = DHCPv4_allocated_ip[1]; 978 | ip[2] = DHCPv4_allocated_ip[2]; 979 | ip[3] = DHCPv4_allocated_ip[3]; 980 | } 981 | 982 | void getGWfromDHCPv4(uint8_t* ip) 983 | { 984 | ip[0] =DHCPv4_allocated_gw[0]; 985 | ip[1] =DHCPv4_allocated_gw[1]; 986 | ip[2] =DHCPv4_allocated_gw[2]; 987 | ip[3] =DHCPv4_allocated_gw[3]; 988 | } 989 | 990 | void getSNfromDHCPv4(uint8_t* ip) 991 | { 992 | ip[0] = DHCPv4_allocated_sn[0]; 993 | ip[1] = DHCPv4_allocated_sn[1]; 994 | ip[2] = DHCPv4_allocated_sn[2]; 995 | ip[3] = DHCPv4_allocated_sn[3]; 996 | } 997 | 998 | void getDNSfromDHCPv4(uint8_t* ip) 999 | { 1000 | ip[0] = DHCPv4_allocated_dns[0]; 1001 | ip[1] = DHCPv4_allocated_dns[1]; 1002 | ip[2] = DHCPv4_allocated_dns[2]; 1003 | ip[3] = DHCPv4_allocated_dns[3]; 1004 | } 1005 | 1006 | uint32_t getDHCPv4Leasetime(void) 1007 | { 1008 | return dhcpv4_lease_time; 1009 | } 1010 | 1011 | char NibbleToHex(uint8_t nibble) 1012 | { 1013 | nibble &= 0x0F; 1014 | if (nibble <= 9) 1015 | return nibble + '0'; 1016 | else 1017 | return nibble + ('A'-0x0A); 1018 | } 1019 | -------------------------------------------------------------------------------- /Internet/DHCP4/dhcpv4.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | //! \file dhcpv4.h 4 | //! \brief DHCP APIs Header file. 5 | //! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. 6 | //! \version 1.1.1 7 | //! \date 2019/10/08 8 | //! \par Revision history 9 | //! <2019/10/08> compare DHCP server ip address 10 | //! <2013/11/18> 1st Release 11 | //! <2012/12/20> V1.1.0 12 | //! 1. Move unreferenced DEFINE to dhcp.c 13 | //! <2012/12/26> V1.1.1 14 | //! \author Eric Jung & MidnightCow 15 | //! \copyright 16 | //! 17 | //! Copyright (c) 2013, WIZnet Co., LTD. 18 | //! All rights reserved. 19 | //! 20 | //! Redistribution and use in source and binary forms, with or without 21 | //! modification, are permitted provided that the following conditions 22 | //! are met: 23 | //! 24 | //! * Redistributions of source code must retain the above copyright 25 | //! notice, this list of conditions and the following disclaimer. 26 | //! * Redistributions in binary form must reproduce the above copyright 27 | //! notice, this list of conditions and the following disclaimer in the 28 | //! documentation and/or other materials provided with the distribution. 29 | //! * Neither the name of the nor the names of its 30 | //! contributors may be used to endorse or promote products derived 31 | //! from this software without specific prior written permission. 32 | //! 33 | //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34 | //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 | //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36 | //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 37 | //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38 | //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39 | //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40 | //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 41 | //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42 | //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 43 | //! THE POSSIBILITY OF SUCH DAMAGE. 44 | // 45 | //***************************************************************************** 46 | #ifndef _DHCP_H_ 47 | #define _DHCP_H_ 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | /* 54 | * @brief 55 | * @details If you want to display debug & processing message, Define _DHCPV4_DEBUG_ 56 | * @note If defined, it depends on 57 | */ 58 | //#define _DHCPV4_DEBUG_ 59 | 60 | 61 | /* Retry to processing DHCP */ 62 | #define MAX_DHCPV4_RETRY 2 ///< Maximum retry count 63 | #define DHCPV4_WAIT_TIME 10 ///< Wait Time 10s 64 | 65 | 66 | /* UDP port numbers for DHCP */ 67 | #define DHCPV4_SERVER_PORT 67 ///< DHCP server port number 68 | #define DHCPV4_CLIENT_PORT 68 ///< DHCP client port number 69 | 70 | 71 | #define MAGIC_COOKIE 0x63825363 ///< You should not modify it number. 72 | 73 | #define DCHPV4_HOST_NAME "WIZnet\0" 74 | 75 | /* 76 | * @brief return value of @ref DHCPv4_run() 77 | */ 78 | enum 79 | { 80 | DHCPV4_FAILED = 0, ///< Processing Fail 81 | DHCPV4_RUNNING, ///< Processing DHCP protocol 82 | DHCP_IPV4_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) 83 | DHCP_IPV4_CHANGED, ///< Change IP address by new ip from DHCP (if cbfunc == null, act as default default_ip_update) 84 | DHCP_IPV4_LEASED, ///< Stand by 85 | DHCPV4_STOPPED ///< Stop processing DHCP protocol 86 | }; 87 | 88 | /* 89 | * @brief DHCP client initialization (outside of the main loop) 90 | * @param s - socket number 91 | * @param buf - buffer for processing DHCP message 92 | */ 93 | void DHCPv4_init(uint8_t s, uint8_t * buf); 94 | 95 | /* 96 | * @brief DHCP 1s Tick Timer handler 97 | * @note SHOULD BE register to your system 1s Tick timer handler 98 | */ 99 | void DHCPv4_time_handler(void); 100 | 101 | /* 102 | * @brief Register call back function 103 | * @param ip_assign - callback func when IP is assigned from DHCP server first 104 | * @param ip_update - callback func when IP is changed 105 | * @param ip_conflict - callback func when the assigned IP is conflict with others. 106 | */ 107 | void reg_dhcpv4_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); 108 | 109 | /* 110 | * @brief DHCP client in the main loop 111 | * @return The value is as the follow \n 112 | * @ref DHCPV4_FAILED \n 113 | * @ref DHCPv4_runNING \n 114 | * @ref DHCP_IPV4_ASSIGN \n 115 | * @ref DHCP_IPV4_CHANGED \n 116 | * @ref DHCP_IPV4_LEASED \n 117 | * @ref DHCPV4_STOPPED \n 118 | * 119 | * @note This function is always called by you main task. 120 | */ 121 | uint8_t DHCPv4_run(void); 122 | 123 | /* 124 | * @brief Stop DHCP processing 125 | * @note If you want to restart. call DHCPv4_init() and DHCPv4_run() 126 | */ 127 | void DHCPv4_stop(void); 128 | 129 | /* Get Network information assigned from DHCP server */ 130 | /* 131 | * @brief Get IP address 132 | * @param ip - IP address to be returned 133 | */ 134 | void getIPfromDHCPv4(uint8_t* ip); 135 | /* 136 | * @brief Get Gateway address 137 | * @param ip - Gateway address to be returned 138 | */ 139 | void getGWfromDHCPv4(uint8_t* ip); 140 | /* 141 | * @brief Get Subnet mask value 142 | * @param ip - Subnet mask to be returned 143 | */ 144 | void getSNfromDHCPv4(uint8_t* ip); 145 | /* 146 | * @brief Get DNS address 147 | * @param ip - DNS address to be returned 148 | */ 149 | void getDNSfromDHCPv4(uint8_t* ip); 150 | 151 | /* 152 | * @brief Get the leased time by DHCP sever 153 | * @return unit 1s 154 | */ 155 | uint32_t getDHCPv4Leasetime(void); 156 | 157 | #ifdef __cplusplus 158 | } 159 | #endif 160 | 161 | #endif /* _DHCP_H_ */ 162 | -------------------------------------------------------------------------------- /Internet/DHCP6/dhcpv6.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | //! \file dhcp6.h 4 | //! \brief DHCPv6 APIs Header file. 5 | //! \details Processig DHCPv6 protocol as SOLICIT, ADVERTISE. 6 | //! \version 0.0.1 7 | //! \date 2016/06/08 8 | //! \par Revision history 9 | //! <2016/07/18> 1st Release 10 | //! \author JustinKim 11 | //! \copyright 12 | //! 13 | //! Copyright (c) 2016, WIZnet Co., LTD. 14 | //! All rights reserved. 15 | //! 16 | //! Redistribution and use in source and binary forms, with or without 17 | //! modification, are permitted provided that the following conditions 18 | //! are met: 19 | //! 20 | //! * Redistributions of source code must retain the above copyright 21 | //! notice, this list of conditions and the following disclaimer. 22 | //! * Redistributions in binary form must reproduce the above copyright 23 | //! notice, this list of conditions and the following disclaimer in the 24 | //! documentation and/or other materials provided with the distribution. 25 | //! * Neither the name of the nor the names of its 26 | //! contributors may be used to endorse or promote products derived 27 | //! from this software without specific prior written permission. 28 | //! 29 | //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 30 | //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 33 | //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34 | //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35 | //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36 | //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 37 | //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 | //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 39 | //! THE POSSIBILITY OF SUCH DAMAGE. 40 | // 41 | //***************************************************************************** 42 | #ifndef _DHCP6_H_ 43 | #define _DHCP6_H_ 44 | #include 45 | #include "W6100.h" 46 | #include "socket.h" 47 | /* 48 | * @brief 49 | * @details If you want to display debug & procssing message, Define _DHCP_DEBUG_ 50 | * @note If defined, it dependens on 51 | */ 52 | //#define _DHCP_DEBUG_ 53 | 54 | /* Retry to processing DHCP */ 55 | #define MAX_DHCP_RETRY 2 ///< Maxium retry count 56 | #define DHCP_WAIT_TIME 10 ///< Wait Time 10s 57 | 58 | /* UDP port numbers for DHCP */ 59 | #define DHCP_SERVER_PORT 547 ///< DHCP server port number 60 | #define DHCP_CLIENT_PORT 546 ///< DHCP client port number 61 | 62 | #define DCHP_HOST_NAME "WIZnet\0" 63 | 64 | /* 65 | * @brief return value of @ref DHCP_run() 66 | */ 67 | enum 68 | { 69 | DHCP_FAILED = 0, ///< Procssing Fail 70 | DHCP_RUNNING, ///< Procssing DHCP proctocol 71 | DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) 72 | DHCP_IP_CHANGED, ///< Change IP address by new ip from DHCP (if cbfunc == null, act as default default_ip_update) 73 | DHCP_IP_LEASED, ///< Stand by 74 | DHCP_STOPPED ///< Stop procssing DHCP protocol 75 | }; 76 | 77 | /** 78 | * @brief 79 | * 80 | * @param asize 81 | * @param agrowby 82 | */ 83 | void InitDhcpOption(unsigned asize, unsigned agrowby); 84 | /** 85 | * @brief 86 | * 87 | * @param value 88 | */ 89 | void AppendDhcpOption(uint8_t value); 90 | /** 91 | * @brief 92 | * 93 | * @param sMark 94 | */ 95 | void DumpDhcpOption(char *sMark); 96 | /** 97 | * @brief 98 | * 99 | * @param Option 100 | */ 101 | void DHCP_Option_Select(uint8_t Option); 102 | /* 103 | * @brief DHCP client initialization (outside of the main loop) 104 | * @param s - socket number 105 | * @param buf - buffer for procssing DHCP message 106 | */ 107 | void DHCP_init(uint8_t s, uint8_t *buf); 108 | 109 | /* 110 | * @brief DHCP 1s Tick Timer handler 111 | * @note SHOULD BE register to your system 1s Tick timer handler 112 | */ 113 | void DHCP_time_handler(void); 114 | 115 | /** 116 | * @brief 117 | * 118 | * @param netinfo 119 | * @return uint8_t 120 | */ 121 | uint8_t DHCP_run(wiz_NetInfo *netinfo); 122 | 123 | /** 124 | * @brief 125 | * 126 | * @return uint8_t 127 | */ 128 | uint8_t DHCP_run2(void); 129 | 130 | /* 131 | * @brief Stop DHCP procssing 132 | * @note If you want to restart. call DHCP_init() and DHCP_run() 133 | */ 134 | void DHCP_stop(void); 135 | 136 | #endif /* _DHCP_H_ */ 137 | -------------------------------------------------------------------------------- /Internet/DNS/dns.c: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | //! \file dns.c 4 | //! \brief DNS APIs Implement file. 5 | //! \details Send DNS query & Receive DNS reponse. \n 6 | //! It depends on stdlib.h & string.h in ansi-c library 7 | //! \version 1.1.0 8 | //! \date 2013/11/18 9 | //! \par Revision history 10 | //! <2013/10/21> 1st Release 11 | //! <2013/12/20> V1.1.0 12 | //! 1. Remove secondary DNS server in DNS_run 13 | //! If 1st DNS_run failed, call DNS_run with 2nd DNS again 14 | //! 2. DNS_timerHandler -> DNS_time_handler 15 | //! 3. Remove the unused define 16 | //! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c 17 | //! <2013/12/20> V1.1.0 18 | //! 19 | //! \author Eric Jung & MidnightCow 20 | //! \copyright 21 | //! 22 | //! Copyright (c) 2013, WIZnet Co., LTD. 23 | //! All rights reserved. 24 | //! 25 | //! Redistribution and use in source and binary forms, with or without 26 | //! modification, are permitted provided that the following conditions 27 | //! are met: 28 | //! 29 | //! * Redistributions of source code must retain the above copyright 30 | //! notice, this list of conditions and the following disclaimer. 31 | //! * Redistributions in binary form must reproduce the above copyright 32 | //! notice, this list of conditions and the following disclaimer in the 33 | //! documentation and/or other materials provided with the distribution. 34 | //! * Neither the name of the nor the names of its 35 | //! contributors may be used to endorse or promote products derived 36 | //! from this software without specific prior written permission. 37 | //! 38 | //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 39 | //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 | //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 41 | //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 42 | //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 43 | //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 44 | //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 45 | //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 46 | //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 | //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 48 | //! THE POSSIBILITY OF SUCH DAMAGE. 49 | // 50 | //***************************************************************************** 51 | 52 | #include 53 | #include 54 | 55 | #include "socket.h" 56 | #include "dns.h" 57 | 58 | #ifdef _DNS_DEBUG_ 59 | #include 60 | #endif 61 | 62 | #define INITRTT 2000L /* Initial smoothed response time */ 63 | #define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */ 64 | 65 | #define TYPE_A 1 /* Host address */ 66 | #define TYPE_NS 2 /* Name server */ 67 | #define TYPE_MD 3 /* Mail destination (obsolete) */ 68 | #define TYPE_MF 4 /* Mail forwarder (obsolete) */ 69 | #define TYPE_CNAME 5 /* Canonical name */ 70 | #define TYPE_SOA 6 /* Start of Authority */ 71 | #define TYPE_MB 7 /* Mailbox name (experimental) */ 72 | #define TYPE_MG 8 /* Mail group member (experimental) */ 73 | #define TYPE_MR 9 /* Mail rename name (experimental) */ 74 | #define TYPE_NULL 10 /* Null (experimental) */ 75 | #define TYPE_WKS 11 /* Well-known sockets */ 76 | #define TYPE_PTR 12 /* Pointer record */ 77 | #define TYPE_HINFO 13 /* Host information */ 78 | #define TYPE_MINFO 14 /* Mailbox information (experimental)*/ 79 | #define TYPE_MX 15 /* Mail exchanger */ 80 | #define TYPE_TXT 16 /* Text strings */ 81 | #define TYPE_AAAA 28 82 | #define TYPE_ANY 255 /* Matches any type */ 83 | 84 | #define CLASS_IN 1 /* The ARPA Internet */ 85 | 86 | /* Round trip timing parameters */ 87 | #define AGAIN 8 /* Average RTT gain = 1/8 */ 88 | #define LAGAIN 3 /* Log2(AGAIN) */ 89 | #define DGAIN 4 /* Mean deviation gain = 1/4 */ 90 | #define LDGAIN 2 /* log2(DGAIN) */ 91 | 92 | /* Header for all domain messages */ 93 | struct dhdr 94 | { 95 | uint16_t id; /* Identification */ 96 | uint8_t qr; /* Query/Response */ 97 | #define QUERY 0 98 | #define RESPONSE 1 99 | uint8_t opcode; 100 | #define IQUERY 1 101 | uint8_t aa; /* Authoratative answer */ 102 | uint8_t tc; /* Truncation */ 103 | uint8_t rd; /* Recursion desired */ 104 | uint8_t ra; /* Recursion available */ 105 | uint8_t rcode; /* Response code */ 106 | #define NO_ERROR 0 107 | #define FORMAT_ERROR 1 108 | #define SERVER_FAIL 2 109 | #define NAME_ERROR 3 110 | #define NOT_IMPL 4 111 | #define REFUSED 5 112 | uint16_t qdcount; /* Question count */ 113 | uint16_t ancount; /* Answer count */ 114 | uint16_t nscount; /* Authority (name server) count */ 115 | uint16_t arcount; /* Additional record count */ 116 | }; 117 | 118 | 119 | uint8_t* pDNSMSG; // DNS message buffer 120 | uint8_t DNS_SOCKET; // SOCKET number for DNS 121 | uint16_t DNS_MSGID; // DNS message ID 122 | 123 | uint32_t dns_1s_tick; // for timout of DNS processing 124 | static uint8_t retry_count; 125 | 126 | /* converts uint16_t from network buffer to a host byte order integer. */ 127 | uint16_t get16(uint8_t * s) 128 | { 129 | uint16_t i; 130 | i = *s++ << 8; 131 | i = i + *s; 132 | return i; 133 | } 134 | 135 | /* copies uint16_t to the network buffer with network byte order. */ 136 | uint8_t * put16(uint8_t * s, uint16_t i) 137 | { 138 | *s++ = i >> 8; 139 | *s++ = i; 140 | return s; 141 | } 142 | 143 | 144 | /* 145 | * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM 146 | * 147 | * Description : This function converts a compressed domain name to the human-readable form 148 | * Arguments : msg - is a pointer to the reply message 149 | * compressed - is a pointer to the domain name in reply message. 150 | * buf - is a pointer to the buffer for the human-readable form name. 151 | * len - is the MAX. size of buffer. 152 | * Returns : the length of compressed message 153 | */ 154 | int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len) 155 | { 156 | uint16_t slen; /* Length of current segment */ 157 | uint8_t * cp; 158 | int clen = 0; /* Total length of compressed name */ 159 | int indirect = 0; /* Set if indirection encountered */ 160 | int nseg = 0; /* Total number of segments in name */ 161 | 162 | cp = compressed; 163 | 164 | for (;;) 165 | { 166 | slen = *cp++; /* Length of this segment */ 167 | 168 | if (!indirect) clen++; 169 | 170 | if ((slen & 0xc0) == 0xc0) 171 | { 172 | if (!indirect) 173 | clen++; 174 | indirect = 1; 175 | /* Follow indirection */ 176 | cp = &msg[((slen & 0x3f)<<8) + *cp]; 177 | slen = *cp++; 178 | } 179 | 180 | if (slen == 0) /* zero length == all done */ 181 | break; 182 | 183 | len -= slen + 1; 184 | 185 | if (len < 0) return -1; 186 | 187 | if (!indirect) clen += slen; 188 | 189 | while (slen-- != 0) *buf++ = (char)*cp++; 190 | *buf++ = '.'; 191 | nseg++; 192 | } 193 | 194 | if (nseg == 0) 195 | { 196 | /* Root name; represent as single dot */ 197 | *buf++ = '.'; 198 | len--; 199 | } 200 | 201 | *buf++ = '\0'; 202 | len--; 203 | 204 | return clen; /* Length of compressed message */ 205 | } 206 | 207 | /* 208 | * PARSE QUESTION SECTION 209 | * 210 | * Description : This function parses the qeustion record of the reply message. 211 | * Arguments : msg - is a pointer to the reply message 212 | * cp - is a pointer to the qeustion record. 213 | * Returns : a pointer the to next record. 214 | */ 215 | uint8_t * dns_question(uint8_t * msg, uint8_t * cp) 216 | { 217 | int len; 218 | char name[MAXCNAME]; 219 | 220 | len = parse_name(msg, cp, name, MAXCNAME); 221 | 222 | 223 | if (len == -1) return 0; 224 | 225 | cp += len; 226 | cp += 2; /* type */ 227 | cp += 2; /* class */ 228 | 229 | return cp; 230 | } 231 | 232 | 233 | /* 234 | * PARSE ANSER SECTION 235 | * 236 | * Description : This function parses the answer record of the reply message. 237 | * Arguments : msg - is a pointer to the reply message 238 | * cp - is a pointer to the answer record. 239 | * Returns : a pointer the to next record. 240 | */ 241 | uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns) 242 | { 243 | int len, type; 244 | char name[MAXCNAME]; 245 | 246 | len = parse_name(msg, cp, name, MAXCNAME); 247 | 248 | if (len == -1) return 0; 249 | 250 | cp += len; 251 | type = get16(cp); 252 | cp += 2; /* type */ 253 | cp += 2; /* class */ 254 | cp += 4; /* ttl */ 255 | cp += 2; /* len */ 256 | 257 | 258 | switch (type) 259 | { 260 | case TYPE_A: 261 | /* Just read the address directly into the structure */ 262 | ip_from_dns[0] = *cp++; 263 | ip_from_dns[1] = *cp++; 264 | ip_from_dns[2] = *cp++; 265 | ip_from_dns[3] = *cp++; 266 | break; 267 | case TYPE_AAAA: 268 | ip_from_dns[0] = *cp++; 269 | ip_from_dns[1] = *cp++; 270 | ip_from_dns[2] = *cp++; 271 | ip_from_dns[3] = *cp++; 272 | ip_from_dns[4] = *cp++; 273 | ip_from_dns[5] = *cp++; 274 | ip_from_dns[6] = *cp++; 275 | ip_from_dns[7] = *cp++; 276 | ip_from_dns[8] = *cp++; 277 | ip_from_dns[9] = *cp++; 278 | ip_from_dns[10] = *cp++; 279 | ip_from_dns[11] = *cp++; 280 | ip_from_dns[12] = *cp++; 281 | ip_from_dns[13] = *cp++; 282 | ip_from_dns[14] = *cp++; 283 | ip_from_dns[15] = *cp++; 284 | break; 285 | case TYPE_CNAME: 286 | case TYPE_MB: 287 | case TYPE_MG: 288 | case TYPE_MR: 289 | case TYPE_NS: 290 | case TYPE_PTR: 291 | /* These types all consist of a single domain name */ 292 | /* convert it to ascii format */ 293 | len = parse_name(msg, cp, name, MAXCNAME); 294 | if (len == -1) return 0; 295 | 296 | cp += len; 297 | break; 298 | case TYPE_HINFO: 299 | len = *cp++; 300 | cp += len; 301 | 302 | len = *cp++; 303 | cp += len; 304 | break; 305 | case TYPE_MX: 306 | cp += 2; 307 | /* Get domain name of exchanger */ 308 | len = parse_name(msg, cp, name, MAXCNAME); 309 | if (len == -1) return 0; 310 | 311 | cp += len; 312 | break; 313 | case TYPE_SOA: 314 | /* Get domain name of name server */ 315 | len = parse_name(msg, cp, name, MAXCNAME); 316 | if (len == -1) return 0; 317 | 318 | cp += len; 319 | 320 | /* Get domain name of responsible person */ 321 | len = parse_name(msg, cp, name, MAXCNAME); 322 | if (len == -1) return 0; 323 | 324 | cp += len; 325 | 326 | cp += 4; 327 | cp += 4; 328 | cp += 4; 329 | cp += 4; 330 | cp += 4; 331 | break; 332 | case TYPE_TXT: 333 | /* Just stash */ 334 | break; 335 | default: 336 | /* Ignore */ 337 | break; 338 | } 339 | 340 | return cp; 341 | } 342 | 343 | /* 344 | * PARSE THE DNS REPLY 345 | * 346 | * Description : This function parses the reply message from DNS server. 347 | * Arguments : dhdr - is a pointer to the header for DNS message 348 | * buf - is a pointer to the reply message. 349 | * len - is the size of reply message. 350 | * Returns : -1 - Domain name lenght is too big 351 | * 0 - Fail (Timout or parse error) 352 | * 1 - Success, 353 | */ 354 | extern uint8_t IP_TYPE; 355 | int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns) 356 | { 357 | uint16_t tmp; 358 | uint16_t i; 359 | uint8_t * msg; 360 | uint8_t * cp; 361 | 362 | msg = pbuf; 363 | memset(pdhdr, 0, sizeof(*pdhdr)); 364 | 365 | pdhdr->id = get16(&msg[0]); 366 | tmp = get16(&msg[2]); 367 | if (tmp & 0x8000) pdhdr->qr = 1; 368 | 369 | pdhdr->opcode = (tmp >> 11) & 0xf; 370 | 371 | if (tmp & 0x0400) pdhdr->aa = 1; 372 | if (tmp & 0x0200) pdhdr->tc = 1; 373 | if (tmp & 0x0100) pdhdr->rd = 1; 374 | if (tmp & 0x0080) pdhdr->ra = 1; 375 | 376 | pdhdr->rcode = tmp & 0xf; 377 | pdhdr->qdcount = get16(&msg[4]); 378 | pdhdr->ancount = get16(&msg[6]); 379 | pdhdr->nscount = get16(&msg[8]); 380 | pdhdr->arcount = get16(&msg[10]); 381 | 382 | 383 | /* Now parse the variable length sections */ 384 | cp = &msg[12]; 385 | 386 | /* Question section */ 387 | for (i = 0; i < pdhdr->qdcount; i++) 388 | { 389 | cp = dns_question(msg, cp); 390 | #ifdef _DNS_DEUBG_ 391 | printf("MAX_DOMAIN_NAME is too small, it should be redfine in dns.h"); 392 | #endif 393 | if(!cp) return -1; 394 | } 395 | 396 | /* Answer section */ 397 | for (i = 0; i < pdhdr->ancount; i++) 398 | { 399 | cp = dns_answer(msg, cp, ip_from_dns); 400 | #ifdef _DNS_DEUBG_ 401 | printf("MAX_DOMAIN_NAME is too small, it should be redfine in dns.h"); 402 | #endif 403 | if(!cp) return -1; 404 | } 405 | 406 | /* Name server (authority) section */ 407 | for (i = 0; i < pdhdr->nscount; i++) 408 | { 409 | ; 410 | } 411 | 412 | /* Additional section */ 413 | for (i = 0; i < pdhdr->arcount; i++) 414 | { 415 | ; 416 | } 417 | 418 | if(pdhdr->rcode == 0) return 1; // No error 419 | else return 0; 420 | } 421 | 422 | 423 | /* 424 | * MAKE DNS QUERY MESSAGE 425 | * 426 | * Description : This function makes DNS query message. 427 | * Arguments : op - Recursion desired 428 | * name - is a pointer to the domain name. 429 | * buf - is a pointer to the buffer for DNS message. 430 | * len - is the MAX. size of buffer. 431 | * Returns : the pointer to the DNS message. 432 | */ 433 | int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len,uint8_t type) 434 | { 435 | uint8_t *cp; 436 | char *cp1; 437 | char sname[MAXCNAME]; 438 | char *dname; 439 | uint16_t p; 440 | uint16_t dlen; 441 | 442 | cp = buf; 443 | 444 | DNS_MSGID++; 445 | cp = put16(cp, DNS_MSGID); 446 | p = (op << 11) | 0x0100; /* Recursion desired */ 447 | cp = put16(cp, p); 448 | cp = put16(cp, 1); 449 | cp = put16(cp, 0); 450 | cp = put16(cp, 0); 451 | cp = put16(cp, 0); 452 | 453 | strcpy(sname, name); 454 | dname = sname; 455 | dlen = strlen(dname); 456 | for (;;) 457 | { 458 | /* Look for next dot */ 459 | cp1 = strchr(dname, '.'); 460 | 461 | if (cp1 != NULL) len = cp1 - dname; /* More to come */ 462 | else len = dlen; /* Last component */ 463 | 464 | *cp++ = len; /* Write length of component */ 465 | if (len == 0) break; 466 | 467 | /* Copy component up to (but not including) dot */ 468 | strncpy((char *)cp, dname, len); 469 | cp += len; 470 | if (cp1 == NULL) 471 | { 472 | *cp++ = 0; /* Last one; write null and finish */ 473 | break; 474 | } 475 | dname += len+1; 476 | dlen -= len+1; 477 | } 478 | #if 1 479 | cp = put16(cp,IP_TYPE); /* type */ 480 | #else 481 | cp = put16(cp, type); /* type */ 482 | #endif 483 | cp = put16(cp, 0x0001); /* class */ 484 | 485 | 486 | return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf))); 487 | } 488 | 489 | /* 490 | * CHECK DNS TIMEOUT 491 | * 492 | * Description : This function check the DNS timeout 493 | * Arguments : None. 494 | * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur 495 | * Note : timeout : retry count and timer both over. 496 | */ 497 | 498 | int8_t check_DNS_timeout(void) 499 | { 500 | 501 | if(dns_1s_tick >= DNS_WAIT_TIME) 502 | { 503 | dns_1s_tick = 0; 504 | if(retry_count >= MAX_DNS_RETRY) { 505 | retry_count = 0; 506 | return -1; // timeout occurred 507 | } 508 | retry_count++; 509 | return 0; // timer over, but no timeout 510 | } 511 | 512 | return 1; // no timer over, no timeout occur 513 | } 514 | 515 | 516 | 517 | /* DNS CLIENT INIT */ 518 | void DNS_init( uint8_t * buf) 519 | { 520 | //DNS_SOCKET = s; // SOCK_DNS 521 | pDNSMSG = buf; // User's shared buffer 522 | DNS_MSGID = DNS_MSG_ID; 523 | } 524 | 525 | /* DNS CLIENT RUN */ 526 | int8_t DNS_run(uint8_t s,uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns,uint8_t mode) 527 | { 528 | int8_t ret; 529 | struct dhdr dhp; 530 | uint8_t ip[4]; 531 | uint8_t addr_len; 532 | uint16_t len, port; 533 | int8_t ret_check_timeout; 534 | 535 | retry_count = 0; 536 | dns_1s_tick = 0; 537 | 538 | // Socket open 539 | 540 | if(mode == AS_IPV4 ){ 541 | socket(s, Sn_MR_UDP4, 0, 0); 542 | addr_len = 4; 543 | } 544 | else if(mode == AS_IPV6){ 545 | socket(s, Sn_MR_UDP6, 0, 0); 546 | addr_len = 16; 547 | } 548 | 549 | #ifdef _DNS_DEBUG_ 550 | printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); 551 | 552 | #endif 553 | 554 | len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE,mode); 555 | sendto(s, pDNSMSG, len, dns_ip, IPPORT_DOMAIN,addr_len); 556 | 557 | while (1) 558 | { 559 | if ((len = getSn_RX_RSR(s)) > 0) 560 | { 561 | if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE; 562 | len = recvfrom(s, pDNSMSG, len, ip, &port,&addr_len); 563 | #ifdef _DNS_DEBUG_ 564 | printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len); 565 | #endif 566 | ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns); 567 | break; 568 | } 569 | // Check Timeout 570 | ret_check_timeout = check_DNS_timeout(); 571 | if (ret_check_timeout < 0) { 572 | 573 | #ifdef _DNS_DEBUG_ 574 | printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); 575 | #endif 576 | return 0; // timeout occurred 577 | } 578 | else if (ret_check_timeout == 0) { 579 | 580 | #ifdef _DNS_DEBUG_ 581 | printf("> DNS Timeout\r\n"); 582 | #endif 583 | sendto(s, pDNSMSG, len, dns_ip, IPPORT_DOMAIN,addr_len); 584 | } 585 | } 586 | close(s); 587 | // Return value 588 | // 0 > : failed / 1 - success 589 | return ret; 590 | } 591 | 592 | 593 | /* DNS TIMER HANDLER */ 594 | void DNS_time_handler(void) 595 | { 596 | dns_1s_tick++; 597 | } 598 | -------------------------------------------------------------------------------- /Internet/DNS/dns.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // 3 | //! \file dns.h 4 | //! \brief DNS APIs Header file. 5 | //! \details Send DNS query & Receive DNS reponse. 6 | //! \version 1.1.0 7 | //! \date 2013/11/18 8 | //! \par Revision history 9 | //! <2013/10/21> 1st Release 10 | //! <2013/12/20> V1.1.0 11 | //! 1. Remove secondary DNS server in DNS_run 12 | //! If 1st DNS_run failed, call DNS_run with 2nd DNS again 13 | //! 2. DNS_timerHandler -> DNS_time_handler 14 | //! 3. Move the no reference define to dns.c 15 | //! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c 16 | //! <2013/12/20> V1.1.0 17 | //! 18 | //! \author Eric Jung & MidnightCow 19 | //! \copyright 20 | //! 21 | //! Copyright (c) 2013, WIZnet Co., LTD. 22 | //! All rights reserved. 23 | //! 24 | //! Redistribution and use in source and binary forms, with or without 25 | //! modification, are permitted provided that the following conditions 26 | //! are met: 27 | //! 28 | //! * Redistributions of source code must retain the above copyright 29 | //! notice, this list of conditions and the following disclaimer. 30 | //! * Redistributions in binary form must reproduce the above copyright 31 | //! notice, this list of conditions and the following disclaimer in the 32 | //! documentation and/or other materials provided with the distribution. 33 | //! * Neither the name of the nor the names of its 34 | //! contributors may be used to endorse or promote products derived 35 | //! from this software without specific prior written permission. 36 | //! 37 | //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 38 | //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 | //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 | //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 41 | //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 42 | //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 43 | //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 44 | //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 45 | //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 | //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 47 | //! THE POSSIBILITY OF SUCH DAMAGE. 48 | // 49 | //***************************************************************************** 50 | 51 | #ifndef _DNS_H_ 52 | #define _DNS_H_ 53 | 54 | #ifdef __cplusplus 55 | extern "C" { 56 | #endif 57 | 58 | #include 59 | /* 60 | * @brief Define it for Debug & Monitor DNS processing. 61 | * @note If defined, it dependens on 62 | */ 63 | //#define _DNS_DEBUG_ 64 | 65 | #define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ 66 | /* 67 | * @brief Maxium length of your queried Domain name 68 | * @todo SHOULD BE defined it equal as or greater than your Domain name lenght + null character(1) 69 | * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack. 70 | */ 71 | #define MAX_DOMAIN_NAME 16 // for example "www.google.com" 72 | 73 | #define MAX_DNS_RETRY 2 ///< Requery Count 74 | #define DNS_WAIT_TIME 3 ///< Wait response time. unit 1s. 75 | 76 | #define IPPORT_DOMAIN 53 ///< DNS server port number 77 | 78 | #define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modifyed it any number 79 | 80 | /* 81 | * @brief DNS process initialize 82 | * @param s : Socket number for DNS 83 | * @param buf : Buffer for DNS message 84 | */ 85 | void DNS_init(uint8_t * buf); 86 | 87 | /* 88 | * @brief DNS process 89 | * @details Send DNS query and receive DNS response 90 | * @param dns_ip : DNS server ip 91 | * @param name : Domain name to be queryed 92 | * @param ip_from_dns : IP address from DNS server 93 | * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n 94 | * 0 : failed (Timeout or Parse error)\n 95 | * 1 : success 96 | * @note This funtion blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME 97 | */ 98 | int8_t DNS_run(uint8_t s,uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns,uint8_t mode); 99 | 100 | /* 101 | * @brief DNS 1s Tick Timer handler 102 | * @note SHOULD BE register to your system 1s Tick timer handler 103 | */ 104 | void DNS_time_handler(void); 105 | 106 | #ifdef __cplusplus 107 | } 108 | #endif 109 | 110 | #endif /* _DNS_H_ */ 111 | -------------------------------------------------------------------------------- /Internet/SNTP/sntp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sntp.c 3 | * 4 | * Created on: 2014. 12. 15. 5 | * Author: Administrator 6 | */ 7 | 8 | 9 | #include 10 | 11 | #include "sntp.h" 12 | #include "socket.h" 13 | 14 | ntpformat NTPformat; 15 | datetime Nowdatetime; 16 | uint8_t ntpmessage[48]; 17 | uint8_t *data_buf; 18 | uint8_t NTP_SOCKET; 19 | uint8_t time_zone; 20 | uint16_t ntp_retry_cnt=0; //counting the ntp retry number 21 | 22 | /* 23 | 00)UTC-12:00 Baker Island, Howland Island (both uninhabited) 24 | 01) UTC-11:00 American Samoa, Samoa 25 | 02) UTC-10:00 (Summer)French Polynesia (most), United States (Aleutian Islands, Hawaii) 26 | 03) UTC-09:30 Marquesas Islands 27 | 04) UTC-09:00 Gambier Islands;(Summer)United States (most of Alaska) 28 | 05) UTC-08:00 (Summer)Canada (most of British Columbia), Mexico (Baja California) 29 | 06) UTC-08:00 United States (California, most of Nevada, most of Oregon, Washington (state)) 30 | 07) UTC-07:00 Mexico (Sonora), United States (Arizona); (Summer)Canada (Alberta) 31 | 08) UTC-07:00 Mexico (Chihuahua), United States (Colorado) 32 | 09) UTC-06:00 Costa Rica, El Salvador, Ecuador (Galapagos Islands), Guatemala, Honduras 33 | 10) UTC-06:00 Mexico (most), Nicaragua;(Summer)Canada (Manitoba, Saskatchewan), United States (Illinois, most of Texas) 34 | 11) UTC-05:00 Colombia, Cuba, Ecuador (continental), Haiti, Jamaica, Panama, Peru 35 | 12) UTC-05:00 (Summer)Canada (most of Ontario, most of Quebec) 36 | 13) UTC-05:00 United States (most of Florida, Georgia, Massachusetts, most of Michigan, New York, North Carolina, Ohio, Washington D.C.) 37 | 14) UTC-04:30 Venezuela 38 | 15) UTC-04:00 Bolivia, Brazil (Amazonas), Chile (continental), Dominican Republic, Canada (Nova Scotia), Paraguay, 39 | 16) UTC-04:00 Puerto Rico, Trinidad and Tobago 40 | 17) UTC-03:30 Canada (Newfoundland) 41 | 18) UTC-03:00 Argentina; (Summer) Brazil (Brasilia, Rio de Janeiro, Sao Paulo), most of Greenland, Uruguay 42 | 19) UTC-02:00 Brazil (Fernando de Noronha), South Georgia and the South Sandwich Islands 43 | 20) UTC-01:00 Portugal (Azores), Cape Verde 44 | 21) UTC±00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira) 45 | 22) UTC±00:00 Spain (Canary Islands), Morocco, United Kingdom 46 | 23) UTC+01:00 Angola, Cameroon, Nigeria, Tunisia; (Summer)Albania, Algeria, Austria, Belgium, Bosnia and Herzegovina, 47 | 24) UTC+01:00 Spain (continental), Croatia, Czech Republic, Denmark, Germany, Hungary, Italy, Kinshasa, Kosovo, 48 | 25) UTC+01:00 Macedonia, France (metropolitan), the Netherlands, Norway, Poland, Serbia, Slovakia, Slovenia, Sweden, Switzerland 49 | 26) UTC+02:00 Libya, Egypt, Malawi, Mozambique, South Africa, Zambia, Zimbabwe, (Summer)Bulgaria, Cyprus, Estonia, 50 | 27) UTC+02:00 Finland, Greece, Israel, Jordan, Latvia, Lebanon, Lithuania, Moldova, Palestine, Romania, Syria, Turkey, Ukraine 51 | 28) UTC+03:00 Belarus, Djibouti, Eritrea, Ethiopia, Iraq, Kenya, Madagascar, Russia (Kaliningrad Oblast), Saudi Arabia, 52 | 29) UTC+03:00 South Sudan, Sudan, Somalia, South Sudan, Tanzania, Uganda, Yemen 53 | 30) UTC+03:30 (Summer)Iran 54 | 31) UTC+04:00 Armenia, Azerbaijan, Georgia, Mauritius, Oman, Russia (European), Seychelles, United Arab Emirates 55 | 32) UTC+04:30 Afghanistan 56 | 33) UTC+05:00 Kazakhstan (West), Maldives, Pakistan, Uzbekistan 57 | 34) UTC+05:30 India, Sri Lanka 58 | 35) UTC+05:45 Nepal 59 | 36) UTC+06:00 Kazakhstan (most), Bangladesh, Russia (Ural: Sverdlovsk Oblast, Chelyabinsk Oblast) 60 | 37) UTC+06:30 Cocos Islands, Myanmar 61 | 38) UTC+07:00 Jakarta, Russia (Novosibirsk Oblast), Thailand, Vietnam 62 | 39) UTC+08:00 China, Hong Kong, Russia (Krasnoyarsk Krai), Malaysia, Philippines, Singapore, Taiwan, most of Mongolia, Western Australia 63 | 40) UTC+09:00 Korea, East Timor, Russia (Irkutsk Oblast), Japan 64 | 41) UTC+09:30 Australia (Northern Territory);(Summer)Australia (South Australia)) 65 | 42) UTC+10:00 Russia (Zabaykalsky Krai); (Summer)Australia (New South Wales, Queensland, Tasmania, Victoria) 66 | 43) UTC+10:30 Lord Howe Island 67 | 44) UTC+11:00 New Caledonia, Russia (Primorsky Krai), Solomon Islands 68 | 45) UTC+11:30 Norfolk Island 69 | 46) UTC+12:00 Fiji, Russia (Kamchatka Krai);(Summer)New Zealand 70 | 47) UTC+12:45 (Summer)New Zealand 71 | 48) UTC+13:00 Tonga 72 | 49) UTC+14:00 Kiribati (Line Islands) 73 | */ 74 | void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx) 75 | { 76 | tstamp seconds = 0; 77 | uint8_t i=0; 78 | for (i = 0; i < 4; i++) 79 | { 80 | seconds = (seconds << 8) | buf[idx + i]; 81 | } 82 | switch (time_zone) 83 | { 84 | case 0: 85 | seconds -= 12*3600; 86 | break; 87 | case 1: 88 | seconds -= 11*3600; 89 | break; 90 | case 2: 91 | seconds -= 10*3600; 92 | break; 93 | case 3: 94 | seconds -= (9*3600+30*60); 95 | break; 96 | case 4: 97 | seconds -= 9*3600; 98 | break; 99 | case 5: 100 | case 6: 101 | seconds -= 8*3600; 102 | break; 103 | case 7: 104 | case 8: 105 | seconds -= 7*3600; 106 | break; 107 | case 9: 108 | case 10: 109 | seconds -= 6*3600; 110 | break; 111 | case 11: 112 | case 12: 113 | case 13: 114 | seconds -= 5*3600; 115 | break; 116 | case 14: 117 | seconds -= (4*3600+30*60); 118 | break; 119 | case 15: 120 | case 16: 121 | seconds -= 4*3600; 122 | break; 123 | case 17: 124 | seconds -= (3*3600+30*60); 125 | break; 126 | case 18: 127 | seconds -= 3*3600; 128 | break; 129 | case 19: 130 | seconds -= 2*3600; 131 | break; 132 | case 20: 133 | seconds -= 1*3600; 134 | break; 135 | case 21: //�? 136 | case 22: 137 | break; 138 | case 23: 139 | case 24: 140 | case 25: 141 | seconds += 1*3600; 142 | break; 143 | case 26: 144 | case 27: 145 | seconds += 2*3600; 146 | break; 147 | case 28: 148 | case 29: 149 | seconds += 3*3600; 150 | break; 151 | case 30: 152 | seconds += (3*3600+30*60); 153 | break; 154 | case 31: 155 | seconds += 4*3600; 156 | break; 157 | case 32: 158 | seconds += (4*3600+30*60); 159 | break; 160 | case 33: 161 | seconds += 5*3600; 162 | break; 163 | case 34: 164 | seconds += (5*3600+30*60); 165 | break; 166 | case 35: 167 | seconds += (5*3600+45*60); 168 | break; 169 | case 36: 170 | seconds += 6*3600; 171 | break; 172 | case 37: 173 | seconds += (6*3600+30*60); 174 | break; 175 | case 38: 176 | seconds += 7*3600; 177 | break; 178 | case 39: 179 | seconds += 8*3600; 180 | break; 181 | case 40: 182 | seconds += 9*3600; 183 | break; 184 | case 41: 185 | seconds += (9*3600+30*60); 186 | break; 187 | case 42: 188 | seconds += 10*3600; 189 | break; 190 | case 43: 191 | seconds += (10*3600+30*60); 192 | break; 193 | case 44: 194 | seconds += 11*3600; 195 | break; 196 | case 45: 197 | seconds += (11*3600+30*60); 198 | break; 199 | case 46: 200 | seconds += 12*3600; 201 | break; 202 | case 47: 203 | seconds += (12*3600+45*60); 204 | break; 205 | case 48: 206 | seconds += 13*3600; 207 | break; 208 | case 49: 209 | seconds += 14*3600; 210 | break; 211 | 212 | } 213 | 214 | //calculation for date 215 | calcdatetime(seconds); 216 | } 217 | 218 | void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf) 219 | { 220 | NTP_SOCKET = s; 221 | 222 | NTPformat.dstaddr[0] = ntp_server[0]; 223 | NTPformat.dstaddr[1] = ntp_server[1]; 224 | NTPformat.dstaddr[2] = ntp_server[2]; 225 | NTPformat.dstaddr[3] = ntp_server[3]; 226 | 227 | time_zone = tz; 228 | 229 | data_buf = buf; 230 | 231 | uint8_t Flag; 232 | NTPformat.leap = 0; /* leap indicator */ 233 | NTPformat.version = 4; /* version number */ 234 | NTPformat.mode = 3; /* mode */ 235 | NTPformat.stratum = 0; /* stratum */ 236 | NTPformat.poll = 0; /* poll interval */ 237 | NTPformat.precision = 0; /* precision */ 238 | NTPformat.rootdelay = 0; /* root delay */ 239 | NTPformat.rootdisp = 0; /* root dispersion */ 240 | NTPformat.refid = 0; /* reference ID */ 241 | NTPformat.reftime = 0; /* reference time */ 242 | NTPformat.org = 0; /* origin timestamp */ 243 | NTPformat.rec = 0; /* receive timestamp */ 244 | NTPformat.xmt = 1; /* transmit timestamp */ 245 | 246 | Flag = (NTPformat.leap<<6)+(NTPformat.version<<3)+NTPformat.mode; //one byte Flag 247 | memcpy(ntpmessage,(void const*)(&Flag),1); 248 | } 249 | 250 | int8_t SNTP_run(datetime *time) 251 | { 252 | uint16_t RSR_len; 253 | uint32_t destip = 0; 254 | uint16_t destport; 255 | uint16_t startindex = 40; //last 8-byte of data_buf[size is 48 byte] is xmt, so the startindex should be 40 256 | #if 1 257 | // 20231019 taylor 258 | uint8_t addr_len; 259 | #endif 260 | 261 | switch(getSn_SR(NTP_SOCKET)) 262 | { 263 | case SOCK_UDP: 264 | if ((RSR_len = getSn_RX_RSR(NTP_SOCKET)) > 0) 265 | { 266 | 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 267 | #if 1 268 | // 20231019 taylor//teddy 240122 269 | #if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300)) 270 | recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport, &addr_len); 271 | #else 272 | recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport); 273 | #endif 274 | #else 275 | recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport); 276 | #endif 277 | 278 | get_seconds_from_ntp_server(data_buf,startindex); 279 | time->yy = Nowdatetime.yy; 280 | time->mo = Nowdatetime.mo; 281 | time->dd = Nowdatetime.dd; 282 | time->hh = Nowdatetime.hh; 283 | time->mm = Nowdatetime.mm; 284 | time->ss = Nowdatetime.ss; 285 | 286 | ntp_retry_cnt=0; 287 | close(NTP_SOCKET); 288 | 289 | return 1; 290 | } 291 | 292 | if(ntp_retry_cnt<0xFFFF) 293 | { 294 | if(ntp_retry_cnt==0)//first send request, no need to wait 295 | { 296 | #if 1 297 | // 20231016 taylor//teddy 240122 298 | #if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300)) 299 | sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port, 4); 300 | #else 301 | sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port); 302 | #endif 303 | #else 304 | sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port); 305 | #endif 306 | ntp_retry_cnt++; 307 | } 308 | else // send request again? it should wait for a while 309 | { 310 | if((ntp_retry_cnt % 0xFFF) == 0) //wait time 311 | { 312 | #if 1 313 | // 20231016 taylor//teddy 240122 314 | #if ((_WIZCHIP_ == 6100) || (_WIZCHIP_ == 6300)) 315 | sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port, 4); 316 | #else 317 | sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port); 318 | #endif 319 | #else 320 | sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port); 321 | #endif 322 | #ifdef _SNTP_DEBUG_ 323 | printf("ntp retry: %d\r\n", ntp_retry_cnt); 324 | #endif 325 | ntp_retry_cnt++; 326 | } 327 | } 328 | } 329 | else //ntp retry fail 330 | { 331 | ntp_retry_cnt=0; 332 | #ifdef _SNTP_DEBUG_ 333 | printf("ntp retry failed!\r\n"); 334 | #endif 335 | close(NTP_SOCKET); 336 | } 337 | break; 338 | case SOCK_CLOSED: 339 | socket(NTP_SOCKET,Sn_MR_UDP,ntp_port,0); 340 | break; 341 | } 342 | // Return value 343 | // 0 - failed / 1 - success 344 | return 0; 345 | } 346 | 347 | void calcdatetime(tstamp seconds) 348 | { 349 | uint8_t yf=0; 350 | uint8_t leap; 351 | tstamp n=0,d=0,total_d=0,rz=0; 352 | uint16_t y=0,r=0,yr=0; 353 | signed long long yd=0; 354 | 355 | n = seconds; 356 | total_d = seconds/(SECS_PERDAY); 357 | d=0; 358 | uint32_t p_year_total_sec=SECS_PERDAY*365; 359 | uint32_t r_year_total_sec=SECS_PERDAY*366; 360 | 361 | while(1) 362 | { 363 | leap = 0; 364 | if( ((EPOCH + r) % 400 == 0) || 365 | (((EPOCH + r) % 100 != 0) && ((EPOCH + r) % 4 == 0)) ) 366 | { 367 | leap = 1; 368 | } 369 | 370 | if(leap) 371 | { 372 | if (n < r_year_total_sec) { 373 | break; 374 | } 375 | n -= r_year_total_sec; 376 | d += 366; 377 | } 378 | else 379 | { 380 | if (n < p_year_total_sec) { 381 | break; 382 | } 383 | n -= p_year_total_sec; 384 | d += 365; 385 | } 386 | 387 | r++; 388 | y++; 389 | } 390 | 391 | y += EPOCH; 392 | 393 | Nowdatetime.yy = y; 394 | 395 | yd=0; 396 | yd = total_d - d; 397 | 398 | yf=1; 399 | while(yd>=28) 400 | { 401 | 402 | if(yf==1 || yf==3 || yf==5 || yf==7 || yf==8 || yf==10 || yf==12) 403 | { 404 | yd -= 31; 405 | if(yd<0)break; 406 | rz += 31; 407 | } 408 | 409 | if (yf==2) 410 | { 411 | if (y%400==0 || (y%100!=0 && y%4==0)) 412 | { 413 | yd -= 29; 414 | if(yd<0)break; 415 | rz += 29; 416 | } 417 | else 418 | { 419 | yd -= 28; 420 | if(yd<0)break; 421 | rz += 28; 422 | } 423 | } 424 | if(yf==4 || yf==6 || yf==9 || yf==11 ) 425 | { 426 | yd -= 30; 427 | if(yd<0)break; 428 | rz += 30; 429 | } 430 | yf += 1; 431 | 432 | } 433 | Nowdatetime.mo=yf; 434 | yr = total_d-d-rz; 435 | 436 | yr += 1; 437 | 438 | Nowdatetime.dd=yr; 439 | 440 | //calculation for time 441 | seconds = seconds%SECS_PERDAY; 442 | Nowdatetime.hh = seconds/3600; 443 | Nowdatetime.mm = (seconds%3600)/60; 444 | Nowdatetime.ss = (seconds%3600)%60; 445 | 446 | } 447 | 448 | tstamp changedatetime_to_seconds(void) 449 | { 450 | tstamp seconds=0; 451 | uint32_t total_day=0; 452 | uint16_t i=0,run_year_cnt=0,l=0; 453 | 454 | l = Nowdatetime.yy;//low 455 | 456 | 457 | for(i=EPOCH;i 16 | 17 | /* 18 | * @brief Define it for Debug & Monitor DNS processing. 19 | * @note If defined, it dependens on 20 | */ 21 | //#define _SNTP_DEBUG_ 22 | 23 | #define MAX_SNTP_BUF_SIZE sizeof(ntpformat) ///< maximum size of DNS buffer. */ 24 | 25 | /* for ntpclient */ 26 | typedef signed char s_char; 27 | typedef unsigned long long tstamp; 28 | typedef unsigned int tdist; 29 | 30 | typedef struct _ntpformat 31 | { 32 | 33 | uint8_t dstaddr[4]; /* destination (local) address */ 34 | char version; /* version number */ 35 | char leap; /* leap indicator */ 36 | char mode; /* mode */ 37 | char stratum; /* stratum */ 38 | char poll; /* poll interval */ 39 | s_char precision; /* precision */ 40 | tdist rootdelay; /* root delay */ 41 | tdist rootdisp; /* root dispersion */ 42 | char refid; /* reference ID */ 43 | tstamp reftime; /* reference time */ 44 | tstamp org; /* origin timestamp */ 45 | tstamp rec; /* receive timestamp */ 46 | tstamp xmt; /* transmit timestamp */ 47 | 48 | 49 | } ntpformat; 50 | 51 | typedef struct _datetime 52 | { 53 | uint16_t yy; 54 | uint8_t mo; 55 | uint8_t dd; 56 | uint8_t hh; 57 | uint8_t mm; 58 | uint8_t ss; 59 | } datetime; 60 | 61 | #define ntp_port 123 //ntp server port number 62 | #define SECS_PERDAY 86400UL // seconds in a day = 60*60*24 63 | #define UTC_ADJ_HRS 9 // SEOUL : GMT+9 64 | #define EPOCH 1900 // NTP start year 65 | 66 | void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx); 67 | void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf); 68 | int8_t SNTP_run(datetime *time); 69 | tstamp changedatetime_to_seconds(void); 70 | void calcdatetime(tstamp seconds); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* SNTP_H_ */ 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 WIZnet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # io6Library 2 | 3 | --- 4 | 5 | ![](https://raw.githubusercontent.com/Wiznet/io6Library/master/Doxygen/img/io6Library.png) 6 | 7 | --- 8 | 9 | [Goto Korean Version](https://midnightcow.tistory.com/141) 10 | 11 | --- 12 | 13 | ## Overview 14 | 15 | 16 | io6Library is an IPv6 integrated Library that can easily integrate and manage user applications that use the [WIZnet](http://www.wiznet.io/) Hardwired Dual TCP/IP Stack Controller ( WIZCHIP ) product family. 17 | 18 | io6Library is implemented to manage the code dependent on the user's specific MCU so that the user does not have to perform the porting operation of the io6Library according to the user MCU. (See How to Use for more information) 19 | ## Contents 20 | 21 | io6Library can be classified into three types as follows. 22 | 23 | - Reigsters Defintion 24 | - Common Registers 25 | : Defines general registers such as network information, mode, interrupt, and so on. 26 | - Socket Registers 27 | : Define SOCKET regsiters such as socket mode, socket communication, socket interrupt, and so on. 28 | 29 | - Each WIZCHIP I/O Access function 30 | - Basic I/O function 31 | : Basic unit function to access Input/Output through HOST interface (SPI, BUS, etc.) defined by WIZCHIP 32 | - Common Register Access Functions 33 | : Function to access Common Register based on Basic I/O Function 34 | - SOCKET Register Access Functions 35 | : Function to Access SOCKET Register based on Basic I / O Function 36 | 37 | - WIZCHIP control APIs for user application integration, management, and migration 38 | - SOCKET APIs 39 | : Like as BSD SOCKET API, SOCKET APIs provide function set that can be related socket commnuincation 40 | - Extra APIs 41 | : It provides functions to support the integration of user applications regardless of WIZCHIP specific Regiter/ Memory, Address Map, Features and so on. 42 | : It can be replaced with WIZCHIP I / O Access funcions for the small footprint of the User Application. 43 | 44 | For more details, refer to [io6Library.chm](https://github.com/Wiznet/io6Library/blob/master/Doxygen/doc/io6Library.chm). 45 | 46 | io6Library.chm may not be up to date, so please refer the document made by [doxygen program](http://www.doxygen.nl/download.html) with Doxyfile.dox project. Doxygen program can made the document to chm, html, or pdf if you want to. 47 | 48 | ## Directory 49 | 50 | ![](https://raw.githubusercontent.com/midnightcow/MyDocument/master/Images/W6100/io6Library_structure.png) 51 | 52 | ioLibrary has the same directory structure as the above figure, and the major directory is as follows. 53 | 54 | - [Ethernet](https://github.com/Wiznet/io6Library/tree/master/Ethernet) 55 | - WIZCHIP specific Directory (EX> [W6100](https://github.com/Wiznet/io6Library/tree/master/Ethernet/W6100) - w6100.h, w6100.c) 56 | - SOCKET API : [socket.h](https://github.com/Wiznet/io6Library/blob/master/Ethernet/socket.h), [socket.c](https://github.com/Wiznet/io6Library/blob/master/Ethernet/socket.c) 57 | - ioLibrary Configruation files : [wizchip_conf.h](https://github.com/Wiznet/io6Library/blob/master/Ethernet/wizchip_conf.h), [wizchip_conf.c](https://github.com/Wiznet/io6Library/blob/master/Ethernet/wizchip_conf.c) 58 | 59 | - [Internet](https://github.com/Wiznet/io6Library/tree/master/Internet) 60 | - Protcols for IP configuration (EX> DHCP, DNS) 61 | - Some protocols will be added 62 | 63 | - [Application](https://github.com/Wiznet/io6Library/tree/master/Application) 64 | - Application Socket Mode Definition : [Application.h](https://github.com/Wiznet/io6Library/blob/master/Application/Application.h) 65 | - [Loopback](https://github.com/Wiznet/io6Library/tree/master/Application/loopback) : TCP, UDP Basic Skeleton Code, [loopback.h](https://github.com/Wiznet/io6Library/blob/master/Application/loopback/loopback.h), [loopback.c](https://github.com/Wiznet/io6Library/blob/master/Application/loopback/loopback.h) 66 | 67 | io6Library users will be able to use it immediately by modifying only a few defintion in wizchip_conf.h. 68 | For more information, see How to Use. 69 | 70 | ## How to use 71 | 72 | ### io6Library Configuration 73 | 74 | Define the type and interface of WIZCHIP defined in wizchip_conf.h, to suit your intended usage. 75 | 76 | - Select the Hardwired Dual TCP/IP Stack Controller to use. 77 | In the following figure, Select one of list in the blue box and define the selected it to \_WIZCHIP\_ like as Red Box. 78 | 79 | ![](https://raw.githubusercontent.com/midnightcow/MyDocument/master/Images/W6100/def_wizchip.png) 80 | 81 | - Select the HOST Interface (Parallel Bus, Serial Bus Mode, etc.) that the user will use for WIZCHIP Access. 82 | In the following figure, Select one of list in the blue box and define the selected it to \_WIZCHIP\_IO\_MODE\_ like as Red Box. 83 | 84 | ![](https://raw.githubusercontent.com/midnightcow/MyDocument/master/Images/W6100/def_host_if.png) 85 | 86 | - Only when Parallel Bus Mode is used, Must set the memory bank base address of HOST to be assigned to WIZCHIPCHIP like as red box. 87 | 88 | ![](https://raw.githubusercontent.com/midnightcow/MyDocument/master/Images/W6100/def_bus_map.png) 89 | 90 | - WIZCHIP PHY Access Mode Configuration 91 | Like as the following figure, Select one of the two approaches of Ethernet PHY access mode defined in blue box and define it as Red box. 92 | 93 | ![](https://github.com/midnightcow/MyDocument/blob/master/Images/W6100/def_wizphy_if.png) 94 | 95 | - \_PHY\_IO\_MODE\_PHYCR\_ : It provides simple control to Ethernet PHY of WIZCHIP thru PHY Command & Status Register such like as PHY Operation Mode and Link Status. 96 | - \_PHY\_\_IO\_MODE\_MII\_ : It provides direct control to Ethernet PHY Register of WIZCHIP PHY thru MDC/MDIO signal. 97 | 98 | 99 | ### Make user-defined functions for WIZCHIP I/O Access 100 | 101 | Make the basic Access I/O function by yourself according to your HOST interface. 102 | This is because the interface control method differs for each user HOST. So, You should make it. 103 | 104 | For example, if you define the following and control WIZCHIP using SPI1 of STM32FXXX 105 | 106 | ```c 107 | #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ 108 | ``` 109 | 110 | Create basic unit functions such as WIZCHIP select / deselect, 1byte read / write, critical section enter / exit etc. via SPI interface as follows. 111 | 112 | Make your basic I/O access functions such as WIZCHIP select/deselect, 1byte read/write and critical section enter/exit through the SPI interface as shown belows. 113 | 114 | - WIZCHIP select/deselect : Function to set/reset any GPIO of STM32FXXX connected with CSn Pin of WIZCHIP 115 | 116 | ```c 117 | void your_wizchip_enable(void) 118 | { 119 | /* void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) */ 120 | HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET) 121 | } 122 | 123 | void your_wizchip_disable(void) 124 | { 125 | HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET) 126 | } 127 | ``` 128 | 129 | - WIZCHIP 1 byte read/write : Function to read and write 1 byte through SPI interface 130 | 131 | ```c 132 | /* Read 1 byte thru SPI */ 133 | uint8_t your_spi_read_byte() 134 | { 135 | uint8_t ret; 136 | /*HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)*/ 137 | HAL_SPI_Receive(SPI1, &ret, 1, 1000); 138 | return ret; 139 | } 140 | 141 | /* Write 1 byte thru SPI */ 142 | void your_spi_wite_byte(uint8_t wd) 143 | { 144 | /* HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout); */ 145 | HAL_SPI_Transmit(SPI1, &wd, 1, 1000); 146 | } 147 | ``` 148 | 149 | - WIZCHIP Critical Section Enter/Exit : Function to protect against events such as interupts and task switching while WIZCHIP is accessing 150 | 151 | ```c 152 | void your_critical_enter(void) 153 | { 154 | __disable_irq(); 155 | } 156 | 157 | void your_critical_exit(void) 158 | { 159 | __enable_irq(); 160 | } 161 | ``` 162 | 163 | - WIZCHIP N bytes read/write Function 164 | : It is not mandatory. 165 | : But, If you want to use WIZCHIP for high speed access using a peripheral such as DMA, make it as follows. 166 | : Even if you do not, you can use N bytes read/write accesses because it is performed by repeating your 1-byte read/write function. 167 | 168 | ```c 169 | void your_spi_dma_write_buf(uint8_t* pbuf, iodata_t len) 170 | { 171 | /* HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) */ 172 | HAL_SPI_Transmit_DMA(SPI1, pbuf, (uint16_t)len); 173 | } 174 | 175 | void your_spi_dma_read_buf(uint8_t* pbuf, iodata_t len) 176 | { 177 | /* HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) */ 178 | HAL_SPI_Receive_DMA(SPI1, pbuf, (uint16_t)len); 179 | } 180 | ``` 181 | 182 | ### Register your defined Function to io6Library 183 | 184 | Register the your defined code made in the above examples before WIZCHIP initialization as below. 185 | 186 | ```c 187 | #include "wizchip_conf.h" // Just only included for using ioLibrary 188 | 189 | void main(void) 190 | { 191 | uint16_t chip_id; 192 | wiz_NetTimeout tmp_timeout = 0; 193 | /* 194 | // Intialize your Target System such as SPI, UART, DMA, and etc. 195 | */ 196 | 197 | /* Register your basic access function to io6Library */ 198 | 199 | //WIZCHIP Enable/Disable 200 | reg_wizchip_cs_cbfunc(your_wizchip_enable, your_wizchip_disable); 201 | 202 | //WIZCHIP Critical Section 203 | reg_wizchip_cris_cbfunc(your_critical_enter, your_critical_exit); 204 | 205 | //WIZCHIP read/write function 206 | reg_wizchip_spi_cbfunc(your_spi_read_byte, your_spi_write_byte, 0, 0); 207 | 208 | // If you made DMA function for readign/writting function, you can register as following 209 | // reg_wizchip_spi_cbfunc(your_spi_read_byte, your_spi_write_byte, your_spi_dma_read_buf, your_spi_dma_write_buf); 210 | // 211 | 212 | /* For io6Library Read/Write Test */ 213 | 214 | // Read Test 215 | ctlwizchip(CW_GET_ID,&chip_id); // Check WIZCHIP ID value for read test 216 | if(chip_id != 0x6100) printf("ERROR : HOST I/F READ\r\n") // It is just example for W6100 217 | 218 | // Write Test 219 | ctlwizchip(CW_PHY_RESET, 0); // Check phyically PHY Link Led to turn off and then on. 220 | 221 | ///////////////////////////////// 222 | // Enjoy, WIZCHIP & io6Library // 223 | // Thank you // 224 | ///////////////////////////////// 225 | } 226 | ``` 227 | 228 | ## Examples for io6Library & [ioLibrary](https://github.com/Wiznet/ioLibrary_Driver) 229 | 230 | You can refer many examples like as http, ftp, and so on related to io6Library & ioLibrary. 231 | 232 | [WIZnet-ioLibrary Examples](https://github.com/Wiznet-ioLibrary) 233 | 234 | ## Available WIZCHIP sets 235 | 236 | 237 | 238 | 239 |
Product NameFigures
W6100-L(Q)
240 | 241 | ## Reference Site 242 | 243 | - WIZnet Homepage : https://www.wiznet.io/ 244 | - WIZCHIP Set : https://www.wiznet.io/product/tcpip-chip/ 245 | - WIZCHIP Modules : https://www.wiznet.io/product/network-module/ 246 | - Technical Documents : [WiKi](http://wizwiki.net/), [WIZCHIP](http://wizwiki.net/https://wizwiki.net/wiki/doku.php?id=products:iethernet:start) 247 | - Q&A, Forum : https://forum.wiznet.io/ 248 | 249 | - Simple IPv6 intrduction : https://maker.wiznet.io/wp-content/uploads/2019/04/WoW_part1.pdf 250 | - Simple W6100 Description : https://maker.wiznet.io/wp-content/uploads/2019/04/WoW_part2.pdf 251 | --------------------------------------------------------------------------------