Jinbuhm Kim
/
W5500_Driver
Wiznet W5500 driver and TCP/UDP loopback
Embed:
(wiki syntax)
Show/hide line numbers
socket.c
00001 /* Wiznet W5500 Library 00002 * Copyright (c) 2013, WIZnet Co., LTD. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "socket.h" 00018 00019 #define SOCK_ANY_PORT_NUM 0xC000; 00020 00021 static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; 00022 static uint16_t sock_io_mode = 0; 00023 static uint16_t sock_is_sending = 0; 00024 static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; 00025 00026 #define CHECK_SOCKNUM() \ 00027 do{ \ 00028 if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ 00029 }while(0); \ 00030 00031 #define CHECK_SOCKMODE(mode) \ 00032 do{ \ 00033 if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ 00034 }while(0); \ 00035 00036 #define CHECK_SOCKINIT() \ 00037 do{ \ 00038 if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ 00039 }while(0); \ 00040 00041 #define CHECK_SOCKDATA() \ 00042 do{ \ 00043 if(len == 0) return SOCKERR_DATALEN; \ 00044 }while(0); \ 00045 00046 00047 00048 int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) 00049 { 00050 CHECK_SOCKNUM(); 00051 switch(protocol) 00052 { 00053 case Sn_MR_TCP : 00054 case Sn_MR_UDP : 00055 case Sn_MR_MACRAW : 00056 break; 00057 default : 00058 return SOCKERR_SOCKMODE; 00059 } 00060 if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; 00061 00062 if(flag != 0) 00063 { 00064 switch(protocol) 00065 { 00066 case Sn_MR_TCP: 00067 if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; 00068 break; 00069 case Sn_MR_UDP: 00070 if(flag & SF_IGMP_VER2) 00071 { 00072 if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; 00073 } 00074 if(flag & SF_UNI_BLOCK) 00075 { 00076 if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; 00077 } 00078 break; 00079 default: 00080 break; 00081 } 00082 } 00083 close(sn); 00084 setSn_MR(sn, (protocol | (flag & 0xF0))); 00085 if(!port) 00086 { 00087 port = sock_any_port++; 00088 if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; 00089 } 00090 setSn_PORT(sn,port); 00091 setSn_CR(sn,Sn_CR_OPEN); 00092 while(getSn_CR(sn)); 00093 sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); 00094 sock_is_sending &= ~(1<<sn); 00095 sock_remained_size[sn] = 0; 00096 while(getSn_SR(sn) == SOCK_CLOSED); 00097 return (int8_t)sn; 00098 } 00099 00100 int8_t close(uint8_t sn) 00101 { 00102 CHECK_SOCKNUM(); 00103 00104 setSn_CR(sn,Sn_CR_CLOSE); 00105 /* wait to process the command... */ 00106 while( getSn_CR(sn) ); 00107 /* clear all interrupt of the socket. */ 00108 setSn_IR(sn, 0xFF); 00109 sock_is_sending &= ~(1<<sn); 00110 sock_remained_size[sn] = 0; 00111 while(getSn_SR(sn) != SOCK_CLOSED); 00112 return SOCK_OK; 00113 } 00114 00115 int8_t listen(uint8_t sn) 00116 { 00117 CHECK_SOCKNUM(); 00118 CHECK_SOCKMODE(Sn_MR_TCP); 00119 CHECK_SOCKINIT(); 00120 setSn_CR(sn,Sn_CR_LISTEN); 00121 while(getSn_CR(sn)); 00122 while(getSn_SR(sn) != SOCK_LISTEN) 00123 { 00124 if(getSn_CR(sn) == SOCK_CLOSED) 00125 { 00126 close(sn); 00127 return SOCKERR_SOCKCLOSED; 00128 } 00129 } 00130 return SOCK_OK; 00131 } 00132 00133 00134 int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port) 00135 { 00136 CHECK_SOCKNUM(); 00137 CHECK_SOCKMODE(Sn_MR_TCP); 00138 CHECK_SOCKINIT(); 00139 if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; 00140 if(port == 0) return SOCKERR_PORTZERO; 00141 setSn_DIPR(sn,addr); 00142 setSn_DPORT(sn,port); 00143 // setSUBR(); // set the subnet mask register 00144 setSn_CR(sn,Sn_CR_CONNECT); 00145 while(getSn_CR(sn)); 00146 if(sock_io_mode & (1<<sn)) return SOCK_BUSY; 00147 while(getSn_SR(sn) != SOCK_ESTABLISHED) 00148 { 00149 if (getSn_IR(sn) & Sn_IR_TIMEOUT) 00150 { 00151 setSn_IR(sn, Sn_IR_TIMEOUT); 00152 return SOCKERR_TIMEOUT; 00153 } 00154 } 00155 // clearSUBR(); // clear the subnet mask again and keep it because of the ARP errata of W5100 00156 return SOCK_OK; 00157 } 00158 00159 int8_t disconnect(uint8_t sn) 00160 { 00161 CHECK_SOCKNUM(); 00162 CHECK_SOCKMODE(Sn_MR_TCP); 00163 setSn_CR(sn,Sn_CR_DISCON); 00164 /* wait to process the command... */ 00165 while(getSn_CR(sn)); 00166 sock_is_sending &= ~(1<<sn); 00167 if(sock_io_mode & (1<<sn)) return SOCK_BUSY; 00168 while(getSn_SR(sn) != SOCK_CLOSED) 00169 { 00170 if(getSn_IR(sn) & Sn_IR_TIMEOUT) 00171 { 00172 close(sn); 00173 return SOCKERR_TIMEOUT; 00174 } 00175 } 00176 return SOCK_OK; 00177 } 00178 00179 int32_t send(uint8_t sn, uint8_t * buf, uint16_t len) 00180 { 00181 uint8_t tmp=0; 00182 uint16_t freesize=0; 00183 00184 CHECK_SOCKNUM(); 00185 CHECK_SOCKMODE(Sn_MR_TCP); 00186 CHECK_SOCKDATA(); 00187 tmp = getSn_SR(sn); 00188 if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS; 00189 if( sock_is_sending & (1<<sn) ) 00190 { 00191 tmp = getSn_IR(sn); 00192 if(tmp & Sn_IR_SENDOK) 00193 { 00194 setSn_IR(sn, Sn_IR_SENDOK); 00195 sock_is_sending &= ~(1<<sn); 00196 } 00197 else if(tmp & Sn_IR_TIMEOUT) 00198 { 00199 close(sn); 00200 return SOCKERR_TIMEOUT; 00201 } 00202 else return SOCK_BUSY; 00203 } 00204 freesize = getSn_TxMAX(sn); 00205 if (len > freesize) len = freesize; // check size not to exceed MAX size. 00206 while(1) 00207 { 00208 freesize = getSn_TX_FSR(sn); 00209 tmp = getSn_SR(sn); 00210 if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) 00211 { 00212 close(sn); 00213 return SOCKERR_SOCKSTATUS; 00214 } 00215 if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; 00216 if(len <= freesize) break; 00217 } 00218 wiz_send_data(sn, buf, len); 00219 setSn_CR(sn,Sn_CR_SEND); 00220 /* wait to process the command... */ 00221 while(getSn_CR(sn)); 00222 sock_is_sending |= (1 << sn); 00223 /* 00224 if(sock_io_mode & (1<<sn)) return len; 00225 while( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) !=Sn_IR_SENDOK ) 00226 { 00227 if(tmp & Sn_IR_TIMEOUT) 00228 { 00229 close(sn); 00230 return SOCKERR_TIMEOUT; 00231 } 00232 } 00233 setSn_IR(sn, Sn_IR_SENDOK); 00234 */ 00235 return len; 00236 } 00237 00238 00239 int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len) 00240 { 00241 uint8_t tmp = 0; 00242 uint16_t recvsize = 0; 00243 CHECK_SOCKNUM(); 00244 CHECK_SOCKMODE(Sn_MR_TCP); 00245 CHECK_SOCKDATA(); 00246 00247 recvsize = getSn_RxMAX(sn); 00248 if(recvsize < len) len = recvsize; 00249 while(1) 00250 { 00251 recvsize = getSn_RX_RSR(sn); 00252 tmp = getSn_SR(sn); 00253 if (tmp != SOCK_ESTABLISHED) 00254 { 00255 if(tmp == SOCK_CLOSE_WAIT) 00256 { 00257 if(recvsize != 0) break; 00258 else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) 00259 { 00260 close(sn); 00261 return SOCKERR_SOCKSTATUS; 00262 } 00263 } 00264 else 00265 { 00266 close(sn); 00267 return SOCKERR_SOCKSTATUS; 00268 } 00269 } 00270 if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY; 00271 if(recvsize != 0) break; 00272 }; 00273 if(recvsize < len) len = recvsize; 00274 wiz_recv_data(sn, buf, len); 00275 setSn_CR(sn,Sn_CR_RECV); 00276 while(getSn_CR(sn)); 00277 return len; 00278 } 00279 00280 int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port) 00281 { 00282 uint8_t tmp = 0; 00283 uint16_t freesize = 0; 00284 CHECK_SOCKNUM(); 00285 //CHECK_SOCKMODE(Sn_MR_UDP); 00286 switch(getSn_MR(sn) & 0x0F) 00287 { 00288 case Sn_MR_UDP: 00289 case Sn_MR_MACRAW: 00290 break; 00291 default: 00292 return SOCKERR_SOCKMODE; 00293 } 00294 CHECK_SOCKDATA(); 00295 if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; 00296 if(port == 0) return SOCKERR_PORTZERO; 00297 tmp = getSn_SR(sn); 00298 if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS; 00299 00300 if( sock_is_sending & (1<<sn) ) 00301 { 00302 tmp = getSn_IR(sn); 00303 if(tmp & Sn_IR_SENDOK) 00304 { 00305 setSn_IR(sn, Sn_IR_SENDOK); 00306 sock_is_sending &= ~(1<<sn); 00307 } 00308 else if(tmp & Sn_IR_TIMEOUT) 00309 { 00310 close(sn); 00311 return SOCKERR_TIMEOUT; 00312 } 00313 else return SOCK_BUSY; 00314 } 00315 00316 setSn_DIPR(sn,addr); 00317 setSn_DPORT(sn,port); 00318 freesize = getSn_TxMAX(sn); 00319 if (len > freesize) len = freesize; // check size not to exceed MAX size. 00320 while(1) 00321 { 00322 freesize = getSn_TX_FSR(sn); 00323 if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; 00324 if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; 00325 if(len <= freesize) break; 00326 }; 00327 wiz_send_data(sn, buf, len); 00328 // setSUBR(); // set the subnet mask register 00329 setSn_CR(sn,Sn_CR_SEND); 00330 /* wait to process the command... */ 00331 while(getSn_CR(sn)); 00332 sock_is_sending |= (1<<sn); 00333 #if 0 00334 if(sock_io_mode & (1<<sn)) return len; 00335 while ( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) != Sn_IR_SENDOK ) 00336 { 00337 if(tmp & Sn_IR_TIMEOUT) 00338 { 00339 setSn_IR(sn, (Sn_IR_SENDOK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */ 00340 return SOCKERR_TIMEOUT; 00341 } 00342 } 00343 // clearSUBR(); // clear the subnet mask again and keep it because of the ARP errata of W5100 00344 setSn_IR(sn, Sn_IR_SENDOK); 00345 #endif 00346 return len; 00347 } 00348 00349 00350 00351 int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port, uint8_t* packinfo) 00352 { 00353 uint8_t mr; 00354 uint8_t head[8]; 00355 uint16_t pack_len=0; 00356 00357 CHECK_SOCKNUM(); 00358 //CHECK_SOCKMODE(Sn_MR_UDP); 00359 switch((mr=getSn_MR(sn)) & 0x0F) 00360 { 00361 case Sn_MR_UDP: 00362 case Sn_MR_MACRAW: 00363 break; 00364 default: 00365 return SOCKERR_SOCKMODE; 00366 } 00367 CHECK_SOCKDATA(); 00368 if(sock_remained_size[sn] == 0) 00369 { 00370 while(1) 00371 { 00372 pack_len = getSn_RX_RSR(sn); 00373 if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; 00374 if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY; 00375 if(pack_len != 0) break; 00376 }; 00377 } 00378 *packinfo = 0x00; 00379 switch (mr & 0x07) 00380 { 00381 case Sn_MR_UDP : 00382 if(sock_remained_size[sn] == 0) 00383 { 00384 wiz_recv_data(sn, head, 8); 00385 setSn_CR(sn,Sn_CR_RECV); 00386 while(getSn_CR(sn)); 00387 // read peer's IP address, port number & packet length 00388 addr[0] = head[0]; 00389 addr[1] = head[1]; 00390 addr[2] = head[2]; 00391 addr[3] = head[3]; 00392 *port = head[4]; 00393 *port = (*port << 8) + head[5]; 00394 sock_remained_size[sn] = head[6]; 00395 sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7]; 00396 *packinfo = 0x80; 00397 } 00398 if(len < sock_remained_size[sn]) pack_len = len; 00399 else pack_len = sock_remained_size[sn]; 00400 // 00401 // Need to packet length check (default 1472) 00402 // 00403 wiz_recv_data(sn, buf, pack_len); // data copy. 00404 break; 00405 case Sn_MR_MACRAW : 00406 if(sock_remained_size[sn] == 0) 00407 { 00408 wiz_recv_data(sn, head, 2); 00409 setSn_CR(sn,Sn_CR_RECV); 00410 while(getSn_CR(sn)); 00411 // read peer's IP address, port number & packet length 00412 sock_remained_size[sn] = head[0]; 00413 sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1]; 00414 if(sock_remained_size[sn] > 1514) 00415 { 00416 close(sn); 00417 return SOCKFATAL_PACKLEN; 00418 } 00419 } 00420 if(len < sock_remained_size[sn]) pack_len = len; 00421 else pack_len = sock_remained_size[sn]; 00422 wiz_recv_data(sn,buf,pack_len); 00423 break; 00424 default: 00425 wiz_recv_ignore(sn, pack_len); // data copy. 00426 sock_remained_size[sn] = pack_len; 00427 break; 00428 } 00429 setSn_CR(sn,Sn_CR_RECV); 00430 /* wait to process the command... */ 00431 while(getSn_CR(sn)) ; 00432 sock_remained_size[sn] -= pack_len; 00433 if(sock_remained_size[sn] != 0) *packinfo |= 0x01; 00434 return pack_len; 00435 } 00436 00437 00438 int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg) 00439 { 00440 uint8_t tmp = 0; 00441 CHECK_SOCKNUM(); 00442 switch(cstype) 00443 { 00444 case CS_SET_IOMODE: 00445 tmp = *((uint8_t*)arg); 00446 if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1<<sn); 00447 else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn); 00448 else return SOCKERR_ARG; 00449 break; 00450 case CS_GET_IOMODE: 00451 *((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; 00452 break; 00453 case CS_GET_MAXTXBUF: 00454 *((uint16_t*)arg) = getSn_TxMAX(sn); 00455 break; 00456 case CS_GET_MAXRXBUF: 00457 *((uint16_t*)arg) = getSn_RxMAX(sn); 00458 break; 00459 case CS_CLR_INTERRUPT: 00460 if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; 00461 setSn_IR(sn,*(uint8_t*)arg); 00462 break; 00463 case CS_GET_INTERRUPT: 00464 *((uint8_t*)arg) = getSn_IR(sn); 00465 break; 00466 case CS_SET_INTMASK: 00467 if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; 00468 setSn_IMR(sn,*(uint8_t*)arg); 00469 break; 00470 case CS_GET_INTMASK: 00471 *((uint8_t*)arg) = getSn_IMR(sn); 00472 default: 00473 return SOCKERR_ARG; 00474 } 00475 return SOCK_OK; 00476 } 00477 00478 int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg) 00479 { 00480 00481 CHECK_SOCKNUM(); 00482 switch(sotype) 00483 { 00484 case SO_TTL: 00485 setSn_TTL(sn,*(uint8_t*)arg); 00486 break; 00487 case SO_TOS: 00488 setSn_TOS(sn,*(uint8_t*)arg); 00489 break; 00490 case SO_MSS: 00491 setSn_MSSR(sn,*(uint16_t*)arg); 00492 break; 00493 case SO_DESTIP: 00494 setSn_DIPR(sn, (uint8_t*)arg); 00495 break; 00496 case SO_DESTPORT: 00497 setSn_DPORT(sn, *(uint16_t*)arg); 00498 break; 00499 case SO_KEEPALIVESEND: 00500 CHECK_SOCKMODE(Sn_MR_TCP); 00501 if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; 00502 setSn_CR(sn,Sn_CR_SEND_KEEP); 00503 while(getSn_CR(sn) != 0) 00504 { 00505 if (getSn_IR(sn) & Sn_IR_TIMEOUT) 00506 { 00507 setSn_IR(sn, Sn_IR_TIMEOUT); 00508 return SOCKERR_TIMEOUT; 00509 } 00510 } 00511 break; 00512 case SO_KEEPALIVEAUTO: 00513 CHECK_SOCKMODE(Sn_MR_TCP); 00514 setSn_KPALVTR(sn,*(uint8_t*)arg); 00515 break; 00516 default: 00517 return SOCKERR_ARG; 00518 } 00519 return SOCK_OK; 00520 } 00521 00522 int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg) 00523 { 00524 CHECK_SOCKNUM(); 00525 switch(sotype) 00526 { 00527 case SO_FLAG: 00528 *(uint8_t*)arg = getSn_MR(sn) & 0xF0; 00529 break; 00530 case SO_TTL: 00531 *(uint8_t*) arg = getSn_TTL(sn); 00532 break; 00533 case SO_TOS: 00534 *(uint8_t*) arg = getSn_TOS(sn); 00535 break; 00536 case SO_MSS: 00537 *(uint8_t*) arg = getSn_MSSR(sn); 00538 case SO_DESTIP: 00539 getSn_DIPR(sn, (uint8_t*)arg); 00540 break; 00541 case SO_DESTPORT: 00542 *(uint16_t*) arg = getSn_DPORT(sn); 00543 break; 00544 case SO_KEEPALIVEAUTO: 00545 CHECK_SOCKMODE(Sn_MR_TCP); 00546 *(uint16_t*) arg = getSn_KPALVTR(sn); 00547 break; 00548 case SO_SENDBUF: 00549 *(uint16_t*) arg = getSn_TX_FSR(sn); 00550 case SO_RECVBUF: 00551 *(uint16_t*) arg = getSn_RX_RSR(sn); 00552 case SO_STATUS: 00553 *(uint8_t*) arg = getSn_SR(sn); 00554 break; 00555 case SO_REMAINSIZE: 00556 if(getSn_MR(sn) == Sn_MR_TCP) 00557 *(uint16_t*)arg = getSn_RX_RSR(sn); 00558 else 00559 *(uint16_t*)arg = sock_remained_size[sn]; 00560 break; 00561 default: 00562 return SOCKERR_SOCKOPT; 00563 } 00564 return SOCK_OK; 00565 }
Generated on Tue Jul 12 2022 18:48:21 by 1.7.2