// DS Wifi interface code // Copyright (C) 2005-2006 Stephen Stair - sgstair@akkit.org - http://www.akkit.org // wifi_arm7.c - arm7 wifi interface code /****************************************************************************** DSWifi Lib and test materials are licenced under the MIT open source licence: Copyright (c) 2005-2006 Stephen Stair Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ #include #include "dsregs.h" #include "wifi_arm7.h" #include "spinlock.h" // .h file with code for spinlocking in it. volatile Wifi_MainStruct * WifiData = 0; WifiSyncHandler synchandler = 0; int keepalive_time = 0; int chdata_save5 = 0; ////////////////////////////////////////////////////////////////////////// // // Flash support functions // char FlashData[512]; void Read_Flash(int address, char * destination, int length) { int i; while(SPI_CR&0x80); SPI_CR=0x8900; SPI_DATA=3; while(SPI_CR&0x80); SPI_DATA=(address>>16)&255; while(SPI_CR&0x80); SPI_DATA=(address>>8)&255; while(SPI_CR&0x80); SPI_DATA=(address)&255; while(SPI_CR&0x80); for(i=0;i511) return 0; return FlashData[address]; } int ReadFlashBytes(int address, int numbytes) { int dataout=0; int i; for(i=0;i510) return 0; return ReadFlashBytes(address,2); } ////////////////////////////////////////////////////////////////////////// // // WFC data loading // /* int crc16_slow(u8 * data, int length) { int i,j,d, crc; crc=0x0000; for(i=0;i>15))&1) crc = (crc<<1)^0x8005; else crc=crc<<1; d=d>>1; } } crc &=0xFFFF; return crc; } */ int crc16_slow(u8 * data, int length) { int i,j, crc; crc=0x0000; for(i=0;i>1)^0xA001; else crc=crc>>1; } } crc &=0xFFFF; return crc; } void GetWfcSettings(void) { u8 data[256]; int i,n, c; unsigned long s; c=0; u32 wfcBase = ReadFlashBytes(0x20, 2) * 8 - 0x400; for(i=0;i<3;i++) WifiData->wfc_enable[i]=0; for(i=0;i<3;i++) { Read_Flash( wfcBase +(i<<8),(char *)data,256); // check for validity (crc16) if(crc16_slow(data,256)==0x0000 && data[0xE7]==0x00) { // passed the test WifiData->wfc_enable[c] = 0x80 | (data[0xE6]&0x0F); WifiData->wfc_ap[c].channel=0; for(n=0;n<6;n++) WifiData->wfc_ap[c].bssid[n]=0; for(n=0;n<16;n++) WifiData->wfc_wepkey[c][n]=data[0x80+n]; for(n=0;n<32;n++) WifiData->wfc_ap[c].ssid[n]=data[0x40+n]; for(n=0;n<32;n++) if(!data[0x40+n]) break; WifiData->wfc_ap[c].ssid_len=n; WifiData->wfc_config[c][0]=((unsigned long *)(data+0xC0))[0]; WifiData->wfc_config[c][1]=((unsigned long *)(data+0xC0))[1]; WifiData->wfc_config[c][3]=((unsigned long *)(data+0xC0))[2]; WifiData->wfc_config[c][4]=((unsigned long *)(data+0xC0))[3]; s=0; for(n=0;n>24) | ((s&0xFF00)<<8) | ((s&0xFF0000)>>8); // htonl WifiData->wfc_config[c][2]=s; c++; } } } ////////////////////////////////////////////////////////////////////////// // // Other support // int Wifi_BBRead(int a) { while(W_BBSIOBUSY&1); W_BBSIOCNT=a | 0x6000; while(W_BBSIOBUSY&1); return W_BBSIOREAD; } int Wifi_BBWrite(int a, int b) { int i; i=0x2710; while((W_BBSIOBUSY&1)) { if(!i--) return -1; } W_BBSIOWRITE=b; W_BBSIOCNT=a | 0x5000; i=0x2710; while((W_BBSIOBUSY&1)) { if(!i--) return 0; } return 0; } void Wifi_RFWrite(int writedata) { while(W_RFSIOBUSY&1); W_RFSIODATA1=writedata; W_RFSIODATA2=writedata>>16; while(W_RFSIOBUSY&1); } int PowerChip_ReadWrite(int cmd, int data) { if(cmd&0x80) data=0; while(SPI_CR&0x80); SPI_CR=0x8802; SPI_DATA=cmd; while(SPI_CR&0x80); SPI_CR=0x8002; SPI_DATA=data; while(SPI_CR&0x80); data=SPI_DATA; SPI_CR=0; return data; } #define LED_LONGBLINK 1 #define LED_SHORTBLINK 3 #define LED_ON 0 int led_state=0; void SetLedState(int state) { int i; if(state>3 || state<0) return; if(state!=led_state) { led_state=state; i=PowerChip_ReadWrite(0x80,0); i=i&0xCF; i |= state<<4; PowerChip_ReadWrite(0,i); } } void ProxySetLedState(int state) { if(WifiData->flags9&WFLAG_ARM9_USELED) SetLedState(state); } ////////////////////////////////////////////////////////////////////////// // // Main functionality // int RF_Reglist[] = { 0x146, 0x148, 0x14A, 0x14C, 0x120, 0x122, 0x154, 0x144, 0x130, 0x132, 0x140, 0x142, 0x38, 0x124, 0x128, 0x150 }; void Wifi_RFInit() { int i,j; int channel_extrabits; int numchannels; int channel_extrabytes; int temp; for(i=0;i<16;i++) { WIFI_REG(RF_Reglist[i])=ReadFlashHWord(0x44+i*2); } numchannels=ReadFlashByte(0x42); channel_extrabits=ReadFlashByte(0x41); channel_extrabytes=(channel_extrabits+7)/8; WIFI_REG(0x184)=((channel_extrabits>>7)<<8) | (channel_extrabits&0x7F); j=0xCE; if(ReadFlashByte(0x40)==3) { for(i=0;i>18)==9 ) { chdata_save5 = temp&(~0x7C00); } } } else { for(i=0;i>1; WIFI_REG(0x8062) = 0x5F5E; WIFI_REG(0x8030) = 0x8001; } void Wifi_WakeUp() { u32 i; WIFI_REG(0x8036)=0; swiDelay( 67109 ); // 8ms delay WIFI_REG(0x8168)=0; i=Wifi_BBRead(1); Wifi_BBWrite(1,i&0x7f); Wifi_BBWrite(1,i); swiDelay( 335544 ); // 40ms delay Wifi_RFInit(); } void Wifi_Shutdown() { int a; if(ReadFlashByte(0x40)==2) { Wifi_RFWrite(0xC008); } a=Wifi_BBRead(0x1E); Wifi_BBWrite(0x1E,a|0x3F); WIFI_REG(0x168)=0x800D; WIFI_REG(0x36)=1; } void Wifi_CopyMacAddr(volatile void * dest, volatile void * src) { ((u16 *)dest)[0]=((u16 *)src)[0]; ((u16 *)dest)[1]=((u16 *)src)[1]; ((u16 *)dest)[2]=((u16 *)src)[2]; } int Wifi_CmpMacAddr(volatile void * mac1,volatile void * mac2) { return (((u16 *)mac1)[0]==((u16 *)mac2)[0]) && (((u16 *)mac1)[1]==((u16 *)mac2)[1]) && (((u16 *)mac1)[2]==((u16 *)mac2)[2]); } ////////////////////////////////////////////////////////////////////////// // // MAC Copy functions // u16 inline Wifi_MACRead(u32 MAC_Base, u32 MAC_Offset) { MAC_Base += MAC_Offset; if(MAC_Base>=(WIFI_REG(0x52)&0x1FFE)) MAC_Base -= ((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); return WIFI_REG(0x4000+MAC_Base); } void Wifi_MACCopy(u16 * dest, u32 MAC_Base, u32 MAC_Offset, u32 length) { int endrange,subval; int thislength; endrange = (WIFI_REG(0x52)&0x1FFE); subval=((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); MAC_Base += MAC_Offset; if(MAC_Base>=endrange) MAC_Base -= subval; while(length>0) { thislength=length; if(thislength>(endrange-MAC_Base)) thislength=endrange-MAC_Base; length-=thislength; while(thislength>0) { *(dest++) = WIFI_REG(0x4000+MAC_Base); MAC_Base+=2; thislength-=2; } MAC_Base-=subval; } } void Wifi_MACWrite(u16 * src, u32 MAC_Base, u32 MAC_Offset, u32 length) { int endrange,subval; int thislength; endrange = (WIFI_REG(0x52)&0x1FFE); subval=((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); MAC_Base += MAC_Offset; if(MAC_Base>=endrange) MAC_Base -= subval; while(length>0) { thislength=length; if(length>(endrange-MAC_Base)) length=endrange-MAC_Base; length-=thislength; while(thislength>0) { WIFI_REG(0x4000+MAC_Base) = *(src++); MAC_Base+=2; thislength-=2; } MAC_Base-=subval; } } int Wifi_QueueRxMacData(u32 base, u32 len) { int buflen, temp,macofs, tempout; macofs=0; buflen=(WifiData->rxbufIn-WifiData->rxbufOut-1)*2; if(buflen<0) buflen += WIFI_RXBUFFER_SIZE; if(buflenstats[WSTAT_RXQUEUEDLOST]++; return 0; } WifiData->stats[WSTAT_RXQUEUEDPACKETS]++; WifiData->stats[WSTAT_RXQUEUEDBYTES]+=len; temp=WIFI_RXBUFFER_SIZE-(WifiData->rxbufOut*2); tempout=WifiData->rxbufOut; if(len>temp) { Wifi_MACCopy((u16*)WifiData->rxbufData+tempout,base,macofs,temp); macofs+=temp; len-=temp; tempout=0; } Wifi_MACCopy((u16*)WifiData->rxbufData+tempout,base,macofs,len); tempout+=len/2; if(tempout>=(WIFI_RXBUFFER_SIZE/2)) tempout-=(WIFI_RXBUFFER_SIZE/2); WifiData->rxbufOut=tempout; if(synchandler) synchandler(); return 1; } int Wifi_CheckTxBuf(s32 offset) { offset+=WifiData->txbufIn; if(offset>=WIFI_TXBUFFER_SIZE/2) offset-=WIFI_TXBUFFER_SIZE/2; return WifiData->txbufData[offset]; } // non-wrapping function. int Wifi_CopyFirstTxData(s32 macbase) { int seglen, readbase,max, packetlen,length; packetlen=Wifi_CheckTxBuf(5); readbase=WifiData->txbufIn; length = (packetlen+12-4+1)/2; max=WifiData->txbufOut-WifiData->txbufIn; if(max<0) max+=WIFI_TXBUFFER_SIZE/2; if(max0) { seglen=length; if(readbase+seglen>WIFI_TXBUFFER_SIZE/2) seglen=WIFI_TXBUFFER_SIZE/2-readbase; length-=seglen; while(seglen--) { WIFI_REG(0x4000+macbase)=WifiData->txbufData[readbase++]; macbase+=2; } if(readbase>=WIFI_TXBUFFER_SIZE/2) readbase-=WIFI_TXBUFFER_SIZE/2; } WifiData->txbufIn=readbase; WifiData->stats[WSTAT_TXPACKETS]++; WifiData->stats[WSTAT_TXBYTES]+=packetlen+12-4; WifiData->stats[WSTAT_TXDATABYTES]+=packetlen-4; return packetlen; } u16 arm7q[1024]; u16 arm7qlen = 0; void Wifi_TxRaw(u16 * data, int datalen) { datalen = (datalen+3)&(~3); Wifi_MACWrite(data, 0, 0, datalen); // WIFI_REG(0xB8)=0x0001; WIFI_REG(0xA8)=0x8000; WifiData->stats[WSTAT_TXPACKETS]++; WifiData->stats[WSTAT_TXBYTES]+=datalen; WifiData->stats[WSTAT_TXDATABYTES]+=datalen-12; } int Wifi_TxCheck(void) { if(WIFI_REG(0xA8)&0x8000) return 0; return 1; } ////////////////////////////////////////////////////////////////////////// // // Wifi Interrupts // void Wifi_Intr_RxEnd(void) { int base; int packetlen; int full_packetlen; int cut, temp; int tIME; tIME=REG_IME; REG_IME=0; cut=0; while(WIFI_REG(0x54)!=WIFI_REG(0x5A)) { base = WIFI_REG(0x5A)<<1; packetlen=Wifi_MACRead(base,8); full_packetlen=12+((packetlen+3)&(~3)); WifiData->stats[WSTAT_RXPACKETS]++; WifiData->stats[WSTAT_RXBYTES]+=full_packetlen; WifiData->stats[WSTAT_RXDATABYTES]+=full_packetlen-12; // process packet here temp=Wifi_ProcessReceivedFrame(base,full_packetlen); // returns packet type if(temp&WifiData->reqPacketFlags || WifiData->reqReqFlags&WFLAG_REQ_PROMISC) { // if packet type is requested, forward it to the rx queue keepalive_time=0; if(!Wifi_QueueRxMacData(base,full_packetlen)) { // failed, ignore for now. } } base += full_packetlen; if(base>=(WIFI_REG(0x52)&0x1FFE)) base -= ((WIFI_REG(0x52)&0x1FFE)-(WIFI_REG(0x50)&0x1FFE)); WIFI_REG(0x5A)=base>>1; if(cut++>5) break; } REG_IME=tIME; } #define CNT_STAT_START WSTAT_HW_1B0 #define CNT_STAT_NUM 18 u16 count_ofs_list[CNT_STAT_NUM] = { 0x1B0, 0x1B2, 0x1B4, 0x1B6, 0x1B8, 0x1BA, 0x1BC, 0x1BE, 0x1C0, 0x1C4, 0x1D0, 0x1D2, 0x1D4, 0x1D6, 0x1D8, 0x1DA, 0x1DC, 0x1DE }; void Wifi_Intr_CntOverflow(void) { int i; int s,d; s=CNT_STAT_START; for(i=0;istats[s++]+=(d&0xFF); WifiData->stats[s++]+=((d>>8)&0xFF); } } void Wifi_Intr_StartTx(void) { if(WifiData->reqReqFlags&WFLAG_REQ_PROMISC) { // attempt to ensure packet is received } } void Wifi_Intr_TxEnd(void) { // assume that we can now tx something new. if(arm7qlen) { Wifi_TxRaw(arm7q, arm7qlen); keepalive_time=0; arm7qlen=0; return; } if((WifiData->txbufOut!=WifiData->txbufIn) && (!(WifiData->curReqFlags&WFLAG_REQ_APCONNECT) || WifiData->authlevel==WIFI_AUTHLEVEL_ASSOCIATED)) { if(Wifi_CopyFirstTxData(0)) { keepalive_time=0; if(WIFI_REG(0x4008)==0) { WIFI_REG(0x4008)=WifiData->maxrate7; } // if rate dne, fill it in. if(WIFI_REG(0x400C)&0x4000) { // wep is enabled, fill in the IV. WIFI_REG(0x4024) = (W_RANDOM ^ (W_RANDOM<<7) ^ (W_RANDOM<<15))&0xFFFF; WIFI_REG(0x4026) = ((W_RANDOM ^ (W_RANDOM>>7))&0xFF) | (WifiData->wepkeyid7<<14); } // WIFI_REG(0xB8)=0x0001; WIFI_REG(0xA8)=0x8000; WIFI_REG(0xAE)=0x000D; } } } void Wifi_Intr_TBTT(void) { if(WIFI_REG(0xA8)&0x8000) { WIFI_REG(0xAE)=0x000D; } } void Wifi_Intr_DoNothing(void) { } void Wifi_Interrupt(void) { int wIF; if(!WifiData) return; if(!(WifiData->flags7&WFLAG_ARM7_RUNNING)) return; do { REG_IF=0x01000000; // now that we've cleared the wireless IF, kill the bit in regular IF. wIF= W_IE & W_IF; if(wIF& 0x0001) { W_IF=0x0001; Wifi_Intr_RxEnd(); } // 0) Rx End if(wIF& 0x0002) { W_IF=0x0002; Wifi_Intr_TxEnd(); } // 1) Tx End if(wIF& 0x0004) { W_IF=0x0004; Wifi_Intr_DoNothing(); } // 2) Rx Cntup if(wIF& 0x0008) { W_IF=0x0008; Wifi_Intr_DoNothing(); } // 3) Tx Err if(wIF& 0x0010) { W_IF=0x0010; Wifi_Intr_CntOverflow(); } // 4) Count Overflow if(wIF& 0x0020) { W_IF=0x0020; Wifi_Intr_CntOverflow(); } // 5) AckCount Overflow if(wIF& 0x0040) { W_IF=0x0040; Wifi_Intr_DoNothing(); } // 6) Start Rx if(wIF& 0x0080) { W_IF=0x0080; Wifi_Intr_StartTx(); } // 7) Start Tx if(wIF& 0x0100) { W_IF=0x0100; Wifi_Intr_DoNothing(); } // 8) if(wIF& 0x0200) { W_IF=0x0200; Wifi_Intr_DoNothing(); } // 9) if(wIF& 0x0400) { W_IF=0x0400; Wifi_Intr_DoNothing(); } //10) if(wIF& 0x0800) { W_IF=0x0800; Wifi_Intr_DoNothing(); } //11) RF Wakeup if(wIF& 0x1000) { W_IF=0x1000; Wifi_Intr_DoNothing(); } //12) MP End if(wIF& 0x2000) { W_IF=0x2000; Wifi_Intr_DoNothing(); } //13) ACT End if(wIF& 0x4000) { W_IF=0x4000; Wifi_Intr_TBTT(); } //14) TBTT if(wIF& 0x8000) { W_IF=0x8000; Wifi_Intr_DoNothing(); } //15) PreTBTT wIF= W_IE & W_IF; } while(wIF); } void Wifi_Update(void) { int i; if(!WifiData) return; WifiData->random ^=(W_RANDOM ^ (W_RANDOM<<11) ^ (W_RANDOM<<22)); WifiData->stats[WSTAT_ARM7_UPDATES]++; WifiData->stats[WSTAT_DEBUG]=WIFI_REG(0xA8); if(WIFI_REG(0xA8)&0x8000) { WIFI_REG(0xAE)=0x000D; } // check flags, to see if we need to change anything switch(WifiData->curMode) { case WIFIMODE_DISABLED: ProxySetLedState(LED_ON); if(WifiData->reqMode!=WIFIMODE_DISABLED) { Wifi_Start(); WifiData->curMode=WIFIMODE_NORMAL; } break; case WIFIMODE_NORMAL: // main switcher function ProxySetLedState(LED_LONGBLINK); if(WifiData->reqMode==WIFIMODE_DISABLED) { Wifi_Stop(); WifiData->curMode=WIFIMODE_DISABLED; break; } if(WifiData->reqMode==WIFIMODE_SCAN) { WifiData->counter7=WIFI_REG(0xFA); // timer hword 2 (each tick is 65.5ms) WifiData->curMode=WIFIMODE_SCAN; break; } if((WifiData->reqReqFlags ^ WifiData->curReqFlags) & WFLAG_REQ_APCONNECT) { if(WifiData->curReqFlags& WFLAG_REQ_APCONNECT) { // already connected; disconnect WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; } else { // not connected - connect! if(WifiData->reqReqFlags&WFLAG_REQ_APCOPYVALUES) { WifiData->wepkeyid7=WifiData->wepkeyid9; WifiData->wepmode7=WifiData->wepmode9; WifiData->apchannel7=WifiData->apchannel9; Wifi_CopyMacAddr(WifiData->bssid7,WifiData->bssid9); Wifi_CopyMacAddr(WifiData->apmac7,WifiData->apmac9); for(i=0;i<20;i++) WifiData->wepkey7[i]=WifiData->wepkey9[i]; for(i=0;i<34;i++) WifiData->ssid7[i]=WifiData->ssid9[i]; for(i=0;i<16;i++) WifiData->baserates7[i]=WifiData->baserates9[i]; if(WifiData->reqReqFlags&WFLAG_REQ_APADHOC) WifiData->curReqFlags |= WFLAG_REQ_APADHOC; else WifiData->curReqFlags &= ~WFLAG_REQ_APADHOC; } Wifi_SetWepKey((void *)WifiData->wepkey7); Wifi_SetWepMode(WifiData->wepmode7); // latch BSSID W_BSSID[0]= ((u16 *)WifiData->bssid7)[0]; W_BSSID[1]= ((u16 *)WifiData->bssid7)[1]; W_BSSID[2]= ((u16 *)WifiData->bssid7)[2]; //WIFI_REG(0xD0) &= ~0x0400; WIFI_REG(0xD0) |= 0x0400; WifiData->reqChannel=WifiData->apchannel7; Wifi_SetChannel(WifiData->apchannel7); if(WifiData->curReqFlags&WFLAG_REQ_APADHOC) { WifiData->authlevel=WIFI_AUTHLEVEL_ASSOCIATED; } else { Wifi_SendOpenSystemAuthPacket(); WifiData->authlevel=WIFI_AUTHLEVEL_DISCONNECTED; } WifiData->txbufIn=WifiData->txbufOut; // empty tx buffer. WifiData->curReqFlags |= WFLAG_REQ_APCONNECT; WifiData->counter7=WIFI_REG(0xFA); // timer hword 2 (each tick is 65.5ms) WifiData->curMode=WIFIMODE_ASSOCIATE; WifiData->authctr=0; } } break; case WIFIMODE_SCAN: ProxySetLedState(LED_LONGBLINK); if(WifiData->reqMode!=WIFIMODE_SCAN) { WifiData->curMode=WIFIMODE_NORMAL; break; } if(((u16)(WIFI_REG(0xFA)-WifiData->counter7))>6) { // jump ship! WifiData->counter7=WIFI_REG(0xFA); WifiData->reqChannel++; { int i; for(i=0;iaplist[i].flags & WFLAG_APDATA_ACTIVE) { WifiData->aplist[i].timectr++; if(WifiData->aplist[i].timectr>WIFI_AP_TIMEOUT) { WifiData->aplist[i].rssi=0; WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=0; // update rssi later. } } } } if(WifiData->reqChannel==14) WifiData->reqChannel=1; } break; case WIFIMODE_ASSOCIATE: ProxySetLedState(LED_LONGBLINK); if(WifiData->authlevel==WIFI_AUTHLEVEL_ASSOCIATED) { WifiData->curMode=WIFIMODE_ASSOCIATED; break; } if(((u16)(WIFI_REG(0xFA)-WifiData->counter7))>20) { // ~1 second, reattempt connect stage WifiData->counter7=WIFI_REG(0xFA); WifiData->authctr++; if(WifiData->authctr>WIFI_MAX_ASSOC_RETRY) { WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; break; } switch(WifiData->authlevel) { case WIFI_AUTHLEVEL_DISCONNECTED: // send auth packet if(!(WifiData->curReqFlags&WFLAG_REQ_APADHOC)) { Wifi_SendOpenSystemAuthPacket(); break; } WifiData->authlevel=WIFI_AUTHLEVEL_ASSOCIATED; break; case WIFI_AUTHLEVEL_DEASSOCIATED: case WIFI_AUTHLEVEL_AUTHENTICATED: // send assoc packet Wifi_SendAssocPacket(); break; case WIFI_AUTHLEVEL_ASSOCIATED: WifiData->curMode=WIFIMODE_ASSOCIATED; break; } } if(!(WifiData->reqReqFlags & WFLAG_REQ_APCONNECT)) { WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; WifiData->curMode=WIFIMODE_NORMAL; break; } break; case WIFIMODE_ASSOCIATED: ProxySetLedState(LED_SHORTBLINK); keepalive_time++; if(keepalive_time>WIFI_KEEPALIVE_COUNT) { keepalive_time=0; Wifi_SendNullFrame(); } if((u16)(WIFI_REG(0xFA)-WifiData->pspoll_period)>WIFI_PS_POLL_CONST) { WifiData->pspoll_period=WIFI_REG(0xFA); // Wifi_SendPSPollFrame(); } if(!(WifiData->reqReqFlags & WFLAG_REQ_APCONNECT)) { W_BSSID[0]= ((u16 *)WifiData->bssid7)[0]; W_BSSID[1]= ((u16 *)WifiData->bssid7)[1]; W_BSSID[2]= ((u16 *)WifiData->bssid7)[2]; //WIFI_REG(0xD0) &= ~0x0400; WifiData->curMode=WIFIMODE_NORMAL; WifiData->authlevel=WIFI_AUTHLEVEL_DISCONNECTED; if(WifiData->curReqFlags &WFLAG_REQ_APCONNECT) { // deassociate, then return WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; } else { // not connected for some reason, return. WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; WifiData->curMode=WIFIMODE_ASSOCIATE; } break; } if(WifiData->authlevel!=WIFI_AUTHLEVEL_ASSOCIATED) { WifiData->curMode=WIFIMODE_ASSOCIATE; break; } break; case WIFIMODE_CANNOTASSOCIATE: ProxySetLedState(LED_LONGBLINK); if(!(WifiData->reqReqFlags & WFLAG_REQ_APCONNECT)) { WifiData->curReqFlags &=~WFLAG_REQ_APCONNECT; WifiData->curMode=WIFIMODE_NORMAL; break; } break; } if(WifiData->curChannel!=WifiData->reqChannel) { Wifi_SetChannel(WifiData->reqChannel); } // check Rx Wifi_Intr_RxEnd(); // check if we need to tx anything if(Wifi_TxCheck()) Wifi_Intr_TxEnd(); // easiest way to do so at the moment. } ////////////////////////////////////////////////////////////////////////// // // Wifi User-called Functions // void erasemem(void * mem, int length) { int i; char * m = (char *)mem; for(i=0;icurChannel=1; WifiData->reqChannel=1; WifiData->curMode=WIFIMODE_DISABLED; WifiData->reqMode=WIFIMODE_DISABLED; WifiData->reqPacketFlags=WFLAG_PACKET_ALL & (~WFLAG_PACKET_BEACON); WifiData->curReqFlags=0; WifiData->reqReqFlags=0; WifiData->maxrate7=0x0A; int i; for(i=0x4000;i<0x6000;i+=2) WIFI_REG(i)=0; // load in the WFC data. GetWfcSettings(); for(i=0;i<6;i++) WifiData->MacAddr[i]=ReadFlashByte(0x36+i); W_IE=0; Wifi_WakeUp(); Wifi_MacInit(); Wifi_RFInit(); Wifi_BBInit(); // Set Default Settings W_MACADDR[0]=((u16 *)WifiData->MacAddr)[0]; W_MACADDR[1]=((u16 *)WifiData->MacAddr)[1]; W_MACADDR[2]=((u16 *)WifiData->MacAddr)[2]; W_RETRLIMIT=7; Wifi_SetMode(2); Wifi_SetWepMode(WEPMODE_NONE); Wifi_SetChannel(1); Wifi_BBWrite(0x13, 0x00); Wifi_BBWrite(0x35, 0x1F); // Wifi_Shutdown(); WifiData->random ^=(W_RANDOM ^ (W_RANDOM<<11) ^ (W_RANDOM<<22)); WifiData->flags7 |= WFLAG_ARM7_ACTIVE; } void Wifi_Deinit() { Wifi_Stop(); POWERCNT7 &= ~2; } void Wifi_Start() { int i, tIME; tIME=REG_IME; REG_IME=0; Wifi_Stop(); // Wifi_WakeUp(); WIFI_REG(0x8032) = 0x8000; WIFI_REG(0x8134) = 0xFFFF; WIFI_REG(0x802A) = 0; W_AIDS = 0; WIFI_REG(0x80E8) = 1; WIFI_REG(0x8038) = 0x0000; WIFI_REG(0x20) = 0x0000; WIFI_REG(0x22) = 0x0000; WIFI_REG(0x24) = 0x0000; Wifi_TxSetup(); Wifi_RxSetup(); WIFI_REG(0x8030) = 0x8000; /* switch(WIFI_REG(0x8006)&7) { case 0: // infrastructure mode? W_IF=0xFFFF; W_IE=0x003F; WIFI_REG(0x81AE)=0x1fff; //WIFI_REG(0x81AA)=0x0400; WIFI_REG(0x80D0)=0xffff; WIFI_REG(0x80E0)=0x0008; WIFI_REG(0x8008)=0; WIFI_REG(0x800A)=0; WIFI_REG(0x80E8)=0; WIFI_REG(0x8004)=1; //SetStaState(0x40); break; case 1: // ad-hoc mode? -- beacons are required to be created! W_IF=0xFFF; W_IE=0x703F; WIFI_REG(0x81AE)=0x1fff; WIFI_REG(0x81AA)=0; // 0x400 WIFI_REG(0x80D0)=0x0301; WIFI_REG(0x80E0)=0x000D; WIFI_REG(0x8008)=0xE000; WIFI_REG(0x800A)=0; WIFI_REG(0x8004)=1; //?? WIFI_REG(0x80EA)=1; WIFI_REG(0x80AE)=2; break; case 2: // DS comms mode? */ W_IF=0xFFFF; //W_IE=0xE03F; W_IE=0x40B3; WIFI_REG(0x81AE)=0x1fff; WIFI_REG(0x81AA)=0; //0x68 W_BSSID[0]=0xFFFF; W_BSSID[1]=0xFFFF; W_BSSID[2]=0xFFFF; WIFI_REG(0x80D0)=0x0181; // 0x181 WIFI_REG(0x80E0)=0x000B; WIFI_REG(0x8008)=0; WIFI_REG(0x800A)=0; WIFI_REG(0x8004)=1; WIFI_REG(0x80E8)=1; WIFI_REG(0x80EA)=1; //SetStaState(0x20); /* break; case 3: case 4: break; } */ WIFI_REG(0x8048)=0x0000; Wifi_DisableTempPowerSave(); //WIFI_REG(0x80AE)=0x0002; W_POWERSTATE |= 2; WIFI_REG(0xAC) = 0xFFFF; i=0xFA0; while(i!=0 && !(WIFI_REG(0x819C)&0x80)) i--; WifiData->flags7 |=WFLAG_ARM7_RUNNING; REG_IME=tIME; } void Wifi_Stop() { int tIME; tIME=REG_IME; WifiData->flags7 &= ~WFLAG_ARM7_RUNNING; W_IE=0; WIFI_REG(0x8004) = 0; WIFI_REG(0x80EA) = 0; WIFI_REG(0x80E8) = 0; WIFI_REG(0x8008) = 0; WIFI_REG(0x800A) = 0; WIFI_REG(0x80AC) = 0xFFFF; WIFI_REG(0x80B4) = 0xFFFF; // Wifi_Shutdown(); REG_IME=tIME; } void Wifi_SetChannel(int channel) { int i,n,l; if(channel<1 || channel>13) return; channel-=1; switch(ReadFlashByte(0x40)) { case 2: case 5: Wifi_RFWrite(ReadFlashBytes(0xf2+channel*6,3)); Wifi_RFWrite(ReadFlashBytes(0xf5+channel*6,3)); swiDelay( 12583 ); // 1500 us delay if(chdata_save5 & 0x10000) { if(chdata_save5 & 0x8000) break; n = ReadFlashByte(0x154+channel); Wifi_RFWrite( chdata_save5 | ((n&0x1F)<<10) ); } else { Wifi_BBWrite(0x1E, ReadFlashByte(0x146+channel)); } break; case 3: n=ReadFlashByte(0x42); n+=0xCF; l=ReadFlashByte(n-1); for(i=0;icurChannel=channel+1; } void Wifi_SetWepKey(void * wepkey) { int i; for(i=0;i<16;i++) { W_WEPKEY0[i]=((u16 *)wepkey)[i]; W_WEPKEY1[i]=((u16 *)wepkey)[i]; W_WEPKEY2[i]=((u16 *)wepkey)[i]; W_WEPKEY3[i]=((u16 *)wepkey)[i]; } } void Wifi_SetWepMode(int wepmode) { if(wepmode<0 || wepmode>7) return; if(wepmode==0) { WIFI_REG(0x32)=0x0000; } else { WIFI_REG(0x32)=0x8000; } if(wepmode==0) wepmode=1; W_MODE_WEP = (W_MODE_WEP & 0xFFC7) | (wepmode<<3); } void Wifi_SetBeaconPeriod(int beacon_period) { if(beacon_period<0x10 || beacon_period>0x3E7) return; WIFI_REG(0x8C)=beacon_period; } void Wifi_SetMode(int wifimode) { if(wifimode>3 || wifimode<0) return; W_MODE_WEP = (W_MODE_WEP& 0xfff8) | wifimode; } void Wifi_SetPreambleType(int preamble_type) { if(preamble_type>1 || preamble_type<0) return; WIFI_REG(0x80BC) = (WIFI_REG(0x80BC) & 0xFFBF) | (preamble_type<<6); } void Wifi_DisableTempPowerSave() { WIFI_REG(0x8038) &= ~2; WIFI_REG(0x8048) = 0; } ////////////////////////////////////////////////////////////////////////// // // 802.11b system, tied in a bit with the : int Wifi_TxQueue(u16 * data, int datalen) { int i,j; if(arm7qlen) { if(Wifi_TxCheck()) { Wifi_TxRaw(arm7q,arm7qlen); arm7qlen=0; j=(datalen+1)>>1; if(j>1024) return 0; for(i=0;i>1; if(j>1024) return 0; for(i=0;iapmac7); Wifi_CopyMacAddr(data+22,WifiData->MacAddr); Wifi_CopyMacAddr(data+28,WifiData->bssid7); ((u16 *)data)[17]=0; // fill in wep-specific stuff if(headerflags&0x4000) { ((u32 *)data)[9]=((W_RANDOM ^ (W_RANDOM<<7) ^ (W_RANDOM<<15))&0x0FFF) | (WifiData->wepkeyid7<<30); // I'm lazy and certainly haven't done this to spec. ((u16 *)data)[6]=headerflags; return 28+12; } else { ((u16 *)data)[6]=headerflags; return 24+12; } } int Wifi_SendOpenSystemAuthPacket() { // max size is 12+24+4+6 = 46 u8 data[64]; int i; i=Wifi_GenMgtHeader(data,0x00B0); ((u16 *)(data+i))[0]=0; // Authentication algorithm number (0=open system) ((u16 *)(data+i))[1]=1; // Authentication sequence number ((u16 *)(data+i))[2]=0; // Authentication status code (reserved for this message, =0) ((u16 *)data)[4]=0x000A; ((u16 *)data)[5]=i+6-12+4; return Wifi_TxQueue((u16 *)data, i+6); } int Wifi_SendSharedKeyAuthPacket(void) { // max size is 12+24+4+6 = 46 u8 data[64]; int i; i=Wifi_GenMgtHeader(data,0x00B0); ((u16 *)(data+i))[0]=1; // Authentication algorithm number (1=shared key) ((u16 *)(data+i))[1]=1; // Authentication sequence number ((u16 *)(data+i))[2]=0; // Authentication status code (reserved for this message, =0) ((u16 *)data)[4]=0x000A; ((u16 *)data)[5]=i+6-12+4; return Wifi_TxQueue((u16 *)data, i+6); } int Wifi_SendSharedKeyAuthPacket2(int challenge_length, u8 * challenge_Text) { // max size is 12+24+4+6 = 46 u8 data[320]; int i,j; i=Wifi_GenMgtHeader(data,0x40B0); ((u16 *)(data+i))[0]=1; // Authentication algorithm number (1=shared key) ((u16 *)(data+i))[1]=3; // Authentication sequence number ((u16 *)(data+i))[2]=0; // Authentication status code (reserved for this message, =0) data[i+6]=0x10; // 16=challenge text block data[i+7]=challenge_length; for(j=0;jwepmode7) { ((u16 *)(data+i))[0]=0x0031; // CAPS info } else { ((u16 *)(data+i))[0]=0x0021; // CAPS info } ((u16 *)(data+i))[1]=WIFI_REG(0x8E); // Listen interval i+=4; data[i++]=0; // SSID element data[i++]=WifiData->ssid7[0]; for(j=0;jssid7[0];j++) data[i++]=WifiData->ssid7[1+j]; if((WifiData->baserates7[0]&0x7f)!=2) { for(j=1;j<16;j++) WifiData->baserates7[i]=WifiData->baserates7[j-1]; } WifiData->baserates7[0]=0x82; if((WifiData->baserates7[1]&0x7f)!=4) { for(j=2;j<16;j++) WifiData->baserates7[j]=WifiData->baserates7[j-1]; } WifiData->baserates7[1]=0x04; WifiData->baserates7[15]=0; for(j=0;j<16;j++) if(WifiData->baserates7[j]==0) break; numrates=j; for(j=2;jbaserates7[j] &= 0x7F; data[i++]=1; // rate set data[i++]=numrates; for(j=0;jbaserates7[j]; // reset header fields with needed data ((u16 *)data)[4]=0x000A; ((u16 *)data)[5]=i-12+4; return Wifi_TxQueue((u16 *)data, i); } int Wifi_SendNullFrame() { // max size is 12+16 = 28 u8 data[32]; // tx header ((u16 *)data)[0]=0; ((u16 *)data)[1]=0; ((u16 *)data)[2]=0; ((u16 *)data)[3]=0; ((u16 *)data)[4]=WifiData->maxrate7; ((u16 *)data)[5]=18+4; // fill in packet header fields ((u16 *)data)[6]=0x0148; ((u16 *)data)[7]=0; Wifi_CopyMacAddr(data+16,WifiData->apmac7); Wifi_CopyMacAddr(data+22,WifiData->MacAddr); return Wifi_TxQueue((u16 *)data, 30); } int Wifi_SendPSPollFrame() { // max size is 12+16 = 28 u8 data[32]; // tx header ((u16 *)data)[0]=0; ((u16 *)data)[1]=0; ((u16 *)data)[2]=0; ((u16 *)data)[3]=0; ((u16 *)data)[4]=WifiData->maxrate7; ((u16 *)data)[5]=16+4; // fill in packet header fields ((u16 *)data)[6]=0x01A4; ((u16 *)data)[7]=0xC000 | W_AIDS; Wifi_CopyMacAddr(data+16,WifiData->apmac7); Wifi_CopyMacAddr(data+22,WifiData->MacAddr); return Wifi_TxQueue((u16 *)data, 28); } int Wifi_ProcessReceivedFrame(int macbase, int framelen) { Wifi_RxHeader packetheader; u16 control_802; Wifi_MACCopy((u16 *)&packetheader,macbase,0,12); control_802=Wifi_MACRead(macbase,12); switch((control_802>>2)&0x3F) { // Management Frames case 0x20: // 1000 00 Beacon case 0x14: // 0101 00 Probe Response // process probe responses too. // mine data from the beacon... { u8 data[512]; u8 wepmode,fromsta; u8 segtype,seglen; u8 channel; u8 wpamode; u8 rateset[16]; u16 ptr_ssid; u16 maxrate; u16 curloc; u32 datalen; u16 i,j,compatible; datalen=packetheader.byteLength; if(datalen>512) datalen=512; Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); wepmode=0; maxrate=0; if(((u16 *)data)[5+12]&0x0010) { // capability info, WEP bit wepmode=1; } fromsta=Wifi_CmpMacAddr(data+10, data+16); curloc=12+24; // 12 fixed bytes, 24 802.11 header compatible=1; ptr_ssid=0; channel=WifiData->curChannel; wpamode=0; do { if(curloc>=datalen) break; segtype=data[curloc++]; seglen=data[curloc++]; switch(segtype) { case 0: // SSID element ptr_ssid=curloc-2; break; case 1: // rate set (make sure we're compatible) compatible=0; maxrate=0; j=0; for(i=0;imaxrate) maxrate=data[curloc+i]&0x7F; if(j<15 && data[curloc+i]&0x80) rateset[j++]=data[curloc+i]; } for(i=0;iaplist[i].bssid,data+16)) { seglen++; if(Spinlock_Acquire(WifiData->aplist[i])==SPINLOCK_OK) { WifiData->aplist[i].timectr=0; WifiData->aplist[i].flags=WFLAG_APDATA_ACTIVE | (wepmode?WFLAG_APDATA_WEP:0) | (fromsta?0:WFLAG_APDATA_ADHOC); if(compatible==1) WifiData->aplist[i].flags |= WFLAG_APDATA_COMPATIBLE; if(compatible==2) WifiData->aplist[i].flags |= WFLAG_APDATA_EXTCOMPATIBLE; if(wpamode==1) WifiData->aplist[i].flags |= WFLAG_APDATA_WPA; WifiData->aplist[i].maxrate=maxrate; Wifi_CopyMacAddr(WifiData->aplist[i].macaddr,data+10); // src: +10 if(ptr_ssid) { WifiData->aplist[i].ssid_len=data[ptr_ssid+1]; if(WifiData->aplist[i].ssid_len>32) WifiData->aplist[i].ssid_len=32; for(j=0;japlist[i].ssid_len;j++) { WifiData->aplist[i].ssid[j]=data[ptr_ssid+2+j]; } WifiData->aplist[i].ssid[j]=0; } if(WifiData->curChannel==channel) { // only use RSSI when we're on the right channel if(WifiData->aplist[i].rssi_past[0]==0) { // min rssi is 2, heh. WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=packetheader.rssi_&255; } else { for(j=0;j<7;j++) { WifiData->aplist[i].rssi_past[j]=WifiData->aplist[i].rssi_past[j+1]; } WifiData->aplist[i].rssi_past[7]=packetheader.rssi_&255; } } WifiData->aplist[i].channel=channel; for(j=0;j<16;j++) WifiData->aplist[i].base_rates[j]=rateset[j]; Spinlock_Release(WifiData->aplist[i]); } else { // couldn't update beacon - oh well :\ there'll be other beacons. } } else { if(WifiData->aplist[i].flags & WFLAG_APDATA_ACTIVE) { // WifiData->aplist[i].timectr++; } else { if(segtype==255) segtype=i; } } } if(seglen==0) { // we couldn't find an existing record if(segtype==255) { j=0; for(i=0;iaplist[i].timectr>j) { j=WifiData->aplist[i].timectr; segtype=i; } } } // stuff new data in i=segtype; if(Spinlock_Acquire(WifiData->aplist[i])==SPINLOCK_OK) { Wifi_CopyMacAddr(WifiData->aplist[i].bssid,data+16); // bssid: +16 Wifi_CopyMacAddr(WifiData->aplist[i].macaddr,data+10); // src: +10 WifiData->aplist[i].timectr=0; WifiData->aplist[i].flags=WFLAG_APDATA_ACTIVE | (wepmode?WFLAG_APDATA_WEP:0) | (fromsta?0:WFLAG_APDATA_ADHOC); if(compatible==1) WifiData->aplist[i].flags |= WFLAG_APDATA_COMPATIBLE; if(compatible==2) WifiData->aplist[i].flags |= WFLAG_APDATA_EXTCOMPATIBLE; if(wpamode==1) WifiData->aplist[i].flags |= WFLAG_APDATA_WPA; WifiData->aplist[i].maxrate=maxrate; if(ptr_ssid) { WifiData->aplist[i].ssid_len=data[ptr_ssid+1]; if(WifiData->aplist[i].ssid_len>32) WifiData->aplist[i].ssid_len=32; for(j=0;japlist[i].ssid_len;j++) { WifiData->aplist[i].ssid[j]=data[ptr_ssid+2+j]; } WifiData->aplist[i].ssid[j]=0; } if(WifiData->curChannel==channel) { // only use RSSI when we're on the right channel WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=packetheader.rssi_&255; } else { WifiData->aplist[i].rssi_past[0]=WifiData->aplist[i].rssi_past[1]= WifiData->aplist[i].rssi_past[2]=WifiData->aplist[i].rssi_past[3]= WifiData->aplist[i].rssi_past[4]=WifiData->aplist[i].rssi_past[5]= WifiData->aplist[i].rssi_past[6]=WifiData->aplist[i].rssi_past[7]=0; // update rssi later. } WifiData->aplist[i].channel=channel; for(j=0;j<16;j++) WifiData->aplist[i].base_rates[j]=rateset[j]; Spinlock_Release(WifiData->aplist[i]); } else { // couldn't update beacon - oh well :\ there'll be other beacons. } } } } if(((control_802>>2)&0x3F)==0x14) return WFLAG_PACKET_MGT; return WFLAG_PACKET_BEACON; case 0x04: // 0001 00 Assoc Response case 0x0C: // 0011 00 Reassoc Response // we might have been associated, let's check. { int datalen,i; u8 data[64]; datalen=packetheader.byteLength; if(datalen>64) datalen=64; Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); if(Wifi_CmpMacAddr(data+4,WifiData->MacAddr)) { // packet is indeed sent to us. if(Wifi_CmpMacAddr(data+16,WifiData->bssid7)) { // packet is indeed from the base station we're trying to associate to. if(((u16 *)(data+24))[1]==0) { // status code, 0==success W_AIDS=((u16 *)(data+24))[2]; WIFI_REG(0x2A)=((u16 *)(data+24))[2]; // set max rate WifiData->maxrate7=0xA; for(i=0;i<((u8 *)(data+24))[7];i++) { if(((u8 *)(data+24))[8+i]==0x84 || ((u8 *)(data+24))[8+i]==0x04) { WifiData->maxrate7=0x14; } } if(WifiData->authlevel==WIFI_AUTHLEVEL_AUTHENTICATED || WifiData->authlevel==WIFI_AUTHLEVEL_DEASSOCIATED) { WifiData->authlevel=WIFI_AUTHLEVEL_ASSOCIATED; WifiData->authctr=0; } } else { // status code = failure! WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; } } } } return WFLAG_PACKET_MGT; case 0x00: // 0000 00 Assoc Request case 0x08: // 0010 00 Reassoc Request case 0x10: // 0100 00 Probe Request case 0x24: // 1001 00 ATIM case 0x28: // 1010 00 Disassociation return WFLAG_PACKET_MGT; case 0x2C: // 1011 00 Authentication // check auth response to ensure we're in { int datalen; u8 data[384]; datalen=packetheader.byteLength; if(datalen>384) datalen=384; Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); if(Wifi_CmpMacAddr(data+4,WifiData->MacAddr)) { // packet is indeed sent to us. if(Wifi_CmpMacAddr(data+16,WifiData->bssid7)) { // packet is indeed from the base station we're trying to associate to. if(((u16 *)(data+24))[0]==0) { // open system auth if(((u16 *)(data+24))[1]==2) { // seq 2, should be final sequence if(((u16 *)(data+24))[2]==0) { // status code: successful if(WifiData->authlevel==WIFI_AUTHLEVEL_DISCONNECTED) { WifiData->authlevel=WIFI_AUTHLEVEL_AUTHENTICATED; WifiData->authctr=0; Wifi_SendAssocPacket(); } } else { // status code: rejected, try something else Wifi_SendSharedKeyAuthPacket(); } } } else if(((u16 *)(data+24))[0]==1) { // shared key auth if(((u16 *)(data+24))[1]==2) { // seq 2, challenge text if(((u16 *)(data+24))[2]==0) { // status code: successful // scrape challenge text and send challenge reply if(data[24+6]==0x10) { // 16 = challenge text - this value must be 0x10 or else! Wifi_SendSharedKeyAuthPacket2(data[24+7],data+24+8); } } else { // rejected, just give up. WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; } } else if(((u16 *)(data+24))[1]==4) { // seq 4, accept/deny if(((u16 *)(data+24))[2]==0) { // status code: successful if(WifiData->authlevel==WIFI_AUTHLEVEL_DISCONNECTED) { WifiData->authlevel=WIFI_AUTHLEVEL_AUTHENTICATED; WifiData->authctr=0; Wifi_SendAssocPacket(); } } else { // status code: rejected. Cry in the corner. WifiData->curMode=WIFIMODE_CANNOTASSOCIATE; } } } } } } return WFLAG_PACKET_MGT; case 0x30: // 1100 00 Deauthentication { int datalen; u8 data[64]; datalen=packetheader.byteLength; if(datalen>64) datalen=64; Wifi_MACCopy((u16 *)data,macbase,12,(datalen+1)&~1); if(Wifi_CmpMacAddr(data+4,WifiData->MacAddr)) { // packet is indeed sent to us. if(Wifi_CmpMacAddr(data+16,WifiData->bssid7)) { // packet is indeed from the base station we're trying to associate to. // bad things! they booted us!. // back to square 1. if(WifiData->curReqFlags&WFLAG_REQ_APADHOC){ WifiData->authlevel=WIFI_AUTHLEVEL_AUTHENTICATED; Wifi_SendAssocPacket(); } else { WifiData->authlevel=WIFI_AUTHLEVEL_DISCONNECTED; Wifi_SendOpenSystemAuthPacket(); } } } } return WFLAG_PACKET_MGT; // Control Frames case 0x29: // 1010 01 PowerSave Poll case 0x2D: // 1011 01 RTS case 0x31: // 1100 01 CTS case 0x35: // 1101 01 ACK case 0x39: // 1110 01 CF-End case 0x3D: // 1111 01 CF-End+CF-Ack return WFLAG_PACKET_CTRL; // Data Frames case 0x02: // 0000 10 Data case 0x06: // 0001 10 Data + CF-Ack case 0x0A: // 0010 10 Data + CF-Poll case 0x0E: // 0011 10 Data + CF-Ack + CF-Poll // We like data! return WFLAG_PACKET_DATA; case 0x12: // 0100 10 Null Function case 0x16: // 0101 10 CF-Ack case 0x1A: // 0110 10 CF-Poll case 0x1E: // 0111 10 CF-Ack + CF-Poll return WFLAG_PACKET_DATA; default: // ignore! return 0; } } int Wifi_CreateTxFrame(int frametype, void * dest, int destlen) { switch(frametype) { default: return 0; } } ////////////////////////////////////////////////////////////////////////// // sync functions void Wifi_Sync() { Wifi_Update(); } void Wifi_SetSyncHandler(WifiSyncHandler sh) { synchandler=sh; }