前項の W5300をアクセスする関数を使って、UDP や TCP/IP を使いやすくするような関数群を書きます。
実は、socket に準じた関数群を書いたのですが、IN_ADDR とか、MCUで使うには無駄かな?と思える部分が多かったので書き直しました。
時間が許せば、関数ごとに説明を付け加えたいと思っていますが…
この程度書けば、後はアプリケーションで使うだけかな?という参考までにしてください。
なお、デバッグ中ですので、たびたび変更が入ると思います。
2010.04.03 更新
2010.11.16 修正 687行目
00001 /************************************************************************/ 00002 /* */ 00003 /* FILE : netapi.c */ 00004 /* DATE : 2010.01.20 */ 00005 /* DESCRIPTION : NetWork API */ 00006 /* CPU TYPE : NO ARCH */ 00007 /* CopyRight(C) by MCM Co.,Ltd. */ 00008 /************************************************************************/ 00009 #ifndef USE_ROM_BIOS 00010 00011 #include "typedef.h" 00012 #include "w5300.h" 00013 #include "global.h" 00014 #include "stdutils.h" 00015 #include "h8delay.h" 00016 #include "netapi.h" 00017 00018 00019 #if 0 00020 #define _NETAPI_DEBUG_PRINT_ (1) 00021 #endif 00022 00023 static SOCKET find_empty_socket(void); 00024 static NETAPI wait_change_state(SOCKET sock, ushort state); 00025 static bool check_transmit_done(SOCKET socket); 00026 static void do_send(SOCKET sock, void *buf, long len); 00027 static SOCKET w5300_open(ushort protocol, ushort myport); 00028 00029 00030 /************************************************************************/ 00031 /* */ 00032 /* 通信に必要なIP情報領域 */ 00033 /* */ 00034 /************************************************************************/ 00035 hw_address_t my_mac_adr = { 0x00, 0x50, 0xc2, 0x96, 0x01, 0x0e }; 00036 ip_address_t my_gw_adrs = { 192, 168, 0, 1 }; 00037 ip_address_t my_ip_mask = { 255, 255, 255, 0 }; 00038 ip_address_t my_ip_adrs = { 192, 168, 0, 70 }; 00039 ip_address_t my_ns_adrs = { 192, 168, 0, 1 }; 00040 00041 00042 /************************************************************************/ 00043 /* ソケット管理テーブル */ 00044 /************************************************************************/ 00045 SOCKET_CTRL socket_table[MAX_SOCKET_NUMBER]; 00046 00047 /************************************************************************/ 00048 /* */ 00049 /* ソケットを使用する前の初期化 */ 00050 /* */ 00051 /************************************************************************/ 00052 void netapi_init(void) 00053 { 00054 short ii; 00055 00056 /* W5300 のソフトリアセット */ 00057 w5300_soft_reset(); 00058 00059 /* ソケット領域を0クリアする */ 00060 for(ii = 0 ; ii < MAX_SOCKET_NUMBER ; ++ii) { 00061 memset(&socket_table[ii], 0, sizeof(SOCKET_CTRL)); 00062 } 00063 } 00064 00065 00066 /************************************************************************/ 00067 /* */ 00068 /* */ 00069 /* */ 00070 /************************************************************************/ 00071 void if_up(void) 00072 { 00073 /* ソフトリセット */ 00074 w5300_soft_reset(); 00075 /* MAC アドレスをW5300 にセット */ 00076 set_mac_adrs(&my_mac_adr); 00077 /* W5300 に通信に必要なアドレスをセットする */ 00078 set_ip_data((ushort *)CMN_IP_ADDRESS, &my_ip_adrs); 00079 set_ip_data((ushort *)CMN_SUBNET_ADDRESS, &my_ip_mask); 00080 set_ip_data((ushort *)CMN_GW_ADDRESS, &my_gw_adrs); 00081 } 00082 00083 00084 /************************************************************************/ 00085 /* */ 00086 /* */ 00087 /* */ 00088 /************************************************************************/ 00089 void if_down(void) 00090 { 00091 static const uchar ip_dmy[] = { 0, 0, 0, 0, 0, 0}; 00092 00093 set_ip_data((ushort *)CMN_SUBNET_ADDRESS, (void *)ip_dmy); 00094 set_ip_data((ushort *)CMN_IP_ADDRESS, (void *)ip_dmy); 00095 set_ip_data((ushort *)CMN_GW_ADDRESS, (void *)ip_dmy); 00096 set_mac_adrs((void *)ip_dmy); 00097 w5300_soft_reset(); 00098 } 00099 00100 00101 /************************************************************************/ 00102 /* */ 00103 /* システムの Interface Config情報をセットする */ 00104 /* */ 00105 /************************************************************************/ 00106 void set_my_ifconfig(my_if_config *cfg) 00107 { 00108 /* MAC Address */ 00109 memcpy(&my_mac_adr, &cfg->mac_adr, sizeof(hw_address_t)); 00110 /* IP Address */ 00111 my_ip_adrs._long = cfg->ip_adrs._long; 00112 /* Net Mask */ 00113 my_ip_mask._long = cfg->ip_mask._long; 00114 /* Gate Way */ 00115 my_gw_adrs._long = cfg->gw_adrs._long; 00116 /* Name Server */ 00117 my_ns_adrs._long = cfg->ns_adrs._long; 00118 } 00119 00120 00121 /************************************************************************/ 00122 /* */ 00123 /* システムの Interface Config情報を取得する */ 00124 /* */ 00125 /************************************************************************/ 00126 void get_my_ifconfig(my_if_config *cfg) 00127 { 00128 /* MAC Address */ 00129 memcpy(&cfg->mac_adr, &my_mac_adr, sizeof(hw_address_t)); 00130 /* IP Address */ 00131 cfg->ip_adrs._long = my_ip_adrs._long; 00132 /* Net Mask */ 00133 cfg->ip_mask._long = my_ip_mask._long; 00134 /* Gate Way */ 00135 cfg->gw_adrs._long = my_gw_adrs._long; 00136 /* Name Server */ 00137 cfg->ns_adrs._long = my_ns_adrs._long; 00138 } 00139 00140 00141 /************************************************************************/ 00142 /* */ 00143 /* 空いているソケットを探し出す */ 00144 /* */ 00145 /************************************************************************/ 00146 static SOCKET find_empty_socket(void) 00147 { 00148 short ii; 00149 00150 for(ii = (MAX_SOCKET_NUMBER - 1) ; ii >= 0 ; --ii) { 00151 if(socket_table[ii].inuse == SOCKET_EMPTY) { 00152 if(get_nic_status(ii) == SOCK_STATUS_CLOSED) { 00153 /* 領域をクリア */ 00154 memset(&socket_table[ii], NULL, sizeof(SOCKET_CTRL)); 00155 /* ソケット使用中フラグ */ 00156 socket_table[ii].inuse = SOCKET_INUSE; 00157 /* ソケット番号を返す */ 00158 return ii; 00159 } 00160 } 00161 } 00162 /* 見つからなかった */ 00163 return ERR_NOSOCKET; 00164 } 00165 00166 00167 /************************************************************************/ 00168 /* */ 00169 /* ソケットの開放 */ 00170 /* */ 00171 /************************************************************************/ 00172 NETAPI closesocket(SOCKET sock) 00173 { 00174 if(socket_table[sock].inuse == SOCKET_INUSE) { 00175 /*TCPでESTABLISHEDの場合は、FINを送信 */ 00176 if(socket_table[sock].socktype == SOCK_STREAM) { 00177 if(get_nic_status(sock) == SOCK_STATUS_ESTAB) { 00178 nic_command(sock, SOCK_CMD_DISCON); 00179 } 00180 } 00181 00182 /* Closeコマンドを発行する */ 00183 nic_command(sock, SOCK_CMD_CLOSE); 00184 00185 /* 割り込みビット・クリア */ 00186 clear_sock_ir(sock, 0xff); 00187 clear_master_ir(sock); 00188 00189 /* 未使用状態にする */ 00190 socket_table[sock].inuse = SOCKET_EMPTY; 00191 00192 return ERR_OK; 00193 } 00194 return ERR_NOTOPEN; 00195 } 00196 00197 00198 /************************************************************************/ 00199 /* */ 00200 /* 指定の状態になるまで待つ */ 00201 /* */ 00202 /************************************************************************/ 00203 static NETAPI wait_change_state(SOCKET sock, ushort state) 00204 { 00205 ulong tm; 00206 00207 for(tm = 0 ; tm < 100000L ; ++tm) { 00208 if(get_nic_status(sock) == state) { 00209 return ERR_OK; 00210 } 00211 } 00212 /* タイムアウト */ 00213 return ERR_TIMEOUT; 00214 } 00215 00216 00217 /************************************************************************/ 00218 /* */ 00219 /* 前回の送信が完了したかチェックする */ 00220 /* */ 00221 /************************************************************************/ 00222 static bool check_transmit_done(SOCKET socket) 00223 { 00224 short tm; 00225 00226 if(socket_table[socket].checkTxDone) { 00227 socket_table[socket].checkTxDone = false; 00228 /* 送信完了割り込みフラグが立つまで待つ (約30秒) */ 00229 for(tm = 0 ; tm < 30000 ; ++tm) { 00230 if((get_sock_ir(socket) & SOCK_IR_SENDOK) != 0) { 00231 clear_sock_ir(socket, SOCK_IR_SENDOK); 00232 return false; 00233 } 00234 if(get_nic_status(socket) == SOCK_STATUS_CLOSED) return true; 00235 delay_1mS(); 00236 } 00237 /* タイムアウト */ 00238 return true; 00239 } 00240 /* チェック不要なので正常終了 */ 00241 return false; 00242 } 00243 00244 00245 /************************************************************************/ 00246 /* */ 00247 /* 送信する */ 00248 /* */ 00249 /************************************************************************/ 00250 static void do_send(SOCKET sock, void *buf, long len) 00251 { 00252 long wlen; 00253 ushort *txfifo; 00254 00255 /* W5300の受信FIFOアドレスを取得 */ 00256 txfifo = get_txfifo_adr(sock); 00257 00258 /* 書き込むデータ数を計算 */ 00259 wlen = ((len + 1) & 0xfffe) / 2; 00260 00261 /* バッファに書き込む(bufはWORDアラインとは限らないのでBYTEアクセス) */ 00262 while(wlen--) { 00263 *txfifo = (*((ubyte *)buf) << 8) | *((ubyte *)buf + 1); 00264 buf = ((ushort *)buf) + 1; 00265 } 00266 00267 /* 送信バイト数セット */ 00268 set_tx_data_size(sock, len); 00269 00270 /* 送信コマンド */ 00271 nic_command(sock, SOCK_CMD_SEND); 00272 00273 /* 次回の送信前に送信完了をチェックするフラグ */ 00274 socket_table[sock].checkTxDone = true; 00275 } 00276 00277 00278 /************************************************************************/ 00279 /* */ 00280 /* W5300 を 指定されたプロトコルでオープンする */ 00281 /* */ 00282 /************************************************************************/ 00283 static SOCKET w5300_open(ushort protocol, ushort myport) 00284 { 00285 SOCKET sock, ret, stat; 00286 00287 /* 空いているソケットを探す */ 00288 if((sock = find_empty_socket()) < 0) return ERR_NOSOCKET; 00289 00290 /* このソケットのプロトコル */ 00291 socket_table[sock].socktype = protocol; 00292 00293 /* プロトコルをW5300へ指定する */ 00294 set_socket_mode(sock, (protocol|SOCK_MODE_INITD)); 00295 00296 00297 /* MTU の設定(ADSLを意識) */ 00298 set_socket_mss(sock, 1452); 00299 00300 /* 自分のポート番号をセット */ 00301 set_my_port_data(sock, myport); 00302 00303 /* ソケットをオープンする */ 00304 nic_command(sock, SOCK_CMD_OPEN); 00305 00306 /* オープンを待つ */ 00307 switch(protocol) { 00308 case SOCK_PROT_TCP: 00309 stat = SOCK_STATUS_INIT; 00310 break; 00311 00312 case SOCK_PROT_UDP: 00313 stat = SOCK_STATUS_UDP; 00314 break; 00315 00316 case SOCK_PROT_IPRAW: 00317 stat = SOCK_STATUS_IPRAW; 00318 break; 00319 00320 case SOCK_PROT_MACRAW: 00321 stat = SOCK_STATUS_MACRAW; 00322 break; 00323 } 00324 00325 if((ret = wait_change_state(sock, stat)) == ERR_OK) { 00326 #ifdef _NETAPI_DEBUG_PRINT_ 00327 printf("w5300_open() success. protocol : %X\r\n", protocol); 00328 #endif 00329 /* 正常終了 */ 00330 return sock; 00331 } 00332 00333 /* 異常終了なのでソケットを開放してエラーで戻る */ 00334 closesocket(sock); 00335 return ret; 00336 } 00337 00338 00339 /************************************************************************/ 00340 /* */ 00341 /* W5300 のIRレジスタと status レジスタの値を取得 */ 00342 /* */ 00343 /************************************************************************/ 00344 void get_chip_status(SOCKET sock, ushort *ir, ushort *st) 00345 { 00346 *ir = get_sock_ir(sock); /* 割り込みレジスタ */ 00347 /* clear_sock_ir(sock, 0xff); 読み込んだのでIRをクリア */ 00348 *st = get_nic_status(sock); /* ステータスレジスタ */ 00349 } 00350 00351 00352 /************************************************************************/ 00353 /* */ 00354 /* 指定のアドレスへ TCP/IP で接続する */ 00355 /* */ 00356 /************************************************************************/ 00357 SOCKET tcp_connect(ushort myport, ulong yourip, ushort yourport, ushort flag) 00358 { 00359 SOCKET sock; 00360 NETAPI ret; 00361 ushort ir; 00362 ulong tm; 00363 00364 /* W5300 のオープン */ 00365 if((sock = w5300_open(SOCK_PROT_TCP, myport)) < 0) return sock; 00366 00367 /* 接続先のポート番号 */ 00368 set_dest_port_data(sock, yourport); 00369 00370 /* 接続先IPアドレスのセット */ 00371 set_dest_ip_data(sock, yourip); 00372 00373 00374 /* 割り込み状態をクリアして connect コマンドの発行 */ 00375 clear_sock_ir(sock, 0xff); 00376 nic_command(sock, SOCK_CMD_CONNECT); 00377 00378 /* 接続完了まで待つ場合 (30Sec)*/ 00379 if(flag & WAIT_UNTIL_DONE) { 00380 ret = ERR_TOCON; 00381 for(tm = 0 ; tm < 3000L ; ++tm) { 00382 ir = get_sock_ir(sock); 00383 /* 接続完了の場合 */ 00384 if(ir & SOCK_IR_CON) return sock; 00385 /* エラーになったか調べて対応の処理を行う */ 00386 if(ir & SOCK_IR_TIMEOUT) goto EXIT_PROC; 00387 if(ir & SOCK_IR_DISCON) goto EXIT_PROC; 00388 /* ちょっと時間待ち */ 00389 delay_10mS(); 00390 } 00391 } 00392 00393 EXIT_PROC: 00394 /* ソケットの開放 */ 00395 closesocket(sock); 00396 return ret; 00397 } 00398 00399 00400 /************************************************************************/ 00401 /* */ 00402 /* TCP/IP で接続待ちにする */ 00403 /* */ 00404 /************************************************************************/ 00405 SOCKET tcp_listen(ushort myport) 00406 { 00407 SOCKET sock; 00408 NETAPI ret; 00409 00410 /* W5300 のオープン */ 00411 if((sock = w5300_open(SOCK_PROT_TCP, myport)) < 0) { 00412 return sock; 00413 } 00414 00415 /* 割り込み状態をクリアして listen コマンドの発行 */ 00416 clear_sock_ir(sock, 0xff); 00417 nic_command(sock, SOCK_CMD_LISTEN); 00418 00419 /* 状態遷移を待つ */ 00420 if((ret = wait_change_state(sock, SOCK_STATUS_LISTEN)) != ERR_OK) { 00421 return ret; 00422 } 00423 00424 /* 正常終了 */ 00425 return sock; 00426 } 00427 00428 00429 /************************************************************************/ 00430 /* */ 00431 /* TCP/IP 切断 */ 00432 /* */ 00433 /************************************************************************/ 00434 NETAPI tcp_disconnect(SOCKET sock) 00435 { 00436 return closesocket(sock); 00437 } 00438 00439 00440 /************************************************************************/ 00441 /* */ 00442 /* 受信されたデータ数を取得(外部向け) */ 00443 /* */ 00444 /************************************************************************/ 00445 long get_tcp_recvln(SOCKET sock) 00446 { 00447 return get_rx_recv_size(sock); 00448 } 00449 00450 00451 /************************************************************************/ 00452 /* */ 00453 /* TCP/IP データ受信 */ 00454 /* */ 00455 /************************************************************************/ 00456 long tcp_recv(SOCKET sock, void *buf, long buflen, ushort flag) 00457 { 00458 volatile ushort *rxfifo; 00459 SOCKET_CTRL *sc; 00460 long wlen; 00461 00462 /* バッファに書き込んだバイト数(初期化) */ 00463 wlen = NULL; 00464 00465 /* Socketデータ領域のアドレスを取得 */ 00466 sc = &socket_table[sock]; 00467 00468 if(sc->inuse == SOCKET_INUSE) { 00469 00470 /* TCPモードかチェックする */ 00471 if(sc->socktype != SOCK_PROT_TCP) return ERR_PROTOCOL; 00472 00473 /* ……………………………………………………………………………… 00474 Ugh! ここで、回線断を検出すると、バッファに残りのデータが 00475 ある場合、そのデータが取り込めなくなる。 00476 ………………………………………………………………………………*/ 00477 00478 /* W5300の受信FIFOアドレスを取得 */ 00479 rxfifo = get_rxfifo_adr(sock); 00480 00481 /* Dummy Read 00482 W5300の仕様で TX_FIFO をアクセスした直後に 00483 RX_FIFO のアクセスができないため、MODEレジスタを読んでおく 00484 */ 00485 get_socket_mode(sock); 00486 00487 while(1) { 00488 /* バッファ長だけ書き込んだのなら終わり */ 00489 if(buflen == NULL) { 00490 /* データも無くなっていたら、受信コマンド */ 00491 if(sc->recvlen == NULL) nic_command(sock, SOCK_CMD_RECV); 00492 goto EXIT_RECVPROC; 00493 } 00494 00495 /* 読み込み途中のデータが無ければ新しいデータを取り込む準備 */ 00496 if(sc->recvlen == NULL) { 00497 /* 未取り込みのデータ数(無ければ終わり) */ 00498 if(get_rx_recv_size(sock) == NULL) { 00499 /* 受信コマンド */ 00500 nic_command(sock, SOCK_CMD_RECV); 00501 goto EXIT_RECVPROC; 00502 } 00503 /* このパケットのデータ数を記憶(PACKET INFO.) */ 00504 sc->recvlen = *rxfifo; 00505 /* 最初のデータ */ 00506 sc->recvdat = *rxfifo; 00507 /* MSBから取り込む */ 00508 sc->msb = true; 00509 00510 #ifdef _NETAPI_DEBUG_PRINT_ 00511 printf("\r\n[RecvLen=%d]", sc->recvlen); 00512 #endif 00513 00514 } 00515 00516 /* 最初に変数を更新しておく */ 00517 --sc->recvlen; /* 取り込めるデータ数 */ 00518 --buflen; /* 書き込めるデータ数 */ 00519 ++wlen; /* 書き込んだデータ数 */ 00520 00521 /* bufにデータを1バイト書き込む 00522 書き込み先がWORD境界とは限らないのでバイト書き込み */ 00523 if(sc->msb) { 00524 *(ubyte *)buf = (sc->recvdat >> 8); 00525 sc->msb = false; 00526 } else { 00527 *(ubyte *)buf = sc->recvdat; 00528 sc->msb = true; 00529 if(sc->recvlen) sc->recvdat = *rxfifo; 00530 } 00531 00532 #ifdef _NETAPI_DEBUG_PRINT_ 00533 printf("%c", *(ubyte *)buf); 00534 #endif 00535 00536 /* 次の書き込みアドレス */ 00537 buf = ((uchar *)buf) + 1; 00538 00539 /* 1Packet分読んだ場合、RECVコマンドを発行する */ 00540 if(sc->recvlen == 0) { 00541 nic_command(sock, SOCK_CMD_RECV); 00542 #if 1 00543 /* Ugh! ………………………………………………………………… 00544 HTTPなどのように、大量のデータが来て、 W5300で用意した 00545 バッファが一杯になった後、 KeepAliveが出るまで、受信し 00546 なくなる。 00547 この場合、強制的に KeepAliveを送信するとWindowが更新さ 00548 れて受信が再開されるが、一度この方法を使うと KeepAlive 00549 機能が停止してしまうので、連続したデータを扱って Close 00550 するようなコネクション以外は使わないようにすること。 00551 ………………………………………………………………………*/ 00552 { 00553 if(flag & IGNOR_KEEPALIVE) { 00554 /* Ugh! 1パケット受信完了、強引にKeepAliveを送ってWinodwを更新 */ 00555 ushort kptime = get_kpalvtimer(sock); 00556 set_kpalvtimer(sock, 0); 00557 nic_command(sock, SOCK_CMD_SENDKEEP); 00558 set_kpalvtimer(sock, kptime); 00559 #ifdef _NETAPI_DEBUG_PRINT_ 00560 printf("\r\nSEND KEEP ALIVE PACKET"); 00561 #endif 00562 } 00563 } 00564 #endif 00565 } 00566 } 00567 } 00568 return ERR_NOTOPEN; 00569 00570 EXIT_RECVPROC: 00571 #ifdef _NETAPI_DEBUG_PRINT_ 00572 if(wlen > 0) printf("\r\ntcp_recv() len=%ld", wlen); 00573 #endif 00574 return wlen; 00575 } 00576 00577 00578 /************************************************************************/ 00579 /* */ 00580 /* TCP/IP データ送信 */ 00581 /* */ 00582 /************************************************************************/ 00583 long tcp_send(SOCKET sock, const void *buf, long datalen, ushort flag) 00584 { 00585 if(socket_table[sock].inuse == SOCKET_INUSE) { 00586 /* TCPモードかチェックする */ 00587 if(socket_table[sock].socktype != SOCK_PROT_TCP) return ERR_PROTOCOL; 00588 00589 /* !Ugh 接続中か? */ 00590 if(get_nic_status(sock) != SOCK_STATUS_ESTAB) { 00591 return ERR_NOTCONN; 00592 } 00593 if(get_sock_ir(sock) & SOCK_IR_DISCON) { 00594 return ERR_NOTCONN; 00595 } 00596 00597 /* 前回の送信があれば、完了を待つ */ 00598 if(check_transmit_done(sock)) return ERR_SENDTO; 00599 00600 /* 送信バッファに空きがなければエラーで戻る */ 00601 if(get_tx_free_size(sock) < datalen) return ERR_NOBUFF; 00602 00603 /* NICへデータを書き込み送信する */ 00604 do_send(sock, buf, datalen); 00605 00606 if(flag & WAIT_UNTIL_DONE) { 00607 if(check_transmit_done(sock)) return ERR_SENDTO; 00608 } 00609 00610 return datalen; 00611 } 00612 return ERR_NOTOPEN; 00613 } 00614 00615 00616 /************************************************************************/ 00617 /* */ 00618 /* W5300 を UDP でオープンする */ 00619 /* */ 00620 /************************************************************************/ 00621 SOCKET udp_open(ushort myport) 00622 { 00623 SOCKET sock; 00624 00625 sock = w5300_open(SOCK_PROT_UDP, myport); 00626 nic_command(sock, SOCK_CMD_RECV); 00627 return sock; 00628 } 00629 00630 00631 /************************************************************************/ 00632 /* */ 00633 /* UDPデータ受信 */ 00634 /* */ 00635 /************************************************************************/ 00636 long udp_recv(SOCKET sock, void *buf, long len, ulong *yourip, ushort *yourport) 00637 { 00638 volatile ushort *rxfifo; 00639 SOCKET_CTRL *sc; 00640 ulong tmp; 00641 ushort ctr, dlen, rlen, rd; 00642 00643 rlen = 0; 00644 00645 /* Socketデータ領域のアドレスを取得 */ 00646 sc = &socket_table[sock]; 00647 00648 00649 if(sc->inuse == SOCKET_INUSE) { 00650 /* UDPモードかチェックする */ 00651 if(get_nic_status(sock) != SOCK_STATUS_UDP) { 00652 #ifdef _NETAPI_DEBUG_PRINT_ 00653 printf("udp_recv() Not UDP MODE!\r\n"); 00654 #endif 00655 return ERR_PROTOCOL; 00656 } 00657 00658 /* 受信データがあるか? */ 00659 if(get_rx_recv_size(sock) == NULL) { 00660 nic_command(sock, SOCK_CMD_RECV); 00661 goto UDP_RXEND; 00662 } 00663 00664 /* W5300の受信FIFOアドレスを取得 */ 00665 rxfifo = get_rxfifo_adr(sock); 00666 00667 /* UDPのPacketInfoを取り込む IP / PORT / LENGTH */ 00668 tmp = (*rxfifo << 16) | *rxfifo; 00669 if(yourip) { *yourip = tmp; } 00670 00671 tmp = *rxfifo; 00672 if(yourport) { *yourport = tmp; } 00673 00674 dlen = *rxfifo; 00675 00676 #ifdef _NETAPI_DEBUG_PRINT_ 00677 printf("UDP DATA ip=%lX port=%d len=%d\r\n", *yourip, *yourport, dlen); 00678 #endif 00679 00680 /* FIFOから読み込む回数 */ 00681 ctr = ((dlen + 1) & 0xfffe) / 2; 00682 00683 /* 扱うデータが偶数 or 奇数バイト?のフラグ */ 00684 sc->msb = true; 00685 00686 while(true) { 00687 if(!dlen) break; 00688 /* 偶数バイトの場合 RX_FIFO からデータを読み込む */ 00689 if(sc->msb == true) { 00690 rd = *rxfifo; 00691 --ctr; 00692 } 00693 00694 /* buf が満杯ではなく、データもある場合 */ 00695 if(len && dlen) { 00696 if(sc->msb) { 00697 *(uchar *)buf = (rd >> 8); 00698 sc->msb = false; 00699 } else { 00700 *(uchar *)buf = (rd & 0xff); 00701 sc->msb = true; 00702 } 00703 ++rlen, --dlen, --len; 00704 buf = (uchar *)buf + 1; 00705 } 00706 } 00707 00708 UDP_RXEND: 00709 /* 受信コマンド */ 00710 nic_command(sock, SOCK_CMD_RECV); 00711 return rlen; 00712 } 00713 #ifdef _NETAPI_DEBUG_PRINT_ 00714 printf("udp_recv() Socket Not Open\r\n"); 00715 #endif 00716 return ERR_NOTOPEN; 00717 } 00718 00719 00720 /************************************************************************/ 00721 /* */ 00722 /* UDP データ送信 */ 00723 /* */ 00724 /************************************************************************/ 00725 long udp_send(SOCKET sock, void *buf, long len, ulong yourip, ushort yourport) 00726 { 00727 if(socket_table[sock].inuse == SOCKET_INUSE) { 00728 /* UDPモードかチェックする */ 00729 if(get_nic_status(sock) != SOCK_STATUS_UDP) { 00730 #ifdef _NETAPI_DEBUG_PRINT_ 00731 printf("udp_send() Not UDP MODE!\r\n"); 00732 #endif 00733 return ERR_PROTOCOL; 00734 } 00735 00736 /* 前回の送信があれば、完了を待つ */ 00737 if(check_transmit_done(sock)) return ERR_NOTCONN; 00738 00739 /* 送信バッファに空きがなければエラーで戻る */ 00740 if(get_tx_free_size(sock) < len) return ERR_NOBUFF; 00741 00742 /* 宛先IPとポート番号を設定 */ 00743 #ifdef _NETAPI_DEBUG_PRINT_ 00744 printf("udp_send() YourIP : %08lX\r\n", yourip); 00745 printf("udp_send() YourPort : %d\r\n", yourport); 00746 #endif 00747 set_dest_ip_data(sock, yourip); 00748 set_dest_port_data(sock, yourport); 00749 00750 /* NICへデータを書き込み送信する */ 00751 do_send(sock, buf, len); 00752 00753 #if 0 00754 /* 次回の送信前に送信完了をチェック */ 00755 socket_table[sock].checkTxDone = true; 00756 #else 00757 /* 送信完了を待つ */ 00758 if(check_transmit_done(sock)) { 00759 #ifdef _NETAPI_DEBUG_PRINT_ 00760 printf("udp_send() Send Error!\r\n"); 00761 #endif 00762 return ERR_NOTCONN; 00763 } 00764 #endif 00765 00766 #ifdef _NETAPI_DEBUG_PRINT_ 00767 printf("udp_send() Send OK! len=%d\r\n", len); 00768 #endif 00769 return len; 00770 } 00771 return ERR_NOTOPEN; 00772 } 00773 00774 00775 00776 /************************************************************************/ 00777 /* */ 00778 /* エンディアンに関する処理 */ 00779 /* */ 00780 /************************************************************************/ 00781 ushort swaps(ushort i) 00782 { 00783 return ((i & 0xFF) << 8) | ((i >> 8)& 0xFF); 00784 } 00785 00786 00787 /************************************************************************/ 00788 /* */ 00789 /************************************************************************/ 00790 ulong swapl(ulong l) 00791 { 00792 ulong ret = 0; 00793 ret = (l & 0xFF) << 24; 00794 ret |= ((l >> 8) & 0xFF) << 16; 00795 ret |= ((l >> 16) & 0xFF) << 8; 00796 ret |= ((l >> 24) & 0xFF); 00797 return ret; 00798 } 00799 00800 00801 /************************************************************************/ 00802 /* */ 00803 /************************************************************************/ 00804 ushort htons(ushort hostshort) 00805 { 00806 #if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_) 00807 return swaps(hostshort); 00808 #else 00809 return hostshort; 00810 #endif 00811 } 00812 00813 00814 /************************************************************************/ 00815 /* */ 00816 /************************************************************************/ 00817 ulong htonl(ulong hostlong) 00818 { 00819 #if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_) 00820 return swapl(hostlong); 00821 #else 00822 return hostlong; 00823 #endif 00824 } 00825 00826 00827 /************************************************************************/ 00828 /* */ 00829 /************************************************************************/ 00830 ulong ntohs(ushort netshort) 00831 { 00832 #if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_) 00833 return htons(netshort); 00834 #else 00835 return netshort; 00836 #endif 00837 } 00838 00839 00840 /************************************************************************/ 00841 /* */ 00842 /************************************************************************/ 00843 ulong ntohl(ulong netlong) 00844 { 00845 #if (SYSTEM_ENDIAN == _ENDIAN_LITTLE_) 00846 return htonl(netlong); 00847 #else 00848 return netlong; 00849 #endif 00850 } 00851 00852 00853 /************************************************************************/ 00854 /* */ 00855 /* 文字表記に関する処理 */ 00856 /* */ 00857 /* ulong addr -> "999.999.999.999" に変換 */ 00858 /************************************************************************/ 00859 char * inet_ntoa(ulong addr) 00860 { 00861 /* Ugh! バッファを勝手に作って使ってる ← 仕様らしい */ 00862 static char addr_str[16]; 00863 00864 /* "999.999.999.999" に変換 */ 00865 memset(addr_str,0,16); 00866 sprintf(addr_str, "%d.%d.%d.%d", 00867 (short)((addr >> 24) & 0xFF), 00868 (short)((addr >> 16) & 0xFF), 00869 (short)((addr >> 8) & 0xFF), 00870 (short)((addr ) & 0xFF) 00871 ); 00872 return addr_str; 00873 } 00874 00875 00876 /************************************************************************/ 00877 /* "999.999.999.999" を ulong に変換 */ 00878 /************************************************************************/ 00879 ulong inet_addr(uchar * addr) 00880 { 00881 uchar ii; 00882 ulong inetaddr; 00883 00884 inetaddr = 0L; 00885 00886 if(!addr) return NULL; 00887 00888 for(ii = 0 ; ii < 4 ; ++ii) { 00889 inetaddr <<= 8; 00890 inetaddr |= (ubyte)(atoi((char *)addr) & 0xFF); 00891 while(1) { 00892 if(*addr < ' ') goto EXIT_PROC; 00893 if(*addr == '.') { 00894 ++addr; 00895 break; 00896 } 00897 /* 処理中に数字以外があった場合 */ 00898 if((ii < 3) && ((*addr < '0') || (*addr > '9'))) return NULL; 00899 /* 次の文字 */ 00900 ++addr; 00901 } 00902 } 00903 00904 EXIT_PROC: 00905 return inetaddr; 00906 } 00907 00908 00909 /************************************************************************/ 00910 /* MAC アドレスを "99:99:99:99:99:99" に変換 */ 00911 /************************************************************************/ 00912 char * mac_ntoa(char* str, uchar* addr) 00913 { 00914 if(!addr) return NULL; 00915 00916 sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", 00917 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 00918 00919 return str; 00920 } 00921 00922 00923 /************************************************************************/ 00924 /* "99:99:99:99:99:99" を数値に変換して6バイトの領域に書き込む */ 00925 /* */ 00926 /* */ 00927 /* 戻り値 : ポインタ dst */ 00928 /* */ 00929 /************************************************************************/ 00930 char * mac_addr(ubyte *dst, ubyte *addr) 00931 { 00932 short ii; 00933 ubyte dd; 00934 00935 if(!addr) return NULL; 00936 00937 for(ii = 0 ; ii < 6 ; ++ii) { 00938 dst[ii] = 0; 00939 while(1) { 00940 if(*addr < '0') goto EXIT_PROC; 00941 00942 /* ':' の読み飛ばし */ 00943 if(*addr == ':') { 00944 if(ii < 5) { 00945 ++addr; 00946 break; 00947 } else { 00948 goto EXIT_PROC; 00949 } 00950 } 00951 00952 /* 小文字の場合、大文字にする */ 00953 if(*addr >= 'a') dd = *addr - 0x20; /* To Upper Case */ 00954 else dd = *addr; 00955 00956 /* 文字を16進に変換 */ 00957 dd = dd - '0'; 00958 if(dd > 9) dd -= 7; 00959 00960 /* 結果を更新 */ 00961 dst[ii] <<= 4; 00962 dst[ii] += dd; 00963 00964 /* 16進数ではない場合 */ 00965 if(dd > 0xf) { goto EXIT_PROC; } 00966 00967 /* 次の読み込み位置 */ 00968 ++addr; 00969 } 00970 } 00971 EXIT_PROC: 00972 /* 途中で終了している場合は、クリアする */ 00973 if(ii < 5) memset(dst, 0, sizeof(hw_address_t)); 00974 return (char *)dst; 00975 } 00976 00977 #endif /* nodef(USE_ROM_BIOS) */
事項は、インクルードしているヘッダー・ファイルになります。
WIZNet W5300/5