MCU

コンテンツ

WIZNet W5300 その四 netapi.c


前項の 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

最終更新のRSS
Last-modified: 2010-11-16 (火) 21:35:29 2654日前
HTML convert time: 0.041 sec.