Added more wifi emulation. Some fixes, and support for two new types of management frames, as well as support for sending data frames.

This commit is contained in:
luigi__ 2009-03-27 16:12:07 +00:00
parent f2918281a3
commit f588bcf10e
3 changed files with 378 additions and 63 deletions

View File

@ -527,6 +527,10 @@ void NDS_DeInit(void) {
Screen_DeInit(); Screen_DeInit();
MMU_DeInit(); MMU_DeInit();
gpu3D->NDS_3D_Close(); gpu3D->NDS_3D_Close();
#ifdef EXPERIMENTAL_WIFI
WIFI_SoftAP_Shutdown(&wifiMac);
#endif
} }
BOOL NDS_SetROM(u8 * rom, u32 mask) BOOL NDS_SetROM(u8 * rom, u32 mask)
@ -999,7 +1003,7 @@ void NDS_Reset( void)
_MMU_write32<ARMCPU_ARM9>(0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i])); _MMU_write32<ARMCPU_ARM9>(0x027FFE00+i*4, LE_TO_LOCAL_32(((u32*)MMU.CART_ROM)[i]));
} }
// Write the Nintendo logo checksum to memory (the firmware needs it to see the cart) // Write the header checksum to memory (the firmware needs it to see the cart)
_MMU_write16<ARMCPU_ARM9>(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E)); _MMU_write16<ARMCPU_ARM9>(0x027FF808, T1ReadWord(MMU.CART_ROM, 0x15E));
MainScreen.offset = 0; MainScreen.offset = 0;
@ -1015,6 +1019,15 @@ void NDS_Reset( void)
gpu3D->NDS_3D_Reset(); gpu3D->NDS_3D_Reset();
SPU_Reset(); SPU_Reset();
cheatsSearchClose(); cheatsSearchClose();
#ifdef EXPERIMENTAL_WIFI
WIFI_Init(&wifiMac);
WIFI_SoftAP_Shutdown(&wifiMac);
WIFI_SoftAP_Init(&wifiMac);
#endif
memcpy(FW_Mac, (MMU.fw.data + 0x36), 6);
} }
int NDS_ImportSave(const char *filename) int NDS_ImportSave(const char *filename)

View File

@ -18,10 +18,9 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "wifi.h" #include "wifi.h"
#include "armcpu.h" #include "armcpu.h"
#include "NDSSystem.h"
#ifdef EXPERIMENTAL_WIFI #ifdef EXPERIMENTAL_WIFI
@ -45,7 +44,7 @@ void WIFI_Host_ShutdownSystem(void) ;
*******************************************************************************/ *******************************************************************************/
const u8 FW_Mac[6] = { 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56 } ; u8 FW_Mac[6] = { 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56 } ;
const u8 FW_WIFIInit[32] = { 0x02,0x00, 0x17,0x00, 0x26,0x00, 0x18,0x18, const u8 FW_WIFIInit[32] = { 0x02,0x00, 0x17,0x00, 0x26,0x00, 0x18,0x18,
0x48,0x00, 0x40,0x48, 0x58,0x00, 0x42,0x00, 0x48,0x00, 0x40,0x48, 0x58,0x00, 0x42,0x00,
0x40,0x01, 0x64,0x80, 0xE0,0xE0, 0x43,0x24, 0x40,0x01, 0x64,0x80, 0xE0,0xE0, 0x43,0x24,
@ -451,18 +450,30 @@ static void WIFI_RXPutWord(wifimac_t *wifi,u16 val)
/* abort when RX data queuing is not enabled */ /* abort when RX data queuing is not enabled */
if (!(wifi->RXCnt & 0x8000)) return ; if (!(wifi->RXCnt & 0x8000)) return ;
/* abort when ringbuffer is full */ /* abort when ringbuffer is full */
if (wifi->RXReadCursor == wifi->RXHWWriteCursor) return ; //if (wifi->RXReadCursor == wifi->RXHWWriteCursor) return ;
/*if(wifi->RXHWWriteCursor >= wifi->RXReadCursor)
{
printf("WIFI: write cursor (%04X) above READCSR (%04X). Cannot write received packet.\n",
wifi->RXHWWriteCursor, wifi->RXReadCursor);
return;
}*/
/* write the data to cursor position */ /* write the data to cursor position */
wifi->circularBuffer[wifi->RXHWWriteCursor & 0xFFF] = val; wifi->circularBuffer[wifi->RXHWWriteCursor & 0xFFF] = val;
// printf("wifi: written word %04X to circbuf addr %04X\n", val, (wifi->RXHWWriteCursor << 1)); // printf("wifi: written word %04X to circbuf addr %04X\n", val, (wifi->RXHWWriteCursor << 1));
/* move cursor by one */ /* move cursor by one */
//printf("written one word to %04X (start %04X, end %04X), ", wifi->RXHWWriteCursor, wifi->RXRangeBegin, wifi->RXRangeEnd);
wifi->RXHWWriteCursor++ ; wifi->RXHWWriteCursor++ ;
/* wrap around */ /* wrap around */
wifi->RXHWWriteCursor %= (wifi->RXRangeEnd - wifi->RXRangeBegin) >> 1 ; // wifi->RXHWWriteCursor %= (wifi->RXRangeEnd - wifi->RXRangeBegin) >> 1 ;
// printf("new addr=%04X\n", wifi->RXHWWriteCursor);
if(wifi->RXHWWriteCursor >= ((wifi->RXRangeEnd & 0x1FFE) >> 1))
wifi->RXHWWriteCursor = ((wifi->RXRangeBegin & 0x1FFE) >> 1);
} }
static void WIFI_TXStart(wifimac_t *wifi,u8 slot) static void WIFI_TXStart(wifimac_t *wifi,u8 slot)
{ {
//printf("wifi: send attempt on slot %i, txcnt=%04X, slotcnt=%04X\n",
// slot, wifi->TXCnt, wifi->TXSlot[slot]);
if (wifi->TXSlot[slot] & 0x8000) /* is slot enabled? */ if (wifi->TXSlot[slot] & 0x8000) /* is slot enabled? */
{ {
u16 txLen ; u16 txLen ;
@ -476,7 +487,7 @@ static void WIFI_TXStart(wifimac_t *wifi,u8 slot)
/* zero length */ /* zero length */
if (txLen==0) return ; if (txLen==0) return ;
/* unsupported txRate */ /* unsupported txRate */
switch (/*ntohs*/(wifi->circularBuffer[address+4])) switch (/*ntohs*/(wifi->circularBuffer[address+4] & 0xFF))
{ {
case 10: /* 1 mbit */ case 10: /* 1 mbit */
case 20: /* 2 mbit */ case 20: /* 2 mbit */
@ -488,9 +499,21 @@ static void WIFI_TXStart(wifimac_t *wifi,u8 slot)
/* FIXME: calculate FCS */ /* FIXME: calculate FCS */
WIFI_triggerIRQ(wifi,/*WIFI_IRQ_SENDSTART*/7) ; WIFI_triggerIRQ(wifi,/*WIFI_IRQ_SENDSTART*/7) ;
WIFI_Host_SendData(wifi->udpSocket,wifi->channel,(u8 *)&wifi->circularBuffer[address],txLen) ;
if(slot > wifi->txCurSlot)
wifi->txCurSlot = slot;
wifi->txSlotBusy[slot] = 1;
wifi->txSlotAddr[slot] = address;
wifi->txSlotLen[slot] = txLen;
wifi->txSlotRemainingBytes[slot] = (txLen + 12);
/* WIFI_Host_SendData(wifi->udpSocket,wifi->channel,(u8 *)&wifi->circularBuffer[address],txLen) ;
WIFI_SoftAP_RecvPacketFromDS(wifi, (u8*)&wifi->circularBuffer[address+6], txLen); WIFI_SoftAP_RecvPacketFromDS(wifi, (u8*)&wifi->circularBuffer[address+6], txLen);
WIFI_triggerIRQ(wifi,/*WIFI_IRQ_SENDCOMPLETE*/1) ; WIFI_triggerIRQ(wifi,/*WIFI_IRQ_SENDCOMPLETE*-/1) ;
wifi->circularBuffer[address] = 0x0001;
wifi->circularBuffer[address+4] &= 0x00FF;*/
} }
} }
@ -509,13 +532,24 @@ void WIFI_write16(wifimac_t *wifi,u32 address, u16 val)
{ {
/* access to the circular buffer */ /* access to the circular buffer */
address &= 0x1FFF ; address &= 0x1FFF ;
//printf("wifi: circbuf write at %04X, %04X, readcsr=%04X, wrcsr=%04X(%04X)\n",
// address, val, wifi->RXReadCursor, wifi->RXHWWriteCursorReg, wifi->RXHWWriteCursor);
/* if((address == 0x0BFE) && (val == 0x061E))
{
extern void emu_halt();
emu_halt();
}*/
wifi->circularBuffer[address >> 1] = val ; wifi->circularBuffer[address >> 1] = val ;
return ; return ;
} }
if (!(address & 0x00007000)) action = TRUE ; if (!(address & 0x00007000)) action = TRUE ;
// printf("wifi write at %08X, %04X\n", address, val);
/* mirrors => register address */ /* mirrors => register address */
address &= 0x00000FFF ; address &= 0x00000FFF ;
//if((address < 0x158) || ((address > 0x168) && (address < 0x17C)) || (address > 0x184))
// printf("wifi write at %08X, %04X\n", address, val);
/* FILE *f = fopen("wifidbg.txt", "a");
fprintf(f, "wifi write at %08X, %04X\n", address, val);
fclose(f);*/
switch (address) switch (address)
{ {
case REG_WIFI_ID: case REG_WIFI_ID:
@ -582,26 +616,35 @@ void WIFI_write16(wifimac_t *wifi,u32 address, u16 val)
break; break;
case REG_WIFI_RXCNT: case REG_WIFI_RXCNT:
wifi->RXCnt = val; wifi->RXCnt = val;
if(wifi->RXCnt & 0x0001)
{
wifi->RXHWWriteCursor = wifi->RXHWWriteCursorReg = wifi->RXHWWriteCursorLatched;
//printf("wifi: write wrcsr %04X\n", wifi->RXHWWriteCursorReg);
}
break; break;
case REG_WIFI_RXRANGEBEGIN: case REG_WIFI_RXRANGEBEGIN:
wifi->RXRangeBegin = val ; wifi->RXRangeBegin = val ;
// printf("wifi: rx range begin=%04X\n", val); if(wifi->RXHWWriteCursor < ((val & 0x1FFE) >> 1))
wifi->RXHWWriteCursor = ((val & 0x1FFE) >> 1);
//printf("wifi: rx range begin=%04X\n", val);
break ; break ;
case REG_WIFI_RXRANGEEND: case REG_WIFI_RXRANGEEND:
wifi->RXRangeEnd = val ; wifi->RXRangeEnd = val ;
if(wifi->RXHWWriteCursor >= ((val & 0x1FFE) >> 1))
wifi->RXHWWriteCursor = ((wifi->RXRangeBegin & 0x1FFE) >> 1);
//printf("wifi: rx range end=%04X\n", val); //printf("wifi: rx range end=%04X\n", val);
break ; break ;
case REG_WIFI_WRITECSRLATCH: case REG_WIFI_WRITECSRLATCH:
if ((action) && (wifi->RXCnt & 1)) /* only when action register and CSR change enabled */ if (action) /* only when action register and CSR change enabled */
{ {
// printf("wifi: rx write cursor=%04X\n", (val << 1)); wifi->RXHWWriteCursorLatched = val ;
wifi->RXHWWriteCursor = val ;
} }
break ; break ;
case REG_WIFI_CIRCBUFRADR: case REG_WIFI_CIRCBUFRADR:
wifi->CircBufReadAddress = (val & 0x1FFE); wifi->CircBufReadAddress = (val & 0x1FFE);
break ; break ;
case REG_WIFI_RXREADCSR: case REG_WIFI_RXREADCSR:
//printf("wifi: write readcsr %04X\n", val);
wifi->RXReadCursor = val ; wifi->RXReadCursor = val ;
break ; break ;
case REG_WIFI_CIRCBUFWADR: case REG_WIFI_CIRCBUFWADR:
@ -609,6 +652,7 @@ void WIFI_write16(wifimac_t *wifi,u32 address, u16 val)
break ; break ;
case REG_WIFI_CIRCBUFWRITE: case REG_WIFI_CIRCBUFWRITE:
/* set value into the circ buffer, and move cursor to the next hword on action */ /* set value into the circ buffer, and move cursor to the next hword on action */
//printf("wifi: circbuf fifo write at %04X, %04X (action=%i)\n", (wifi->CircBufWriteAddress & 0x1FFF), val, action);
wifi->circularBuffer[(wifi->CircBufWriteAddress >> 1) & 0xFFF] = val ; wifi->circularBuffer[(wifi->CircBufWriteAddress >> 1) & 0xFFF] = val ;
if (action) if (action)
{ {
@ -635,23 +679,29 @@ void WIFI_write16(wifimac_t *wifi,u32 address, u16 val)
wifi->TXSlot[(address - REG_WIFI_TXLOC1) >> 2] = val ; wifi->TXSlot[(address - REG_WIFI_TXLOC1) >> 2] = val ;
break ; break ;
case REG_WIFI_TXOPT: case REG_WIFI_TXOPT:
if (val == 0xFFFF) /* if (val == 0xFFFF)
{ {
/* reset TX logic */ /* reset TX logic *-/
/* CHECKME */ /* CHECKME *-/
// wifi->TXSlot[0] = 0 ; wifi->TXSlot[1] = 0 ; wifi->TXSlot[2] = 0 ; // wifi->TXSlot[0] = 0 ; wifi->TXSlot[1] = 0 ; wifi->TXSlot[2] = 0 ;
wifi->TXOpt = 0 ; wifi->TXOpt = 0 ;
wifi->TXCnt = 0 ; wifi->TXCnt = 0 ;
} else } else
{ {
wifi->TXOpt = val ; wifi->TXOpt = val ;
} }*/
wifi->TXCnt &= ~val;
break ; break ;
case REG_WIFI_TXCNT: case REG_WIFI_TXCNT:
wifi->TXCnt = val ; wifi->TXCnt |= val ;
if (val & 0x01) WIFI_TXStart(wifi,0) ; if (val & 0x01) WIFI_TXStart(wifi,0) ;
if (val & 0x04) WIFI_TXStart(wifi,1) ; if (val & 0x04) WIFI_TXStart(wifi,1) ;
if (val & 0x08) WIFI_TXStart(wifi,2) ; if (val & 0x08) WIFI_TXStart(wifi,2) ;
/* if(val&0x04)
{
extern void emu_halt();
emu_halt();
}*/
break ; break ;
case REG_WIFI_RFIOCNT: case REG_WIFI_RFIOCNT:
WIFI_setRF_CNT(wifi,val) ; WIFI_setRF_CNT(wifi,val) ;
@ -711,6 +761,7 @@ void WIFI_write16(wifimac_t *wifi,u32 address, u16 val)
// printf("wifi power reg %03X write %04X\n", address, val); // printf("wifi power reg %03X write %04X\n", address, val);
// break; // break;
default: default:
// printf("wifi: write unhandled reg %03X, %04X\n", address, val);
// val = 0 ; /* not handled yet */ // val = 0 ; /* not handled yet */
break ; break ;
} }
@ -733,14 +784,29 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
if (((address & 0x00007000) >= 0x00004000) && ((address & 0x00007000) < 0x00006000)) if (((address & 0x00007000) >= 0x00004000) && ((address & 0x00007000) < 0x00006000))
{ {
/* access to the circular buffer */ /* access to the circular buffer */
//printf("wifi: circbuf read at %04X\n", (address & 0x1FFF)); //printf("wifi: circbuf read at %04X, readcsr=%04X, wrcsr=%04X(%04X)\n",
// (address & 0x1FFF), wifi->RXReadCursor, wifi->RXHWWriteCursorReg, wifi->RXHWWriteCursor);
/* if((address == 0x04804C38) &&
(wifi->circularBuffer[(address & 0x1FFF) >> 1] != 0x0000) &&
(wifi->circularBuffer[(address & 0x1FFF) >> 1] != 0x5A5A) &&
(wifi->circularBuffer[(address & 0x1FFF) >> 1] != 0xA5A5))
{
extern void emu_halt();
emu_halt();
}*/
// if(address == 0x04804C3E)
// return 0x0014;
return wifi->circularBuffer[(address & 0x1FFF) >> 1] ; return wifi->circularBuffer[(address & 0x1FFF) >> 1] ;
} }
if (!(address & 0x00007000)) action = TRUE ; if (!(address & 0x00007000)) action = TRUE ;
//if((address != 0x04808214) && (address != 0x0480803C) && (address != 0x048080F8) && (address != 0x048080FA) && (address != 0x0480819C)) //if((address != 0x04808214) && (address != 0x0480803C) && (address != 0x048080F8) && (address != 0x048080FA) && (address != 0x0480819C))
// printf("wifi read at %08X\n", address);
/* mirrors => register address */ /* mirrors => register address */
address &= 0x00000FFF ; address &= 0x00000FFF ;
// if((address < 0x158) || ((address > 0x168) && (address < 0x17C)) || (address > 0x184))
// printf("wifi read at %08X\n", address);
/* FILE *f = fopen("wifidbg.txt", "a");
fprintf(f, "wifi read at %08X\n", address);
fclose(f);*/
switch (address) switch (address)
{ {
case REG_WIFI_ID: case REG_WIFI_ID:
@ -750,8 +816,10 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
case REG_WIFI_WEP: case REG_WIFI_WEP:
return wifi->wepMode ; return wifi->wepMode ;
case REG_WIFI_IE: case REG_WIFI_IE:
//printf("wifi: read ie (%04X)\n", wifi->IE.val);
return wifi->IE.val ; return wifi->IE.val ;
case REG_WIFI_IF: case REG_WIFI_IF:
//printf("wifi: read if (%04X)\n", wifi->IF.val);
return wifi->IF.val ; return wifi->IF.val ;
case REG_WIFI_POWERSTATE: case REG_WIFI_POWERSTATE:
return ((wifi->powerOn ? 0x0000 : 0x0200) | (wifi->powerOnPending ? 0x0102 : 0x0000)); return ((wifi->powerOn ? 0x0000 : 0x0200) | (wifi->powerOnPending ? 0x0102 : 0x0000));
@ -771,10 +839,12 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
case REG_WIFI_MAC0: case REG_WIFI_MAC0:
case REG_WIFI_MAC1: case REG_WIFI_MAC1:
case REG_WIFI_MAC2: case REG_WIFI_MAC2:
//printf("read mac addr: word %i = %02X\n", (address - REG_WIFI_MAC0) >> 1, wifi->mac.words[(address - REG_WIFI_MAC0) >> 1]);
return wifi->mac.words[(address - REG_WIFI_MAC0) >> 1] ; return wifi->mac.words[(address - REG_WIFI_MAC0) >> 1] ;
case REG_WIFI_BSS0: case REG_WIFI_BSS0:
case REG_WIFI_BSS1: case REG_WIFI_BSS1:
case REG_WIFI_BSS2: case REG_WIFI_BSS2:
//printf("read bssid addr: word %i = %02X\n", (address - REG_WIFI_BSS0) >> 1, wifi->bss.words[(address - REG_WIFI_BSS0) >> 1]);
return wifi->bss.words[(address - REG_WIFI_BSS0) >> 1] ; return wifi->bss.words[(address - REG_WIFI_BSS0) >> 1] ;
case REG_WIFI_RXCNT: case REG_WIFI_RXCNT:
return wifi->RXCnt; return wifi->RXCnt;
@ -782,6 +852,7 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
return wifi->RXRangeBegin ; return wifi->RXRangeBegin ;
case REG_WIFI_CIRCBUFREAD: case REG_WIFI_CIRCBUFREAD:
temp = wifi->circularBuffer[((wifi->RXRangeBegin + wifi->CircBufReadAddress) >> 1) & 0x0FFF] ; temp = wifi->circularBuffer[((wifi->RXRangeBegin + wifi->CircBufReadAddress) >> 1) & 0x0FFF] ;
//printf("wifi: circbuf fifo read at %04X, action=%i\n", (wifi->RXRangeBegin + wifi->CircBufReadAddress), action);
if (action) if (action)
{ {
wifi->CircBufReadAddress += 2 ; wifi->CircBufReadAddress += 2 ;
@ -811,10 +882,20 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
return temp; return temp;
case REG_WIFI_CIRCBUFRADR: case REG_WIFI_CIRCBUFRADR:
return wifi->CircBufReadAddress ; return wifi->CircBufReadAddress ;
case REG_WIFI_RXHWWRITECSR:
//printf("wifi: read writecsr (%04X)\n", wifi->RXHWWriteCursorReg);
return wifi->RXHWWriteCursorReg;
case REG_WIFI_RXREADCSR: case REG_WIFI_RXREADCSR:
//printf("wifi: read readcsr (%04X)\n", wifi->RXReadCursor);
return wifi->RXReadCursor; return wifi->RXReadCursor;
case REG_WIFI_RXBUF_COUNT: case REG_WIFI_RXBUF_COUNT:
return wifi->RXBufCount ; return wifi->RXBufCount ;
case REG_WIFI_TXREQ_READ:
return wifi->TXCnt;
case REG_WIFI_TXBUSY:
return ((wifi->txSlotBusy[0] ? 0x01 : 0x00) | (wifi->txSlotBusy[1] ? 0x04 : 0x00) | (wifi->txSlotBusy[2] ? 0x08 : 0x00));
case REG_WIFI_TXSTAT:
return wifi->TXStat;
case REG_WIFI_EXTRACOUNTCNT: case REG_WIFI_EXTRACOUNTCNT:
return wifi->eCountEnable?1:0 ; return wifi->eCountEnable?1:0 ;
case REG_WIFI_EXTRACOUNT: case REG_WIFI_EXTRACOUNT:
@ -838,8 +919,12 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
case REG_WIFI_AID_HIGH: case REG_WIFI_AID_HIGH:
return wifi->aid ; return wifi->aid ;
case 0x214: case 0x214:
//printf("wifi: read reg 0x0214\n");
return 0x0009; return 0x0009;
case 0x19C:
break;
default: default:
// printf("wifi: read unhandled reg %03X\n", address);
return wifi->ioMem[address >> 1]; return wifi->ioMem[address >> 1];
} }
} }
@ -868,20 +953,45 @@ void WIFI_usTrigger(wifimac_t *wifi)
} }
/* receive check, given a 2 mbit connection, 2 bits per usec can be transfered. */ /* receive check, given a 2 mbit connection, 2 bits per usec can be transfered. */
/* for a packet of 32 Bytes, at least 128 usec passed, we will use the 32 byte accuracy to reduce load */ /* for a packet of 32 Bytes, at least 128 usec passed, we will use the 32 byte accuracy to reduce load */
if (!(wifi->RXCheckCounter++ & 0x7F)) /*if (!(wifi->RXCheckCounter++ & 0x7F))
{ {
/* check if data arrived in the meantime */ /* check if data arrived in the meantime *-/
rcvSize = WIFI_Host_RecvData(wifi->udpSocket,dataBuffer,0x2000) ; rcvSize = WIFI_Host_RecvData(wifi->udpSocket,dataBuffer,0x2000) ;
if (rcvSize) if (rcvSize)
{ {
u16 i ; u16 i ;
/* process data, put it into mac memory */ /* process data, put it into mac memory *-/
WIFI_triggerIRQ(wifi,/*WIFI_IRQ_RECVSTART*/6) ; WIFI_triggerIRQ(wifi,/*WIFI_IRQ_RECVSTART*-/6) ;
for (i=0;i<(rcvSize+1) << 1;i++) for (i=0;i<(rcvSize+1) << 1;i++)
{ {
WIFI_RXPutWord(wifi,((u16 *)dataBuffer)[i]) ; WIFI_RXPutWord(wifi,((u16 *)dataBuffer)[i]) ;
} }
WIFI_triggerIRQ(wifi,/*WIFI_IRQ_RECVCOMPLETE*/0) ; WIFI_triggerIRQ(wifi,/*WIFI_IRQ_RECVCOMPLETE*-/0) ;
}
}*/
if((wifi->usec & 3) == 0)
{
int slot = wifi->txCurSlot;
if(wifi->txSlotBusy[slot])
{
wifi->txSlotRemainingBytes[slot]--;
if(wifi->txSlotRemainingBytes[slot] == 0)
{
wifi->txSlotBusy[slot] = 0;
WIFI_SoftAP_RecvPacketFromDS(wifi, (u8*)&wifi->circularBuffer[wifi->txSlotAddr[slot]], wifi->txSlotLen[slot]);
while((wifi->txSlotBusy[wifi->txCurSlot] == 0) && (wifi->txCurSlot > 0))
wifi->txCurSlot--;
wifi->circularBuffer[wifi->txSlotAddr[slot]] = 0x0001;
wifi->circularBuffer[wifi->txSlotAddr[slot]+4] &= 0x00FF;
wifi->TXStat = (0x0001 | (slot << 12));
WIFI_triggerIRQ(wifi, 1);
}
} }
} }
} }
@ -908,7 +1018,7 @@ u8 SoftAP_Beacon[58] = {
/* Frame body */ /* Frame body */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
0x64, 0x00, // Beacon interval 0x64, 0x00, // Beacon interval
0xFF, 0xFF, // Capablilty information 0x0F, 0x00, // Capablilty information
0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID 0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID
0x01, 0x02, 0x82, 0x84, // Supported rates 0x01, 0x02, 0x82, 0x84, // Supported rates
0x05, 0x04, 0x00, 0x00, 0x00, 0x00, // TIM 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, // TIM
@ -921,7 +1031,7 @@ u8 SoftAP_ProbeResponse[52] = {
/* 802.11 header */ /* 802.11 header */
0x50, 0x00, // Frame control 0x50, 0x00, // Frame control
0x00, 0x00, // Duration ID 0x00, 0x00, // Duration ID
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Receiver 0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender 0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID 0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID
0x00, 0x00, // Sequence control 0x00, 0x00, // Sequence control
@ -929,7 +1039,7 @@ u8 SoftAP_ProbeResponse[52] = {
/* Frame body */ /* Frame body */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Timestamp
0x64, 0x00, // Beacon interval 0x64, 0x00, // Beacon interval
0xFF, 0xFF, // Capablilty information 0x0F, 0x00, // Capablilty information
0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID 0x00, 0x06, 'S', 'o', 'f', 't', 'A', 'P', // SSID
0x01, 0x02, 0x82, 0x84, // Supported rates 0x01, 0x02, 0x82, 0x84, // Supported rates
@ -937,6 +1047,43 @@ u8 SoftAP_ProbeResponse[52] = {
0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00
}; };
u8 SoftAP_AuthFrame[34] = {
/* 802.11 header */
0xB0, 0x00, // Frame control
0x00, 0x00, // Duration ID
0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID
0x00, 0x00, // Sequence control
/* Frame body */
0x00, 0x00, // Authentication algorithm
0x02, 0x00, // Authentication sequence
0x00, 0x00, // Status
/* CRC32 */
0x00, 0x00, 0x00, 0x00
};
u8 SoftAP_AssocResponse[38] = {
/* 802.11 header */
0x10, 0x00, // Frame control
0x00, 0x00, // Duration ID
0x00, 0x09, 0xBF, 0x12, 0x34, 0x56, // Receiver
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // Sender
0x00, 0xF0, 0x1A, 0x2B, 0x3C, 0x4D, // BSSID
0x00, 0x00, // Sequence control
/* Frame body */
0x0F, 0x00, // Capability information
0x00, 0x00, // Status
0x01, 0xC0, // Assocation ID
0x01, 0x02, 0x82, 0x84, // Supported rates
/* CRC32 */
0x00, 0x00, 0x00, 0x00
};
// http://www.codeproject.com/KB/recipes/crc32_large.aspx // http://www.codeproject.com/KB/recipes/crc32_large.aspx
u32 reflect(u32 ref, char ch) u32 reflect(u32 ref, char ch)
{ {
@ -961,19 +1108,13 @@ u32 WIFI_SoftAP_GetCRC32(u8 *data, int len)
crc = (crc >> 8) ^ SoftAP_CRC32Table[(crc & 0xFF) ^ *data++]; crc = (crc >> 8) ^ SoftAP_CRC32Table[(crc & 0xFF) ^ *data++];
return (crc ^ 0xFFFFFFFF); return (crc ^ 0xFFFFFFFF);
// return 0x1D46B6B8;
} }
int WIFI_SoftAP_Init(wifimac_t *wifi) int WIFI_SoftAP_Init(wifimac_t *wifi)
{ {
sockaddr_t addr; char errbuf[PCAP_ERRBUF_SIZE];
pcap_if_t *alldevs;
wifi->SoftAP.sock = socket(AF_INET, SOCK_RAW, 0);
memset(&addr, 0, sizeof(addr));
addr.sa_family = AF_INET;
*(u32*)&addr.sa_data[2] = htonl(INADDR_ANY);
*(u16*)&addr.sa_data[0] = htons(80);
bind(wifi->SoftAP.sock, &addr, sizeof(addr));
wifi->SoftAP.usecCounter = 0; wifi->SoftAP.usecCounter = 0;
@ -993,39 +1134,48 @@ int WIFI_SoftAP_Init(wifimac_t *wifi)
SoftAP_CRC32Table[i] = reflect(SoftAP_CRC32Table[i], 32); SoftAP_CRC32Table[i] = reflect(SoftAP_CRC32Table[i], 32);
} }
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
printf("SoftAP: PCAP error with pcap_findalldevs_ex(): %s\n", errbuf);
return 0;
}
wifi->SoftAP.bridge = pcap_open(alldevs[CommonSettings.wifiBridgeAdapterNum].name, PACKET_SIZE, 0, 1, NULL, errbuf);
if(wifi->SoftAP.bridge == NULL)
{
printf("SoftAP: PCAP error with pcap_open(): %s\n", errbuf);
return 0;
}
pcap_freealldevs(alldevs);
return 1; return 1;
} }
void WIFI_SoftAP_Shutdown(wifimac_t *wifi) void WIFI_SoftAP_Shutdown(wifimac_t *wifi)
{ {
// pcap_close(wifi->SoftAP.bridge);
} }
/*void WIFI_SoftAP_SendWordToDS(wifimac_t *wifi, u16 data)
{
if(wifi->RXCnt & 0x8000)
{
//
}
}*/
void WIFI_SoftAP_RecvPacketFromDS(wifimac_t *wifi, u8 *packet, int len) void WIFI_SoftAP_RecvPacketFromDS(wifimac_t *wifi, u8 *packet, int len)
{ {
u16 frameCtl = *(u16*)&packet[0]; int alignedLen = ((len+3) & (~3));
u16 frameCtl = *(u16*)&packet[12];
//printf("wifi: packet arrived, frame ctl = %04X\n", frameCtl); //printf("wifi: packet arrived, len = %i (%i), frame ctl = %04X\n", len, alignedLen, frameCtl);
switch((frameCtl >> 2) & 0x3) switch((frameCtl >> 2) & 0x3)
{ {
case 0: case 0x0: // Management
{ {
switch((frameCtl >> 4) & 0xF) switch((frameCtl >> 4) & 0xF)
{ {
case 4: // Probe request case 0x4: // Probe request
{ {
u8 proberes[52]; u8 proberes[52];
memcpy(proberes, SoftAP_ProbeResponse, 52); memcpy(proberes, SoftAP_ProbeResponse, 52);
memcpy(&proberes[4], FW_Mac, 6);
u64 timestamp = (wifi->SoftAP.usecCounter / 1000); // FIXME: is it correct? u64 timestamp = (wifi->SoftAP.usecCounter / 1000); // FIXME: is it correct?
*(u64*)&proberes[24] = timestamp; *(u64*)&proberes[24] = timestamp;
u32 crc32 = WIFI_SoftAP_GetCRC32(proberes, 48); u32 crc32 = WIFI_SoftAP_GetCRC32(proberes, 48);
@ -1036,7 +1186,7 @@ void WIFI_SoftAP_RecvPacketFromDS(wifimac_t *wifi, u8 *packet, int len)
wifi->SoftAP.curPacket = new u8[52+12]; wifi->SoftAP.curPacket = new u8[52+12];
wifi->SoftAP.curPacket[0] = 0x11; wifi->SoftAP.curPacket[0] = 0x10;
wifi->SoftAP.curPacket[1] = 0x00; wifi->SoftAP.curPacket[1] = 0x00;
wifi->SoftAP.curPacket[2] = 0x40; wifi->SoftAP.curPacket[2] = 0x40;
wifi->SoftAP.curPacket[3] = 0x00; wifi->SoftAP.curPacket[3] = 0x00;
@ -1045,12 +1195,82 @@ void WIFI_SoftAP_RecvPacketFromDS(wifimac_t *wifi, u8 *packet, int len)
wifi->SoftAP.curPacket[6] = 0x14; wifi->SoftAP.curPacket[6] = 0x14;
wifi->SoftAP.curPacket[7] = 0x00; wifi->SoftAP.curPacket[7] = 0x00;
wifi->SoftAP.curPacket[8] = 0x30; wifi->SoftAP.curPacket[8] = 0x30;
/* wifi->SoftAP.curPacket[7] = 0x09;
wifi->SoftAP.curPacket[8] = 0x2C;*/
wifi->SoftAP.curPacket[9] = 0x00; wifi->SoftAP.curPacket[9] = 0x00;
wifi->SoftAP.curPacket[10] = 0x00; wifi->SoftAP.curPacket[10] = 0x00;
wifi->SoftAP.curPacket[11] = 0x00; wifi->SoftAP.curPacket[11] = 0x00;
memcpy((wifi->SoftAP.curPacket+12), proberes, 52); memcpy((wifi->SoftAP.curPacket+12), proberes, 52);
wifi->SoftAP.curPacketSize = 52+12; wifi->SoftAP.curPacketSize = 52+12;
wifi->SoftAP.curPacketPos = -200;
wifi->SoftAP.curPacketSending = TRUE;
}
break;
case 0xB: // Authentication
{
u8 authframe[36];
memcpy(authframe, SoftAP_AuthFrame, 34);
memcpy(&authframe[4], FW_Mac, 6);
u32 crc32 = WIFI_SoftAP_GetCRC32(authframe, 30);
*(u32*)&authframe[32] = crc32;
if(wifi->SoftAP.curPacket)
delete wifi->SoftAP.curPacket;
wifi->SoftAP.curPacket = new u8[36+12];
wifi->SoftAP.curPacket[0] = 0x10;
wifi->SoftAP.curPacket[1] = 0x00;
wifi->SoftAP.curPacket[2] = 0x40;
wifi->SoftAP.curPacket[3] = 0x00;
wifi->SoftAP.curPacket[4] = 0x01;
wifi->SoftAP.curPacket[5] = 0x00;
wifi->SoftAP.curPacket[6] = 0x14;
wifi->SoftAP.curPacket[7] = 0x00;
wifi->SoftAP.curPacket[8] = 0x20;
wifi->SoftAP.curPacket[9] = 0x00;
wifi->SoftAP.curPacket[10] = 0x00;
wifi->SoftAP.curPacket[11] = 0x00;
memcpy((wifi->SoftAP.curPacket+12), authframe, 36);
wifi->SoftAP.curPacketSize = 36+12;
wifi->SoftAP.curPacketPos = 0;
wifi->SoftAP.curPacketSending = TRUE;
}
break;
case 0x0: // Association request
{
u8 assocres[40];
memcpy(assocres, SoftAP_AssocResponse, 38);
memcpy(&assocres[4], FW_Mac, 6);
u32 crc32 = WIFI_SoftAP_GetCRC32(assocres, 34);
*(u32*)&assocres[36] = crc32;
if(wifi->SoftAP.curPacket)
delete wifi->SoftAP.curPacket;
wifi->SoftAP.curPacket = new u8[40+12];
wifi->SoftAP.curPacket[0] = 0x10;
wifi->SoftAP.curPacket[1] = 0x00;
wifi->SoftAP.curPacket[2] = 0x40;
wifi->SoftAP.curPacket[3] = 0x00;
wifi->SoftAP.curPacket[4] = 0x01;
wifi->SoftAP.curPacket[5] = 0x00;
wifi->SoftAP.curPacket[6] = 0x14;
wifi->SoftAP.curPacket[7] = 0x00;
wifi->SoftAP.curPacket[8] = 0x24;
wifi->SoftAP.curPacket[9] = 0x00;
wifi->SoftAP.curPacket[10] = 0x00;
wifi->SoftAP.curPacket[11] = 0x00;
memcpy((wifi->SoftAP.curPacket+12), assocres, 40);
wifi->SoftAP.curPacketSize = 36+12;
wifi->SoftAP.curPacketPos = 0; wifi->SoftAP.curPacketPos = 0;
wifi->SoftAP.curPacketSending = TRUE; wifi->SoftAP.curPacketSending = TRUE;
} }
@ -1058,6 +1278,45 @@ void WIFI_SoftAP_RecvPacketFromDS(wifimac_t *wifi, u8 *packet, int len)
} }
} }
break; break;
case 0x2: // Data
{
/* We convert the packet into an Ethernet packet */
int eflen = (alignedLen - 4 - 30 + 14);
u8 *ethernetframe = new u8[eflen];
/* Destination address */
ethernetframe[0] = packet[28];
ethernetframe[1] = packet[29];
ethernetframe[2] = packet[30];
ethernetframe[3] = packet[31];
ethernetframe[4] = packet[32];
ethernetframe[5] = packet[33];
/* Source address */
ethernetframe[6] = packet[22];
ethernetframe[7] = packet[23];
ethernetframe[8] = packet[24];
ethernetframe[9] = packet[25];
ethernetframe[10] = packet[26];
ethernetframe[11] = packet[27];
/* EtherType */
ethernetframe[12] = packet[42];
ethernetframe[13] = packet[43];
/* Frame body */
memcpy((ethernetframe + 14), (packet + 44), (alignedLen - 30 - 4));
/* Checksum */
/* TODO ? */
pcap_sendpacket(wifi->SoftAP.bridge, ethernetframe, eflen);
delete ethernetframe;
}
break;
} }
} }
@ -1102,7 +1361,7 @@ void WIFI_SoftAP_SendBeacon(wifimac_t *wifi)
memcpy((wifi->SoftAP.curPacket+12), beacon, 58); memcpy((wifi->SoftAP.curPacket+12), beacon, 58);
wifi->SoftAP.curPacketSize = 58+12; wifi->SoftAP.curPacketSize = 58+12;
wifi->SoftAP.curPacketPos = 0; wifi->SoftAP.curPacketPos = -4;
wifi->SoftAP.curPacketSending = TRUE; wifi->SoftAP.curPacketSending = TRUE;
} }
@ -1112,9 +1371,12 @@ void WIFI_SoftAP_usTrigger(wifimac_t *wifi)
if(!wifi->SoftAP.curPacketSending) if(!wifi->SoftAP.curPacketSending)
{ {
if((wifi->SoftAP.usecCounter % 100000) == 0) //if(wifi->ioMem[0xD0 >> 1] & 0x0400)
{ {
WIFI_SoftAP_SendBeacon(wifi); if((wifi->SoftAP.usecCounter % 100000) == 0)
{
WIFI_SoftAP_SendBeacon(wifi);
}
} }
} }
@ -1123,20 +1385,34 @@ void WIFI_SoftAP_usTrigger(wifimac_t *wifi)
/* ie ~8 microseconds to transfer a word. */ /* ie ~8 microseconds to transfer a word. */
if((wifi->SoftAP.curPacketSending) && !(wifi->SoftAP.usecCounter & 7)) if((wifi->SoftAP.curPacketSending) && !(wifi->SoftAP.usecCounter & 7))
{ {
if(wifi->SoftAP.curPacketPos == 0) /* if(wifi->SoftAP.curPacketPos == -4)
{
WIFI_triggerIRQ(wifi, 6); WIFI_triggerIRQ(wifi, 6);
}
else*/ if(wifi->SoftAP.curPacketPos >= 0)
{
if(wifi->SoftAP.curPacketPos == 0)
{
WIFI_triggerIRQ(wifi, 6);
}
u16 word = wifi->SoftAP.curPacket[wifi->SoftAP.curPacketPos]; u16 word = (wifi->SoftAP.curPacket[wifi->SoftAP.curPacketPos] | (wifi->SoftAP.curPacket[wifi->SoftAP.curPacketPos+1] << 8));
//WIFI_SoftAP_SendWordToDS(wifi, word); //WIFI_SoftAP_SendWordToDS(wifi, word);
WIFI_RXPutWord(wifi, word); // if(wifi->SoftAP.curPacketPos<12)
// printf("wifi: writing word %i (%04X) of packet to %04X\n",
// wifi->SoftAP.curPacketPos, word, wifi->RXHWWriteCursor);
WIFI_RXPutWord(wifi, word);
}
wifi->SoftAP.curPacketPos++; wifi->SoftAP.curPacketPos += 2;
if(wifi->SoftAP.curPacketPos == wifi->SoftAP.curPacketSize) if(wifi->SoftAP.curPacketPos >= wifi->SoftAP.curPacketSize)
{ {
wifi->SoftAP.curPacketSize = 0; wifi->SoftAP.curPacketSize = 0;
wifi->SoftAP.curPacketPos = 0; wifi->SoftAP.curPacketPos = 0;
wifi->SoftAP.curPacketSending = FALSE; wifi->SoftAP.curPacketSending = FALSE;
wifi->RXHWWriteCursorReg = ((wifi->RXHWWriteCursor + 1) & (~1));
WIFI_triggerIRQ(wifi, 0); WIFI_triggerIRQ(wifi, 0);
} }
} }

View File

@ -20,11 +20,13 @@
#ifndef WIFI_H #ifndef WIFI_H
#define WIFI_H #define WIFI_H
#include <stdio.h>
#include "types.h" #include "types.h"
#ifdef EXPERIMENTAL_WIFI #ifdef EXPERIMENTAL_WIFI
/* standardize socket interface for linux and windows */ /* standardize socket interface for linux and windows */
/* TODO: get rid of the socket thing, as we're going to use libpcap */
#ifdef WIN32 #ifdef WIN32
#include <winsock2.h> #include <winsock2.h>
#define socket_t SOCKET #define socket_t SOCKET
@ -44,6 +46,14 @@
#define BASEPORT 7000 /* channel 1: 7000 ... channel 13: 7012 */ #define BASEPORT 7000 /* channel 1: 7000 ... channel 13: 7012 */
/* FIXME: make it configureable */ /* FIXME: make it configureable */
#define HAVE_REMOTE
#define WPCAP
#define PACKET_SIZE 65535
#define _INC_STDIO
#include <pcap.h>
#include <remote-ext.h> //uh?
#define REG_WIFI_ID 0x000 #define REG_WIFI_ID 0x000
#define REG_WIFI_MODE 0x004 #define REG_WIFI_MODE 0x004
#define REG_WIFI_WEP 0x006 #define REG_WIFI_WEP 0x006
@ -87,6 +97,8 @@
#define REG_WIFI_TXLOC3 0x0A8 #define REG_WIFI_TXLOC3 0x0A8
#define REG_WIFI_TXOPT 0x0AC #define REG_WIFI_TXOPT 0x0AC
#define REG_WIFI_TXCNT 0x0AE #define REG_WIFI_TXCNT 0x0AE
#define REG_WIFI_TXREQ_READ 0x0B0
#define REG_WIFI_TXBUSY 0x0B6
#define REG_WIFI_TXSTAT 0x0B8 #define REG_WIFI_TXSTAT 0x0B8
#define REG_WIFI_RXFILTER 0x0D0 #define REG_WIFI_RXFILTER 0x0D0
#define REG_WIFI_USCOUNTERCNT 0x0E8 #define REG_WIFI_USCOUNTERCNT 0x0E8
@ -389,8 +401,14 @@ typedef struct
u16 TXSlot[3] ; u16 TXSlot[3] ;
u16 TXCnt ; u16 TXCnt ;
u16 TXOpt ; u16 TXOpt ;
u16 TXStat;
u16 BEACONSlot ; u16 BEACONSlot ;
BOOL BEACON_enable ; BOOL BEACON_enable ;
u8 txCurSlot;
u8 txSlotBusy[3];
u32 txSlotAddr[3];
u32 txSlotLen[3];
u32 txSlotRemainingBytes[3];
/* receiving */ /* receiving */
u16 RXCnt ; u16 RXCnt ;
@ -437,6 +455,8 @@ typedef struct
u16 RXRangeBegin ; u16 RXRangeBegin ;
u16 RXRangeEnd ; u16 RXRangeEnd ;
u16 RXHWWriteCursor ; u16 RXHWWriteCursor ;
u16 RXHWWriteCursorReg;
u16 RXHWWriteCursorLatched;
u16 RXReadCursor ; u16 RXReadCursor ;
u16 RXUnits ; u16 RXUnits ;
u16 RXBufCount ; u16 RXBufCount ;
@ -447,6 +467,12 @@ typedef struct
u16 CircBufWrEnd ; u16 CircBufWrEnd ;
u16 CircBufWrSkip ; u16 CircBufWrSkip ;
/* tx packets */
u8 *curPacket[3];
int curPacketSize[3];
int curPacketPos[3];
BOOL curPacketSending[3];
/* i/o mem */ /* i/o mem */
u16 ioMem[0x800]; u16 ioMem[0x800];
@ -456,7 +482,7 @@ typedef struct
/* SoftAP */ /* SoftAP */
struct _SoftAP struct _SoftAP
{ {
socket_t sock; pcap_t *bridge;
u64 usecCounter; u64 usecCounter;
@ -544,7 +570,7 @@ typedef struct _FW_WFCProfile
} FW_WFCProfile; } FW_WFCProfile;
/* wifi data to be stored in firmware, when no firmware image was loaded */ /* wifi data to be stored in firmware, when no firmware image was loaded */
extern const u8 FW_Mac[6]; extern u8 FW_Mac[6];
extern const u8 FW_WIFIInit[32] ; extern const u8 FW_WIFIInit[32] ;
extern const u8 FW_BBInit[105] ; extern const u8 FW_BBInit[105] ;
extern const u8 FW_RFInit[36] ; extern const u8 FW_RFInit[36] ;