source: rtems/c/src/lib/libbsp/arm/nds/dswifi/arm9/source/wifi_arm9.c @ ca11e781

4.104.115
Last change on this file since ca11e781 was ca11e781, checked in by Ralf Corsepius <ralf.corsepius@…>, on 12/07/09 at 07:12:20

Eliminate various warnings.

  • Property mode set to 100644
File size: 28.0 KB
Line 
1// DS Wifi interface code
2// Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org
3// wifi_arm9.c - arm9 wifi support code
4/******************************************************************************
5DSWifi Lib and test materials are licenced under the MIT open source licence:
6Copyright (c) 2005-2006 Stephen Stair
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice shall be included in all
16copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24SOFTWARE.
25******************************************************************************/
26
27#include <unistd.h>
28
29#include <nds.h>
30#include "dsregs.h"
31
32#include "wifi_arm9.h"
33#include <stdarg.h>
34#include <stdlib.h>
35#include <sys/socket.h>
36
37
38
39
40
41
42
43
44
45#ifdef WIFI_USE_TCP_SGIP
46
47#include "sgIP.h"
48
49
50sgIP_Hub_HWInterface * wifi_hw;
51
52
53int sgIP_DisableInterrupts() {
54        int a;
55        a=REG_IME;
56        REG_IME=0;
57        return a;
58}
59void sgIP_RestoreInterrupts(int old_ime) {
60        REG_IME=old_ime;
61}
62
63void sgIP_IntrWaitEvent() {
64 //  __asm( ".ARM\n swi 0x060000\n" );
65        int i,j;
66        j=0;
67        for(i=0;i<20000;i++) {
68                j+=i;
69        }
70}
71
72void * sgIP_malloc(int size) __attribute__((weak));
73void sgIP_free(void * ptr) __attribute__((weak));
74
75
76
77//////////////////////////////////////////////////////////////////////////
78// wifi heap allocator system
79
80#define WHEAP_RECORD_FLAG_INUSE     0
81#define WHEAP_RECORD_FLAG_UNUSED    1
82#define WHEAP_RECORD_FLAG_FREED     2
83
84typedef struct WHEAP_RECORD {
85    struct WHEAP_RECORD * next;
86    unsigned short flags, unused;
87    int size;
88} wHeapRecord;
89
90#ifdef SGIP_DEBUG
91#define WHEAP_FILL_START    0xAA
92#define WHEAP_FILL_END      0xBB
93#define WHEAP_PAD_START     4
94#define WHEAP_PAD_END       4
95#define WHEAP_DO_PAD
96#else
97#define WHEAP_PAD_START     0
98#define WHEAP_PAD_END       0
99#undef WHEAP_DO_PAD
100#endif
101#define WHEAP_RECORD_SIZE   (sizeof(wHeapRecord))
102#define WHEAP_PAD_SIZE      ((WHEAP_PAD_START)+(WHEAP_PAD_END))
103#define WHEAP_SIZE_CUTOFF   ((WHEAP_RECORD_SIZE)+64)
104
105
106int wHeapsize;
107wHeapRecord * wHeapStart; // start of heap
108wHeapRecord * wHeapFirst; // first free block
109void wHeapAllocInit(int size) {
110    wHeapStart=(wHeapRecord *)malloc(size);
111    wHeapFirst=wHeapStart;
112    wHeapStart->flags=WHEAP_RECORD_FLAG_UNUSED;
113    wHeapStart->next=0;
114    wHeapStart->size=size-sizeof(wHeapRecord);
115}
116
117
118void * wHeapAlloc(int size) {
119    wHeapRecord * rec = wHeapFirst;
120    void * voidptr;
121    int n;
122    size=(size+3)&(~3);
123    if(size==0) size=4;
124    size+=WHEAP_PAD_SIZE;
125    if(!rec) { SGIP_DEBUG_MESSAGE(("wHeapAlloc: heap full!")); return 0; } // should not happen given normal use.
126    while(rec->size<size) {
127        if(!rec->next) { SGIP_DEBUG_MESSAGE(("wHeapAlloc: heap too full!")); return 0; } // cannot alloc
128        if(rec->next->flags!=WHEAP_RECORD_FLAG_INUSE) { // try to merge with next one
129            rec->size+=rec->next->size+WHEAP_RECORD_SIZE;
130            rec->next=rec->next->next;
131        } else { // skip ahead to more friendly waters
132            rec=rec->next;
133            while(rec->next) {
134                if(rec->flags!=WHEAP_RECORD_FLAG_INUSE) break;
135                rec=rec->next;
136            }
137            if(rec->flags==WHEAP_RECORD_FLAG_INUSE) { SGIP_DEBUG_MESSAGE(("wHeapAlloc: heap too full!")); return 0; } // no empty slots :(
138        }
139    }
140    rec->flags=WHEAP_RECORD_FLAG_INUSE;
141    n=rec->size-size;
142    voidptr = ((char *)rec)+WHEAP_RECORD_SIZE+WHEAP_PAD_START;
143    if(n<WHEAP_SIZE_CUTOFF) { // pad to include unused portion
144        rec->unused=n;
145    } else { // chop block into 2
146        wHeapRecord * rec2;
147        rec2=(wHeapRecord *)(((char *)rec)+WHEAP_RECORD_SIZE+size);
148        rec2->flags=WHEAP_RECORD_FLAG_UNUSED;
149        rec2->size=rec->size-size-WHEAP_RECORD_SIZE;
150        rec->size=size;
151        rec2->next=rec->next;
152        rec->next=rec2;
153        rec->unused=0;
154    }
155    if(rec==wHeapFirst) {
156        while(wHeapFirst->next && wHeapFirst->flags==WHEAP_RECORD_FLAG_INUSE) wHeapFirst=wHeapFirst->next;
157        if(wHeapFirst->flags==WHEAP_RECORD_FLAG_INUSE) wHeapFirst=0;
158    }
159#ifdef WHEAP_DO_PAD
160    {
161        int i;
162        for(i=0;i<WHEAP_PAD_START;i++) {
163            (((unsigned char *)rec)+WHEAP_RECORD_SIZE)[i]=WHEAP_FILL_START;
164        }
165        for(i=0;i<WHEAP_PAD_END;i++) {
166            (((unsigned char *)rec)+WHEAP_RECORD_SIZE+size-WHEAP_PAD_END)[i]=WHEAP_FILL_END;
167        }
168    }
169#endif
170    return voidptr;
171}
172
173void wHeapFree(void * data) {
174    wHeapRecord * rec = (wHeapRecord *)(((char *)data)-WHEAP_RECORD_SIZE-WHEAP_PAD_START);
175#ifdef WHEAP_DO_PAD
176    {
177        int size=rec->size-rec->unused;
178        int i;
179        for(i=0;i<WHEAP_PAD_START;i++) {
180            if((((unsigned char *)rec)+WHEAP_RECORD_SIZE)[i]!=WHEAP_FILL_START) break;
181        }
182        if(i!=WHEAP_PAD_START) { // note heap error
183            SGIP_DEBUG_MESSAGE(("wHeapFree: Corruption found before allocated data! 0x%X",data));
184        }
185        for(i=0;i<WHEAP_PAD_END;i++) {
186            if((((unsigned char *)rec)+WHEAP_RECORD_SIZE+size-WHEAP_PAD_END)[i]!=WHEAP_FILL_END) break;
187        }
188        if(i!=WHEAP_PAD_END) { // note heap error
189            SGIP_DEBUG_MESSAGE(("wHeapFree: Corruption found after allocated data! 0x%x",data));
190        }
191    }
192#endif
193    if(rec->flags!=WHEAP_RECORD_FLAG_INUSE) { // note heap error
194        SGIP_DEBUG_MESSAGE(("wHeapFree: Data already freed! 0x%X",data));
195    }
196    rec->flags=WHEAP_RECORD_FLAG_FREED;
197    if(rec<wHeapFirst || !wHeapFirst) wHeapFirst=rec; // reposition the "starting" pointer.
198}
199
200
201//////////////////////////////////////////////////////////////////////////
202
203
204
205
206
207void * sgIP_malloc(int size) { return wHeapAlloc(size); }
208void sgIP_free(void * ptr) { wHeapFree(ptr); }
209
210
211#endif
212
213
214
215
216
217void ethhdr_print(char f, void * d) {
218        char buffer[33];
219        int i;
220        int t,c;
221        buffer[0]=f;
222        buffer[1]=':';
223        buffer[14]=' ';
224        buffer[27]=' ';
225        buffer[32]=0;
226        for(i=0;i<6;i++) {
227                t=((u8 *)d)[i];
228                c=t&15;
229                if(c>9) c+='A'-10; else c+='0';
230                buffer[3+i*2]=c;
231                c=(t>>4)&15;
232                if(c>9) c+='A'-10; else c+='0';
233                buffer[2+i*2]=c;
234
235                t=((u8 *)d)[i+6];
236                c=t&15;
237                if(c>9) c+='A'-10; else c+='0';
238                buffer[16+i*2]=c;
239                c=(t>>4)&15;
240                if(c>9) c+='A'-10; else c+='0';
241                buffer[15+i*2]=c;
242        }
243        for(i=0;i<2;i++) {
244                t=((u8 *)d)[i+12];
245                c=t&15;
246                if(c>9) c+='A'-10; else c+='0';
247                buffer[29+i*2]=c;
248                c=(t>>4)&15;
249                if(c>9) c+='A'-10; else c+='0';
250                buffer[28+i*2]=c;
251        }
252        SGIP_DEBUG_MESSAGE((buffer));
253}
254
255
256
257
258Wifi_MainStruct Wifi_Data_Struct;
259
260volatile Wifi_MainStruct * WifiData = 0;
261
262WifiPacketHandler packethandler = 0;
263WifiSyncHandler synchandler = 0;
264
265void erasemem(void * mem, int length) {
266        int i;
267        char * m = (char *)mem;
268        for(i=0;i<length;i++)
269                m[i]=0;
270}
271
272void Wifi_CopyMacAddr(volatile void * dest, volatile void * src) {
273        ((u16 *)dest)[0]=((u16 *)src)[0];
274        ((u16 *)dest)[1]=((u16 *)src)[1];
275        ((u16 *)dest)[2]=((u16 *)src)[2];
276}
277
278int Wifi_CmpMacAddr(volatile void * mac1,volatile  void * mac2) {
279        return (((u16 *)mac1)[0]==((u16 *)mac2)[0]) && (((u16 *)mac1)[1]==((u16 *)mac2)[1]) && (((u16 *)mac1)[2]==((u16 *)mac2)[2]);
280}
281
282
283
284u32 Wifi_TxBufferWordsAvailable(void) {
285        s32 size=WifiData->txbufIn-WifiData->txbufOut-1;
286        if(size<0) size += WIFI_TXBUFFER_SIZE/2;
287        return size;
288}
289void Wifi_TxBufferWrite(s32 start, s32 len, u16 * data) {
290        int writelen;
291        while(len>0) {
292                writelen=len;
293                if(writelen>(WIFI_TXBUFFER_SIZE/2)-start) writelen=(WIFI_TXBUFFER_SIZE/2)-start;
294                len-=writelen;
295                while(writelen) {
296                        WifiData->txbufData[start++]=*(data++);
297                        writelen--;
298                }
299                start=0;
300        }
301}
302
303int Wifi_RxRawReadPacket(s32 packetID, s32 readlength, u16 * data) {
304        int readlen,read_data;
305        readlength= (readlength+1)/2;
306        read_data=0;
307        while(readlength>0) {
308                readlen=readlength;
309                if(readlen>(WIFI_RXBUFFER_SIZE/2)-packetID) readlen=(WIFI_RXBUFFER_SIZE/2)-packetID;
310                readlength-=readlen;
311                read_data+=readlen;
312                while(readlen>0) {
313                        *(data++) = WifiData->rxbufData[packetID++];
314                        readlen--;
315                }
316                packetID=0;
317        }
318        return read_data;
319}
320
321u16 Wifi_RxReadOffset(s32 base, s32 offset) {
322        base+=offset;
323        if(base>=(WIFI_RXBUFFER_SIZE/2)) base -= (WIFI_RXBUFFER_SIZE/2);
324        return WifiData->rxbufData[base];
325}
326
327// datalen = size of packet from beginning of 802.11 header to end, but not including CRC.
328int Wifi_RawTxFrame(u16 datalen, u16 rate, u16 * data) {
329        Wifi_TxHeader txh;
330        int sizeneeded;
331        int base;
332        sizeneeded=((datalen+12+4+3)/4)*2;
333        if(sizeneeded>Wifi_TxBufferWordsAvailable()) {WifiData->stats[WSTAT_TXQUEUEDREJECTED]++; return -1; }
334        txh.tx_rate=rate;
335        txh.tx_length=datalen+4;
336        base = WifiData->txbufOut;
337        Wifi_TxBufferWrite(base,6,(u16 *)&txh);
338        base += 6;
339        if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
340        Wifi_TxBufferWrite(base,((datalen+3)/4)*2,data);
341        base += ((datalen+3)/4)*2;
342        if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
343        WifiData->txbufOut=base;
344        WifiData->stats[WSTAT_TXQUEUEDPACKETS]++;
345        WifiData->stats[WSTAT_TXQUEUEDBYTES]+=sizeneeded;
346   if(synchandler) synchandler();
347   return 0;
348}
349
350
351void Wifi_RawSetPacketHandler(WifiPacketHandler wphfunc) {
352        packethandler=wphfunc;
353}
354void Wifi_SetSyncHandler(WifiSyncHandler wshfunc) {
355   synchandler=wshfunc;
356}
357
358void Wifi_DisableWifi() {
359        WifiData->reqMode=WIFIMODE_DISABLED;
360        WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT;
361}
362void Wifi_EnableWifi() {
363        WifiData->reqMode=WIFIMODE_NORMAL;
364        WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT;
365}
366void Wifi_SetPromiscuousMode(int enable) {
367        if(enable) WifiData->reqReqFlags |= WFLAG_REQ_PROMISC;
368        else WifiData->reqReqFlags &= ~WFLAG_REQ_PROMISC;
369}
370
371void Wifi_ScanMode() {
372        WifiData->reqMode=WIFIMODE_SCAN;
373        WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT;
374}
375void Wifi_SetChannel(int channel) {
376        if(channel<1 || channel>13) return;
377        if(WifiData->reqMode==WIFIMODE_NORMAL || WifiData->reqMode==WIFIMODE_SCAN) {
378                WifiData->reqChannel=channel;
379        }
380}
381
382
383int Wifi_GetNumAP() {
384        int i,j;
385        j=0;
386        for(i=0;i<WIFI_MAX_AP;i++) if(WifiData->aplist[i].flags&WFLAG_APDATA_ACTIVE) j++;
387        return j;
388}
389
390int Wifi_GetAPData(int apnum, Wifi_AccessPoint * apdata) {
391        int i,j;
392        if(!apdata) return WIFI_RETURN_PARAMERROR;
393        j=0;
394        for(i=0;i<WIFI_MAX_AP;i++){
395                if(WifiData->aplist[i].flags&WFLAG_APDATA_ACTIVE) {
396                        if(j==apnum) {
397                                while(Spinlock_Acquire(WifiData->aplist[i])!=SPINLOCK_OK);
398                                {
399                                        // additionally calculate average RSSI here
400                                        WifiData->aplist[i].rssi=0;
401                                        for(j=0;j<8;j++) {
402                                                WifiData->aplist[i].rssi+=WifiData->aplist[i].rssi_past[j];
403                                        }
404                                        WifiData->aplist[i].rssi = WifiData->aplist[i].rssi >> 3;
405                                        *apdata = WifiData->aplist[i]; // yay for struct copy!
406                                        Spinlock_Release(WifiData->aplist[i]);
407                                        return WIFI_RETURN_OK;
408                                }
409                        }
410                        j++;
411                }
412        }
413        return WIFI_RETURN_ERROR;
414}
415
416int Wifi_FindMatchingAP(int numaps, Wifi_AccessPoint * apdata, Wifi_AccessPoint * match_dest) {
417        int ap_match,i,j,n;
418        Wifi_AccessPoint ap;
419        u16 macaddrzero[3] = {0,0,0}; // check for empty mac addr
420        ap_match=-1;
421        for(i=0;i<Wifi_GetNumAP();i++){
422                Wifi_GetAPData(i,&ap);
423                for(j=0;j<numaps;j++) {
424                        if(apdata[j].ssid_len>32 || ((signed char)apdata[j].ssid_len)<0) continue;
425                        if(apdata[j].ssid_len>0) { // compare SSIDs
426                                if(apdata[j].ssid_len!=ap.ssid_len) continue;
427                                for(n=0;n<apdata[j].ssid_len;n++) {
428                                        if(apdata[j].ssid[n]!=ap.ssid[n]) break;
429                                }
430                                if(n!=apdata[j].ssid_len) continue;
431                        }
432                        if(!Wifi_CmpMacAddr(apdata[j].macaddr,macaddrzero)) { // compare mac addr
433                                if(!Wifi_CmpMacAddr(apdata[j].macaddr,ap.macaddr)) continue;
434                        }
435                        if(apdata[j].channel!=0) { // compare channels
436                                if(apdata[j].channel!=ap.channel) continue;
437                        }
438                        if(j<ap_match || ap_match==-1) {
439                                ap_match=j;
440                                if(match_dest) *match_dest = ap;
441                        }
442                        if(ap_match==0) return ap_match;
443                }
444        }
445        return ap_match;
446}
447
448int wifi_connect_state = 0; // -1==error, 0==searching, 1==associating, 2==dhcp'ing, 3==done, 4=searching wfc data
449Wifi_AccessPoint wifi_connect_point;
450int Wifi_ConnectAP(Wifi_AccessPoint * apdata, int wepmode, int wepkeyid, u8 * wepkey) {
451        int i;
452        Wifi_AccessPoint ap;
453        wifi_connect_state=-1;
454        if(!apdata) return -1;
455        if(((signed char)apdata->ssid_len)<0 || apdata->ssid_len>32) return -1;
456
457        Wifi_DisconnectAP();
458
459        wifi_connect_state=0;
460        WifiData->wepmode9=wepmode; // copy data
461        WifiData->wepkeyid9=wepkeyid;
462        for(i=0;i<20;i++) {
463                WifiData->wepkey9[i]=wepkey[i];
464        }
465
466
467        i=Wifi_FindMatchingAP(1,apdata,&ap);
468        if(i==0) {
469                Wifi_CopyMacAddr(WifiData->bssid9, ap.bssid);
470                Wifi_CopyMacAddr(WifiData->apmac9, ap.bssid);
471                WifiData->ssid9[0]=ap.ssid_len;
472                for(i=0;i<32;i++) {
473                        WifiData->ssid9[i+1]=ap.ssid[i];
474                }
475                WifiData->apchannel9=ap.channel;
476                for(i=0;i<16;i++) WifiData->baserates9[i]=ap.base_rates[i];
477                WifiData->reqMode=WIFIMODE_NORMAL;
478                WifiData->reqReqFlags |= WFLAG_REQ_APCONNECT | WFLAG_REQ_APCOPYVALUES;
479                wifi_connect_state=1;
480        } else {
481                WifiData->reqMode=WIFIMODE_SCAN;
482                wifi_connect_point = *apdata;
483        }
484        return 0;
485}
486void Wifi_AutoConnect(void) {
487        if(!(WifiData->wfc_enable[0]&0x80)) {
488                wifi_connect_state=ASSOCSTATUS_CANNOTCONNECT;
489        } else {
490                wifi_connect_state=4;
491                WifiData->reqMode=WIFIMODE_SCAN;
492        }
493}
494
495static
496void sgIP_DNS_Record_Localhost(void)
497{
498    sgIP_DNS_Record *rec;
499    const unsigned char * resdata_c = (unsigned char *)&(wifi_hw->ipaddr);
500    rec = sgIP_DNS_GetUnusedRecord();
501    rec->flags=SGIP_DNS_FLAG_ACTIVE | SGIP_DNS_FLAG_BUSY;
502
503    rec->addrlen    = 4;
504    rec->numalias   = 1;
505    gethostname(rec->aliases[0], 256);
506    gethostname(rec->name, 256);
507    rec->numaddr    = 1;
508    rec->addrdata[0] = resdata_c[0];
509    rec->addrdata[1] = resdata_c[1];
510    rec->addrdata[2] = resdata_c[2];
511    rec->addrdata[3] = resdata_c[3];
512    rec->addrclass = AF_INET;
513    rec->TTL = 0;
514
515    rec->flags=SGIP_DNS_FLAG_ACTIVE | SGIP_DNS_FLAG_BUSY|SGIP_DNS_FLAG_RESOLVED;
516}
517
518int Wifi_AssocStatus() {
519        switch(wifi_connect_state) {
520                case -1: // error
521                        return ASSOCSTATUS_CANNOTCONNECT;
522                case 0: // searching
523                        {
524                                int i;
525                                Wifi_AccessPoint ap;
526                                i=Wifi_FindMatchingAP(1,&wifi_connect_point,&ap);
527                                if(i==0) {
528                                        Wifi_CopyMacAddr(WifiData->bssid9, ap.bssid);
529                                        Wifi_CopyMacAddr(WifiData->apmac9, ap.bssid);
530                                        WifiData->ssid9[0]=ap.ssid_len;
531                                        for(i=0;i<32;i++) {
532                                                WifiData->ssid9[i+1]=ap.ssid[i];
533                                        }
534                                        WifiData->apchannel9=ap.channel;
535                                        for(i=0;i<16;i++) WifiData->baserates9[i]=ap.base_rates[i];
536                                        WifiData->reqMode=WIFIMODE_NORMAL;
537                                        WifiData->reqReqFlags |= WFLAG_REQ_APCONNECT | WFLAG_REQ_APCOPYVALUES;
538                                        wifi_connect_state=1;
539                                }
540                        }
541                        return ASSOCSTATUS_SEARCHING;
542                case 1: // associating
543                        switch(WifiData->curMode) {
544                        case WIFIMODE_DISABLED:
545                        case WIFIMODE_NORMAL:
546                        case WIFIMODE_DISASSOCIATE:
547                                return ASSOCSTATUS_DISCONNECTED;
548            case WIFIMODE_SCAN:
549                if(WifiData->reqReqFlags&WFLAG_REQ_APCONNECT) return ASSOCSTATUS_AUTHENTICATING;
550                return ASSOCSTATUS_DISCONNECTED;
551                        case WIFIMODE_ASSOCIATE:
552                                switch(WifiData->authlevel) {
553                                case WIFI_AUTHLEVEL_DISCONNECTED:
554                                        return ASSOCSTATUS_AUTHENTICATING;
555                                case WIFI_AUTHLEVEL_AUTHENTICATED:
556                                case WIFI_AUTHLEVEL_DEASSOCIATED:
557                                        return ASSOCSTATUS_ASSOCIATING;
558                                case WIFI_AUTHLEVEL_ASSOCIATED:
559#ifdef WIFI_USE_TCP_SGIP
560                                        if(wifi_hw) {
561                                                if(!(wifi_hw->ipaddr)) {
562                                                        sgIP_DHCP_Start(wifi_hw,wifi_hw->dns[0]==0);
563                                                        wifi_connect_state=2;
564                                                        return ASSOCSTATUS_ACQUIRINGDHCP;
565                                                }
566                                        }
567                                        sgIP_ARP_SendGratARP(wifi_hw);
568#endif
569                                        wifi_connect_state=3;
570                                        WifiData->flags9|=WFLAG_ARM9_NETREADY;
571                                        return ASSOCSTATUS_ASSOCIATED;
572                                }
573                                break;
574                        case WIFIMODE_ASSOCIATED:
575#ifdef WIFI_USE_TCP_SGIP
576                                if(wifi_hw) {
577                                        if(!(wifi_hw->ipaddr)) {
578                                                sgIP_DHCP_Start(wifi_hw,wifi_hw->dns[0]==0);
579                                                wifi_connect_state=2;
580                                                return ASSOCSTATUS_ACQUIRINGDHCP;
581                                        }
582                                }
583                                sgIP_ARP_SendGratARP(wifi_hw);
584#endif
585                                wifi_connect_state=3;
586                                WifiData->flags9|=WFLAG_ARM9_NETREADY;
587                                return ASSOCSTATUS_ASSOCIATED;
588                        case WIFIMODE_CANNOTASSOCIATE:
589                                return ASSOCSTATUS_CANNOTCONNECT;
590                        }
591                        return ASSOCSTATUS_DISCONNECTED;
592                case 2: // dhcp'ing
593#ifdef WIFI_USE_TCP_SGIP
594                        {
595                                int i;
596                                i=sgIP_DHCP_Update();
597                                if(i!=SGIP_DHCP_STATUS_WORKING) {
598                                        switch(i) {
599                                        case SGIP_DHCP_STATUS_SUCCESS:
600                                                wifi_connect_state=3;
601                                                WifiData->flags9|=WFLAG_ARM9_NETREADY;
602                                                sgIP_ARP_SendGratARP(wifi_hw);
603                        sgIP_DNS_Record_Localhost();
604                                                return ASSOCSTATUS_ASSOCIATED;
605                                        default:
606                                        case SGIP_DHCP_STATUS_IDLE:
607                                        case SGIP_DHCP_STATUS_FAILED:
608                                                Wifi_DisconnectAP();
609                                                wifi_connect_state=-1;
610                                                return ASSOCSTATUS_CANNOTCONNECT;
611
612                                        }
613                                }
614                        }
615#else
616                        // should never get here (dhcp state) without sgIP!
617                        Wifi_DisconnectAP();
618                        wifi_connect_state=-1;
619                        return ASSOCSTATUS_CANNOTCONNECT;
620#endif
621                        return ASSOCSTATUS_ACQUIRINGDHCP;
622                case 3: // connected!
623                        return ASSOCSTATUS_ASSOCIATED;
624                case 4: // search nintendo WFC data for a suitable AP
625                        {
626                                int n,i;
627                                for(n=0;n<3;n++) if(!(WifiData->wfc_enable[n]&0x80)) break;
628                                Wifi_AccessPoint ap;
629                                n=Wifi_FindMatchingAP(n,WifiData->wfc_ap,&ap);
630                                if(n!=-1) {
631#ifdef WIFI_USE_TCP_SGIP
632                                        Wifi_SetIP(WifiData->wfc_config[n][0],WifiData->wfc_config[n][1],WifiData->wfc_config[n][2],WifiData->wfc_config[n][3],WifiData->wfc_config[n][4]);
633#endif
634                                        WifiData->wepmode9=WifiData->wfc_enable[n]&0x03; // copy data
635                                        WifiData->wepkeyid9=(WifiData->wfc_enable[n]>>4)&7;
636                                        for(i=0;i<16;i++) {
637                                                WifiData->wepkey9[i]=WifiData->wfc_wepkey[n][i];
638                                        }
639
640                                        Wifi_CopyMacAddr(WifiData->bssid9, ap.bssid);
641                                        Wifi_CopyMacAddr(WifiData->apmac9, ap.bssid);
642                                        WifiData->ssid9[0]=ap.ssid_len;
643                                        for(i=0;i<32;i++) {
644                                                WifiData->ssid9[i+1]=ap.ssid[i];
645                                        }
646                                        WifiData->apchannel9=ap.channel;
647                                        for(i=0;i<16;i++) WifiData->baserates9[i]=ap.base_rates[i];
648                                        WifiData->reqMode=WIFIMODE_NORMAL;
649                                        WifiData->reqReqFlags |= WFLAG_REQ_APCONNECT | WFLAG_REQ_APCOPYVALUES;
650                                        wifi_connect_state=1;
651                                        return ASSOCSTATUS_SEARCHING;
652
653                                }
654
655                        }
656                        return ASSOCSTATUS_SEARCHING;
657        }
658        return ASSOCSTATUS_CANNOTCONNECT;
659}
660
661
662int Wifi_DisconnectAP() {
663        WifiData->reqMode=WIFIMODE_NORMAL;
664        WifiData->reqReqFlags &= ~WFLAG_REQ_APCONNECT;
665        WifiData->flags9&=~WFLAG_ARM9_NETREADY;
666
667        wifi_connect_state=-1;
668        return 0;
669}
670
671
672#ifdef WIFI_USE_TCP_SGIP
673
674
675
676int Wifi_TransmitFunction(sgIP_Hub_HWInterface * hw, sgIP_memblock * mb) {
677        // convert ethernet frame into wireless frame and output.
678        // ethernet header: 6byte dest, 6byte src, 2byte protocol_id
679        // assumes individual pbuf len is >=14 bytes, it's pretty likely ;) - also hopes pbuf len is a multiple of 2 :|
680        int base,framelen, hdrlen, writelen;
681   int copytotal, copyexpect;
682        u16 framehdr[6+12+2];
683        sgIP_memblock * t;
684   framelen=mb->totallength-14+8 + (WifiData->wepmode7?4:0);
685
686   if(!(WifiData->flags9&WFLAG_ARM9_NETUP)) {
687           SGIP_DEBUG_MESSAGE(("Transmit:err_netdown"));
688           sgIP_memblock_free(mb);
689           return 0; //?
690   }
691        if(framelen+40>Wifi_TxBufferWordsAvailable()*2) { // error, can't send this much!
692                SGIP_DEBUG_MESSAGE(("Transmit:err_space"));
693      sgIP_memblock_free(mb);
694                return 0; //?
695        }
696
697        ethhdr_print('T',mb->datastart);
698        framehdr[0]=0;
699        framehdr[1]=0;
700        framehdr[2]=0;
701        framehdr[3]=0;
702        framehdr[4]=0; // rate, will be filled in by the arm7.
703        hdrlen=18;
704        framehdr[7]=0;
705
706        if(WifiData->curReqFlags&WFLAG_REQ_APADHOC) { // adhoc mode
707                framehdr[6]=0x0008;
708                Wifi_CopyMacAddr(framehdr+14,WifiData->bssid7);
709                Wifi_CopyMacAddr(framehdr+11,WifiData->MacAddr);
710                Wifi_CopyMacAddr(framehdr+8,((u8 *)mb->datastart));
711        } else {
712                framehdr[6]=0x0108;
713                Wifi_CopyMacAddr(framehdr+8,WifiData->bssid7);
714                Wifi_CopyMacAddr(framehdr+11,WifiData->MacAddr);
715                Wifi_CopyMacAddr(framehdr+14,((u8 *)mb->datastart));
716        }
717        if(WifiData->wepmode7)  { framehdr[6] |=0x4000; hdrlen=20; }
718        framehdr[17] = 0;
719        framehdr[18] = 0; // wep IV, will be filled in if needed on the arm7 side.
720        framehdr[19] = 0;
721
722   framehdr[5]=framelen+hdrlen*2-12+4;
723   copyexpect= ((framelen+hdrlen*2-12+4) +12 -4 +1)/2;
724   copytotal=0;
725
726        WifiData->stats[WSTAT_TXQUEUEDPACKETS]++;
727        WifiData->stats[WSTAT_TXQUEUEDBYTES]+=framelen+hdrlen*2;
728
729        base = WifiData->txbufOut;
730        Wifi_TxBufferWrite(base,hdrlen,framehdr);
731        base += hdrlen;
732   copytotal+=hdrlen;
733        if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
734
735        // add LLC header
736        framehdr[0]=0xAAAA;
737        framehdr[1]=0x0003;
738        framehdr[2]=0x0000;
739        framehdr[3]=((u16 *)mb->datastart)[6]; // frame type
740
741        Wifi_TxBufferWrite(base,4,framehdr);
742        base += 4;
743   copytotal+=4;
744        if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
745
746        t=mb;
747        writelen=(mb->thislength-14);
748        if(writelen) {
749                Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)mb->datastart)+7);
750                base+=(writelen+1)/2;
751      copytotal+=(writelen+1)/2;
752                if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
753        }
754        while(mb->next) {
755                mb=mb->next;
756                writelen=mb->thislength;
757                Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)mb->datastart));
758                base+=(writelen+1)/2;
759      copytotal+=(writelen+1)/2;
760                if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
761        }
762   if(WifiData->wepmode7) { // add required extra bytes
763      base+=2;
764      copytotal+=2;
765      if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
766   }
767        WifiData->txbufOut=base; // update fifo out pos, done sending packet.
768
769        sgIP_memblock_free(t); // free packet, as we're the last stop on this chain.
770
771   if(copytotal!=copyexpect) {
772      SGIP_DEBUG_MESSAGE(("Tx exp:%i que:%i",copyexpect,copytotal));
773   }
774   if(synchandler) synchandler();
775        return 0;
776}
777
778int Wifi_Interface_Init(sgIP_Hub_HWInterface * hw) {
779        hw->MTU=2300;
780        hw->ipaddr=(192)|(168<<8)|(1<<16)|(151<<24);
781        hw->snmask=0x00FFFFFF;
782        hw->gateway=(192)|(168<<8)|(1<<16)|(1<<24);
783        hw->dns[0]=(192)|(168<<8)|(1<<16)|(1<<24);
784        hw->hwaddrlen=6;
785        Wifi_CopyMacAddr(hw->hwaddr,WifiData->MacAddr);
786        hw->userdata=0;
787        return 0;
788}
789
790void Wifi_Timer(int num_ms) {
791   Wifi_Update();
792   sgIP_Timer(num_ms);
793}
794
795#endif
796
797unsigned long Wifi_Init(int initflags) {
798        erasemem(&Wifi_Data_Struct,sizeof(Wifi_Data_Struct));
799    DC_FlushAll();
800        WifiData = (Wifi_MainStruct *) (((u32)&Wifi_Data_Struct)| 0x00400000); // should prevent the cache from eating us alive.
801
802#ifdef WIFI_USE_TCP_SGIP
803    switch(initflags & WIFIINIT_OPTION_HEAPMASK) {
804    case WIFIINIT_OPTION_USEHEAP_128:
805        wHeapAllocInit(128*1024);
806        break;
807    case WIFIINIT_OPTION_USEHEAP_64:
808        wHeapAllocInit(64*1024);
809        break;
810    case WIFIINIT_OPTION_USEHEAP_256:
811        wHeapAllocInit(256*1024);
812        break;
813    case WIFIINIT_OPTION_USEHEAP_512:
814        wHeapAllocInit(512*1024);
815        break;
816    case WIFIINIT_OPTION_USECUSTOMALLOC:
817        break;
818    }
819    sgIP_Init();
820
821#endif
822
823        WifiData->flags9 = WFLAG_ARM9_ACTIVE | (initflags & WFLAG_ARM9_INITFLAGMASK) ;
824        return (u32) &Wifi_Data_Struct;
825}
826
827int Wifi_CheckInit() {
828        if(!WifiData) return 0;
829        return ((WifiData->flags7 & WFLAG_ARM7_ACTIVE) && (WifiData->flags9 & WFLAG_ARM9_ARM7READY));
830}
831
832
833void Wifi_Update() {
834        int cnt;
835        int base, base2, len, fulllen;
836        if(!WifiData) return;
837
838#ifdef WIFI_USE_TCP_SGIP
839
840        if(!(WifiData->flags9&WFLAG_ARM9_ARM7READY)) {
841                if(WifiData->flags7 & WFLAG_ARM7_ACTIVE) {
842                        WifiData->flags9 |=WFLAG_ARM9_ARM7READY;
843                        // add network interface.
844                        wifi_hw = sgIP_Hub_AddHardwareInterface(&Wifi_TransmitFunction,&Wifi_Interface_Init);
845            sgIP_timems=WifiData->random; //hacky! but it should work just fine :)
846                }
847        }
848        if(WifiData->authlevel!=WIFI_AUTHLEVEL_ASSOCIATED && WifiData->flags9&WFLAG_ARM9_NETUP) {
849                WifiData->flags9 &= ~(WFLAG_ARM9_NETUP);
850        } else if(WifiData->authlevel==WIFI_AUTHLEVEL_ASSOCIATED && !(WifiData->flags9&WFLAG_ARM9_NETUP)) {
851                WifiData->flags9 |= (WFLAG_ARM9_NETUP);
852        }
853
854#endif
855
856        // check for received packets, forward to whatever wants them.
857        cnt=0;
858        while(WifiData->rxbufIn!=WifiData->rxbufOut) {
859                base = WifiData->rxbufIn;
860                len=Wifi_RxReadOffset(base,4);
861                fulllen=((len+3)&(~3))+12;
862#ifdef WIFI_USE_TCP_SGIP
863                // Do lwIP interfacing for rx here
864                if((Wifi_RxReadOffset(base,6)&0x01CF)==0x0008) // if it is a non-null data packet coming from the AP (toDS==0)
865                {
866                        u16 framehdr[6+12+2+4];
867                        sgIP_memblock * mb;
868                        int hdrlen;
869                        base2=base;
870                        Wifi_RxRawReadPacket(base,22*2,framehdr);
871
872        // ethhdr_print('!',framehdr+8);
873                        if((framehdr[8]==((u16 *)WifiData->MacAddr)[0] && framehdr[9]==((u16 *)WifiData->MacAddr)[1] && framehdr[10]==((u16 *)WifiData->MacAddr)[2]) ||
874                                (framehdr[8]==0xFFFF && framehdr[9]==0xFFFF && framehdr[10]==0xFFFF)) {
875                                // destination matches our mac address, or the broadcast address.
876                                //if(framehdr[6]&0x4000) { // wep enabled (when receiving WEP packets, the IV is stripped for us! how nice :|
877                                //      base2+=24; hdrlen=28;  // base2+=[wifi hdr 12byte]+[802 header hdrlen]+[slip hdr 8byte]
878                                //} else {
879                                        base2+=22; hdrlen=24;
880                                //}
881          //  SGIP_DEBUG_MESSAGE(("%04X %04X %04X %04X %04X",Wifi_RxReadOffset(base2-8,0),Wifi_RxReadOffset(base2-7,0),Wifi_RxReadOffset(base2-6,0),Wifi_RxReadOffset(base2-5,0),Wifi_RxReadOffset(base2-4,0)));
882                                // check for LLC/SLIP header...
883                                if(Wifi_RxReadOffset(base2-4,0)==0xAAAA && Wifi_RxReadOffset(base2-4,1)==0x0003 && Wifi_RxReadOffset(base2-4,2)==0) {
884                                        mb = sgIP_memblock_allocHW(14,len-8-hdrlen);
885                                        if(mb) {
886                                                if(base2>=(WIFI_RXBUFFER_SIZE/2)) base2-=(WIFI_RXBUFFER_SIZE/2);
887                                                Wifi_RxRawReadPacket(base2,(len-8-hdrlen)&(~1),((u16 *)mb->datastart)+7);
888                                                if(len&1) ((u8 *)mb->datastart)[len+14-1-8-hdrlen]=Wifi_RxReadOffset(base2,((len-8-hdrlen)/2))&255;
889                                                Wifi_CopyMacAddr(mb->datastart,framehdr+8); // copy dest
890                                                if(Wifi_RxReadOffset(base,6)&0x0200) { // from DS set?
891                                                        Wifi_CopyMacAddr(((u8 *)mb->datastart)+6,framehdr+14); // copy src from adrs3
892                                                } else {
893                                                        Wifi_CopyMacAddr(((u8 *)mb->datastart)+6,framehdr+11); // copy src from adrs2
894                                                }
895                                                ((u16 *)mb->datastart)[6]=framehdr[(hdrlen/2)+6+3]; // assume LLC exists and is 8 bytes.
896
897                                                ethhdr_print('R',mb->datastart);
898
899                                                // Done generating recieved data packet... now distribute it.
900                                                sgIP_Hub_ReceiveHardwarePacket(wifi_hw,mb);
901
902                                        }
903                                }
904                        }
905                }
906
907#endif
908
909                // check if we have a handler
910                if(packethandler) {
911                        base2=base+6;
912                        if(base2>=(WIFI_RXBUFFER_SIZE/2)) base2-=(WIFI_RXBUFFER_SIZE/2);
913                        (*packethandler)(base2,len);
914                }
915
916                base+=fulllen/2;
917                if(base>=(WIFI_RXBUFFER_SIZE/2)) base-=(WIFI_RXBUFFER_SIZE/2);
918                WifiData->rxbufIn=base;
919
920                if(cnt++>80) break;
921        }
922}
923
924
925//////////////////////////////////////////////////////////////////////////
926// Ip addr get/set functions
927#ifdef WIFI_USE_TCP_SGIP
928
929u32 Wifi_GetIP() {
930        if(wifi_hw) return wifi_hw->ipaddr;
931        return 0;
932}
933
934unsigned long Wifi_GetIPInfo(unsigned long * pGateway,unsigned long * pSnmask,unsigned long * pDns1,unsigned long * pDns2) {
935        if(wifi_hw) {
936                if(pGateway) *pGateway=wifi_hw->gateway;
937                if(pSnmask) *pSnmask=wifi_hw->snmask;
938                if(pDns1) *pDns1=wifi_hw->dns[0];
939                if(pDns2) *pDns2=wifi_hw->dns[1];
940                return wifi_hw->ipaddr;
941        }
942        return 0;
943}
944
945
946void Wifi_SetIP(u32 IPaddr, u32 gateway, u32 subnetmask, u32 dns1, u32 dns2) {
947        if(wifi_hw) {
948                SGIP_DEBUG_MESSAGE(("SetIP%08X %08X %08X",IPaddr,gateway,subnetmask));
949                wifi_hw->ipaddr=IPaddr;
950                wifi_hw->gateway=gateway;
951                wifi_hw->snmask=subnetmask;
952                wifi_hw->dns[0]=dns1;
953                wifi_hw->dns[1]=dns2;
954                // reset arp cache...
955                sgIP_ARP_FlushInterface(wifi_hw);
956        }
957}
958
959void Wifi_SetDHCP(void) {
960
961
962}
963
964#endif
965
966
967int Wifi_GetData(int datatype, int bufferlen, unsigned char * buffer) {
968        int i;
969        if(datatype<0 || datatype>=MAX_WIFIGETDATA) return -1;
970        switch(datatype) {
971        case WIFIGETDATA_MACADDRESS:
972                if(bufferlen<6 || !buffer) return -1;
973                for(i=0;i<6;i++) {
974                        buffer[i]=WifiData->MacAddr[i];
975                }
976                return 6;
977        case WIFIGETDATA_NUMWFCAPS:
978                for(i=0;i<3;i++) if(!(WifiData->wfc_enable[i]&0x80)) break;
979                return i;
980        }
981        return -1;
982}
983
984u32 Wifi_GetStats(int statnum) {
985        if(statnum<0 || statnum>=NUM_WIFI_STATS) return 0;
986        return WifiData->stats[statnum];
987}
988
989
990//////////////////////////////////////////////////////////////////////////
991// sync functions
992
993void Wifi_Sync(void) {
994   Wifi_Update();
995}
996
Note: See TracBrowser for help on using the repository browser.