Jinbuhm Kim
/
W5500_Driver
Wiznet W5500 driver and TCP/UDP loopback
Ethernet/socket.c@0:2513c6696bdc, 2013-12-13 (annotated)
- Committer:
- jbkim
- Date:
- Fri Dec 13 07:35:58 2013 +0000
- Revision:
- 0:2513c6696bdc
Wiznet W5500 library and TCP/UDP loopback program for mbed
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jbkim | 0:2513c6696bdc | 1 | /* Wiznet W5500 Library |
jbkim | 0:2513c6696bdc | 2 | * Copyright (c) 2013, WIZnet Co., LTD. |
jbkim | 0:2513c6696bdc | 3 | * |
jbkim | 0:2513c6696bdc | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
jbkim | 0:2513c6696bdc | 5 | * you may not use this file except in compliance with the License. |
jbkim | 0:2513c6696bdc | 6 | * You may obtain a copy of the License at |
jbkim | 0:2513c6696bdc | 7 | * |
jbkim | 0:2513c6696bdc | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
jbkim | 0:2513c6696bdc | 9 | * |
jbkim | 0:2513c6696bdc | 10 | * Unless required by applicable law or agreed to in writing, software |
jbkim | 0:2513c6696bdc | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
jbkim | 0:2513c6696bdc | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
jbkim | 0:2513c6696bdc | 13 | * See the License for the specific language governing permissions and |
jbkim | 0:2513c6696bdc | 14 | * limitations under the License. |
jbkim | 0:2513c6696bdc | 15 | */ |
jbkim | 0:2513c6696bdc | 16 | |
jbkim | 0:2513c6696bdc | 17 | #include "socket.h" |
jbkim | 0:2513c6696bdc | 18 | |
jbkim | 0:2513c6696bdc | 19 | #define SOCK_ANY_PORT_NUM 0xC000; |
jbkim | 0:2513c6696bdc | 20 | |
jbkim | 0:2513c6696bdc | 21 | static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; |
jbkim | 0:2513c6696bdc | 22 | static uint16_t sock_io_mode = 0; |
jbkim | 0:2513c6696bdc | 23 | static uint16_t sock_is_sending = 0; |
jbkim | 0:2513c6696bdc | 24 | static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; |
jbkim | 0:2513c6696bdc | 25 | |
jbkim | 0:2513c6696bdc | 26 | #define CHECK_SOCKNUM() \ |
jbkim | 0:2513c6696bdc | 27 | do{ \ |
jbkim | 0:2513c6696bdc | 28 | if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ |
jbkim | 0:2513c6696bdc | 29 | }while(0); \ |
jbkim | 0:2513c6696bdc | 30 | |
jbkim | 0:2513c6696bdc | 31 | #define CHECK_SOCKMODE(mode) \ |
jbkim | 0:2513c6696bdc | 32 | do{ \ |
jbkim | 0:2513c6696bdc | 33 | if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ |
jbkim | 0:2513c6696bdc | 34 | }while(0); \ |
jbkim | 0:2513c6696bdc | 35 | |
jbkim | 0:2513c6696bdc | 36 | #define CHECK_SOCKINIT() \ |
jbkim | 0:2513c6696bdc | 37 | do{ \ |
jbkim | 0:2513c6696bdc | 38 | if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ |
jbkim | 0:2513c6696bdc | 39 | }while(0); \ |
jbkim | 0:2513c6696bdc | 40 | |
jbkim | 0:2513c6696bdc | 41 | #define CHECK_SOCKDATA() \ |
jbkim | 0:2513c6696bdc | 42 | do{ \ |
jbkim | 0:2513c6696bdc | 43 | if(len == 0) return SOCKERR_DATALEN; \ |
jbkim | 0:2513c6696bdc | 44 | }while(0); \ |
jbkim | 0:2513c6696bdc | 45 | |
jbkim | 0:2513c6696bdc | 46 | |
jbkim | 0:2513c6696bdc | 47 | |
jbkim | 0:2513c6696bdc | 48 | int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) |
jbkim | 0:2513c6696bdc | 49 | { |
jbkim | 0:2513c6696bdc | 50 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 51 | switch(protocol) |
jbkim | 0:2513c6696bdc | 52 | { |
jbkim | 0:2513c6696bdc | 53 | case Sn_MR_TCP : |
jbkim | 0:2513c6696bdc | 54 | case Sn_MR_UDP : |
jbkim | 0:2513c6696bdc | 55 | case Sn_MR_MACRAW : |
jbkim | 0:2513c6696bdc | 56 | break; |
jbkim | 0:2513c6696bdc | 57 | default : |
jbkim | 0:2513c6696bdc | 58 | return SOCKERR_SOCKMODE; |
jbkim | 0:2513c6696bdc | 59 | } |
jbkim | 0:2513c6696bdc | 60 | if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; |
jbkim | 0:2513c6696bdc | 61 | |
jbkim | 0:2513c6696bdc | 62 | if(flag != 0) |
jbkim | 0:2513c6696bdc | 63 | { |
jbkim | 0:2513c6696bdc | 64 | switch(protocol) |
jbkim | 0:2513c6696bdc | 65 | { |
jbkim | 0:2513c6696bdc | 66 | case Sn_MR_TCP: |
jbkim | 0:2513c6696bdc | 67 | if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; |
jbkim | 0:2513c6696bdc | 68 | break; |
jbkim | 0:2513c6696bdc | 69 | case Sn_MR_UDP: |
jbkim | 0:2513c6696bdc | 70 | if(flag & SF_IGMP_VER2) |
jbkim | 0:2513c6696bdc | 71 | { |
jbkim | 0:2513c6696bdc | 72 | if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; |
jbkim | 0:2513c6696bdc | 73 | } |
jbkim | 0:2513c6696bdc | 74 | if(flag & SF_UNI_BLOCK) |
jbkim | 0:2513c6696bdc | 75 | { |
jbkim | 0:2513c6696bdc | 76 | if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; |
jbkim | 0:2513c6696bdc | 77 | } |
jbkim | 0:2513c6696bdc | 78 | break; |
jbkim | 0:2513c6696bdc | 79 | default: |
jbkim | 0:2513c6696bdc | 80 | break; |
jbkim | 0:2513c6696bdc | 81 | } |
jbkim | 0:2513c6696bdc | 82 | } |
jbkim | 0:2513c6696bdc | 83 | close(sn); |
jbkim | 0:2513c6696bdc | 84 | setSn_MR(sn, (protocol | (flag & 0xF0))); |
jbkim | 0:2513c6696bdc | 85 | if(!port) |
jbkim | 0:2513c6696bdc | 86 | { |
jbkim | 0:2513c6696bdc | 87 | port = sock_any_port++; |
jbkim | 0:2513c6696bdc | 88 | if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; |
jbkim | 0:2513c6696bdc | 89 | } |
jbkim | 0:2513c6696bdc | 90 | setSn_PORT(sn,port); |
jbkim | 0:2513c6696bdc | 91 | setSn_CR(sn,Sn_CR_OPEN); |
jbkim | 0:2513c6696bdc | 92 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 93 | sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); |
jbkim | 0:2513c6696bdc | 94 | sock_is_sending &= ~(1<<sn); |
jbkim | 0:2513c6696bdc | 95 | sock_remained_size[sn] = 0; |
jbkim | 0:2513c6696bdc | 96 | while(getSn_SR(sn) == SOCK_CLOSED); |
jbkim | 0:2513c6696bdc | 97 | return (int8_t)sn; |
jbkim | 0:2513c6696bdc | 98 | } |
jbkim | 0:2513c6696bdc | 99 | |
jbkim | 0:2513c6696bdc | 100 | int8_t close(uint8_t sn) |
jbkim | 0:2513c6696bdc | 101 | { |
jbkim | 0:2513c6696bdc | 102 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 103 | |
jbkim | 0:2513c6696bdc | 104 | setSn_CR(sn,Sn_CR_CLOSE); |
jbkim | 0:2513c6696bdc | 105 | /* wait to process the command... */ |
jbkim | 0:2513c6696bdc | 106 | while( getSn_CR(sn) ); |
jbkim | 0:2513c6696bdc | 107 | /* clear all interrupt of the socket. */ |
jbkim | 0:2513c6696bdc | 108 | setSn_IR(sn, 0xFF); |
jbkim | 0:2513c6696bdc | 109 | sock_is_sending &= ~(1<<sn); |
jbkim | 0:2513c6696bdc | 110 | sock_remained_size[sn] = 0; |
jbkim | 0:2513c6696bdc | 111 | while(getSn_SR(sn) != SOCK_CLOSED); |
jbkim | 0:2513c6696bdc | 112 | return SOCK_OK; |
jbkim | 0:2513c6696bdc | 113 | } |
jbkim | 0:2513c6696bdc | 114 | |
jbkim | 0:2513c6696bdc | 115 | int8_t listen(uint8_t sn) |
jbkim | 0:2513c6696bdc | 116 | { |
jbkim | 0:2513c6696bdc | 117 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 118 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 119 | CHECK_SOCKINIT(); |
jbkim | 0:2513c6696bdc | 120 | setSn_CR(sn,Sn_CR_LISTEN); |
jbkim | 0:2513c6696bdc | 121 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 122 | while(getSn_SR(sn) != SOCK_LISTEN) |
jbkim | 0:2513c6696bdc | 123 | { |
jbkim | 0:2513c6696bdc | 124 | if(getSn_CR(sn) == SOCK_CLOSED) |
jbkim | 0:2513c6696bdc | 125 | { |
jbkim | 0:2513c6696bdc | 126 | close(sn); |
jbkim | 0:2513c6696bdc | 127 | return SOCKERR_SOCKCLOSED; |
jbkim | 0:2513c6696bdc | 128 | } |
jbkim | 0:2513c6696bdc | 129 | } |
jbkim | 0:2513c6696bdc | 130 | return SOCK_OK; |
jbkim | 0:2513c6696bdc | 131 | } |
jbkim | 0:2513c6696bdc | 132 | |
jbkim | 0:2513c6696bdc | 133 | |
jbkim | 0:2513c6696bdc | 134 | int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port) |
jbkim | 0:2513c6696bdc | 135 | { |
jbkim | 0:2513c6696bdc | 136 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 137 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 138 | CHECK_SOCKINIT(); |
jbkim | 0:2513c6696bdc | 139 | if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; |
jbkim | 0:2513c6696bdc | 140 | if(port == 0) return SOCKERR_PORTZERO; |
jbkim | 0:2513c6696bdc | 141 | setSn_DIPR(sn,addr); |
jbkim | 0:2513c6696bdc | 142 | setSn_DPORT(sn,port); |
jbkim | 0:2513c6696bdc | 143 | // setSUBR(); // set the subnet mask register |
jbkim | 0:2513c6696bdc | 144 | setSn_CR(sn,Sn_CR_CONNECT); |
jbkim | 0:2513c6696bdc | 145 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 146 | if(sock_io_mode & (1<<sn)) return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 147 | while(getSn_SR(sn) != SOCK_ESTABLISHED) |
jbkim | 0:2513c6696bdc | 148 | { |
jbkim | 0:2513c6696bdc | 149 | if (getSn_IR(sn) & Sn_IR_TIMEOUT) |
jbkim | 0:2513c6696bdc | 150 | { |
jbkim | 0:2513c6696bdc | 151 | setSn_IR(sn, Sn_IR_TIMEOUT); |
jbkim | 0:2513c6696bdc | 152 | return SOCKERR_TIMEOUT; |
jbkim | 0:2513c6696bdc | 153 | } |
jbkim | 0:2513c6696bdc | 154 | } |
jbkim | 0:2513c6696bdc | 155 | // clearSUBR(); // clear the subnet mask again and keep it because of the ARP errata of W5100 |
jbkim | 0:2513c6696bdc | 156 | return SOCK_OK; |
jbkim | 0:2513c6696bdc | 157 | } |
jbkim | 0:2513c6696bdc | 158 | |
jbkim | 0:2513c6696bdc | 159 | int8_t disconnect(uint8_t sn) |
jbkim | 0:2513c6696bdc | 160 | { |
jbkim | 0:2513c6696bdc | 161 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 162 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 163 | setSn_CR(sn,Sn_CR_DISCON); |
jbkim | 0:2513c6696bdc | 164 | /* wait to process the command... */ |
jbkim | 0:2513c6696bdc | 165 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 166 | sock_is_sending &= ~(1<<sn); |
jbkim | 0:2513c6696bdc | 167 | if(sock_io_mode & (1<<sn)) return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 168 | while(getSn_SR(sn) != SOCK_CLOSED) |
jbkim | 0:2513c6696bdc | 169 | { |
jbkim | 0:2513c6696bdc | 170 | if(getSn_IR(sn) & Sn_IR_TIMEOUT) |
jbkim | 0:2513c6696bdc | 171 | { |
jbkim | 0:2513c6696bdc | 172 | close(sn); |
jbkim | 0:2513c6696bdc | 173 | return SOCKERR_TIMEOUT; |
jbkim | 0:2513c6696bdc | 174 | } |
jbkim | 0:2513c6696bdc | 175 | } |
jbkim | 0:2513c6696bdc | 176 | return SOCK_OK; |
jbkim | 0:2513c6696bdc | 177 | } |
jbkim | 0:2513c6696bdc | 178 | |
jbkim | 0:2513c6696bdc | 179 | int32_t send(uint8_t sn, uint8_t * buf, uint16_t len) |
jbkim | 0:2513c6696bdc | 180 | { |
jbkim | 0:2513c6696bdc | 181 | uint8_t tmp=0; |
jbkim | 0:2513c6696bdc | 182 | uint16_t freesize=0; |
jbkim | 0:2513c6696bdc | 183 | |
jbkim | 0:2513c6696bdc | 184 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 185 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 186 | CHECK_SOCKDATA(); |
jbkim | 0:2513c6696bdc | 187 | tmp = getSn_SR(sn); |
jbkim | 0:2513c6696bdc | 188 | if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS; |
jbkim | 0:2513c6696bdc | 189 | if( sock_is_sending & (1<<sn) ) |
jbkim | 0:2513c6696bdc | 190 | { |
jbkim | 0:2513c6696bdc | 191 | tmp = getSn_IR(sn); |
jbkim | 0:2513c6696bdc | 192 | if(tmp & Sn_IR_SENDOK) |
jbkim | 0:2513c6696bdc | 193 | { |
jbkim | 0:2513c6696bdc | 194 | setSn_IR(sn, Sn_IR_SENDOK); |
jbkim | 0:2513c6696bdc | 195 | sock_is_sending &= ~(1<<sn); |
jbkim | 0:2513c6696bdc | 196 | } |
jbkim | 0:2513c6696bdc | 197 | else if(tmp & Sn_IR_TIMEOUT) |
jbkim | 0:2513c6696bdc | 198 | { |
jbkim | 0:2513c6696bdc | 199 | close(sn); |
jbkim | 0:2513c6696bdc | 200 | return SOCKERR_TIMEOUT; |
jbkim | 0:2513c6696bdc | 201 | } |
jbkim | 0:2513c6696bdc | 202 | else return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 203 | } |
jbkim | 0:2513c6696bdc | 204 | freesize = getSn_TxMAX(sn); |
jbkim | 0:2513c6696bdc | 205 | if (len > freesize) len = freesize; // check size not to exceed MAX size. |
jbkim | 0:2513c6696bdc | 206 | while(1) |
jbkim | 0:2513c6696bdc | 207 | { |
jbkim | 0:2513c6696bdc | 208 | freesize = getSn_TX_FSR(sn); |
jbkim | 0:2513c6696bdc | 209 | tmp = getSn_SR(sn); |
jbkim | 0:2513c6696bdc | 210 | if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) |
jbkim | 0:2513c6696bdc | 211 | { |
jbkim | 0:2513c6696bdc | 212 | close(sn); |
jbkim | 0:2513c6696bdc | 213 | return SOCKERR_SOCKSTATUS; |
jbkim | 0:2513c6696bdc | 214 | } |
jbkim | 0:2513c6696bdc | 215 | if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 216 | if(len <= freesize) break; |
jbkim | 0:2513c6696bdc | 217 | } |
jbkim | 0:2513c6696bdc | 218 | wiz_send_data(sn, buf, len); |
jbkim | 0:2513c6696bdc | 219 | setSn_CR(sn,Sn_CR_SEND); |
jbkim | 0:2513c6696bdc | 220 | /* wait to process the command... */ |
jbkim | 0:2513c6696bdc | 221 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 222 | sock_is_sending |= (1 << sn); |
jbkim | 0:2513c6696bdc | 223 | /* |
jbkim | 0:2513c6696bdc | 224 | if(sock_io_mode & (1<<sn)) return len; |
jbkim | 0:2513c6696bdc | 225 | while( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) !=Sn_IR_SENDOK ) |
jbkim | 0:2513c6696bdc | 226 | { |
jbkim | 0:2513c6696bdc | 227 | if(tmp & Sn_IR_TIMEOUT) |
jbkim | 0:2513c6696bdc | 228 | { |
jbkim | 0:2513c6696bdc | 229 | close(sn); |
jbkim | 0:2513c6696bdc | 230 | return SOCKERR_TIMEOUT; |
jbkim | 0:2513c6696bdc | 231 | } |
jbkim | 0:2513c6696bdc | 232 | } |
jbkim | 0:2513c6696bdc | 233 | setSn_IR(sn, Sn_IR_SENDOK); |
jbkim | 0:2513c6696bdc | 234 | */ |
jbkim | 0:2513c6696bdc | 235 | return len; |
jbkim | 0:2513c6696bdc | 236 | } |
jbkim | 0:2513c6696bdc | 237 | |
jbkim | 0:2513c6696bdc | 238 | |
jbkim | 0:2513c6696bdc | 239 | int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len) |
jbkim | 0:2513c6696bdc | 240 | { |
jbkim | 0:2513c6696bdc | 241 | uint8_t tmp = 0; |
jbkim | 0:2513c6696bdc | 242 | uint16_t recvsize = 0; |
jbkim | 0:2513c6696bdc | 243 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 244 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 245 | CHECK_SOCKDATA(); |
jbkim | 0:2513c6696bdc | 246 | |
jbkim | 0:2513c6696bdc | 247 | recvsize = getSn_RxMAX(sn); |
jbkim | 0:2513c6696bdc | 248 | if(recvsize < len) len = recvsize; |
jbkim | 0:2513c6696bdc | 249 | while(1) |
jbkim | 0:2513c6696bdc | 250 | { |
jbkim | 0:2513c6696bdc | 251 | recvsize = getSn_RX_RSR(sn); |
jbkim | 0:2513c6696bdc | 252 | tmp = getSn_SR(sn); |
jbkim | 0:2513c6696bdc | 253 | if (tmp != SOCK_ESTABLISHED) |
jbkim | 0:2513c6696bdc | 254 | { |
jbkim | 0:2513c6696bdc | 255 | if(tmp == SOCK_CLOSE_WAIT) |
jbkim | 0:2513c6696bdc | 256 | { |
jbkim | 0:2513c6696bdc | 257 | if(recvsize != 0) break; |
jbkim | 0:2513c6696bdc | 258 | else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) |
jbkim | 0:2513c6696bdc | 259 | { |
jbkim | 0:2513c6696bdc | 260 | close(sn); |
jbkim | 0:2513c6696bdc | 261 | return SOCKERR_SOCKSTATUS; |
jbkim | 0:2513c6696bdc | 262 | } |
jbkim | 0:2513c6696bdc | 263 | } |
jbkim | 0:2513c6696bdc | 264 | else |
jbkim | 0:2513c6696bdc | 265 | { |
jbkim | 0:2513c6696bdc | 266 | close(sn); |
jbkim | 0:2513c6696bdc | 267 | return SOCKERR_SOCKSTATUS; |
jbkim | 0:2513c6696bdc | 268 | } |
jbkim | 0:2513c6696bdc | 269 | } |
jbkim | 0:2513c6696bdc | 270 | if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 271 | if(recvsize != 0) break; |
jbkim | 0:2513c6696bdc | 272 | }; |
jbkim | 0:2513c6696bdc | 273 | if(recvsize < len) len = recvsize; |
jbkim | 0:2513c6696bdc | 274 | wiz_recv_data(sn, buf, len); |
jbkim | 0:2513c6696bdc | 275 | setSn_CR(sn,Sn_CR_RECV); |
jbkim | 0:2513c6696bdc | 276 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 277 | return len; |
jbkim | 0:2513c6696bdc | 278 | } |
jbkim | 0:2513c6696bdc | 279 | |
jbkim | 0:2513c6696bdc | 280 | int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port) |
jbkim | 0:2513c6696bdc | 281 | { |
jbkim | 0:2513c6696bdc | 282 | uint8_t tmp = 0; |
jbkim | 0:2513c6696bdc | 283 | uint16_t freesize = 0; |
jbkim | 0:2513c6696bdc | 284 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 285 | //CHECK_SOCKMODE(Sn_MR_UDP); |
jbkim | 0:2513c6696bdc | 286 | switch(getSn_MR(sn) & 0x0F) |
jbkim | 0:2513c6696bdc | 287 | { |
jbkim | 0:2513c6696bdc | 288 | case Sn_MR_UDP: |
jbkim | 0:2513c6696bdc | 289 | case Sn_MR_MACRAW: |
jbkim | 0:2513c6696bdc | 290 | break; |
jbkim | 0:2513c6696bdc | 291 | default: |
jbkim | 0:2513c6696bdc | 292 | return SOCKERR_SOCKMODE; |
jbkim | 0:2513c6696bdc | 293 | } |
jbkim | 0:2513c6696bdc | 294 | CHECK_SOCKDATA(); |
jbkim | 0:2513c6696bdc | 295 | if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; |
jbkim | 0:2513c6696bdc | 296 | if(port == 0) return SOCKERR_PORTZERO; |
jbkim | 0:2513c6696bdc | 297 | tmp = getSn_SR(sn); |
jbkim | 0:2513c6696bdc | 298 | if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS; |
jbkim | 0:2513c6696bdc | 299 | |
jbkim | 0:2513c6696bdc | 300 | if( sock_is_sending & (1<<sn) ) |
jbkim | 0:2513c6696bdc | 301 | { |
jbkim | 0:2513c6696bdc | 302 | tmp = getSn_IR(sn); |
jbkim | 0:2513c6696bdc | 303 | if(tmp & Sn_IR_SENDOK) |
jbkim | 0:2513c6696bdc | 304 | { |
jbkim | 0:2513c6696bdc | 305 | setSn_IR(sn, Sn_IR_SENDOK); |
jbkim | 0:2513c6696bdc | 306 | sock_is_sending &= ~(1<<sn); |
jbkim | 0:2513c6696bdc | 307 | } |
jbkim | 0:2513c6696bdc | 308 | else if(tmp & Sn_IR_TIMEOUT) |
jbkim | 0:2513c6696bdc | 309 | { |
jbkim | 0:2513c6696bdc | 310 | close(sn); |
jbkim | 0:2513c6696bdc | 311 | return SOCKERR_TIMEOUT; |
jbkim | 0:2513c6696bdc | 312 | } |
jbkim | 0:2513c6696bdc | 313 | else return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 314 | } |
jbkim | 0:2513c6696bdc | 315 | |
jbkim | 0:2513c6696bdc | 316 | setSn_DIPR(sn,addr); |
jbkim | 0:2513c6696bdc | 317 | setSn_DPORT(sn,port); |
jbkim | 0:2513c6696bdc | 318 | freesize = getSn_TxMAX(sn); |
jbkim | 0:2513c6696bdc | 319 | if (len > freesize) len = freesize; // check size not to exceed MAX size. |
jbkim | 0:2513c6696bdc | 320 | while(1) |
jbkim | 0:2513c6696bdc | 321 | { |
jbkim | 0:2513c6696bdc | 322 | freesize = getSn_TX_FSR(sn); |
jbkim | 0:2513c6696bdc | 323 | if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; |
jbkim | 0:2513c6696bdc | 324 | if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 325 | if(len <= freesize) break; |
jbkim | 0:2513c6696bdc | 326 | }; |
jbkim | 0:2513c6696bdc | 327 | wiz_send_data(sn, buf, len); |
jbkim | 0:2513c6696bdc | 328 | // setSUBR(); // set the subnet mask register |
jbkim | 0:2513c6696bdc | 329 | setSn_CR(sn,Sn_CR_SEND); |
jbkim | 0:2513c6696bdc | 330 | /* wait to process the command... */ |
jbkim | 0:2513c6696bdc | 331 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 332 | sock_is_sending |= (1<<sn); |
jbkim | 0:2513c6696bdc | 333 | #if 0 |
jbkim | 0:2513c6696bdc | 334 | if(sock_io_mode & (1<<sn)) return len; |
jbkim | 0:2513c6696bdc | 335 | while ( ((tmp = getSn_IR(sn)) & Sn_IR_SENDOK) != Sn_IR_SENDOK ) |
jbkim | 0:2513c6696bdc | 336 | { |
jbkim | 0:2513c6696bdc | 337 | if(tmp & Sn_IR_TIMEOUT) |
jbkim | 0:2513c6696bdc | 338 | { |
jbkim | 0:2513c6696bdc | 339 | setSn_IR(sn, (Sn_IR_SENDOK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */ |
jbkim | 0:2513c6696bdc | 340 | return SOCKERR_TIMEOUT; |
jbkim | 0:2513c6696bdc | 341 | } |
jbkim | 0:2513c6696bdc | 342 | } |
jbkim | 0:2513c6696bdc | 343 | // clearSUBR(); // clear the subnet mask again and keep it because of the ARP errata of W5100 |
jbkim | 0:2513c6696bdc | 344 | setSn_IR(sn, Sn_IR_SENDOK); |
jbkim | 0:2513c6696bdc | 345 | #endif |
jbkim | 0:2513c6696bdc | 346 | return len; |
jbkim | 0:2513c6696bdc | 347 | } |
jbkim | 0:2513c6696bdc | 348 | |
jbkim | 0:2513c6696bdc | 349 | |
jbkim | 0:2513c6696bdc | 350 | |
jbkim | 0:2513c6696bdc | 351 | int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port, uint8_t* packinfo) |
jbkim | 0:2513c6696bdc | 352 | { |
jbkim | 0:2513c6696bdc | 353 | uint8_t mr; |
jbkim | 0:2513c6696bdc | 354 | uint8_t head[8]; |
jbkim | 0:2513c6696bdc | 355 | uint16_t pack_len=0; |
jbkim | 0:2513c6696bdc | 356 | |
jbkim | 0:2513c6696bdc | 357 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 358 | //CHECK_SOCKMODE(Sn_MR_UDP); |
jbkim | 0:2513c6696bdc | 359 | switch((mr=getSn_MR(sn)) & 0x0F) |
jbkim | 0:2513c6696bdc | 360 | { |
jbkim | 0:2513c6696bdc | 361 | case Sn_MR_UDP: |
jbkim | 0:2513c6696bdc | 362 | case Sn_MR_MACRAW: |
jbkim | 0:2513c6696bdc | 363 | break; |
jbkim | 0:2513c6696bdc | 364 | default: |
jbkim | 0:2513c6696bdc | 365 | return SOCKERR_SOCKMODE; |
jbkim | 0:2513c6696bdc | 366 | } |
jbkim | 0:2513c6696bdc | 367 | CHECK_SOCKDATA(); |
jbkim | 0:2513c6696bdc | 368 | if(sock_remained_size[sn] == 0) |
jbkim | 0:2513c6696bdc | 369 | { |
jbkim | 0:2513c6696bdc | 370 | while(1) |
jbkim | 0:2513c6696bdc | 371 | { |
jbkim | 0:2513c6696bdc | 372 | pack_len = getSn_RX_RSR(sn); |
jbkim | 0:2513c6696bdc | 373 | if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; |
jbkim | 0:2513c6696bdc | 374 | if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY; |
jbkim | 0:2513c6696bdc | 375 | if(pack_len != 0) break; |
jbkim | 0:2513c6696bdc | 376 | }; |
jbkim | 0:2513c6696bdc | 377 | } |
jbkim | 0:2513c6696bdc | 378 | *packinfo = 0x00; |
jbkim | 0:2513c6696bdc | 379 | switch (mr & 0x07) |
jbkim | 0:2513c6696bdc | 380 | { |
jbkim | 0:2513c6696bdc | 381 | case Sn_MR_UDP : |
jbkim | 0:2513c6696bdc | 382 | if(sock_remained_size[sn] == 0) |
jbkim | 0:2513c6696bdc | 383 | { |
jbkim | 0:2513c6696bdc | 384 | wiz_recv_data(sn, head, 8); |
jbkim | 0:2513c6696bdc | 385 | setSn_CR(sn,Sn_CR_RECV); |
jbkim | 0:2513c6696bdc | 386 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 387 | // read peer's IP address, port number & packet length |
jbkim | 0:2513c6696bdc | 388 | addr[0] = head[0]; |
jbkim | 0:2513c6696bdc | 389 | addr[1] = head[1]; |
jbkim | 0:2513c6696bdc | 390 | addr[2] = head[2]; |
jbkim | 0:2513c6696bdc | 391 | addr[3] = head[3]; |
jbkim | 0:2513c6696bdc | 392 | *port = head[4]; |
jbkim | 0:2513c6696bdc | 393 | *port = (*port << 8) + head[5]; |
jbkim | 0:2513c6696bdc | 394 | sock_remained_size[sn] = head[6]; |
jbkim | 0:2513c6696bdc | 395 | sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7]; |
jbkim | 0:2513c6696bdc | 396 | *packinfo = 0x80; |
jbkim | 0:2513c6696bdc | 397 | } |
jbkim | 0:2513c6696bdc | 398 | if(len < sock_remained_size[sn]) pack_len = len; |
jbkim | 0:2513c6696bdc | 399 | else pack_len = sock_remained_size[sn]; |
jbkim | 0:2513c6696bdc | 400 | // |
jbkim | 0:2513c6696bdc | 401 | // Need to packet length check (default 1472) |
jbkim | 0:2513c6696bdc | 402 | // |
jbkim | 0:2513c6696bdc | 403 | wiz_recv_data(sn, buf, pack_len); // data copy. |
jbkim | 0:2513c6696bdc | 404 | break; |
jbkim | 0:2513c6696bdc | 405 | case Sn_MR_MACRAW : |
jbkim | 0:2513c6696bdc | 406 | if(sock_remained_size[sn] == 0) |
jbkim | 0:2513c6696bdc | 407 | { |
jbkim | 0:2513c6696bdc | 408 | wiz_recv_data(sn, head, 2); |
jbkim | 0:2513c6696bdc | 409 | setSn_CR(sn,Sn_CR_RECV); |
jbkim | 0:2513c6696bdc | 410 | while(getSn_CR(sn)); |
jbkim | 0:2513c6696bdc | 411 | // read peer's IP address, port number & packet length |
jbkim | 0:2513c6696bdc | 412 | sock_remained_size[sn] = head[0]; |
jbkim | 0:2513c6696bdc | 413 | sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1]; |
jbkim | 0:2513c6696bdc | 414 | if(sock_remained_size[sn] > 1514) |
jbkim | 0:2513c6696bdc | 415 | { |
jbkim | 0:2513c6696bdc | 416 | close(sn); |
jbkim | 0:2513c6696bdc | 417 | return SOCKFATAL_PACKLEN; |
jbkim | 0:2513c6696bdc | 418 | } |
jbkim | 0:2513c6696bdc | 419 | } |
jbkim | 0:2513c6696bdc | 420 | if(len < sock_remained_size[sn]) pack_len = len; |
jbkim | 0:2513c6696bdc | 421 | else pack_len = sock_remained_size[sn]; |
jbkim | 0:2513c6696bdc | 422 | wiz_recv_data(sn,buf,pack_len); |
jbkim | 0:2513c6696bdc | 423 | break; |
jbkim | 0:2513c6696bdc | 424 | default: |
jbkim | 0:2513c6696bdc | 425 | wiz_recv_ignore(sn, pack_len); // data copy. |
jbkim | 0:2513c6696bdc | 426 | sock_remained_size[sn] = pack_len; |
jbkim | 0:2513c6696bdc | 427 | break; |
jbkim | 0:2513c6696bdc | 428 | } |
jbkim | 0:2513c6696bdc | 429 | setSn_CR(sn,Sn_CR_RECV); |
jbkim | 0:2513c6696bdc | 430 | /* wait to process the command... */ |
jbkim | 0:2513c6696bdc | 431 | while(getSn_CR(sn)) ; |
jbkim | 0:2513c6696bdc | 432 | sock_remained_size[sn] -= pack_len; |
jbkim | 0:2513c6696bdc | 433 | if(sock_remained_size[sn] != 0) *packinfo |= 0x01; |
jbkim | 0:2513c6696bdc | 434 | return pack_len; |
jbkim | 0:2513c6696bdc | 435 | } |
jbkim | 0:2513c6696bdc | 436 | |
jbkim | 0:2513c6696bdc | 437 | |
jbkim | 0:2513c6696bdc | 438 | int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg) |
jbkim | 0:2513c6696bdc | 439 | { |
jbkim | 0:2513c6696bdc | 440 | uint8_t tmp = 0; |
jbkim | 0:2513c6696bdc | 441 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 442 | switch(cstype) |
jbkim | 0:2513c6696bdc | 443 | { |
jbkim | 0:2513c6696bdc | 444 | case CS_SET_IOMODE: |
jbkim | 0:2513c6696bdc | 445 | tmp = *((uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 446 | if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1<<sn); |
jbkim | 0:2513c6696bdc | 447 | else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn); |
jbkim | 0:2513c6696bdc | 448 | else return SOCKERR_ARG; |
jbkim | 0:2513c6696bdc | 449 | break; |
jbkim | 0:2513c6696bdc | 450 | case CS_GET_IOMODE: |
jbkim | 0:2513c6696bdc | 451 | *((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; |
jbkim | 0:2513c6696bdc | 452 | break; |
jbkim | 0:2513c6696bdc | 453 | case CS_GET_MAXTXBUF: |
jbkim | 0:2513c6696bdc | 454 | *((uint16_t*)arg) = getSn_TxMAX(sn); |
jbkim | 0:2513c6696bdc | 455 | break; |
jbkim | 0:2513c6696bdc | 456 | case CS_GET_MAXRXBUF: |
jbkim | 0:2513c6696bdc | 457 | *((uint16_t*)arg) = getSn_RxMAX(sn); |
jbkim | 0:2513c6696bdc | 458 | break; |
jbkim | 0:2513c6696bdc | 459 | case CS_CLR_INTERRUPT: |
jbkim | 0:2513c6696bdc | 460 | if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; |
jbkim | 0:2513c6696bdc | 461 | setSn_IR(sn,*(uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 462 | break; |
jbkim | 0:2513c6696bdc | 463 | case CS_GET_INTERRUPT: |
jbkim | 0:2513c6696bdc | 464 | *((uint8_t*)arg) = getSn_IR(sn); |
jbkim | 0:2513c6696bdc | 465 | break; |
jbkim | 0:2513c6696bdc | 466 | case CS_SET_INTMASK: |
jbkim | 0:2513c6696bdc | 467 | if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; |
jbkim | 0:2513c6696bdc | 468 | setSn_IMR(sn,*(uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 469 | break; |
jbkim | 0:2513c6696bdc | 470 | case CS_GET_INTMASK: |
jbkim | 0:2513c6696bdc | 471 | *((uint8_t*)arg) = getSn_IMR(sn); |
jbkim | 0:2513c6696bdc | 472 | default: |
jbkim | 0:2513c6696bdc | 473 | return SOCKERR_ARG; |
jbkim | 0:2513c6696bdc | 474 | } |
jbkim | 0:2513c6696bdc | 475 | return SOCK_OK; |
jbkim | 0:2513c6696bdc | 476 | } |
jbkim | 0:2513c6696bdc | 477 | |
jbkim | 0:2513c6696bdc | 478 | int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg) |
jbkim | 0:2513c6696bdc | 479 | { |
jbkim | 0:2513c6696bdc | 480 | |
jbkim | 0:2513c6696bdc | 481 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 482 | switch(sotype) |
jbkim | 0:2513c6696bdc | 483 | { |
jbkim | 0:2513c6696bdc | 484 | case SO_TTL: |
jbkim | 0:2513c6696bdc | 485 | setSn_TTL(sn,*(uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 486 | break; |
jbkim | 0:2513c6696bdc | 487 | case SO_TOS: |
jbkim | 0:2513c6696bdc | 488 | setSn_TOS(sn,*(uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 489 | break; |
jbkim | 0:2513c6696bdc | 490 | case SO_MSS: |
jbkim | 0:2513c6696bdc | 491 | setSn_MSSR(sn,*(uint16_t*)arg); |
jbkim | 0:2513c6696bdc | 492 | break; |
jbkim | 0:2513c6696bdc | 493 | case SO_DESTIP: |
jbkim | 0:2513c6696bdc | 494 | setSn_DIPR(sn, (uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 495 | break; |
jbkim | 0:2513c6696bdc | 496 | case SO_DESTPORT: |
jbkim | 0:2513c6696bdc | 497 | setSn_DPORT(sn, *(uint16_t*)arg); |
jbkim | 0:2513c6696bdc | 498 | break; |
jbkim | 0:2513c6696bdc | 499 | case SO_KEEPALIVESEND: |
jbkim | 0:2513c6696bdc | 500 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 501 | if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; |
jbkim | 0:2513c6696bdc | 502 | setSn_CR(sn,Sn_CR_SEND_KEEP); |
jbkim | 0:2513c6696bdc | 503 | while(getSn_CR(sn) != 0) |
jbkim | 0:2513c6696bdc | 504 | { |
jbkim | 0:2513c6696bdc | 505 | if (getSn_IR(sn) & Sn_IR_TIMEOUT) |
jbkim | 0:2513c6696bdc | 506 | { |
jbkim | 0:2513c6696bdc | 507 | setSn_IR(sn, Sn_IR_TIMEOUT); |
jbkim | 0:2513c6696bdc | 508 | return SOCKERR_TIMEOUT; |
jbkim | 0:2513c6696bdc | 509 | } |
jbkim | 0:2513c6696bdc | 510 | } |
jbkim | 0:2513c6696bdc | 511 | break; |
jbkim | 0:2513c6696bdc | 512 | case SO_KEEPALIVEAUTO: |
jbkim | 0:2513c6696bdc | 513 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 514 | setSn_KPALVTR(sn,*(uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 515 | break; |
jbkim | 0:2513c6696bdc | 516 | default: |
jbkim | 0:2513c6696bdc | 517 | return SOCKERR_ARG; |
jbkim | 0:2513c6696bdc | 518 | } |
jbkim | 0:2513c6696bdc | 519 | return SOCK_OK; |
jbkim | 0:2513c6696bdc | 520 | } |
jbkim | 0:2513c6696bdc | 521 | |
jbkim | 0:2513c6696bdc | 522 | int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg) |
jbkim | 0:2513c6696bdc | 523 | { |
jbkim | 0:2513c6696bdc | 524 | CHECK_SOCKNUM(); |
jbkim | 0:2513c6696bdc | 525 | switch(sotype) |
jbkim | 0:2513c6696bdc | 526 | { |
jbkim | 0:2513c6696bdc | 527 | case SO_FLAG: |
jbkim | 0:2513c6696bdc | 528 | *(uint8_t*)arg = getSn_MR(sn) & 0xF0; |
jbkim | 0:2513c6696bdc | 529 | break; |
jbkim | 0:2513c6696bdc | 530 | case SO_TTL: |
jbkim | 0:2513c6696bdc | 531 | *(uint8_t*) arg = getSn_TTL(sn); |
jbkim | 0:2513c6696bdc | 532 | break; |
jbkim | 0:2513c6696bdc | 533 | case SO_TOS: |
jbkim | 0:2513c6696bdc | 534 | *(uint8_t*) arg = getSn_TOS(sn); |
jbkim | 0:2513c6696bdc | 535 | break; |
jbkim | 0:2513c6696bdc | 536 | case SO_MSS: |
jbkim | 0:2513c6696bdc | 537 | *(uint8_t*) arg = getSn_MSSR(sn); |
jbkim | 0:2513c6696bdc | 538 | case SO_DESTIP: |
jbkim | 0:2513c6696bdc | 539 | getSn_DIPR(sn, (uint8_t*)arg); |
jbkim | 0:2513c6696bdc | 540 | break; |
jbkim | 0:2513c6696bdc | 541 | case SO_DESTPORT: |
jbkim | 0:2513c6696bdc | 542 | *(uint16_t*) arg = getSn_DPORT(sn); |
jbkim | 0:2513c6696bdc | 543 | break; |
jbkim | 0:2513c6696bdc | 544 | case SO_KEEPALIVEAUTO: |
jbkim | 0:2513c6696bdc | 545 | CHECK_SOCKMODE(Sn_MR_TCP); |
jbkim | 0:2513c6696bdc | 546 | *(uint16_t*) arg = getSn_KPALVTR(sn); |
jbkim | 0:2513c6696bdc | 547 | break; |
jbkim | 0:2513c6696bdc | 548 | case SO_SENDBUF: |
jbkim | 0:2513c6696bdc | 549 | *(uint16_t*) arg = getSn_TX_FSR(sn); |
jbkim | 0:2513c6696bdc | 550 | case SO_RECVBUF: |
jbkim | 0:2513c6696bdc | 551 | *(uint16_t*) arg = getSn_RX_RSR(sn); |
jbkim | 0:2513c6696bdc | 552 | case SO_STATUS: |
jbkim | 0:2513c6696bdc | 553 | *(uint8_t*) arg = getSn_SR(sn); |
jbkim | 0:2513c6696bdc | 554 | break; |
jbkim | 0:2513c6696bdc | 555 | case SO_REMAINSIZE: |
jbkim | 0:2513c6696bdc | 556 | if(getSn_MR(sn) == Sn_MR_TCP) |
jbkim | 0:2513c6696bdc | 557 | *(uint16_t*)arg = getSn_RX_RSR(sn); |
jbkim | 0:2513c6696bdc | 558 | else |
jbkim | 0:2513c6696bdc | 559 | *(uint16_t*)arg = sock_remained_size[sn]; |
jbkim | 0:2513c6696bdc | 560 | break; |
jbkim | 0:2513c6696bdc | 561 | default: |
jbkim | 0:2513c6696bdc | 562 | return SOCKERR_SOCKOPT; |
jbkim | 0:2513c6696bdc | 563 | } |
jbkim | 0:2513c6696bdc | 564 | return SOCK_OK; |
jbkim | 0:2513c6696bdc | 565 | } |