#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define printf pspDebugScreenPrintf #define MATCHING_JOINED 0x1 // Another PSP has joined #define MATCHING_SELECTED 0x2 // Another PSP selected to match #define MATCHING_REJECTED 0x4 // The request has been rejected #define MATCHING_CANCELED 0x5 // The request has been cancelled #define MATCHING_ESTABLISHED 0x7 // Both PSP's have agreed to connect, at this point Lumines // closes the connection and creates a new one with just the // two PSP's in it. #define MATCHING_DISCONNECT 0xa // A PSP has quit, this does not include when the PSP crashes PSP_MODULE_INFO("AdHoc", 0, 1, 1); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER); int adhocTerm(); /* exit callback */ int exit_callback(int arg1, int arg2, void *common){ adhocTerm(); sceKernelExitGame(); return 0; } /* callback thread */ int CallbackThread(SceSize args, void *argp){ int cbid; cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); sceKernelRegisterExitCallback(cbid); sceKernelSleepThreadCB(); return 0; } /* setup the callback thread */ int SetupCallbacks(void){ int thid = 0; thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0); if(thid >= 0) sceKernelStartThread(thid, 0, 0); return thid; } // Define a few states for handling the adhoc events #define PSP_LISTING 1 #define PSP_SELECTED 2 #define PSP_SELECTING 3 #define PSP_WAIT_EST 4 #define PSP_ESTABLISHED 5 int g_Server = 0; int pdpId = 0; int matchingId = 0; int matchChanged = 0; char g_mac[6]; int g_unk1=0; int g_matchEvent=0; int g_matchOptLen=0; char g_matchOptData[1000]; int NetInit = 0; int NetAdhocInit = 0; int NetAdhocctlInit = 0; int NetAdhocctlConnect = 0; int NetAdhocPdpCreate = 0; int NetAdhocMatchingInit = 0; int NetAdhocMatchingCreate = 0; int NetAdhocMatchingStart = 0; //Void used to be pspAdhocMatchingCallback void matchingCallback(int unk1, int event, char *mac2, int optLen, char *optData) { // This is called when there is an event, dont seem to be able to call // procs from here otherwise it causes a crash if(event==MATCHING_JOINED) { AddPsp(mac2, optData, optLen); } else if(event==MATCHING_DISCONNECT) { DelPsp(mac2); } else { g_unk1 = unk1; g_matchEvent = event; g_matchOptLen = optLen; // Copy across the optional data strncpy(g_matchOptData, optData, optLen); // And the MAC address memcpy(g_mac, mac2, sizeof(char) * 6); matchChanged = 1; } } int adhocInit(char *MatchingData) { char mac[6]; struct productStruct product; ClearPspList(); strcpy(product.product, "ULUS99999"); product.unknown = 0; u32 err; printf("sceNetInit()\n"); err = sceNetInit(0x20000, 0x20, 0x1000, 0x20, 0x1000); if (err != 0) return err; NetInit = 1; printf("sceNetAdhocInit()\n"); err = sceNetAdhocInit(); if (err != 0) return err; NetAdhocInit = 1; printf("sceNetAdhocctlInit()\n"); err = sceNetAdhocctlInit(0x2000, 0x20, &product); if (err != 0) return err; NetAdhocctlInit = 1; // Connect err = sceNetAdhocctlConnect(""); if (err != 0) return err; NetAdhocctlConnect = 1; int stateLast = -1; printf("Connecting...\n"); while (1) { int state; err = sceNetAdhocctlGetState(&state); if (err != 0) { printf("sceNetApctlGetState returns $%x\n", err); sceKernelDelayThread(10*1000000); // 10sec to read before exit return -1; } if (state > stateLast) { printf(" connection state %d of 1\n", state); stateLast = state; } if (state == 1) break; // connected // wait a little before polling again sceKernelDelayThread(50*1000); // 50ms } printf("Connected!\n"); sceWlanGetEtherAddr(mac); printf("sceNetAdhocPdpCreate\n"); pdpId = sceNetAdhocPdpCreate(mac, 0x309, // 0x309 in lumines 0x400, // 0x400 in lumines 0); // 0 in lumines if(pdpId <= 0) { printf("pdpId = %x\n", pdpId); return -1; } NetAdhocPdpCreate = 1; printf("sceNetAdhocMatchingInit()\n"); err = sceNetAdhocMatchingInit(0x20000); if(err != 0) { printf("error = %x\n", err); } NetAdhocMatchingInit = 1; printf("sceNetAdhocMatchingCreate()\n"); matchingId = sceNetAdhocMatchingCreate(3, 0xa, 0x22b, 0x800, 0x2dc6c0, 0x5b8d80, 3, 0x7a120, (void *)matchingCallback); if(matchingId < 0) { printf("matchingId = %x\n", matchingId); } NetAdhocMatchingCreate = 1; char tempStr[100]; tempStr[0] = '\0'; /*if(strlen(MatchingData)) { strncpy(tempStr, strrchr(MatchingData, '/')+1, 100); strrchr(tempStr, '.')[0] = '\0'; }*/ //printf("tempStr=%s\n", tempStr); printf("sceNetAdhocMatchingStart()\n"); err = sceNetAdhocMatchingStart(matchingId, // 1 in lumines (presuming what is returned from create) 0x10, // 0x10 0x2000, // 0x2000 0x10, // 0x10 0x2000, // 0x2000 6, "adhoc\0"); //strlen(tempStr)+1, //tempStr); if(err != 0) { printf("error = %x\n", err); } NetAdhocMatchingStart = 1; // All the init functions have passed return 0; } // Define a few states for handling the adhoc events #define PSP_LISTING 1 #define PSP_SELECTED 2 #define PSP_SELECTING 3 #define PSP_WAIT_EST 4 #define PSP_ESTABLISHED 5 //////////////////////////////////////////////////////////////////////////////////// // This is just a quick and easy procedure to wait for a PSP to join, the following // is what is done in Lumines: // // - Wait for a PSP to join // - Add the PSP to the list of machines available // - Wait for the user to select a PSP // - Call sceMatchingSelectTarget // - The other PSP will receive MATCHING_SELECTED event // - The other PSP displays a message to accept or cancel // - If accepted the other PSP calls sceMatchingSelectTarget // - The first PSP receives MATCHING_ESTABLISHED // // In lumines they then close the connection and start a new adhoc connection // with just those two machines in it. /////////////////////////////////////////////////////////////////////////////////// int adhocSelect(void) { SceCtrlData m_PspPad; int err = 0; char mac[10]; char name[100]; int waitAccept = 0; int currentState = PSP_LISTING; int oldButtons = 0; char tempStr[100]; for(;;) { sceCtrlReadBufferPositive(&m_PspPad, 1); pspDebugScreenSetTextColor(0xFFFF); switch(currentState) { case PSP_LISTING: { pspDebugScreenInit(); pspDebugScreenPrintf("Select a server to connect to, or triangle to return\n\n\n"); DisplayPspList(); g_Server = 0; if(m_PspPad.Buttons != oldButtons) { if(m_PspPad.Buttons & PSP_CTRL_UP) { UpList(); } if(m_PspPad.Buttons & PSP_CTRL_DOWN) { DownList(); } if(m_PspPad.Buttons & PSP_CTRL_CROSS) { if(GetPspEntry(mac, name) > 0) { currentState = PSP_SELECTING; sceNetAdhocMatchingSelectTarget(matchingId, mac, 0, 0); } } if(m_PspPad.Buttons & PSP_CTRL_TRIANGLE) return -1; } if(matchChanged) { if(g_matchEvent == MATCHING_SELECTED) { memcpy(mac, g_mac, 6); strcpy(name, g_matchOptData); currentState = PSP_SELECTED; } } break; } case PSP_SELECTING: { pspDebugScreenInit(); sceNetEtherNtostr(mac, tempStr); printf("Waiting for %s to accept the connection\nTo cancel press O\n", tempStr); if(m_PspPad.Buttons != oldButtons) { if(m_PspPad.Buttons & PSP_CTRL_CIRCLE) { sceNetAdhocMatchingCancelTarget(matchingId, mac); currentState = PSP_LISTING; } } if(matchChanged) { if(g_matchEvent == MATCHING_SELECTED) { sceNetAdhocMatchingCancelTarget(matchingId, mac); } else if(g_matchEvent == MATCHING_ESTABLISHED) { currentState = PSP_ESTABLISHED; } else if(g_matchEvent == MATCHING_REJECTED) { currentState = PSP_LISTING; } } break; } case PSP_SELECTED: { g_Server = 1; pspDebugScreenInit(); sceNetEtherNtostr(mac, tempStr); printf("%s has requested a connection\nTo accept the connection press X, to cancel press O\n", tempStr); if(m_PspPad.Buttons != oldButtons) { if(m_PspPad.Buttons & PSP_CTRL_CIRCLE) { sceNetAdhocMatchingCancelTarget(matchingId, mac); currentState = PSP_LISTING; } if(m_PspPad.Buttons & PSP_CTRL_CROSS) { sceNetAdhocMatchingSelectTarget(matchingId, mac, 0, 0); currentState = PSP_WAIT_EST; } } if(matchChanged) { if(g_matchEvent == MATCHING_CANCELED) { currentState = PSP_LISTING; } } break; } case PSP_WAIT_EST: { if(matchChanged) { if(g_matchEvent == MATCHING_ESTABLISHED) { currentState = PSP_ESTABLISHED; } } break; } } matchChanged = 0; oldButtons = m_PspPad.Buttons; if(currentState == PSP_ESTABLISHED) break; sceDisplayWaitVblankStart(); } char macAddr[10]; char *tempMac; if(g_Server) { sceWlanGetEtherAddr(macAddr); tempMac = macAddr; } else { tempMac = mac; } sceNetEtherNtostr(tempMac, tempStr); char ssid[10]; sprintf(ssid, "%c%c%c%c%c%c", tempStr[9], tempStr[10], tempStr[12], tempStr[13], tempStr[15], tempStr[16]); adhocReconnect(ssid); // We only get here if both PSP's have agreed to connect //pspDebugScreenInit(); pspDebugScreenPrintf("\nConnected\n"); if(g_Server) return 1; else return 0; } int adhocReconnect(char *ssid) { int err = 0; // Disconnect Wifi if(NetAdhocctlConnect) { printf("sceNetAdhocctlDisconnect\n"); err = sceNetAdhocctlDisconnect(); if(err != 0) { printf(" returned %x\n", err); } NetAdhocctlConnect = 0; } if(NetAdhocPdpCreate) { printf("sceNetAdhocPdpDelete\n"); err = sceNetAdhocPdpDelete(pdpId,0); if(err != 0) { printf("sceNetAdhocPdpDelete returned %x\n", err); } NetAdhocPdpCreate = 0; } if(NetAdhocMatchingStart) { printf("sceNetAdhocMatchingStop\n"); err = sceNetAdhocMatchingStop(matchingId); if(err != 0) { printf("sceNetAdhocMatchingStop returned %x\n", err); } NetAdhocMatchingStart = 0; } if(NetAdhocMatchingCreate) { printf("sceNetAdhocMatchingDelete\n"); err = sceNetAdhocMatchingDelete(matchingId); if(err != 0) { printf("sceNetAdhocMatchingDelete returned %x\n", err); } NetAdhocMatchingCreate = 0; } if(NetAdhocMatchingInit) { printf("sceNetAdhocMatchingTerm\n"); err = sceNetAdhocMatchingTerm(); if(err != 0) { printf("sceNetAdhocMatchingTerm returned %x\n", err); } NetAdhocMatchingInit = 0; } int stateLast = -1; while (1) { int state; err = sceNetAdhocctlGetState(&state); if (err != 0) { printf("sceNetApctlGetState returns $%x\n", err); sceKernelDelayThread(10*1000000); // 10sec to read before exit return -1; } if (state > stateLast) { printf(" connection state %d of 1\n", state); stateLast = state; } if (state == 0) break; // connected // wait a little before polling again sceKernelDelayThread(50*1000); // 50ms } // Now connect to the PSP using a new SSID // Connect err = sceNetAdhocctlConnect(ssid); if (err != 0) { printf("err=%x\n", err); for(;;) sceDisplayWaitVblankStart(); return err; } NetAdhocctlConnect = 1; stateLast = -1; printf("Connecting...\n"); while (1) { int state; err = sceNetAdhocctlGetState(&state); if (err != 0) { printf("sceNetApctlGetState returns $%x\n", err); sceKernelDelayThread(10*1000000); // 10sec to read before exit return -1; } if (state > stateLast) { printf(" connection state %d of 1\n", state); stateLast = state; } if (state == 1) break; // connected // wait a little before polling again sceKernelDelayThread(50*1000); // 50ms } char macAddr[10]; sceWlanGetEtherAddr(macAddr); printf("sceNetAdhocPdpCreate\n"); pdpId = sceNetAdhocPdpCreate(macAddr, 0x309, // 0x309 in lumines 0x800, // 0x400 in lumines 0); // 0 in lumines if(pdpId <= 0) { printf("pdpId = %x\n", pdpId); return -1; } NetAdhocPdpCreate = 1; } int adhocSend(void *buffer, int length) { int err=0; err = sceNetAdhocPdpSend(pdpId, &g_mac[0], 0x309, buffer, length, 0, // 0 in lumines 1); // 1 in lumines return err; } // Used to send the data and wait for an ack int adhocSendRecvAck(void *buffer, int length) { int err=0; int recvTemp=0; int recvLen=1; int tempLen = length; int sentCount = 0; do { if(tempLen > 0x400) { tempLen = 0x400; } //pspDebugScreenPrintf("server waiting..1\n\n"); //sceKernelDelayThread(5000000); err = adhocSend(buffer, tempLen); if(err < 0) return err; //pspDebugScreenPrintf("server waiting..2\n\n"); //sceKernelDelayThread(5000000); // wait for an ack err = adhocRecvBlocked(&recvTemp, &recvLen); if(err < 0) { pspDebugScreenPrintf("err=%x\n", err); return err; } buffer += 0x400; sentCount += 0x400; tempLen = length - sentCount; } while(sentCount < length); return err; } // Used to receive data and then send an ack int adhocRecvSendAck(void *buffer, unsigned int *length) { int temp=1; int err=0; int tempLen = *length; int rcvdCount = 0; do { if(tempLen > 0x400) { tempLen = 0x400; } err = adhocRecvBlocked(buffer, length); if(err < 0) return err; err = adhocSend(&temp, 1); rcvdCount += 0x400; buffer += 0x400; tempLen = *length - rcvdCount; } while(rcvdCount < *length); // wait for an ack return err; } int adhocRecv(void *buffer, unsigned int *length) { int err=0; int pdpStatLength=20; unsigned int pdpRecvLength=0; unsigned short port=0; char mac[20]; pdpStatStruct pspStat; err = sceNetAdhocGetPdpStat(&pdpStatLength, &pspStat); if(err<0) { printf("error calling GetPdpStat, err=%x\n", err); return err; } if(pspStat.rcvdData > 0) { pdpRecvLength = pspStat.rcvdData; err = sceNetAdhocPdpRecv(pdpId, mac, &port, buffer, &length, 0, // 0 in lumines 1); // 1 in lumines if(err<0) { printf("err=%x\n", err); return err; } else { return 1; } } return 0; } int adhocRecvBlocked(void *buffer, unsigned int *length) { char mac[20]; int port=309; int err=0; do { err = adhocRecv(buffer, length); sceKernelDelayThread(1000); } while (err == 0); return err; } int adhocTerm() { u32 err; if(NetAdhocctlConnect) { printf("sceNetAdhocctlDisconnect\n"); err = sceNetAdhocctlDisconnect(); if(err != 0) { printf(" returned %x\n", err); } NetAdhocctlConnect = 0; } if(NetAdhocPdpCreate) { printf("sceNetAdhocPdpDelete\n"); err = sceNetAdhocPdpDelete(pdpId,0); if(err != 0) { printf("sceNetAdhocPdpDelete returned %x\n", err); } NetAdhocPdpCreate = 0; } if(NetAdhocMatchingStart) { printf("sceNetAdhocMatchingStop\n"); err = sceNetAdhocMatchingStop(matchingId); if(err != 0) { printf("sceNetAdhocMatchingStop returned %x\n", err); } NetAdhocMatchingStart = 0; } if(NetAdhocMatchingCreate) { printf("sceNetAdhocMatchingDelete\n"); err = sceNetAdhocMatchingDelete(matchingId); if(err != 0) { printf("sceNetAdhocMatchingDelete returned %x\n", err); } NetAdhocMatchingCreate = 0; } if(NetAdhocMatchingInit) { printf("sceNetAdhocMatchingTerm\n"); err = sceNetAdhocMatchingTerm(); if(err != 0) { printf("sceNetAdhocMatchingTerm returned %x\n", err); } NetAdhocMatchingInit = 0; } if(NetAdhocctlInit) { printf("sceNetAdhocctlTerm\n"); err = sceNetAdhocctlTerm(); if(err != 0) { printf("sceNetAdhocctlTerm returned %x\n", err); } NetAdhocctlInit = 0; } if(NetAdhocInit) { printf("\nTerminating Adhoc..."); int adhocTerm = sceNetAdhocTerm(); if (adhocTerm < 0) printf("Error terminating Adhoc 0x%08X", adhocTerm); else printf("Done."); sceKernelDelayThread(1000000*3); NetAdhocInit = 0; } if(NetInit) { printf("sceNetTerm\n"); err = sceNetTerm(); if(err != 0) { printf("sceNetTerm returned %x\n", err); } NetInit = 0; } return 0; // assume it worked } /* var init */ int done, err, i, loop, server, size = 0; unsigned int length; char *data; char send_buffer[128*1024]; char rec_buffer[128*1024]; int copy_file(const char *path, int service) { if (service == 1) { int fileCheck; fileCheck = sceIoOpen(path, PSP_O_RDONLY, 0); sceIoClose(fileCheck); if(fileCheck > -1) { int fdin; int fdout; fdin = sceIoOpen(path, PSP_O_RDONLY, 0777); if(fdin >= 0) { int bytesRead = 1; bytesRead = sceIoRead(fdin, send_buffer, sizeof(send_buffer)); char *data; while((bytesRead > 0) && (fdout >= 0)) { bytesRead = sceIoRead(fdin, send_buffer, sizeof(send_buffer)); } data = send_buffer; size = strlen(data); adhocSend(&size, 4); adhocSend(&send_buffer, size); printf("\nSize of Data: %d", size); printf("\nBytes Read: %d", bytesRead); printf("\nBuffer: %s", send_buffer); if(fdin >= 0) sceIoClose(fdin); } return 1; } } else if (service == 2) { int fdout; fdout = sceIoOpen(path, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777); long int bytesWritten = 0; int length = 4; adhocRecvSendAck(&size, &length); while((bytesWritten < size) && (fdout >= 0)) { adhocRecvSendAck(&rec_buffer, &size); bytesWritten = sceIoWrite(fdout, rec_buffer, sizeof(rec_buffer)); } printf("\nSize of Data: %d", size); printf("\nBytes Recieved: %d", sizeof(rec_buffer)); printf("\nBytes Written: %d", bytesWritten); printf("\nBuffer: %s", rec_buffer); if(fdout >= 0) sceIoClose(fdout); return 1; } return 0; } int main(){ /* exit callback */ SetupCallbacks(); pspDebugScreenInit(); int utility = 0; utility = sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON); if (utility < 0) { printf("Error loading PSP_NET_MODULE_COMMON 0x%08X", utility); } utility = sceUtilityLoadNetModule(PSP_NET_MODULE_ADHOC); if (utility < 0) { printf("Error loading PSP_NET_MODULE_ADHOC 0x%08X", utility); } server = 0; //We want to continue for as long as needed (server>=0) while(server>=0) //server becomes -1 when trying to quit { pspDebugScreenSetXY(0,0); /* adhoc initalise functions */ if((adhocInit("") >= 0) && ((server = adhocSelect()) >=0)){ printf("\n\n## AdHoc INITALISED ##\n\n"); sceKernelDelayThread(1000000); /* Display server, or client */ if(server) printf("Server Assigned\n\n"); else printf("Client Assigned\n\n"); /* if this psp is the server */ if(server){ sceKernelDelayThread(1000000); /* client must be waiting for server, so slight delay for server */ // alphabet string data = "abcdefghijklmnopqrstuvwxyz"; size = sizeof(data); printf("Sending data to the client.. size: %d \n", size); err = adhocSendRecvAck(&size, 4); // let client know the size of data printf("Done sending size: %d\ndata: %s\n", size, data); sceKernelDelayThread(1000000); err = adhocSendRecvAck(&data, 4); // send data as void printf("Done sending data: %s\nsize: %d\n", data, size); } else { /* get data from server */ size = 0; length = 4; err = adhocRecvSendAck(&size, &length); // get size of data printf("Done receiving size: %d \nlength: %d \n", size, length); length = size; err = adhocRecvSendAck(&data, &length); // get data data = (char *)data; // type cast received data printf("Received data from server: %s \n", data); } } } /* terminate adhoc */ adhocTerm(); sceKernelExitGame(); return 0; }