#166220 - Pete_Lockwood - Mon Feb 02, 2009 11:57 am
Has anyone successfully used the *Raw* functions in the DSWifi library to run comms directly between two DS units?
I've been amazed to find that almost all discussion of DSWifi seems to be centered on getting the DS attached to a full-on network using an access point. There seems to be very little discussion on using it to have multiple DSes connect directly to each other without going through an access point.
I need to connect multiple DSes together specifically without using an access point but it appears about the closest someone has come is libLobby (?) and from what I gather this isn't considered stable and isn't up to date with the latest libNds anyway.
Are the *Raw* functions the way to go with this?
_________________
It's not an illusion, it just looks like one.
#166223 - elhobbs - Mon Feb 02, 2009 2:22 pm
when I tried raw mode all I ever was able to receive was beacons and other management packets. I think there are some pieces missing from dswifi to fully enable this for direct ds to ds communication. on the plus side I think that sgstair may have resumed work on dswifi with one of the goals being ds to ds direct connections.
#166248 - sgstair - Tue Feb 03, 2009 9:40 am
Hi Pete,
The situation is still pretty complicated :)
When I originally figured out the wifi hardware, I didn't try too hard to figure it all out after I got the "important" stuff working (connecting to access points, etc) - so while the ds wifi lib has somewhat support ad-hoc, I haven't actually ever got it to work.
I do expect this to change though; I'm currently working on reverse engineering the hardware again, more completely this time - and I expect to have everything fully working after this.
That's not to say it will be any time soon; I've got quite a bit of work ahead of me, so it could be several months. But I do intend to get it done as soon as I can.
-Stephen
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/
#166254 - Pete_Lockwood - Tue Feb 03, 2009 12:16 pm
Thanks, I appreciate your taking the time to post.
Just a thought but.. Could it be easier for someone to disassemble the code from a piece of software that already supports ad-hoc and get the answers that way rather than attacking the hardware?
_________________
It's not an illusion, it just looks like one.
#166274 - sgstair - Tue Feb 03, 2009 6:39 pm
As strange as it may seem, -nothing- on the DS has ever supported ad-hoc. I'm sure it can be done, but it requires figuring out hardware that isn't ever used for that purpose.
And the official local multiplayer actually sets up one of the DSes as an access point; which is also pretty complicated.
-Stephen
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/
#166283 - Pete_Lockwood - Tue Feb 03, 2009 7:59 pm
Yowza. Really?
Would you be able to guess whether your existing lib exposes enough to act as a soft access point?
_________________
It's not an illusion, it just looks like one.
#166297 - sgstair - Wed Feb 04, 2009 4:47 am
Yes really, everything done on DS so far is infrastructure mode.
I'm sure it's capable of adhoc, just haven't worked out the filtering mechanism yet.
No, the API does not expose nearly enough to run as a soft-ap. The documentation contains barely enough to do so, but I wouldn't expect anyone to work it out from that :)
Next lib will definitely make it easy though.
-Stephen
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/
#167012 - Pete_Lockwood - Thu Feb 26, 2009 4:13 pm
Is there any technical reason preventing me hacking up the existing ARM7 and ARM9 code to bypass the AP and just send/read packets directly?
Presumably the wireless chip can't/won't stop me doing that and there's enough info in the existing DSWifi library to drive the chip?
_________________
It's not an illusion, it just looks like one.
#167014 - elhobbs - Thu Feb 26, 2009 4:27 pm
nope, nothing to stop you. you just need to figure out the correct sequence/values to write to the wifi registers to allow the packets to be sent and recieved. easy as pie ;)
#167017 - Pete_Lockwood - Thu Feb 26, 2009 5:17 pm
Shouldn't be *that* hard given SG's code already does it :)
If I'm only talking my own protocol to other DSes presumably I don't need to care about the proper 802.11 or networking rules.
_________________
It's not an illusion, it just looks like one.
#167020 - elhobbs - Thu Feb 26, 2009 5:34 pm
I wish you the best of luck. I was not able to get the receiving ds to see any of my packets. my wireless card on my computer can not do promiscuous mode, so I could not even tell if my ds was sending any packets! you need to set the send and receive filters (plus more I would guess) to allow the hardware to send and recieve.
just turning on promiscuous mode on the receiving ds does not allow it to see anything but management packets. I could not figure out how to get it to see anything else. I even tried setting the receive filters to the same as in liblobby with no luck.
#167021 - Maxxie - Thu Feb 26, 2009 5:37 pm
If you got a ralink, it works great for communicating ds<->pc or minitoring two DS communicating.
Even if liblobby has massive flaws on the flowcontrol, take a look at it's sending/receiving part of the source. It can actually do this without an STA (AP)
_________________
Trying to bring more detail into understanding the wireless hardware
#167024 - Pete_Lockwood - Thu Feb 26, 2009 7:24 pm
The receive filters are in the hardware?
_________________
It's not an illusion, it just looks like one.
#167026 - Maxxie - Thu Feb 26, 2009 9:27 pm
Yes.
There are flags to skip receiving on various filters.
Shortly before Martin (no$cash) went MIA he used a busy checking system to capture the skipped and even invalid packets on the DS. They are written into the mem even if ignored later on.
_________________
Trying to bring more detail into understanding the wireless hardware
#167296 - Pete_Lockwood - Sun Mar 08, 2009 2:16 pm
Finally found some time to play with this. Looks like receiving works using the stock DSWifi library, which is kinda interesting as I'd assumed receiving would be troublesome and sending would be easy.
_________________
It's not an illusion, it just looks like one.
#167309 - Pete_Lockwood - Sun Mar 08, 2009 6:58 pm
Got send working too :)
Still need to work out *why* it works where the default DSWifi code doesn't and tidy things up but looks good.
_________________
It's not an illusion, it just looks like one.
#167461 - yellowstar - Thu Mar 12, 2009 7:56 pm
How are you sending raw packets with Dswifi, Pete? I attempted raw packet sending /w Dswifi when you posted about success with this, but my incomplete WMB Host/Client adapted for Dswifi didn't send any packets.(I tried capturing the beacons on channel 11, but no WMB beacons were being sent; I'm calling Wifi_SetChannel(11).) I'm using Wifi_InitDefault(0), and Wifi_ScanMode(). Removing the latter doesn't help. For sending, I'm using Wifi_RawTxFrame. I tried both data rates of 2 and 11, but neither sends anything.
#167465 - Pete_Lockwood - Thu Mar 12, 2009 11:15 pm
I rewrote Wifi_RawTxFrame using Wifi_TransmitFunction as a template. I'm also, currently, as a hack, calling LWIFI_Init after Wifi_Init. This weekend I plan to work out what it is about LWIFI_Init that's different to Wifi_Init with the intention of merging the appropriate differences back into Wifi_Init.
Yes, I said LWIFI_Init :D I just figured since Lobby is able to transmit there'd be no reason DSWifi wouldn't be able to too.
If you wanna PM me your email address I can send you what I have now (incl. a small test app) or you can wait and I'll post back when I've sorted out proper integration of the Init functions.
_________________
It's not an illusion, it just looks like one.
#167467 - yellowstar - Thu Mar 12, 2009 11:35 pm
I can wait; this wmb client/host isn't really a priority currently. Previously, this WMB host/client used to use liblobby, but the host had issues. Sending the pings in a infinite while loop like Juglak's WMB Host caused my host to freeze, and sending the pings in the vblank handler caused the client to time out.
#167471 - Pete_Lockwood - Fri Mar 13, 2009 3:16 am
OK.. I'm somewhat confused. I went back through the Init code and couldn't see a difference that appeared relevant so I started pulling out the Lobby Wifi Init code I'd inserted into DSWifi. Long story short it seems that the only thing needed to get the Raw send working is the rewrite of Wifi_RawTxFrame.
Any chance someone can confirm I'm not going insane? If so, the rewritten function is as follows:
Code: |
int Wifi_RawTxFrame(u16 datalen, u16 rate, u16 * data) {
int base,framelen, hdrlen, writelen;
int copytotal, copyexpect;
u16 framehdr[6 + 12 + 2];
framelen=datalen + 8 + (WifiData->wepmode7 ? 4 : 0);
if(framelen + 40>Wifi_TxBufferWordsAvailable()*2) { // error, can't send this much!
SGIP_DEBUG_MESSAGE(("Transmit:err_space"));
return -1; //?
}
framehdr[0]=0;
framehdr[1]=0;
framehdr[2]=0;
framehdr[3]=0;
framehdr[4]=0; // rate, will be filled in by the arm7.
hdrlen=18;
framehdr[6]=0x0208;
framehdr[7]=0;
// MACs.
memset(framehdr + 8, 0xFF, 18);
if(WifiData->wepmode7)
{
framehdr[6] |=0x4000;
hdrlen=20;
}
framehdr[17] = 0;
framehdr[18] = 0; // wep IV, will be filled in if needed on the arm7 side.
framehdr[19] = 0;
framehdr[5]=framelen+hdrlen * 2 - 12 + 4;
copyexpect= ((framelen+hdrlen * 2 - 12 + 4) + 12 - 4 + 1)/2;
copytotal=0;
WifiData->stats[WSTAT_TXQUEUEDPACKETS]++;
WifiData->stats[WSTAT_TXQUEUEDBYTES] += framelen + hdrlen * 2;
base = WifiData->txbufOut;
Wifi_TxBufferWrite(base,hdrlen,framehdr);
base += hdrlen;
copytotal += hdrlen;
if(base >= (WIFI_TXBUFFER_SIZE / 2)) base -= WIFI_TXBUFFER_SIZE / 2;
// add LLC header
framehdr[0]=0xAAAA;
framehdr[1]=0x0003;
framehdr[2]=0x0000;
unsigned short protocol = 0x08FE;
framehdr[3] = ((protocol >> 8) & 0xFF) | ((protocol << 8) & 0xFF00);
Wifi_TxBufferWrite(base, 4, framehdr);
base += 4;
copytotal += 4;
if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
writelen = datalen;
if(writelen) {
Wifi_TxBufferWrite(base,(writelen+1)/2,data);
base += (writelen + 1) / 2;
copytotal += (writelen + 1) / 2;
if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2;
}
if(WifiData->wepmode7)
{ // add required extra bytes
base += 2;
copytotal += 2;
if(base >= (WIFI_TXBUFFER_SIZE / 2)) base -= WIFI_TXBUFFER_SIZE / 2;
}
WifiData->txbufOut = base; // update fifo out pos, done sending packet.
if(copytotal!=copyexpect)
{
SGIP_DEBUG_MESSAGE(("Tx exp:%i que:%i",copyexpect,copytotal));
}
if(synchandler) synchandler();
return 0;
}
|
My simple test app, which just sends 10 packets a second between a pair of DSes:
Code: |
#include <nds.h>
#include <stdio.h>
#include <dswifi9.h>
#include <string.h>
void Handler(int packetID, int readlength)
{
static char data[4096];
static int bytesRead;
bytesRead = Wifi_RxRawReadPacket(packetID, readlength, (unsigned short *)data);
// Lazy test to see if this is our packet.
if(data[32] == '*' && data[33] == '*')
{
iprintf("\x1b[1;0HRcv:%d ", atoi(data+59));
}
}
int main(void)
{
consoleDemoInit();
Wifi_InitDefault(false);
Wifi_SetPromiscuousMode(1);
Wifi_EnableWifi();
Wifi_RawSetPacketHandler(Handler);
Wifi_SetChannel(10);
iprintf("Touch screen to start");
touchPosition touch;
while(1)
{
scanKeys();
touchRead(&touch);
int pressed = keysDown();
if(pressed & KEY_TOUCH)
break;
}
iprintf("\x1b[0;0H ");
int send = 0;
int f;
unsigned short buffer[100];
while(1)
{
iprintf("\x1b[0;0HSending %d", send);
sprintf((char *)buffer,"***********-T-E-S-T-******:%d", send++);
if(Wifi_RawTxFrame(strlen((char *)buffer) + 1, 0x0014, buffer) != 0)
{
iprintf("\n\nError calling RawTxFrame\n\n");
}
for(f = 0 ; f < 6 ; f++)
swiWaitForVBlank();
}
return 0;
}
|
_________________
It's not an illusion, it just looks like one.
#167481 - sgstair - Fri Mar 13, 2009 4:46 pm
This defeats the intent of that function.
RawTxFrame always has been able to send raw frames, but it sends raw 802.11 frames, not raw ethernet-ish frames.
The difficulty has always been in actually receiving those frames at the other end.
I see what that's doing; it's clever but not correct for this type of communication. it sets the "from DS" bit in the 802.11 header, but the 802.11 standard states that should only happen when an AP is sending data to a client.
Apparently that would be the bit that the DS receive filter is set to filter on by default; so that's useful information. But this is not good for trying to make adhoc work (which should have a control word of 0x0008 rather than 0x0208)
-Stephen
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/
#167482 - elhobbs - Fri Mar 13, 2009 5:31 pm
is this a good idea either? Code: |
// MACs.
memset(framehdr + 8, 0xFF, 18);
|
wouldn't this make it impossible for multiple sessions to exists at the same time?
#167487 - Pete_Lockwood - Fri Mar 13, 2009 7:14 pm
If I can get a bunch of DSes communicating this way, which appears to be the case, I personally don't much mind what the 802.11 standard says I'm supposed to be doing. Yes, it would be nice to do things properly but in the absence of properly I'll settle for workable.
'Sessions' can be handled by passing information in the data if the MAC can't be sent in the proper header format.
Using this approach I always expected I'd haveta handle stuff in my application that you'd usually get for free - but I don't have an AP available and I'm not willing to suffer the pain of LibLobby.
_________________
It's not an illusion, it just looks like one.
#167491 - sgstair - Sat Mar 14, 2009 2:21 am
Yet another reason why I really need to get this right for the next wifilib ;)
can't have everyone going around sending non-standards-compliant traffic. You actually could interfere with legitimate wifi devices by doing this.
_________________
http://blog.akkit.org/ - http://www.akkit.org/dswifi/
#167492 - Pete_Lockwood - Sat Mar 14, 2009 2:37 am
:D
When you do it right I'll be more than happy to make the switch. For now, I'll trust that the very few packets my application will send aren't going to cause an international incident :D
_________________
It's not an illusion, it just looks like one.
#168304 - chebastian - Mon Apr 20, 2009 12:17 pm
Bump.
Im realy interested in making an app where 2ds's are communicating with each other.
Any progress?
#168305 - Pete_Lockwood - Mon Apr 20, 2009 1:19 pm
I assume you're asking SGStair?
_________________
It's not an illusion, it just looks like one.
#168988 - dragontje124 - Mon Jun 08, 2009 5:44 pm
any progress on this?
#169079 - Emmanuel - Sat Jun 13, 2009 3:36 am
Umm, talking about this. I have a slight problem. Having the DS on wifi mode is ok, nothing bad happens, but as soon as there is some sort of signal coming it starts draining the free memory in timed intervals. This timed intervals might be around the 10 secs, and the data is send once per loop. *having a wait for VBL at the end of the loop*
This makes me believe it's the handler function.
Mine is
Code: |
void handler(int packetID, int readlength){
unsigned short * data = new unsigned short[DATA_LENGTH];
if(readlength >= DATA_LENGTH){
readlength = DATA_LENGTH-1;
}
Wifi_RxRawReadPacket(packetID, readlength, data);
multiManage->cleanData();
strncpy(multiManage->receivedData, (char*)data+32, DATA_LENGTH-1);
multiManage->receivedData[DATA_LENGTH-1] = '\0';
multiManage->checkSSBCData();
memset(data, 0, DATA_LENGTH*2);
delete [] data;
data = NULL;
} |
Clean data is simply
Code: |
void MultiManager::cleanData(){
memset(receivedData, 0, DATA_LENGTH);
} |
And checkSSBCData. It's used to convert the obtained data into the
format I'm using.
Code: |
void MultiManager::checkSSBCData(){
if( receivedData[0] == 'S' &&
receivedData[1] == 'S' &&
receivedData[2] == 'B' &&
receivedData[3] == 'C'){
if(otherPlayer != NULL){
delete otherPlayer;
otherPlayer = NULL;
}
bool slash = false;
int counter = 0;
string data = "";
do{
if(receivedData[counter+4] != '/'){
data += receivedData[counter+4];
counter++;
}else{
slash = true;
}
}while(!slash);
int length = 0;
stringstream lengthStream;
lengthStream << data;
lengthStream >> length;
otherPlayer = new SSBCData(&receivedData[4+counter+1] , length);
}
} |
SSBCData objects don't have a single pointer *they are just 1 int and 1 string* so, there shouldn't be memory leaks with them.
Dunno if it's my handler function or the function for communications here.
I'm using the latest Devkit *I think, at least it was the latest before the start of this month* and the function that was developed here. DSwifi was the only lib that had some modifications: I copy pasted this function and added AdHoc at the end and added it to the .h file. And, I had to use a previous version because the latest had some critical section errors or something S:
So far it has worked perfectly, except sometimes there's a freeze, which I think may end up being because of this leak.
#169082 - Pete_Lockwood - Sat Jun 13, 2009 1:41 pm
I'd cut down the code performed in the handler to an absolute minimum, then turn off interrupts when you actually read the network buffers. This is roughly how I use the handler:
First create a simple array of message references:
Code: |
const int maxQSize = 4096;
struct MsgQElement {
int packetID;
int length;
};
MsgQElement InMsgQ[maxQSize];
int InMsgQSize;
|
This is all the handler does:
Code: |
void PacketHandler(int packetID, int length)
{
InMsgQ[InMsgQSize].packetID = packetID;
InMsgQ[InMsgQSize].length = length;
InMsgQSize++;
if(InMsgQSize >= maxQSize)
{
// This would be bad.
}
}
|
Then I have a VBlank function that looks a bit like this, which I call in the one or two places in my code that wait for a VBlank (and more importantly can handle a state change caused by an update coming across the network):
Code: |
void WaitForVBlank(void)
{
// Disable interrupts while we catch up with the network buffers.
// Otherwise, things will go bad because we'll be doing stuff and
// the Wifi will still be reading more buffers at the same time.
REG_IME = 0;
if(InMsgQSize)
{
updated = ReadNetworkBuffers();
}
REG_IME = 1;
if(updated)
{
UpdateEverything();
}
// Actually wait for the VBlank now
swiWaitForVBlank();
}
|
And finally the piece that actually deals with the network buffers:
Code: |
bool ReadNetworkBuffers()
{
int f;
bool updated = false;
for(f = 0 ; f < InMsgQSize ; f++)
{
Wifi_RxRawReadPacket(InMsgQ[f].packetID, InMsgQ[f].length, (unsigned short *)InBuffer);
updated |= ProcessBuffer(InBuffer);
}
InMsgQSize = 0;
return updated;
}
|
Will that resolve your leak? Don't know, but I do know that when I used to process the buffer immediately in the handler things would get messy after a while. It's best to exit the callback as soon as possible then come back when program flow is under your control.
_________________
It's not an illusion, it just looks like one.
Last edited by Pete_Lockwood on Sun Jun 14, 2009 3:35 pm; edited 1 time in total
#169086 - Emmanuel - Sun Jun 14, 2009 9:54 am
It fixed a leak I had in the receiving side, and the freezing in the sending side.
Now, I just need to do some fixes in the sending of data, but performance has increased so much, and your idea of keeping an array of referrences to messages gave me an idea and all in all the performance in the COMM side has increased a lot, just in the aspects it was failing before.
Thanks.
#169318 - melw - Thu Jul 02, 2009 10:11 pm
One could do yet another comparison between DS Wifi library and Lib Lobby and see where the registers differ. If also the former can send 802.11 beacon frames, it shouldn't be too far from receiving data frames either. Could it be as simple as missing the correct RX filter setting (0x0D in WiFi registers)?
Probably not. :)
Anyhow, just dropping random thoughts. I actually took few hours and converted the Pong example from LibLobby to use modified DsWifi library as my personal playground. But like Sgstair said, this isn't too useful as long as the traffic isn't transmitted in data frames.