2012-11-01 16:19:01 +01:00
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
2012-11-04 23:01:49 +01:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 16:19:01 +01:00
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2019-11-10 06:23:19 +07:00
# if __linux__ || __APPLE__
# include <unistd.h>
# include <sys/types.h>
# include <sys/mman.h>
# include <fcntl.h>
# endif
2013-11-28 12:38:45 +01:00
# include "net/resolve.h"
# include "util/text/parsers.h"
2020-08-10 00:12:51 -07:00
# include "Common/Serialize/Serializer.h"
# include "Common/Serialize/SerializeFuncs.h"
# include "Common/Serialize/SerializeMap.h"
2013-11-28 12:38:45 +01:00
# include "Core/HLE/HLE.h"
2014-03-15 11:22:19 -07:00
# include "Core/HLE/FunctionWrappers.h"
2019-08-18 11:53:39 -07:00
# include "Core/HLE/sceKernelMemory.h"
2013-11-28 12:38:45 +01:00
# include "Core/MIPS/MIPS.h"
# include "Core/Config.h"
2015-04-05 18:09:35 -07:00
# include "Core/MemMapHelpers.h"
2020-01-18 02:32:09 +07:00
# include "Core/Util/PortManager.h"
2012-11-01 16:19:01 +01:00
# include "sceKernel.h"
2013-06-17 08:04:31 -04:00
# include "sceKernelThread.h"
2013-07-15 17:55:00 -04:00
# include "sceKernelMutex.h"
2012-11-01 16:19:01 +01:00
# include "sceUtility.h"
2014-08-01 01:55:42 +07:00
# include "Core/HLE/proAdhoc.h"
2014-06-24 23:43:03 +07:00
# include "Core/HLE/sceNetAdhoc.h"
2014-08-01 01:55:42 +07:00
# include "Core/HLE/sceNet.h"
2020-08-12 20:28:14 +07:00
# include "Core/HLE/sceNp.h"
2015-03-08 20:07:03 +08:00
# include "Core/Reporting.h"
2020-07-20 11:38:39 +02:00
# include "Core/Instance.h"
2014-06-24 23:43:03 +07:00
2013-03-24 22:41:42 +01:00
static bool netInited ;
2019-12-24 00:04:03 +07:00
bool netInetInited ;
2020-07-28 07:38:10 +07:00
2016-02-13 20:27:07 +08:00
u32 netDropRate = 0 ;
u32 netDropDuration = 0 ;
2019-08-18 11:53:39 -07:00
u32 netPoolAddr = 0 ;
u32 netThread1Addr = 0 ;
u32 netThread2Addr = 0 ;
2013-03-24 22:41:42 +01:00
2013-06-17 19:27:59 -04:00
static struct SceNetMallocStat netMallocStat ;
2013-06-17 18:50:38 -04:00
2013-06-20 03:15:07 -04:00
static std : : map < int , ApctlHandler > apctlHandlers ;
2020-08-12 17:57:11 +07:00
SceNetApctlInfoInternal netApctlInfo ;
2020-07-27 09:51:53 +07:00
2020-07-28 07:38:10 +07:00
bool netApctlInited ;
u32 netApctlState ;
u32 apctlThreadHackAddr = 0 ;
u32_le apctlThreadCode [ 3 ] ;
SceUID apctlThreadID = 0 ;
int actionAfterApctlMipsCall ;
std : : recursive_mutex apctlEvtMtx ;
std : : deque < ApctlArgs > apctlEvents ;
u32 Net_Term ( ) ;
int NetApctl_Term ( ) ;
void NetApctl_InitInfo ( ) ;
2020-08-09 21:20:42 -07:00
void AfterApctlMipsCall : : DoState ( PointerWrap & p ) {
auto s = p . Section ( " AfterApctlMipsCall " , 1 , 1 ) ;
if ( ! s )
return ;
// Just in case there are "s" corruption in the future where s.ver is a negative number
if ( s > = 1 ) {
Do ( p , handlerID ) ;
Do ( p , oldState ) ;
Do ( p , newState ) ;
Do ( p , event ) ;
Do ( p , error ) ;
Do ( p , argsAddr ) ;
} else {
handlerID = - 1 ;
oldState = 0 ;
newState = 0 ;
event = 0 ;
error = 0 ;
argsAddr = 0 ;
}
}
2020-07-28 07:38:10 +07:00
void AfterApctlMipsCall : : run ( MipsCall & call ) {
u32 v0 = currentMIPS - > r [ MIPS_REG_V0 ] ;
DEBUG_LOG ( SCENET , " AfterApctlMipsCall::run [ID=%i][OldState=%d][NewState=%d][Event=%d][Error=%d][ArgsPtr=%08x] [cbId: %u][retV0: %08x] " , handlerID , oldState , newState , event , error , argsAddr , call . cbId , v0 ) ;
//call.setReturnValue(v0);
}
void AfterApctlMipsCall : : SetData ( int HandlerID , int OldState , int NewState , int Event , int Error , u32_le ArgsAddr ) {
handlerID = HandlerID ;
oldState = OldState ;
newState = NewState ;
event = Event ;
error = Error ;
argsAddr = ArgsAddr ;
}
2020-02-25 16:29:06 +07:00
static int InitLocalhostIP ( ) {
2020-08-17 23:33:27 -07:00
// The entire 127.*.*.* is reserved for loopback.
uint32_t localIP = 0x7F000001 + PPSSPP_ID - 1 ;
g_localhostIP . in . sin_family = AF_INET ;
g_localhostIP . in . sin_addr . s_addr = htonl ( localIP ) ;
2020-08-17 23:08:35 -07:00
g_localhostIP . in . sin_port = 0 ;
2019-11-10 06:23:19 +07:00
2020-08-17 23:33:27 -07:00
// If lookup fails, we'll assume it's not local.
isLocalServer = false ;
2019-11-10 06:23:19 +07:00
2020-08-17 23:33:27 -07:00
addrinfo * resultAddr = nullptr ;
std : : string error ;
if ( net : : DNSResolve ( g_Config . proAdhocServer , " " , & resultAddr , error , net : : DNSType : : IPV4 ) ) {
for ( addrinfo * ptr = resultAddr ; ptr ! = nullptr ; ptr = ptr - > ai_next ) {
auto addr4 = ( ( sockaddr_in * ) ptr - > ai_addr ) - > sin_addr . s_addr ;
isLocalServer = ( ntohl ( addr4 ) & 0x7F000000 ) = = 0x7F000000 ;
2019-11-10 06:23:19 +07:00
}
2020-08-17 23:33:27 -07:00
net : : DNSResolveFree ( resultAddr ) ;
resultAddr = nullptr ;
2019-11-10 06:23:19 +07:00
}
return 0 ;
}
2020-07-28 07:38:10 +07:00
void __NetApctlInit ( ) {
netApctlInited = false ;
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED ;
apctlHandlers . clear ( ) ;
memset ( & netApctlInfo , 0 , sizeof ( netApctlInfo ) ) ;
}
2014-12-08 04:40:08 -05:00
static void __ResetInitNetLib ( ) {
2013-03-24 22:41:42 +01:00
netInited = false ;
2013-06-20 03:15:07 -04:00
netInetInited = false ;
2013-03-24 22:41:42 +01:00
2013-07-17 17:34:17 -04:00
memset ( & netMallocStat , 0 , sizeof ( netMallocStat ) ) ;
2020-03-02 03:59:13 +07:00
memset ( & parameter , 0 , sizeof ( parameter ) ) ;
2013-03-24 22:41:42 +01:00
}
2020-08-02 08:49:58 +07:00
void __NetCallbackInit ( ) {
// Init Network Callbacks
dummyThreadHackAddr = __CreateHLELoop ( dummyThreadCode , " sceNetAdhoc " , " __NetTriggerCallbacks " , " dummythreadhack " ) ;
matchingThreadHackAddr = __CreateHLELoop ( matchingThreadCode , " sceNetAdhocMatching " , " __NetMatchingCallbacks " , " matchingThreadHack " ) ;
apctlThreadHackAddr = __CreateHLELoop ( apctlThreadCode , " sceNetApctl " , " __NetApctlCallbacks " , " apctlThreadHack " ) ;
// Newer one should be placed last to prevent callbacks going to the wrong after action after loading from old save state
actionAfterMatchingMipsCall = __KernelRegisterActionType ( AfterMatchingMipsCall : : Create ) ;
actionAfterAdhocMipsCall = __KernelRegisterActionType ( AfterAdhocMipsCall : : Create ) ;
actionAfterApctlMipsCall = __KernelRegisterActionType ( AfterApctlMipsCall : : Create ) ;
}
2013-07-17 17:36:51 -04:00
void __NetInit ( ) {
2020-01-18 02:32:09 +07:00
// Windows: Assuming WSAStartup already called beforehand
2016-01-24 16:52:39 +08:00
portOffset = g_Config . iPortOffset ;
2020-03-19 15:21:00 +07:00
isOriPort = g_Config . bEnableUPnP & & g_Config . bUPnPUseOriginalPort ;
2020-01-18 02:32:09 +07:00
minSocketTimeoutUS = g_Config . iMinTimeout * 1000UL ;
2020-07-20 09:40:56 +02:00
2020-02-25 16:29:06 +07:00
InitLocalhostIP ( ) ;
2019-12-24 00:04:03 +07:00
SceNetEtherAddr mac ;
getLocalMac ( & mac ) ;
2020-08-17 23:08:35 -07:00
INFO_LOG ( SCENET , " LocalHost IP will be %s [%s] " , inet_ntoa ( g_localhostIP . in . sin_addr ) , mac2str ( & mac ) . c_str ( ) ) ;
2020-07-18 08:19:43 +07:00
// TODO: May be we should initialize & cleanup somewhere else than here for PortManager to be used as general purpose for whatever port forwarding PPSSPP needed
__UPnPInit ( ) ;
2020-02-25 16:29:06 +07:00
2013-07-17 17:36:51 -04:00
__ResetInitNetLib ( ) ;
2020-07-28 07:38:10 +07:00
__NetApctlInit ( ) ;
2020-08-02 08:49:58 +07:00
__NetCallbackInit ( ) ;
2020-07-28 07:38:10 +07:00
}
void __NetApctlShutdown ( ) {
if ( apctlThreadHackAddr ) {
kernelMemory . Free ( apctlThreadHackAddr ) ;
apctlThreadHackAddr = 0 ;
}
2013-07-17 17:36:51 -04:00
}
void __NetShutdown ( ) {
2020-03-26 16:10:50 +07:00
// Network Cleanup
Net_Term ( ) ;
2020-07-18 08:19:43 +07:00
2020-07-28 07:38:10 +07:00
__NetApctlShutdown ( ) ;
2013-07-17 17:36:51 -04:00
__ResetInitNetLib ( ) ;
2020-01-18 02:32:09 +07:00
2020-03-23 21:51:45 +07:00
// Since PortManager supposed to be general purpose for whatever port forwarding PPSSPP needed, may be we shouldn't clear & restore ports in here? it will be cleared and restored by PortManager's destructor when exiting PPSSPP anyway
2020-07-18 08:19:43 +07:00
__UPnPShutdown ( ) ;
2013-07-17 17:36:51 -04:00
}
2020-07-28 07:38:10 +07:00
static void __UpdateApctlHandlers ( u32 oldState , u32 newState , u32 flag , u32 error ) {
std : : lock_guard < std : : recursive_mutex > apctlGuard ( apctlEvtMtx ) ;
apctlEvents . push_back ( { oldState , newState , flag , error } ) ;
}
2013-06-20 03:15:07 -04:00
2020-07-28 07:38:10 +07:00
// Make sure MIPS calls have been fully executed before the next notifyApctlHandlers
void notifyApctlHandlers ( int oldState , int newState , int flag , int error ) {
__UpdateApctlHandlers ( oldState , newState , flag , error ) ;
2013-06-17 18:50:38 -04:00
}
2013-03-24 22:41:42 +01:00
// This feels like a dubious proposition, mostly...
2013-06-17 08:43:29 -04:00
void __NetDoState ( PointerWrap & p ) {
2020-07-28 07:38:10 +07:00
auto s = p . Section ( " sceNet " , 1 , 4 ) ;
2013-09-14 20:23:03 -07:00
if ( ! s )
return ;
2019-12-24 00:04:03 +07:00
auto cur_netInited = netInited ;
auto cur_netInetInited = netInetInited ;
auto cur_netApctlInited = netApctlInited ;
2020-08-09 21:20:42 -07:00
Do ( p , netInited ) ;
Do ( p , netInetInited ) ;
Do ( p , netApctlInited ) ;
Do ( p , apctlHandlers ) ;
Do ( p , netMallocStat ) ;
2016-02-21 07:33:06 +08:00
if ( s < 2 ) {
netDropRate = 0 ;
netDropDuration = 0 ;
} else {
2020-08-09 21:20:42 -07:00
Do ( p , netDropRate ) ;
Do ( p , netDropDuration ) ;
2016-02-21 07:33:06 +08:00
}
2019-08-18 11:53:39 -07:00
if ( s < 3 ) {
netPoolAddr = 0 ;
netThread1Addr = 0 ;
netThread2Addr = 0 ;
} else {
2020-08-09 21:20:42 -07:00
Do ( p , netPoolAddr ) ;
Do ( p , netThread1Addr ) ;
Do ( p , netThread2Addr ) ;
2019-08-18 11:53:39 -07:00
}
2020-07-28 07:38:10 +07:00
if ( s > = 4 ) {
2020-08-09 21:20:42 -07:00
Do ( p , netApctlState ) ;
Do ( p , netApctlInfo ) ;
Do ( p , actionAfterApctlMipsCall ) ;
2020-07-28 07:38:10 +07:00
__KernelRestoreActionType ( actionAfterApctlMipsCall , AfterApctlMipsCall : : Create ) ;
2020-08-09 21:20:42 -07:00
Do ( p , apctlThreadHackAddr ) ;
Do ( p , apctlThreadID ) ;
2020-08-02 12:57:27 +07:00
}
else {
2020-08-02 14:02:49 +07:00
actionAfterApctlMipsCall = - 1 ;
2020-08-02 12:57:27 +07:00
apctlThreadHackAddr = 0 ;
apctlThreadID = 0 ;
2020-07-28 07:38:10 +07:00
}
2019-12-24 00:04:03 +07:00
// Let's not change "Inited" value when Loading SaveState in the middle of multiplayer to prevent memory & port leaks
if ( p . mode = = p . MODE_READ ) {
netApctlInited = cur_netApctlInited ;
netInetInited = cur_netInetInited ;
netInited = cur_netInited ;
2020-07-28 07:38:10 +07:00
// Previously, this wasn't being saved. It needs its own space.
2020-08-02 12:57:27 +07:00
if ( ! apctlThreadHackAddr | | ( apctlThreadHackAddr & & strcmp ( " apctlThreadHack " , kernelMemory . GetBlockTag ( apctlThreadHackAddr ) ) ! = 0 ) ) {
2020-07-28 07:38:10 +07:00
u32 blockSize = sizeof ( apctlThreadCode ) ;
apctlThreadHackAddr = kernelMemory . Alloc ( blockSize , false , " apctlThreadHack " ) ;
}
// Restore Apctl Loop MIPS code to prevent crashes after loading from SaveState
if ( apctlThreadHackAddr ) Memory : : Memcpy ( apctlThreadHackAddr , apctlThreadCode , sizeof ( apctlThreadCode ) ) ;
2019-12-24 00:04:03 +07:00
}
2019-08-18 11:53:39 -07:00
}
2020-07-27 09:51:53 +07:00
template < typename I > std : : string num2hex ( I w , size_t hex_len ) {
static const char * digits = " 0123456789ABCDEF " ;
std : : string rc ( hex_len , ' 0 ' ) ;
for ( size_t i = 0 , j = ( hex_len - 1 ) * 4 ; i < hex_len ; + + i , j - = 4 )
rc [ i ] = digits [ ( w > > j ) & 0x0f ] ;
return rc ;
}
std : : string error2str ( u32 errorCode ) {
std : : string str = " " ;
if ( ( ( errorCode > > 31 ) & 1 ) ! = 0 )
str + = " ERROR " ;
if ( ( ( errorCode > > 30 ) & 1 ) ! = 0 )
str + = " CRITICAL " ;
switch ( ( errorCode > > 16 ) & 0xfff ) {
case 0x41 :
str + = " NET " ;
break ;
default :
str + = " UNK " + num2hex ( u16 ( ( errorCode > > 16 ) & 0xfff ) , 3 ) + " " ;
}
switch ( ( errorCode > > 8 ) & 0xff ) {
case 0x00 :
str + = " COMMON " ;
break ;
case 0x01 :
str + = " CORE " ;
break ;
case 0x02 :
str + = " INET " ;
break ;
case 0x03 :
str + = " POECLIENT " ;
break ;
case 0x04 :
str + = " RESOLVER " ;
break ;
case 0x05 :
str + = " DHCP " ;
break ;
case 0x06 :
str + = " ADHOC_AUTH " ;
break ;
case 0x07 :
str + = " ADHOC " ;
break ;
case 0x08 :
str + = " ADHOC_MATCHING " ;
break ;
case 0x09 :
str + = " NETCNF " ;
break ;
case 0x0a :
str + = " APCTL " ;
break ;
case 0x0b :
str + = " ADHOCCTL " ;
break ;
case 0x0c :
str + = " UNKNOWN1 " ;
break ;
case 0x0d :
str + = " WLAN " ;
break ;
case 0x0e :
str + = " EAPOL " ;
break ;
case 0x0f :
str + = " 8021x " ;
break ;
case 0x10 :
str + = " WPA " ;
break ;
case 0x11 :
str + = " UNKNOWN2 " ;
break ;
case 0x12 :
str + = " TRANSFER " ;
break ;
case 0x13 :
str + = " ADHOC_DISCOVER " ;
break ;
case 0x14 :
str + = " ADHOC_DIALOG " ;
break ;
case 0x15 :
str + = " WISPR " ;
break ;
default :
str + = " UNKNOWN " + num2hex ( u8 ( ( errorCode > > 8 ) & 0xff ) ) + " " ;
}
str + = num2hex ( u8 ( errorCode & 0xff ) ) ;
return str ;
}
2020-07-28 07:38:10 +07:00
void __NetApctlCallbacks ( )
{
std : : lock_guard < std : : recursive_mutex > apctlGuard ( apctlEvtMtx ) ;
int delayus = 10000 ;
// How AP works probably like this: Game use sceNetApctl function -> sceNetApctl let the hardware know and do their's thing and have a new State -> Let the game know the resulting State through Event on their handler
if ( ! apctlEvents . empty ( ) )
{
auto args = apctlEvents . front ( ) ;
auto oldState = & args . data [ 0 ] ;
auto newState = & args . data [ 1 ] ;
auto event = & args . data [ 2 ] ;
auto error = & args . data [ 3 ] ;
apctlEvents . pop_front ( ) ;
// Adjust delay according to current event. Added an extra delay to prevent I/O Timing method from causing disconnection
2020-08-12 17:57:11 +07:00
if ( * event = = PSP_NET_APCTL_EVENT_CONNECT_REQUEST | | * event = = PSP_NET_APCTL_EVENT_GET_IP | | * event = = PSP_NET_APCTL_EVENT_SCAN_REQUEST )
2020-07-28 07:38:10 +07:00
delayus = ( adhocEventDelayMS + 2 * adhocExtraPollDelayMS ) * 1000 ;
else
delayus = ( adhocEventPollDelayMS + 2 * adhocExtraPollDelayMS ) * 1000 ;
// Do we need to change the oldState? even if there was error?
//if (*error == 0)
* oldState = netApctlState ;
// Need to make sure netApctlState is updated before calling the callback's mipscall so the game can GetState()/GetInfo() within their handler's subroutine and make use the new State/Info
// Should we update NewState & Error accordingly to Event before executing the mipscall ? sceNetApctl* functions might want to set the error value tho, so we probably should leave it untouched
//*error = 0;
switch ( * event ) {
case PSP_NET_APCTL_EVENT_CONNECT_REQUEST :
netApctlState = PSP_NET_APCTL_STATE_JOINING ; // Should we set the State to PSP_NET_APCTL_STATE_DISCONNECTED if there was error?
if ( * error = = 0 ) apctlEvents . push_front ( { netApctlState , netApctlState , PSP_NET_APCTL_EVENT_ESTABLISHED , 0 } ) ; // Should we use PSP_NET_APCTL_EVENT_EAP_AUTH if securityType is not NONE?
break ;
case PSP_NET_APCTL_EVENT_ESTABLISHED :
netApctlState = PSP_NET_APCTL_STATE_GETTING_IP ;
if ( * error = = 0 ) apctlEvents . push_front ( { netApctlState , netApctlState , PSP_NET_APCTL_EVENT_GET_IP , 0 } ) ;
break ;
case PSP_NET_APCTL_EVENT_GET_IP :
netApctlState = PSP_NET_APCTL_STATE_GOT_IP ;
NetApctl_InitInfo ( ) ;
break ;
case PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST :
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED ;
break ;
case PSP_NET_APCTL_EVENT_SCAN_REQUEST :
netApctlState = PSP_NET_APCTL_STATE_SCANNING ;
if ( * error = = 0 ) apctlEvents . push_front ( { netApctlState , netApctlState , PSP_NET_APCTL_EVENT_SCAN_COMPLETE , 0 } ) ;
break ;
case PSP_NET_APCTL_EVENT_SCAN_COMPLETE :
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED ;
break ;
case PSP_NET_APCTL_EVENT_EAP_AUTH : // Is this suppose to happen between JOINING and ESTABLISHED ?
netApctlState = PSP_NET_APCTL_STATE_EAP_AUTH ;
if ( * error = = 0 ) apctlEvents . push_front ( { netApctlState , netApctlState , PSP_NET_APCTL_EVENT_KEY_EXCHANGE , 0 } ) ; // not sure if KEY_EXCHANGE is the next step after AUTH or not tho
break ;
case PSP_NET_APCTL_EVENT_KEY_EXCHANGE : // Is this suppose to happen between JOINING and ESTABLISHED ?
netApctlState = PSP_NET_APCTL_STATE_KEY_EXCHANGE ;
if ( * error = = 0 ) apctlEvents . push_front ( { netApctlState , netApctlState , PSP_NET_APCTL_EVENT_ESTABLISHED , 0 } ) ;
break ;
case PSP_NET_APCTL_EVENT_RECONNECT :
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED ;
if ( * error = = 0 ) apctlEvents . push_front ( { netApctlState , netApctlState , PSP_NET_APCTL_EVENT_CONNECT_REQUEST , 0 } ) ;
break ;
}
// Do we need to change the newState? even if there were error?
//if (*error == 0)
* newState = netApctlState ;
2020-08-02 14:02:49 +07:00
// Since 0 is a valid index to types_ we use -1 to detects if it was loaded from an old save state
if ( actionAfterApctlMipsCall < 0 ) {
actionAfterApctlMipsCall = __KernelRegisterActionType ( AfterApctlMipsCall : : Create ) ;
}
2020-07-28 07:38:10 +07:00
// Run mipscall. Should we skipped executing the mipscall if oldState == newState?
for ( std : : map < int , ApctlHandler > : : iterator it = apctlHandlers . begin ( ) ; it ! = apctlHandlers . end ( ) ; + + it ) {
DEBUG_LOG ( SCENET , " ApctlCallback [ID=%i][OldState=%d][NewState=%d][Event=%d][Error=%d][ArgsPtr=%08x] " , it - > first , * oldState , * newState , * event , * error , it - > second . argument ) ;
args . data [ 4 ] = it - > second . argument ;
AfterApctlMipsCall * after = ( AfterApctlMipsCall * ) __KernelCreateAction ( actionAfterApctlMipsCall ) ;
after - > SetData ( it - > first , * oldState , * newState , * event , * error , it - > second . argument ) ;
hleEnqueueCall ( it - > second . entryPoint , 5 , args . data , after ) ;
}
}
2020-08-12 20:28:14 +07:00
// We are temporarily borrowing APctl thread for NpAuth callbacks for testing to simulate authentication
if ( ! npAuthEvents . empty ( ) )
{
auto args = npAuthEvents . front ( ) ;
auto id = & args . data [ 0 ] ;
auto result = & args . data [ 1 ] ;
auto argAddr = & args . data [ 2 ] ;
npAuthEvents . pop_front ( ) ;
delayus = ( adhocEventDelayMS + 2 * adhocExtraPollDelayMS ) * 1000 ;
int handlerID = * id - 1 ;
for ( std : : map < int , NpAuthHandler > : : iterator it = npAuthHandlers . begin ( ) ; it ! = npAuthHandlers . end ( ) ; + + it ) {
if ( it - > first = = handlerID ) {
DEBUG_LOG ( SCENET , " NpAuthCallback [HandlerID=%i][RequestID=%d][Result=%d][ArgsPtr=%08x] " , it - > first , * id , * result , it - > second . argument ) ;
// TODO: Update result / args.data[1] with the actual ticket length (or error code?)
hleEnqueueCall ( it - > second . entryPoint , 3 , args . data ) ;
}
}
}
2020-07-28 07:38:10 +07:00
// Must be delayed long enough whenever there is a pending callback.
hleDelayResult ( 0 , " Prevent Apctl thread from blocking " , delayus ) ;
}
2019-08-18 11:53:39 -07:00
static inline u32 AllocUser ( u32 size , bool fromTop , const char * name ) {
2020-04-05 07:01:45 -07:00
u32 addr = userMemory . Alloc ( size , fromTop , name ) ;
2019-08-18 11:53:39 -07:00
if ( addr = = - 1 )
return 0 ;
return addr ;
}
static inline void FreeUser ( u32 & addr ) {
if ( addr ! = 0 )
userMemory . Free ( addr ) ;
addr = 0 ;
2013-03-24 22:41:42 +01:00
}
2020-03-26 16:10:50 +07:00
u32 Net_Term ( ) {
2019-12-24 00:04:03 +07:00
// May also need to Terminate netAdhocctl and netAdhoc to free some resources & threads, since the game (ie. GTA:VCS, Wipeout Pulse, etc) might not called them before calling sceNetTerm and causing them to behave strangely on the next sceNetInit & sceNetAdhocInit
2020-03-26 16:10:50 +07:00
NetAdhocctl_Term ( ) ;
NetAdhoc_Term ( ) ;
2014-06-24 23:43:03 +07:00
2020-03-26 16:10:50 +07:00
// TODO: Not implemented yet
2020-07-28 07:38:10 +07:00
NetApctl_Term ( ) ;
2020-03-26 16:10:50 +07:00
//NetInet_Term();
2019-12-24 00:04:03 +07:00
// Library is initialized
if ( netInited ) {
// Delete PDP Sockets
deleteAllPDP ( ) ;
// Delete PTP Sockets
deleteAllPTP ( ) ;
// Delete GameMode Buffer
//deleteAllGMB();
// Terminate Internet Library
//sceNetInetTerm();
// Unload Internet Modules (Just keep it in memory... unloading crashes?!)
// if (_manage_modules != 0) sceUtilityUnloadModule(PSP_MODULE_NET_INET);
// Library shutdown
}
2019-08-18 11:53:39 -07:00
FreeUser ( netPoolAddr ) ;
FreeUser ( netThread1Addr ) ;
FreeUser ( netThread2Addr ) ;
2020-03-26 16:10:50 +07:00
netInited = false ;
2014-08-01 01:55:42 +07:00
2014-06-24 23:43:03 +07:00
return 0 ;
}
2020-03-26 16:10:50 +07:00
static u32 sceNetTerm ( ) {
WARN_LOG ( SCENET , " sceNetTerm() " ) ;
int retval = Net_Term ( ) ;
// Give time to make sure everything are cleaned up
hleDelayResult ( retval , " give time to init/cleanup " , adhocEventDelayMS * 1000 ) ;
return retval ;
}
2019-12-24 00:04:03 +07:00
/*
Parameters :
poolsize - Memory pool size ( appears to be for the whole of the networking library ) .
calloutprio - Priority of the SceNetCallout thread .
calloutstack - Stack size of the SceNetCallout thread ( defaults to 4096 on non 1.5 firmware regardless of what value is passed ) .
netintrprio - Priority of the SceNetNetintr thread .
netintrstack - Stack size of the SceNetNetintr thread ( defaults to 4096 on non 1.5 firmware regardless of what value is passed ) .
*/
2020-02-10 13:35:11 +07:00
static int sceNetInit ( u32 poolSize , u32 calloutPri , u32 calloutStack , u32 netinitPri , u32 netinitStack ) {
2019-12-24 00:04:03 +07:00
// TODO: Create Network Threads using given priority & stack
2019-08-18 11:53:39 -07:00
// TODO: The correct behavior is actually to allocate more and leak the other threads/pool.
// But we reset here for historic reasons (GTA:VCS potentially triggers this.)
if ( netInited )
2020-05-04 21:44:40 +07:00
Net_Term ( ) ; // This cleanup attempt might not worked when SaveState were loaded in the middle of multiplayer game and re-entering multiplayer, thus causing memory leaks & wasting binded ports. May be we shouldn't save/load "Inited" vars on SaveState?
2014-06-24 23:43:03 +07:00
2019-08-18 11:53:39 -07:00
if ( poolSize = = 0 ) {
return hleLogError ( SCENET , SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE , " invalid pool size " ) ;
} else if ( calloutPri < 0x08 | | calloutPri > 0x77 ) {
return hleLogError ( SCENET , SCE_KERNEL_ERROR_ILLEGAL_PRIORITY , " invalid callout thread priority " ) ;
} else if ( netinitPri < 0x08 | | netinitPri > 0x77 ) {
return hleLogError ( SCENET , SCE_KERNEL_ERROR_ILLEGAL_PRIORITY , " invalid init thread priority " ) ;
}
// TODO: Should also start the threads, probably? For now, let's just allocate.
// TODO: Respect the stack size if firmware set to 1.50?
u32 stackSize = 4096 ;
netThread1Addr = AllocUser ( stackSize , true , " netstack1 " ) ;
if ( netThread1Addr = = 0 ) {
return hleLogError ( SCENET , SCE_KERNEL_ERROR_NO_MEMORY , " unable to allocate thread " ) ;
}
netThread2Addr = AllocUser ( stackSize , true , " netstack2 " ) ;
if ( netThread2Addr = = 0 ) {
FreeUser ( netThread1Addr ) ;
return hleLogError ( SCENET , SCE_KERNEL_ERROR_NO_MEMORY , " unable to allocate thread " ) ;
}
netPoolAddr = AllocUser ( poolSize , false , " netpool " ) ;
if ( netPoolAddr = = 0 ) {
FreeUser ( netThread1Addr ) ;
FreeUser ( netThread2Addr ) ;
return hleLogError ( SCENET , SCE_KERNEL_ERROR_NO_MEMORY , " unable to allocate pool " ) ;
}
2015-01-04 12:20:49 +01:00
WARN_LOG ( SCENET , " sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d) at %08x " , poolSize , calloutPri , calloutStack , netinitPri , netinitStack , currentMIPS - > pc ) ;
2013-03-24 22:41:42 +01:00
netInited = true ;
2019-12-24 00:04:03 +07:00
netMallocStat . pool = poolSize ; // This should be the poolSize isn't?
netMallocStat . maximum = poolSize / 2 ; // According to JPCSP's sceNetGetMallocStat this is Currently Used size = (poolSize - free), faked to half the pool
netMallocStat . free = poolSize - netMallocStat . maximum ;
// Clear Socket Translator Memory
memset ( & pdp , 0 , sizeof ( pdp ) ) ;
memset ( & ptp , 0 , sizeof ( ptp ) ) ;
2014-08-01 01:55:42 +07:00
2019-08-18 11:53:39 -07:00
return hleLogSuccessI ( SCENET , 0 ) ;
2012-11-01 16:19:01 +01:00
}
2019-12-24 00:04:03 +07:00
// Free(delete) thread info / data.
// Normal usage: sceKernelDeleteThread followed by sceNetFreeThreadInfo with the same threadID as argument
static int sceNetFreeThreadinfo ( SceUID thid ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetFreeThreadinfo(%i) " , thid ) ;
return 0 ;
}
// Abort a thread.
static int sceNetThreadAbort ( SceUID thid ) {
ERROR_LOG ( SCENET , " UNIMPL sceNetThreadAbort(%i) " , thid ) ;
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 sceWlanGetEtherAddr ( u32 addrAddr ) {
2019-08-18 12:34:31 -07:00
if ( ! Memory : : IsValidRange ( addrAddr , 6 ) ) {
// More correctly, it should crash.
return hleLogError ( SCENET , SCE_KERNEL_ERROR_ILLEGAL_ADDR , " illegal address " ) ;
}
u8 * addr = Memory : : GetPointer ( addrAddr ) ;
2019-11-10 06:23:19 +07:00
if ( PPSSPP_ID > 1 ) {
Memory : : Memset ( addrAddr , PPSSPP_ID , 6 ) ;
}
else
2014-12-08 04:40:08 -05:00
// Read MAC Address from config
2019-08-18 12:34:31 -07:00
if ( ! ParseMacAddress ( g_Config . sMACAddress . c_str ( ) , addr ) ) {
2014-07-07 16:29:48 -04:00
ERROR_LOG ( SCENET , " Error parsing mac address %s " , g_Config . sMACAddress . c_str ( ) ) ;
2019-08-18 12:34:31 -07:00
Memory : : Memset ( addrAddr , 0 , 6 ) ;
} else {
CBreakPoints : : ExecMemCheck ( addrAddr , true , 6 , currentMIPS - > pc ) ;
2013-11-28 12:38:45 +01:00
}
2019-08-18 12:34:31 -07:00
return hleLogSuccessI ( SCENET , hleDelayResult ( 0 , " get ether mac " , 200 ) ) ;
2012-11-01 16:19:01 +01:00
}
2014-12-08 04:40:08 -05:00
static u32 sceNetGetLocalEtherAddr ( u32 addrAddr ) {
2013-10-26 15:47:52 +01:00
return sceWlanGetEtherAddr ( addrAddr ) ;
}
2014-12-08 04:40:08 -05:00
static u32 sceWlanDevIsPowerOn ( ) {
2019-08-18 12:34:31 -07:00
return hleLogSuccessVerboseI ( SCENET , g_Config . bEnableWlan ? 1 : 0 ) ;
2012-11-23 10:33:19 +01:00
}
2014-12-08 04:40:08 -05:00
static u32 sceWlanGetSwitchState ( ) {
2019-08-18 12:34:31 -07:00
return hleLogSuccessVerboseI ( SCENET , g_Config . bEnableWlan ? 1 : 0 ) ;
2012-11-01 16:19:01 +01:00
}
2013-08-29 23:47:03 -07:00
// Probably a void function, but often returns a useful value.
2020-03-19 13:46:02 +07:00
static void sceNetEtherNtostr ( u32 macPtr , u32 bufferPtr ) {
2013-09-07 21:19:21 +02:00
DEBUG_LOG ( SCENET , " sceNetEtherNtostr(%08x, %08x) " , macPtr , bufferPtr ) ;
2013-08-29 23:47:03 -07:00
if ( Memory : : IsValidAddress ( bufferPtr ) & & Memory : : IsValidAddress ( macPtr ) ) {
char * buffer = ( char * ) Memory : : GetPointer ( bufferPtr ) ;
const u8 * mac = Memory : : GetPointer ( macPtr ) ;
// MAC address is always 6 bytes / 48 bits.
2020-03-19 13:46:02 +07:00
sprintf ( buffer , " %02x:%02x:%02x:%02x:%02x:%02x " ,
2013-08-29 23:47:03 -07:00
mac [ 0 ] , mac [ 1 ] , mac [ 2 ] , mac [ 3 ] , mac [ 4 ] , mac [ 5 ] ) ;
2020-03-19 13:46:02 +07:00
VERBOSE_LOG ( SCENET , " sceNetEtherNtostr - [%s] " , buffer ) ;
2013-06-17 08:15:43 -04:00
}
2013-08-29 23:47:03 -07:00
}
2013-06-17 18:50:38 -04:00
2013-08-29 23:47:03 -07:00
static int hex_to_digit ( int c ) {
if ( c > = ' 0 ' & & c < = ' 9 ' )
return c - ' 0 ' ;
if ( c > = ' a ' & & c < = ' f ' )
return c - ' a ' + 10 ;
if ( c > = ' A ' & & c < = ' F ' )
return c - ' A ' + 10 ;
return - 1 ;
}
// Probably a void function, but sometimes returns a useful-ish value.
2020-03-19 13:46:02 +07:00
static void sceNetEtherStrton ( u32 bufferPtr , u32 macPtr ) {
2013-09-07 21:19:21 +02:00
DEBUG_LOG ( SCENET , " sceNetEtherStrton(%08x, %08x) " , bufferPtr , macPtr ) ;
2013-09-01 01:05:35 -07:00
2013-08-29 23:47:03 -07:00
if ( Memory : : IsValidAddress ( bufferPtr ) & & Memory : : IsValidAddress ( macPtr ) ) {
const char * buffer = ( char * ) Memory : : GetPointer ( bufferPtr ) ;
u8 * mac = Memory : : GetPointer ( macPtr ) ;
// MAC address is always 6 pairs of hex digits.
// TODO: Funny stuff happens if it's too short.
u8 value = 0 ;
for ( int i = 0 ; i < 6 & & * buffer ! = 0 ; + + i ) {
value = 0 ;
int c = hex_to_digit ( * buffer + + ) ;
if ( c ! = - 1 ) {
value | = c < < 4 ;
}
c = hex_to_digit ( * buffer + + ) ;
if ( c ! = - 1 ) {
value | = c ;
}
* mac + + = value ;
// Skip a single character in between.
// TODO: Strange behavior on the PSP, let's just null check.
if ( * buffer + + = = 0 ) {
break ;
}
}
2020-07-23 07:41:41 +07:00
VERBOSE_LOG ( SCENET , " sceNetEtherStrton - [%s] " , mac2str ( ( SceNetEtherAddr * ) Memory : : GetPointer ( macPtr ) ) . c_str ( ) ) ;
2013-08-29 23:47:03 -07:00
// Seems to maybe kinda return the last value. Probably returns void.
2020-03-19 13:46:02 +07:00
//return value;
2013-08-29 23:47:03 -07:00
}
2013-06-04 00:39:03 -04:00
}
2013-06-17 08:04:31 -04:00
// Write static data since we don't actually manage any memory for sceNet* yet.
2014-12-08 04:40:08 -05:00
static int sceNetGetMallocStat ( u32 statPtr ) {
2013-09-07 21:19:21 +02:00
WARN_LOG ( SCENET , " UNTESTED sceNetGetMallocStat(%x) " , statPtr ) ;
2013-06-17 08:04:31 -04:00
if ( Memory : : IsValidAddress ( statPtr ) )
Memory : : WriteStruct ( statPtr , & netMallocStat ) ;
else
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNTESTED sceNetGetMallocStat(%x): tried to request invalid address! " , statPtr ) ;
2013-06-17 08:04:31 -04:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static int sceNetInetInit ( ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetInit() " ) ;
2014-08-01 01:55:42 +07:00
if ( netInetInited ) return ERROR_NET_INET_ALREADY_INITIALIZED ;
2013-06-20 03:15:07 -04:00
netInetInited = true ;
return 0 ;
}
2019-12-24 00:04:03 +07:00
int sceNetInetTerm ( ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetTerm() " ) ;
2013-06-20 03:15:07 -04:00
netInetInited = false ;
return 0 ;
}
2020-07-28 07:38:10 +07:00
void NetApctl_InitInfo ( ) {
2020-07-27 09:51:53 +07:00
memset ( & netApctlInfo , 0 , sizeof ( netApctlInfo ) ) ;
2020-07-28 07:38:10 +07:00
// Set dummy/fake values, these probably not suppose to have valid info before connected to an AP, right?
std : : string APname = " Wifi " ; // fake AP/hotspot
truncate_cpy ( netApctlInfo . name , sizeof ( netApctlInfo . name ) , APname . c_str ( ) ) ;
truncate_cpy ( netApctlInfo . ssid , sizeof ( netApctlInfo . ssid ) , APname . c_str ( ) ) ;
memcpy ( netApctlInfo . bssid , " \1 \1 \2 \2 \3 \3 " , sizeof ( netApctlInfo . bssid ) ) ; // fake AP's mac address
netApctlInfo . ssidLength = static_cast < unsigned int > ( APname . length ( ) ) ;
2020-07-27 09:51:53 +07:00
netApctlInfo . strength = 99 ;
netApctlInfo . channel = g_Config . iWlanAdhocChannel ;
if ( netApctlInfo . channel = = PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC ) netApctlInfo . channel = defaultWlanChannel ;
// Get Local IP Address
sockaddr_in sockAddr ;
2020-07-28 07:38:10 +07:00
getLocalIp ( & sockAddr ) ; // This will be valid IP, we probably not suppose to have a valid IP before connected to any AP, right?
char ipstr [ INET_ADDRSTRLEN ] = " 127.0.0.1 " ; // Patapon 3 seems to try to get current IP using ApctlGetInfo() right after ApctlInit(), what kind of IP should we use as default before ApctlConnect()? it shouldn't be a valid IP, right?
2020-07-27 09:51:53 +07:00
inet_ntop ( AF_INET , & sockAddr . sin_addr , ipstr , sizeof ( ipstr ) ) ;
truncate_cpy ( netApctlInfo . ip , sizeof ( netApctlInfo . ip ) , ipstr ) ;
// Change the last number to 1 to indicate a common dns server/internet gateway
( ( u8 * ) & sockAddr . sin_addr . s_addr ) [ 3 ] = 1 ;
inet_ntop ( AF_INET , & sockAddr . sin_addr , ipstr , sizeof ( ipstr ) ) ;
truncate_cpy ( netApctlInfo . gateway , sizeof ( netApctlInfo . gateway ) , ipstr ) ;
truncate_cpy ( netApctlInfo . primaryDns , sizeof ( netApctlInfo . primaryDns ) , ipstr ) ;
truncate_cpy ( netApctlInfo . secondaryDns , sizeof ( netApctlInfo . secondaryDns ) , " 8.8.8.8 " ) ;
truncate_cpy ( netApctlInfo . subNetMask , sizeof ( netApctlInfo . subNetMask ) , " 255.255.255.0 " ) ;
2020-07-28 07:38:10 +07:00
}
static int sceNetApctlInit ( int stackSize , int initPriority ) {
WARN_LOG ( SCENET , " UNTESTED %s(%i, %i) " , __FUNCTION__ , stackSize , initPriority ) ;
if ( netApctlInited )
return ERROR_NET_APCTL_ALREADY_INITIALIZED ;
2020-07-27 09:51:53 +07:00
2020-07-28 07:38:10 +07:00
// Set default value before connected to an AP
memset ( & netApctlInfo , 0 , sizeof ( netApctlInfo ) ) ; // NetApctl_InitInfo();
2020-08-12 17:57:11 +07:00
std : : string APname = " Wifi " ; // fake AP/hotspot
truncate_cpy ( netApctlInfo . name , sizeof ( netApctlInfo . name ) , APname . c_str ( ) ) ;
truncate_cpy ( netApctlInfo . ssid , sizeof ( netApctlInfo . ssid ) , APname . c_str ( ) ) ;
memcpy ( netApctlInfo . bssid , " \1 \1 \2 \2 \3 \3 " , sizeof ( netApctlInfo . bssid ) ) ; // fake AP's mac address
netApctlInfo . ssidLength = static_cast < unsigned int > ( APname . length ( ) ) ;
2020-07-28 07:38:10 +07:00
truncate_cpy ( netApctlInfo . ip , sizeof ( netApctlInfo . ip ) , " 0.0.0.0 " ) ;
truncate_cpy ( netApctlInfo . gateway , sizeof ( netApctlInfo . gateway ) , " 0.0.0.0 " ) ;
truncate_cpy ( netApctlInfo . primaryDns , sizeof ( netApctlInfo . primaryDns ) , " 0.0.0.0 " ) ;
truncate_cpy ( netApctlInfo . secondaryDns , sizeof ( netApctlInfo . secondaryDns ) , " 0.0.0.0 " ) ;
truncate_cpy ( netApctlInfo . subNetMask , sizeof ( netApctlInfo . subNetMask ) , " 0.0.0.0 " ) ;
// Create APctl fake-Thread
apctlThreadID = __KernelCreateThread ( " ApctlThread " , __KernelGetCurThreadModuleId ( ) , apctlThreadHackAddr , initPriority , stackSize , PSP_THREAD_ATTR_USER , 0 , true ) ;
if ( apctlThreadID > 0 ) {
__KernelStartThread ( apctlThreadID , 0 , 0 ) ;
}
2020-07-27 09:51:53 +07:00
2013-06-20 03:15:07 -04:00
netApctlInited = true ;
2020-07-28 07:38:10 +07:00
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED ;
2013-06-20 03:15:07 -04:00
return 0 ;
}
2020-07-28 07:38:10 +07:00
int NetApctl_Term ( ) {
// Cleanup Apctl resources
// Delete fake PSP Thread
if ( apctlThreadID ! = 0 ) {
__KernelStopThread ( apctlThreadID , SCE_KERNEL_ERROR_THREAD_TERMINATED , " ApctlThread stopped " ) ;
__KernelDeleteThread ( apctlThreadID , SCE_KERNEL_ERROR_THREAD_TERMINATED , " ApctlThread deleted " ) ;
apctlThreadID = 0 ;
}
2013-07-15 17:55:00 -04:00
netApctlInited = false ;
2020-07-28 07:38:10 +07:00
netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED ;
2013-06-20 03:15:07 -04:00
return 0 ;
}
2020-07-28 07:38:10 +07:00
int sceNetApctlTerm ( ) {
WARN_LOG ( SCENET , " UNTESTED %s() " , __FUNCTION__ ) ;
return NetApctl_Term ( ) ;
}
2020-07-27 09:51:53 +07:00
static int sceNetApctlGetInfo ( int code , u32 pInfoAddr ) {
WARN_LOG ( SCENET , " UNTESTED %s(%i, %08x) " , __FUNCTION__ , code , pInfoAddr ) ;
if ( ! netApctlInited )
return hleLogError ( SCENET , ERROR_NET_APCTL_NOT_IN_BSS , " apctl not in bss " ) ; // Only have valid info after joining an AP and got an IP, right?
if ( ! Memory : : IsValidAddress ( pInfoAddr ) )
return hleLogError ( SCENET , - 1 , " apctl invalid arg " ) ;
u8 * info = Memory : : GetPointer ( pInfoAddr ) ; // FIXME: Points to a union instead of a struct thus each field have the same address
switch ( code ) {
case PSP_NET_APCTL_INFO_PROFILE_NAME :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . name ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - ProfileName: %s " , netApctlInfo . name ) ;
break ;
case PSP_NET_APCTL_INFO_BSSID :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . bssid ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - BSSID: %s " , mac2str ( ( SceNetEtherAddr * ) & netApctlInfo . bssid ) . c_str ( ) ) ;
break ;
case PSP_NET_APCTL_INFO_SSID :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . ssid ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - SSID: %s " , netApctlInfo . ssid ) ;
break ;
case PSP_NET_APCTL_INFO_SSID_LENGTH :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . ssidLength ) ;
break ;
case PSP_NET_APCTL_INFO_SECURITY_TYPE :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . securityType ) ;
break ;
case PSP_NET_APCTL_INFO_STRENGTH :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . strength ) ;
break ;
case PSP_NET_APCTL_INFO_CHANNEL :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . channel ) ;
break ;
case PSP_NET_APCTL_INFO_POWER_SAVE :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . powerSave ) ;
break ;
case PSP_NET_APCTL_INFO_IP :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . ip ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - IP: %s " , netApctlInfo . ip ) ;
break ;
case PSP_NET_APCTL_INFO_SUBNETMASK :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . subNetMask ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - SubNet Mask: %s " , netApctlInfo . subNetMask ) ;
break ;
case PSP_NET_APCTL_INFO_GATEWAY :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . gateway ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - Gateway IP: %s " , netApctlInfo . gateway ) ;
break ;
case PSP_NET_APCTL_INFO_PRIMDNS :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . primaryDns ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - Primary DNS: %s " , netApctlInfo . primaryDns ) ;
break ;
case PSP_NET_APCTL_INFO_SECDNS :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . secondaryDns ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - Secondary DNS: %s " , netApctlInfo . secondaryDns ) ;
break ;
case PSP_NET_APCTL_INFO_USE_PROXY :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . useProxy ) ;
break ;
case PSP_NET_APCTL_INFO_PROXY_URL :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . proxyUrl ) ;
DEBUG_LOG ( SCENET , " ApctlInfo - Proxy URL: %s " , netApctlInfo . proxyUrl ) ;
break ;
case PSP_NET_APCTL_INFO_PROXY_PORT :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . proxyPort ) ;
break ;
case PSP_NET_APCTL_INFO_8021_EAP_TYPE :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . eapType ) ;
break ;
case PSP_NET_APCTL_INFO_START_BROWSER :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . startBrowser ) ;
break ;
case PSP_NET_APCTL_INFO_WIFISP :
Memory : : WriteStruct ( pInfoAddr , & netApctlInfo . wifisp ) ;
break ;
default :
return hleLogError ( SCENET , ERROR_NET_APCTL_INVALID_CODE , " apctl invalid code " ) ;
}
return hleLogSuccessI ( SCENET , 0 ) ;
}
2020-08-08 03:53:55 +07:00
int NetApctl_AddHandler ( u32 handlerPtr , u32 handlerArg ) {
2013-06-20 03:15:07 -04:00
bool foundHandler = false ;
2013-07-07 18:16:15 -07:00
u32 retval = 0 ;
2013-06-20 03:15:07 -04:00
struct ApctlHandler handler ;
memset ( & handler , 0 , sizeof ( handler ) ) ;
2013-07-07 18:16:15 -07:00
while ( apctlHandlers . find ( retval ) ! = apctlHandlers . end ( ) )
+ + retval ;
2013-06-20 03:15:07 -04:00
handler . entryPoint = handlerPtr ;
handler . argument = handlerArg ;
2020-08-08 03:53:55 +07:00
for ( std : : map < int , ApctlHandler > : : iterator it = apctlHandlers . begin ( ) ; it ! = apctlHandlers . end ( ) ; it + + ) {
if ( it - > second . entryPoint = = handlerPtr ) {
2013-06-20 03:15:07 -04:00
foundHandler = true ;
break ;
}
}
2020-08-08 03:53:55 +07:00
if ( ! foundHandler & & Memory : : IsValidAddress ( handlerPtr ) ) {
if ( apctlHandlers . size ( ) > = MAX_APCTL_HANDLERS ) {
ERROR_LOG ( SCENET , " Failed to Add handler(%x, %x): Too many handlers " , handlerPtr , handlerArg ) ;
2013-06-20 03:15:07 -04:00
retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS ; // TODO: What's the proper error code for Apctl's TOO_MANY_HANDLERS?
return retval ;
}
2013-07-07 18:16:15 -07:00
apctlHandlers [ retval ] = handler ;
2020-08-08 03:53:55 +07:00
WARN_LOG ( SCENET , " Added Apctl handler(%x, %x): %d " , handlerPtr , handlerArg , retval ) ;
2013-06-20 03:15:07 -04:00
}
2014-08-01 01:55:42 +07:00
else {
2020-08-08 03:53:55 +07:00
ERROR_LOG ( SCENET , " Existing Apctl handler(%x, %x) " , handlerPtr , handlerArg ) ;
2014-08-01 01:55:42 +07:00
}
2013-06-20 03:15:07 -04:00
// The id to return is the number of handlers currently registered
return retval ;
}
2020-08-08 03:53:55 +07:00
// TODO: How many handlers can the PSP actually have for Apctl?
// TODO: Should we allow the same handler to be added more than once?
static u32 sceNetApctlAddHandler ( u32 handlerPtr , u32 handlerArg ) {
INFO_LOG ( SCENET , " %s(%08x, %08x) " , __FUNCTION__ , handlerPtr , handlerArg ) ;
return NetApctl_AddHandler ( handlerPtr , handlerArg ) ;
}
int NetApctl_DelHandler ( u32 handlerID ) {
if ( apctlHandlers . find ( handlerID ) ! = apctlHandlers . end ( ) ) {
2013-06-20 03:15:07 -04:00
apctlHandlers . erase ( handlerID ) ;
2020-08-08 03:53:55 +07:00
WARN_LOG ( SCENET , " Deleted Apctl handler: %d " , handlerID ) ;
2013-06-20 03:15:07 -04:00
}
2014-08-01 01:55:42 +07:00
else {
2020-08-08 03:53:55 +07:00
ERROR_LOG ( SCENET , " Invalid Apctl handler: %d " , handlerID ) ;
2014-08-01 01:55:42 +07:00
}
2013-06-20 03:15:07 -04:00
return 0 ;
}
2020-08-08 03:53:55 +07:00
static int sceNetApctlDelHandler ( u32 handlerID ) {
INFO_LOG ( SCENET , " %s(%d) " , __FUNCTION__ , handlerID ) ;
return NetApctl_DelHandler ( handlerID ) ;
}
2014-12-08 04:40:08 -05:00
static int sceNetInetInetAton ( const char * hostname , u32 addrPtr ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetInetAton(%s, %08x) " , hostname , addrPtr ) ;
2013-07-08 22:40:16 +02:00
return - 1 ;
}
2015-01-04 02:34:52 +01:00
int sceNetInetPoll ( void * fds , u32 nfds , int timeout ) { // timeout in miliseconds
2014-08-01 01:55:42 +07:00
DEBUG_LOG ( SCENET , " UNTESTED sceNetInetPoll(%p, %d, %i) at %08x " , fds , nfds , timeout , currentMIPS - > pc ) ;
int retval = - 1 ;
SceNetInetPollfd * fdarray = ( SceNetInetPollfd * ) fds ; // SceNetInetPollfd/pollfd, sceNetInetPoll() have similarity to BSD poll() but pollfd have different size on 64bit
2019-11-10 06:23:19 +07:00
//#ifdef _WIN32
2014-08-01 01:55:42 +07:00
//WSAPoll only available for Vista or newer, so we'll use an alternative way for XP since Windows doesn't have poll function like *NIX
if ( nfds > FD_SETSIZE ) return - 1 ;
fd_set readfds , writefds , exceptfds ;
FD_ZERO ( & readfds ) ; FD_ZERO ( & writefds ) ; FD_ZERO ( & exceptfds ) ;
for ( int i = 0 ; i < ( s32 ) nfds ; i + + ) {
if ( fdarray [ i ] . events & ( INET_POLLRDNORM ) ) FD_SET ( fdarray [ i ] . fd , & readfds ) ; // (POLLRDNORM | POLLIN)
if ( fdarray [ i ] . events & ( INET_POLLWRNORM ) ) FD_SET ( fdarray [ i ] . fd , & writefds ) ; // (POLLWRNORM | POLLOUT)
//if (fdarray[i].events & (ADHOC_EV_ALERT)) // (POLLRDBAND | POLLPRI) // POLLERR
FD_SET ( fdarray [ i ] . fd , & exceptfds ) ;
fdarray [ i ] . revents = 0 ;
}
timeval tmout ;
tmout . tv_sec = timeout / 1000 ; // seconds
tmout . tv_usec = ( timeout % 1000 ) * 1000 ; // microseconds
retval = select ( nfds , & readfds , & writefds , & exceptfds , & tmout ) ;
if ( retval < 0 ) return - 1 ;
retval = 0 ;
for ( int i = 0 ; i < ( s32 ) nfds ; i + + ) {
if ( FD_ISSET ( fdarray [ i ] . fd , & readfds ) ) fdarray [ i ] . revents | = INET_POLLRDNORM ; //POLLIN
if ( FD_ISSET ( fdarray [ i ] . fd , & writefds ) ) fdarray [ i ] . revents | = INET_POLLWRNORM ; //POLLOUT
fdarray [ i ] . revents & = fdarray [ i ] . events ;
if ( FD_ISSET ( fdarray [ i ] . fd , & exceptfds ) ) fdarray [ i ] . revents | = ADHOC_EV_ALERT ; // POLLPRI; // POLLERR; // can be raised on revents regardless of events bitmask?
if ( fdarray [ i ] . revents ) retval + + ;
}
//#else
/*
// Doesn't work properly yet
pollfd * fdtmp = ( pollfd * ) malloc ( sizeof ( pollfd ) * nfds ) ;
// Note: sizeof(pollfd) = 16bytes in 64bit and 8bytes in 32bit, while sizeof(SceNetInetPollfd) is always 8bytes
for ( int i = 0 ; i < ( s32 ) nfds ; i + + ) {
fdtmp [ i ] . fd = fdarray [ i ] . fd ;
fdtmp [ i ] . events = 0 ;
if ( fdarray [ i ] . events & INET_POLLRDNORM ) fdtmp [ i ] . events | = ( POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI ) ;
if ( fdarray [ i ] . events & INET_POLLWRNORM ) fdtmp [ i ] . events | = ( POLLOUT | POLLWRNORM | POLLWRBAND ) ;
fdtmp [ i ] . revents = 0 ;
fdarray [ i ] . revents = 0 ;
}
retval = poll ( fdtmp , ( nfds_t ) nfds , timeout ) ; //retval = WSAPoll(fdarray, nfds, timeout);
for ( int i = 0 ; i < ( s32 ) nfds ; i + + ) {
if ( fdtmp [ i ] . revents & ( POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI ) ) fdarray [ i ] . revents | = INET_POLLRDNORM ;
if ( fdtmp [ i ] . revents & ( POLLOUT | POLLWRNORM | POLLWRBAND ) ) fdarray [ i ] . revents | = INET_POLLWRNORM ;
fdarray [ i ] . revents & = fdarray [ i ] . events ;
if ( fdtmp [ i ] . revents & POLLERR ) fdarray [ i ] . revents | = POLLERR ; //INET_POLLERR // can be raised on revents regardless of events bitmask?
}
free ( fdtmp ) ;
*/
//#endif
return retval ;
}
2014-12-08 04:40:08 -05:00
static int sceNetInetRecv ( int socket , u32 bufPtr , u32 bufLen , u32 flags ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetRecv(%i, %08x, %i, %08x) " , socket , bufPtr , bufLen , flags ) ;
2013-07-08 22:40:16 +02:00
return - 1 ;
}
2014-12-08 04:40:08 -05:00
static int sceNetInetSend ( int socket , u32 bufPtr , u32 bufLen , u32 flags ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetSend(%i, %08x, %i, %08x) " , socket , bufPtr , bufLen , flags ) ;
2013-07-08 22:40:16 +02:00
return - 1 ;
}
2013-06-20 03:15:07 -04:00
2014-12-08 04:40:08 -05:00
static int sceNetInetGetErrno ( ) {
2014-08-01 01:55:42 +07:00
ERROR_LOG ( SCENET , " UNTESTED sceNetInetGetErrno() " ) ;
int error = errno ;
switch ( error ) {
case ETIMEDOUT :
return INET_ETIMEDOUT ;
case EISCONN :
return INET_EISCONN ;
case EINPROGRESS :
return INET_EINPROGRESS ;
//case EAGAIN:
// return INET_EAGAIN;
}
return error ; //-1;
2013-07-08 22:40:16 +02:00
}
2014-12-08 04:40:08 -05:00
static int sceNetInetSocket ( int domain , int type , int protocol ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetSocket(%i, %i, %i) " , domain , type , protocol ) ;
2013-07-08 22:40:16 +02:00
return - 1 ;
}
2014-12-08 04:40:08 -05:00
static int sceNetInetSetsockopt ( int socket , int level , int optname , u32 optvalPtr , int optlen ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetSetsockopt(%i, %i, %i, %08x, %i) " , socket , level , optname , optvalPtr , optlen ) ;
2013-07-08 22:40:16 +02:00
return - 1 ;
}
2014-12-08 04:40:08 -05:00
static int sceNetInetConnect ( int socket , u32 sockAddrInternetPtr , int addressLength ) {
2013-09-07 21:19:21 +02:00
ERROR_LOG ( SCENET , " UNIMPL sceNetInetConnect(%i, %08x, %i) " , socket , sockAddrInternetPtr , addressLength ) ;
2013-07-08 22:40:16 +02:00
return - 1 ;
}
2013-06-20 03:15:07 -04:00
2020-08-08 03:53:55 +07:00
int sceNetApctlConnect ( int connIndex ) {
2020-08-12 17:57:11 +07:00
WARN_LOG ( SCENET , " UNTESTED %s(%i) " , __FUNCTION__ , connIndex ) ;
2020-07-28 07:38:10 +07:00
// Is this connIndex is the index to the scanning's result data or sceNetApctlGetBSSDescIDListUser result?
2020-07-27 09:51:53 +07:00
__UpdateApctlHandlers ( 0 , 0 , PSP_NET_APCTL_EVENT_CONNECT_REQUEST , 0 ) ;
2020-08-12 17:57:11 +07:00
//hleDelayResult(0, "give time to init/cleanup", adhocEventDelayMS * 1000);
2020-07-27 09:51:53 +07:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static int sceNetApctlDisconnect ( ) {
2014-01-31 19:08:52 -05:00
ERROR_LOG ( SCENET , " UNIMPL %s() " , __FUNCTION__ ) ;
// Like its 'sister' function sceNetAdhocctlDisconnect, we need to alert Apctl handlers that a disconnect took place
2014-01-31 23:16:39 -05:00
// or else games like Phantasy Star Portable 2 will hang at certain points (e.g. returning to the main menu after trying to connect to PSN).
2020-07-28 07:38:10 +07:00
2014-01-31 19:08:52 -05:00
__UpdateApctlHandlers ( 0 , 0 , PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST , 0 ) ;
return 0 ;
}
2020-08-08 03:53:55 +07:00
int NetApctl_GetState ( ) {
return netApctlState ;
}
2020-07-27 09:51:53 +07:00
static int sceNetApctlGetState ( u32 pStateAddr ) {
//if (!netApctlInited) return hleLogError(SCENET, ERROR_NET_APCTL_NOT_IN_BSS, "apctl not in bss");
// Valid Arguments
if ( Memory : : IsValidAddress ( pStateAddr ) ) {
// Return Thread Status
2020-08-08 03:53:55 +07:00
Memory : : Write_U32 ( NetApctl_GetState ( ) , pStateAddr ) ;
2020-07-27 09:51:53 +07:00
// Return Success
return hleLogSuccessI ( SCENET , 0 ) ;
}
return hleLogError ( SCENET , - 1 , " apctl invalid arg " ) ;
}
2020-08-08 03:53:55 +07:00
int NetApctl_ScanUser ( ) {
2020-07-27 09:51:53 +07:00
// Scan probably only works when not in connected state, right?
2020-07-28 07:38:10 +07:00
if ( netApctlState ! = PSP_NET_APCTL_STATE_DISCONNECTED )
2020-07-27 09:51:53 +07:00
return hleLogError ( SCENET , ERROR_NET_APCTL_NOT_DISCONNECTED , " apctl not disconnected " ) ;
__UpdateApctlHandlers ( 0 , 0 , PSP_NET_APCTL_EVENT_SCAN_REQUEST , 0 ) ;
return 0 ;
}
2020-08-08 03:53:55 +07:00
static int sceNetApctlScanUser ( ) {
ERROR_LOG ( SCENET , " UNIMPL %s() " , __FUNCTION__ ) ;
return NetApctl_ScanUser ( ) ;
}
2020-07-27 09:51:53 +07:00
static int sceNetApctlGetBSSDescIDListUser ( u32 sizeAddr , u32 bufAddr ) {
WARN_LOG ( SCENET , " UNTESTED %s(%08x, %08x) " , __FUNCTION__ , sizeAddr , bufAddr ) ;
const int userInfoSize = 8 ;
int entries = 1 ;
if ( ! Memory : : IsValidAddress ( sizeAddr ) )
hleLogError ( SCENET , - 1 , " apctl invalid arg " ) ;
int size = Memory : : Read_U32 ( sizeAddr ) ;
// Return size required
Memory : : Write_U32 ( entries * userInfoSize , sizeAddr ) ;
if ( bufAddr ! = 0 & & Memory : : IsValidAddress ( sizeAddr ) ) {
int offset = 0 ;
for ( int i = 0 ; i < entries ; i + + ) {
// Check if enough space available to write the next structure
if ( offset + userInfoSize > size ) {
break ;
}
DEBUG_LOG ( SCENET , " %s returning %d at %08x " , __FUNCTION__ , i , bufAddr + offset ) ;
// Pointer to next Network structure in list
Memory : : Write_U32 ( ( i + 1 ) * userInfoSize + bufAddr , bufAddr + offset ) ;
offset + = 4 ;
// Entry ID
Memory : : Write_U32 ( i , bufAddr + offset ) ;
offset + = 4 ;
}
// Fix the last Pointer
if ( offset > 0 )
Memory : : Write_U32 ( 0 , bufAddr + offset - userInfoSize ) ;
}
return hleLogWarning ( SCENET , 0 , " untested " ) ;
}
static int sceNetApctlGetBSSDescEntryUser ( int entryId , int infoId , u32 resultAddr ) {
WARN_LOG ( SCENET , " UNTESTED %s(%i, %i, %08x) " , __FUNCTION__ , entryId , infoId , resultAddr ) ;
if ( ! Memory : : IsValidAddress ( resultAddr ) )
hleLogError ( SCENET , - 1 , " apctl invalid arg " ) ;
switch ( infoId ) {
case PSP_NET_APCTL_DESC_IBSS : // IBSS, 6 bytes
Memory : : WriteStruct ( resultAddr , & netApctlInfo . bssid ) ;
break ;
case PSP_NET_APCTL_DESC_SSID_NAME :
// Return 32 bytes
Memory : : WriteStruct ( resultAddr , & netApctlInfo . ssid ) ;
break ;
case PSP_NET_APCTL_DESC_SSID_NAME_LENGTH :
// Return one 32-bit value
Memory : : WriteStruct ( resultAddr , & netApctlInfo . ssidLength ) ;
break ;
case PSP_NET_APCTL_DESC_SIGNAL_STRENGTH :
// Return 1 byte
Memory : : WriteStruct ( resultAddr , & netApctlInfo . strength ) ;
break ;
case PSP_NET_APCTL_DESC_SECURITY :
// Return one 32-bit value
Memory : : WriteStruct ( resultAddr , & netApctlInfo . securityType ) ;
break ;
default :
return hleLogError ( SCENET , ERROR_NET_APCTL_INVALID_CODE , " unknown info id " ) ;
}
return hleLogWarning ( SCENET , 0 , " untested " ) ;
}
static int sceNetApctlScanSSID2 ( ) {
ERROR_LOG ( SCENET , " UNIMPL %s() " , __FUNCTION__ ) ;
2020-08-08 03:53:55 +07:00
return NetApctl_ScanUser ( ) ;
2020-07-27 09:51:53 +07:00
}
static int sceNetApctlGetBSSDescIDList2 ( u32 Arg1 , u32 Arg2 , u32 Arg3 , u32 Arg4 ) {
return hleLogError ( SCENET , 0 , " unimplemented " ) ;
}
static int sceNetApctlGetBSSDescEntry2 ( u32 Arg1 , u32 Arg2 , u32 Arg3 , u32 Arg4 ) {
return hleLogError ( SCENET , 0 , " unimplemented " ) ;
}
2014-12-08 04:40:08 -05:00
static int sceNetResolverInit ( )
2014-09-02 15:40:42 -04:00
{
ERROR_LOG ( SCENET , " UNIMPL %s() " , __FUNCTION__ ) ;
return 0 ;
}
2020-07-27 09:51:53 +07:00
static int sceNetApctlAddInternalHandler ( u32 handlerPtr , u32 handlerArg ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%08x, %08x) " , __FUNCTION__ , handlerPtr , handlerArg ) ;
// This seems to be a 2nd kind of handler
2020-08-08 03:53:55 +07:00
return NetApctl_AddHandler ( handlerPtr , handlerArg ) ;
2020-07-27 09:51:53 +07:00
}
static int sceNetApctlDelInternalHandler ( u32 handlerID ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%i) " , __FUNCTION__ , handlerID ) ;
// This seems to be a 2nd kind of handler
2020-08-08 03:53:55 +07:00
return NetApctl_DelHandler ( handlerID ) ;
2020-07-27 09:51:53 +07:00
}
static int sceNetApctl_A7BB73DF ( u32 handlerPtr , u32 handlerArg ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%08x, %08x) " , __FUNCTION__ , handlerPtr , handlerArg ) ;
// This seems to be a 3rd kind of handler
return sceNetApctlAddHandler ( handlerPtr , handlerArg ) ;
}
static int sceNetApctl_6F5D2981 ( u32 handlerID ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%i) " , __FUNCTION__ , handlerID ) ;
// This seems to be a 3rd kind of handler
return sceNetApctlDelHandler ( handlerID ) ;
}
static int sceNetApctl_lib2_69745F0A ( int handlerId ) {
return hleLogError ( SCENET , 0 , " unimplemented " ) ;
}
static int sceNetApctl_lib2_4C19731F ( int code , u32 pInfoAddr ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%i, %08x) " , __FUNCTION__ , code , pInfoAddr ) ;
return sceNetApctlGetInfo ( code , pInfoAddr ) ;
}
static int sceNetApctlScan ( ) {
ERROR_LOG ( SCENET , " UNIMPL %s() " , __FUNCTION__ ) ;
2020-08-08 03:53:55 +07:00
return NetApctl_ScanUser ( ) ;
2020-07-27 09:51:53 +07:00
}
static int sceNetApctlGetBSSDescIDList ( u32 sizeAddr , u32 bufAddr ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%08x, %08x) " , __FUNCTION__ , sizeAddr , bufAddr ) ;
return sceNetApctlGetBSSDescIDListUser ( sizeAddr , bufAddr ) ;
}
static int sceNetApctlGetBSSDescEntry ( int entryId , int infoId , u32 resultAddr ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%i, %i, %08x) " , __FUNCTION__ , entryId , infoId , resultAddr ) ;
return sceNetApctlGetBSSDescEntryUser ( entryId , infoId , resultAddr ) ;
}
static int sceNetApctl_lib2_C20A144C ( int connIndex , u32 ps3MacAddressPtr ) {
ERROR_LOG ( SCENET , " UNIMPL %s(%i, %08x) " , __FUNCTION__ , connIndex , ps3MacAddressPtr ) ;
return sceNetApctlConnect ( connIndex ) ;
}
2015-03-08 20:07:03 +08:00
static int sceNetUpnpInit ( int unknown1 , int unknown2 )
{
2015-03-08 20:10:10 +08:00
ERROR_LOG_REPORT_ONCE ( sceNetUpnpInit , SCENET , " UNIMPLsceNetUpnpInit %d,%d " , unknown1 , unknown2 ) ;
2015-03-08 20:07:03 +08:00
return 0 ;
}
static int sceNetUpnpStart ( )
{
ERROR_LOG ( SCENET , " UNIMPLsceNetUpnpStart " ) ;
return 0 ;
}
static int sceNetUpnpStop ( )
{
ERROR_LOG ( SCENET , " UNIMPLsceNetUpnpStop " ) ;
return 0 ;
}
static int sceNetUpnpTerm ( )
{
ERROR_LOG ( SCENET , " UNIMPLsceNetUpnpTerm " ) ;
return 0 ;
}
static int sceNetUpnpGetNatInfo ( )
{
ERROR_LOG ( SCENET , " UNIMPLsceNetUpnpGetNatInfo " ) ;
return 0 ;
}
2016-02-13 20:27:07 +08:00
static int sceNetGetDropRate ( u32 dropRateAddr , u32 dropDurationAddr )
{
Memory : : Write_U32 ( netDropRate , dropRateAddr ) ;
Memory : : Write_U32 ( netDropDuration , dropDurationAddr ) ;
2016-02-21 13:18:03 +08:00
return hleLogSuccessInfoI ( SCENET , 0 ) ;
2016-02-13 20:27:07 +08:00
}
static int sceNetSetDropRate ( u32 dropRate , u32 dropDuration )
{
netDropRate = dropRate ;
netDropDuration = dropDuration ;
2016-02-21 13:18:03 +08:00
return hleLogSuccessInfoI ( SCENET , 0 ) ;
2016-02-13 20:27:07 +08:00
}
2013-06-17 08:43:29 -04:00
const HLEFunction sceNet [ ] = {
2019-08-18 11:53:39 -07:00
{ 0X39AF39A6 , & WrapI_UUUUU < sceNetInit > , " sceNetInit " , ' i ' , " xxxxx " } ,
2015-03-22 16:57:56 -07:00
{ 0X281928A9 , & WrapU_V < sceNetTerm > , " sceNetTerm " , ' x ' , " " } ,
2020-03-19 13:46:02 +07:00
{ 0X89360950 , & WrapV_UU < sceNetEtherNtostr > , " sceNetEtherNtostr " , ' v ' , " xx " } ,
{ 0XD27961C9 , & WrapV_UU < sceNetEtherStrton > , " sceNetEtherStrton " , ' v ' , " xx " } ,
2015-03-22 16:57:56 -07:00
{ 0X0BF0A3AE , & WrapU_U < sceNetGetLocalEtherAddr > , " sceNetGetLocalEtherAddr " , ' x ' , " x " } ,
2019-12-24 00:04:03 +07:00
{ 0X50647530 , & WrapI_I < sceNetFreeThreadinfo > , " sceNetFreeThreadinfo " , ' i ' , " i " } ,
2015-03-22 16:57:56 -07:00
{ 0XCC393E48 , & WrapI_U < sceNetGetMallocStat > , " sceNetGetMallocStat " , ' i ' , " x " } ,
2019-12-24 00:04:03 +07:00
{ 0XAD6844C6 , & WrapI_I < sceNetThreadAbort > , " sceNetThreadAbort " , ' i ' , " i " } ,
2012-11-01 16:19:01 +01:00
} ;
2013-06-17 08:43:29 -04:00
const HLEFunction sceNetResolver [ ] = {
2015-03-22 16:57:56 -07:00
{ 0X224C5F44 , nullptr , " sceNetResolverStartNtoA " , ' ? ' , " " } ,
{ 0X244172AF , nullptr , " sceNetResolverCreate " , ' ? ' , " " } ,
{ 0X94523E09 , nullptr , " sceNetResolverDelete " , ' ? ' , " " } ,
{ 0XF3370E61 , & WrapI_V < sceNetResolverInit > , " sceNetResolverInit " , ' i ' , " " } ,
{ 0X808F6063 , nullptr , " sceNetResolverStop " , ' ? ' , " " } ,
{ 0X6138194A , nullptr , " sceNetResolverTerm " , ' ? ' , " " } ,
{ 0X629E2FB7 , nullptr , " sceNetResolverStartAtoN " , ' ? ' , " " } ,
{ 0X14C17EF9 , nullptr , " sceNetResolverStartNtoAAsync " , ' ? ' , " " } ,
{ 0XAAC09184 , nullptr , " sceNetResolverStartAtoNAsync " , ' ? ' , " " } ,
{ 0X12748EB9 , nullptr , " sceNetResolverWaitAsync " , ' ? ' , " " } ,
{ 0X4EE99358 , nullptr , " sceNetResolverPollAsync " , ' ? ' , " " } ,
2012-11-01 16:19:01 +01:00
} ;
2013-06-17 08:43:29 -04:00
const HLEFunction sceNetInet [ ] = {
2015-03-22 16:57:56 -07:00
{ 0X17943399 , & WrapI_V < sceNetInetInit > , " sceNetInetInit " , ' i ' , " " } ,
{ 0X4CFE4E56 , nullptr , " sceNetInetShutdown " , ' ? ' , " " } ,
{ 0XA9ED66B9 , & WrapI_V < sceNetInetTerm > , " sceNetInetTerm " , ' i ' , " " } ,
{ 0X8B7B220F , & WrapI_III < sceNetInetSocket > , " sceNetInetSocket " , ' i ' , " iii " } ,
{ 0X2FE71FE7 , & WrapI_IIIUI < sceNetInetSetsockopt > , " sceNetInetSetsockopt " , ' i ' , " iiixi " } ,
{ 0X4A114C7C , nullptr , " sceNetInetGetsockopt " , ' ? ' , " " } ,
{ 0X410B34AA , & WrapI_IUI < sceNetInetConnect > , " sceNetInetConnect " , ' i ' , " ixi " } ,
{ 0X805502DD , nullptr , " sceNetInetCloseWithRST " , ' ? ' , " " } ,
{ 0XD10A1A7A , nullptr , " sceNetInetListen " , ' ? ' , " " } ,
{ 0XDB094E1B , nullptr , " sceNetInetAccept " , ' ? ' , " " } ,
{ 0XFAABB1DD , & WrapI_VUI < sceNetInetPoll > , " sceNetInetPoll " , ' i ' , " pxi " } ,
{ 0X5BE8D595 , nullptr , " sceNetInetSelect " , ' ? ' , " " } ,
{ 0X8D7284EA , nullptr , " sceNetInetClose " , ' ? ' , " " } ,
{ 0XCDA85C99 , & WrapI_IUUU < sceNetInetRecv > , " sceNetInetRecv " , ' i ' , " ixxx " } ,
{ 0XC91142E4 , nullptr , " sceNetInetRecvfrom " , ' ? ' , " " } ,
{ 0XEECE61D2 , nullptr , " sceNetInetRecvmsg " , ' ? ' , " " } ,
{ 0X7AA671BC , & WrapI_IUUU < sceNetInetSend > , " sceNetInetSend " , ' i ' , " ixxx " } ,
{ 0X05038FC7 , nullptr , " sceNetInetSendto " , ' ? ' , " " } ,
{ 0X774E36F4 , nullptr , " sceNetInetSendmsg " , ' ? ' , " " } ,
{ 0XFBABE411 , & WrapI_V < sceNetInetGetErrno > , " sceNetInetGetErrno " , ' i ' , " " } ,
{ 0X1A33F9AE , nullptr , " sceNetInetBind " , ' ? ' , " " } ,
{ 0XB75D5B0A , nullptr , " sceNetInetInetAddr " , ' ? ' , " " } ,
{ 0X1BDF5D13 , & WrapI_CU < sceNetInetInetAton > , " sceNetInetInetAton " , ' i ' , " sx " } ,
{ 0XD0792666 , nullptr , " sceNetInetInetNtop " , ' ? ' , " " } ,
{ 0XE30B8C19 , nullptr , " sceNetInetInetPton " , ' ? ' , " " } ,
{ 0X8CA3A97E , nullptr , " sceNetInetGetPspError " , ' ? ' , " " } ,
{ 0XE247B6D6 , nullptr , " sceNetInetGetpeername " , ' ? ' , " " } ,
{ 0X162E6FD5 , nullptr , " sceNetInetGetsockname " , ' ? ' , " " } ,
{ 0X80A21ABD , nullptr , " sceNetInetSocketAbort " , ' ? ' , " " } ,
{ 0X39B0C7D3 , nullptr , " sceNetInetGetUdpcbstat " , ' ? ' , " " } ,
{ 0XB3888AD4 , nullptr , " sceNetInetGetTcpcbstat " , ' ? ' , " " } ,
2012-11-01 16:19:01 +01:00
} ;
2013-03-25 00:07:30 +01:00
2013-06-17 08:43:29 -04:00
const HLEFunction sceNetApctl [ ] = {
2020-07-27 09:51:53 +07:00
{ 0XCFB957C6 , & WrapI_I < sceNetApctlConnect > , " sceNetApctlConnect " , ' i ' , " i " } ,
2015-03-22 16:57:56 -07:00
{ 0X24FE91A1 , & WrapI_V < sceNetApctlDisconnect > , " sceNetApctlDisconnect " , ' i ' , " " } ,
2020-07-27 09:51:53 +07:00
{ 0X5DEAC81B , & WrapI_U < sceNetApctlGetState > , " sceNetApctlGetState " , ' i ' , " x " } ,
2015-03-22 16:57:56 -07:00
{ 0X8ABADD51 , & WrapU_UU < sceNetApctlAddHandler > , " sceNetApctlAddHandler " , ' x ' , " xx " } ,
2020-07-27 09:51:53 +07:00
{ 0XE2F91F9B , & WrapI_II < sceNetApctlInit > , " sceNetApctlInit " , ' i ' , " ii " } ,
2015-03-22 16:57:56 -07:00
{ 0X5963991B , & WrapI_U < sceNetApctlDelHandler > , " sceNetApctlDelHandler " , ' i ' , " x " } ,
{ 0XB3EDD0EC , & WrapI_V < sceNetApctlTerm > , " sceNetApctlTerm " , ' i ' , " " } ,
2020-07-27 09:51:53 +07:00
{ 0X2BEFDF23 , & WrapI_IU < sceNetApctlGetInfo > , " sceNetApctlGetInfo " , ' i ' , " ix " } ,
{ 0XA3E77E13 , & WrapI_V < sceNetApctlScanSSID2 > , " sceNetApctlScanSSID2 " , ' i ' , " " } ,
{ 0XE9B2E5E6 , & WrapI_V < sceNetApctlScanUser > , " sceNetApctlScanUser " , ' i ' , " " } ,
{ 0XF25A5006 , & WrapI_UUUU < sceNetApctlGetBSSDescIDList2 > , " sceNetApctlGetBSSDescIDList2 " , ' i ' , " xxxx " } ,
{ 0X2935C45B , & WrapI_UUUU < sceNetApctlGetBSSDescEntry2 > , " sceNetApctlGetBSSDescEntry2 " , ' i ' , " xxxx " } ,
{ 0X04776994 , & WrapI_IIU < sceNetApctlGetBSSDescEntryUser > , " sceNetApctlGetBSSDescEntryUser " , ' i ' , " iix " } ,
{ 0X6BDDCB8C , & WrapI_UU < sceNetApctlGetBSSDescIDListUser > , " sceNetApctlGetBSSDescIDListUser " , ' i ' , " xx " } ,
{ 0X7CFAB990 , & WrapI_UU < sceNetApctlAddInternalHandler > , " sceNetApctlAddInternalHandler " , ' i ' , " xx " } ,
{ 0XE11BAFAB , & WrapI_U < sceNetApctlDelInternalHandler > , " sceNetApctlDelInternalHandler " , ' i ' , " x " } ,
{ 0XA7BB73DF , & WrapI_UU < sceNetApctl_A7BB73DF > , " sceNetApctl_A7BB73DF " , ' i ' , " xx " } ,
{ 0X6F5D2981 , & WrapI_U < sceNetApctl_6F5D2981 > , " sceNetApctl_6F5D2981 " , ' i ' , " x " } ,
{ 0X69745F0A , & WrapI_I < sceNetApctl_lib2_69745F0A > , " sceNetApctl_lib2_69745F0A " , ' i ' , " i " } ,
{ 0X4C19731F , & WrapI_IU < sceNetApctl_lib2_4C19731F > , " sceNetApctl_lib2_4C19731F " , ' i ' , " ix " } ,
{ 0XB3CF6849 , & WrapI_V < sceNetApctlScan > , " sceNetApctlScan " , ' i ' , " " } ,
{ 0X0C7FFA5C , & WrapI_UU < sceNetApctlGetBSSDescIDList > , " sceNetApctlGetBSSDescIDList " , ' i ' , " xx " } ,
{ 0X96BEB231 , & WrapI_IIU < sceNetApctlGetBSSDescEntry > , " sceNetApctlGetBSSDescEntry " , ' i ' , " iix " } ,
2020-07-28 07:38:10 +07:00
{ 0XC20A144C , & WrapI_IU < sceNetApctl_lib2_C20A144C > , " sceNetApctl_lib2_C20A144C " , ' i ' , " ix " } ,
// Fake function for PPSSPP's use.
{ 0X756E6F10 , & WrapV_V < __NetApctlCallbacks > , " __NetApctlCallbacks " , ' v ' , " " } ,
2012-11-01 16:19:01 +01:00
} ;
2013-06-17 08:43:29 -04:00
const HLEFunction sceWlanDrv [ ] = {
2015-03-22 16:57:56 -07:00
{ 0XD7763699 , & WrapU_V < sceWlanGetSwitchState > , " sceWlanGetSwitchState " , ' x ' , " " } ,
{ 0X0C622081 , & WrapU_U < sceWlanGetEtherAddr > , " sceWlanGetEtherAddr " , ' x ' , " x " } ,
{ 0X93440B11 , & WrapU_V < sceWlanDevIsPowerOn > , " sceWlanDevIsPowerOn " , ' x ' , " " } ,
2012-11-01 16:19:01 +01:00
} ;
2015-03-08 20:07:03 +08:00
// see http://www.kingx.de/forum/showthread.php?tid=35164
const HLEFunction sceNetUpnp [ ] = {
2015-03-22 16:57:56 -07:00
{ 0X27045362 , & WrapI_V < sceNetUpnpGetNatInfo > , " sceNetUpnpGetNatInfo " , ' i ' , " " } ,
{ 0X3432B2E5 , & WrapI_V < sceNetUpnpStart > , " sceNetUpnpStart " , ' i ' , " " } ,
{ 0X3E32ED9E , & WrapI_V < sceNetUpnpStop > , " sceNetUpnpStop " , ' i ' , " " } ,
{ 0X540491EF , & WrapI_V < sceNetUpnpTerm > , " sceNetUpnpTerm " , ' i ' , " " } ,
{ 0XE24220B5 , & WrapI_II < sceNetUpnpInit > , " sceNetUpnpInit " , ' i ' , " ii " } ,
2015-03-08 20:07:03 +08:00
} ;
2016-02-13 20:27:07 +08:00
const HLEFunction sceNetIfhandle [ ] = {
2016-02-21 13:18:03 +08:00
{ 0xC80181A2 , & WrapI_UU < sceNetGetDropRate > , " sceNetGetDropRate " , ' i ' , " pp " } ,
{ 0xFD8585E1 , & WrapI_UU < sceNetSetDropRate > , " sceNetSetDropRate " , ' i ' , " ii " } ,
2016-02-13 20:27:07 +08:00
} ;
2013-06-17 08:43:29 -04:00
void Register_sceNet ( ) {
2012-11-01 16:19:01 +01:00
RegisterModule ( " sceNet " , ARRAY_SIZE ( sceNet ) , sceNet ) ;
RegisterModule ( " sceNetResolver " , ARRAY_SIZE ( sceNetResolver ) , sceNetResolver ) ;
RegisterModule ( " sceNetInet " , ARRAY_SIZE ( sceNetInet ) , sceNetInet ) ;
RegisterModule ( " sceNetApctl " , ARRAY_SIZE ( sceNetApctl ) , sceNetApctl ) ;
}
2013-06-17 08:43:29 -04:00
void Register_sceWlanDrv ( ) {
2012-11-01 16:19:01 +01:00
RegisterModule ( " sceWlanDrv " , ARRAY_SIZE ( sceWlanDrv ) , sceWlanDrv ) ;
}
2015-03-08 20:07:03 +08:00
void Register_sceNetUpnp ( ) {
RegisterModule ( " sceNetUpnp " , ARRAY_SIZE ( sceNetUpnp ) , sceNetUpnp ) ;
}
2016-02-13 20:27:07 +08:00
void Register_sceNetIfhandle ( ) {
RegisterModule ( " sceNetIfhandle " , ARRAY_SIZE ( sceNetIfhandle ) , sceNetIfhandle ) ;
}