Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
WIZ550io
W5500