@ -13,6 +13,7 @@
# include "core/hle/kernel/event.h"
# include "core/hle/kernel/handle_table.h"
# include "core/hle/kernel/resource_limit.h"
# include "core/hle/kernel/shared_page.h"
# include "core/hle/result.h"
# include "core/hle/service/ac/ac.h"
# include "core/hle/service/ac/ac_i.h"
@ -40,76 +41,143 @@ void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) {
void Module : : Interface : : ConnectAsync ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
rp . Skip ( 2 , false ) ; // ProcessId descriptor
const u32 pid = rp . PopPID ( ) ;
ac - > connect_event = rp . PopObject < Kernel : : Event > ( ) ;
rp . Skip ( 2 , false ) ; // Buffer descriptor
if ( ac - > connect_event ) {
ac - > connect_event - > SetName ( " AC:connect_event " ) ;
ac - > connect_event - > Signal ( ) ;
ac - > ac_connected = true ;
}
ac - > Connect ( pid ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultSuccess ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called " ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called , pid={} " , pid ) ;
}
void Module : : Interface : : GetConnectResult ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
rp . Skip ( 2 , false ) ; // ProcessId descriptor
[[maybe_unused]] const u32 pid = rp . PopPID ( ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultSuccess ) ;
rb . Push ( ac - > connect_result ) ;
}
void Module : : Interface : : CancelConnectAsync ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
const u32 pid = rp . PopPID ( ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ac - > ac_connected ? ErrorAlreadyConnected : ErrorNotConnected ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called, pid={} " , pid ) ;
}
void Module : : Interface : : CloseAsync ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
rp . Skip ( 2 , false ) ; // ProcessId descriptor
const u32 pid = rp . PopPID ( ) ;
ac - > close_event = rp . PopObject < Kernel : : Event > ( ) ;
if ( ac - > ac_connected & & ac - > disconnect_event ) {
ac - > disconnect_event - > Signal ( ) ;
}
if ( ac - > close_event ) {
ac - > close_event - > SetName ( " AC:close_event " ) ;
ac - > close_event - > Signal ( ) ;
}
ac - > ac_connected = false ;
ac - > Disconnect ( pid ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultSuccess ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called, pid={} " , pid ) ;
}
void Module : : Interface : : GetCloseResult ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
rp . Skip ( 2 , false ) ; // ProcessId descriptor
[[maybe_unused]] const u32 pid = rp . PopPID ( ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultSuccess ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called " ) ;
rb . Push ( ac - > close_result ) ;
}
void Module : : Interface : : GetWifiStatus ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
bool can_reach_internet = false ;
std : : shared_ptr < SOC : : SOC_U > socu_module = SOC : : GetService ( ac - > system ) ;
if ( socu_module ) {
can_reach_internet = socu_module - > GetDefaultInterfaceInfo ( ) . has_value ( ) ;
if ( ! ac - > ac_connected ) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ErrorNotConnected ) ;
return ;
}
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( ResultSuccess ) ;
rb . Push < u32 > ( static_cast < u32 > ( can_reach_internet ? ( Settings : : values . is_new_3ds
? WifiStatus : : STATUS_CONNECTED_N3DS
: WifiStatus : : STATUS_CONNECTED_O3DS )
: WifiStatus : : STATUS_DISCONNECTED ) ) ;
rb . Push < u32 > ( static_cast < u32 > ( WifiStatus : : STATUS_CONNECTED_SLOT1 ) ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called " ) ;
}
void Module : : Interface : : GetCurrentAPInfo ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
const u32 len = rp . Pop < u32 > ( ) ;
const u32 pid = rp . PopPID ( ) ;
if ( ! ac - > ac_connected ) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ErrorNotConnected ) ;
return ;
}
constexpr const char * citra_ap = " Citra_AP " ;
constexpr s16 good_signal_strength = 60 ;
constexpr u8 unknown1_value = 6 ;
constexpr u8 unknown2_value = 5 ;
constexpr u8 unknown3_value = 5 ;
constexpr u8 unknown4_value = 0 ;
SharedPage : : Handler & shared_page = ac - > system . Kernel ( ) . GetSharedPageHandler ( ) ;
SharedPage : : MacAddress mac = shared_page . GetMacAddress ( ) ;
APInfo info {
. ssid_len = static_cast < u32 > ( std : : strlen ( citra_ap ) ) ,
. bssid = mac ,
. padding = 0 ,
. signal_strength = good_signal_strength ,
. link_level = static_cast < u8 > ( shared_page . GetWifiLinkLevel ( ) ) ,
. unknown1 = unknown1_value ,
. unknown2 = unknown2_value ,
. unknown3 = unknown3_value ,
. unknown4 = unknown4_value ,
} ;
std : : strncpy ( info . ssid . data ( ) , citra_ap , info . ssid . size ( ) ) ;
std : : vector < u8 > out_info ( len ) ;
std : : memcpy ( out_info . data ( ) , & info , std : : min ( len , static_cast < u32 > ( sizeof ( info ) ) ) ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
rb . Push ( ResultSuccess ) ;
rb . PushStaticBuffer ( out_info , 0 ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called, pid={} " , pid ) ;
}
void Module : : Interface : : GetConnectingInfraPriority ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
if ( ! ac - > ac_connected ) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ErrorNotConnected ) ;
return ;
}
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( ResultSuccess ) ;
rb . Push < u32 > ( static_cast < u32 > ( InfraPriority : : PRIORITY_HIGH ) ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called " ) ;
}
void Module : : Interface : : GetStatus ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( ResultSuccess ) ;
rb . Push < u32 > ( static_cast < u32 > ( ac - > ac_connected ? NetworkStatus : : STATUS_INTERNET
: NetworkStatus : : STATUS_DISCONNECTED ) ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called " ) ;
}
void Module : : Interface : : GetInfraPriority ( Kernel : : HLERequestContext & ctx ) {
@ -118,16 +186,28 @@ void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( ResultSuccess ) ;
rb . Push < u32 > ( 0 ) ; // Infra Priority, default 0
rb . Push < u32 > ( static_cast < u32 > ( InfraPriority : : PRIORITY_HIGH ) ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called " ) ;
}
void Module : : Interface : : SetFromApplication ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
const u32 unknown = rp . Pop < u32 > ( ) ;
auto config = rp . PopStaticBuffer ( ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
rb . Push ( ResultSuccess ) ;
rb . PushStaticBuffer ( config , 0 ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called, unknown={} " , unknown ) ;
}
void Module : : Interface : : SetRequestEulaVersion ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
u32 major = rp . Pop < u8 > ( ) ;
u32 minor = rp . Pop < u8 > ( ) ;
const u32 major = rp . Pop < u8 > ( ) ;
const u32 minor = rp . Pop < u8 > ( ) ;
const std : : vector < u8 > & ac_config = rp . PopStaticBuffer ( ) ;
@ -140,6 +220,19 @@ void Module::Interface::SetRequestEulaVersion(Kernel::HLERequestContext& ctx) {
LOG_WARNING ( Service_AC , " (STUBBED) called, major={}, minor={} " , major , minor ) ;
}
void Module : : Interface : : GetNZoneBeaconNotFoundEvent ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
rp . PopPID ( ) ;
auto event = rp . PopObject < Kernel : : Event > ( ) ;
event - > Signal ( ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultSuccess ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called " ) ;
}
void Module : : Interface : : RegisterDisconnectEvent ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
rp . Skip ( 2 , false ) ; // ProcessId descriptor
@ -168,30 +261,93 @@ void Module::Interface::GetConnectingProxyEnable(Kernel::HLERequestContext& ctx)
void Module : : Interface : : IsConnected ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
u32 unk = rp . Pop < u32 > ( ) ;
u32 unk_descriptor = rp . Pop < u32 > ( ) ;
u32 unk_param = rp . Pop < u32 > ( ) ;
const u32 unk = rp . Pop < u32 > ( ) ;
const u32 pid = rp . PopPID ( ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( ResultSuccess ) ;
rb . Push ( ac - > ac_connected ) ;
LOG_WARNING ( Service_AC , " (STUBBED) called unk=0x{:08X} descriptor=0x{:08X} param=0x{:08X} " , unk ,
unk_descriptor , unk_param ) ;
LOG_DEBUG ( Service_AC , " (STUBBED) called unk=0x{:08X} pid={} " , unk , pid ) ;
}
void Module : : Interface : : SetClientVersion ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx ) ;
u32 version = rp . Pop < u32 > ( ) ;
rp . Skip( 2 , false ) ; // ProcessId descriptor
const u32 version = rp . Pop < u32 > ( ) ;
rp . PopPID( ) ;
LOG_ WARNIN G( Service_AC , " (STUBBED) called, version: 0x{:08X} " , version ) ;
LOG_ DEBU G( Service_AC , " (STUBBED) called, version: 0x{:08X} " , version ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultSuccess ) ;
}
void Module : : Connect ( u32 pid ) {
if ( connect_event ) {
connect_event - > SetName ( " AC:connect_event " ) ;
connect_event - > Signal ( ) ;
}
if ( connected_pids . size ( ) = = 0 ) {
// TODO(PabloMK7) Publish to subscriber 0x300
ac_connected = true ;
// TODO(PabloMK7) Move shared page modification to NWM once it is implemented.
SharedPage : : Handler & shared_page = system . Kernel ( ) . GetSharedPageHandler ( ) ;
const bool can_access_internet = CanAccessInternet ( ) ;
if ( can_access_internet ) {
shared_page . SetWifiState ( SharedPage : : WifiState : : Internet ) ;
shared_page . SetWifiLinkLevel ( SharedPage : : WifiLinkLevel : : Best ) ;
} else {
shared_page . SetWifiState ( SharedPage : : WifiState : : Enabled ) ;
shared_page . SetWifiLinkLevel ( SharedPage : : WifiLinkLevel : : Off ) ;
}
}
if ( connected_pids . find ( pid ) = = connected_pids . end ( ) ) {
connected_pids . insert ( pid ) ;
connect_result = ResultSuccess ;
} else {
connect_result = ErrorAlreadyConnected ;
}
}
void Module : : Disconnect ( u32 pid ) {
if ( close_event ) {
close_event - > SetName ( " AC:close_event " ) ;
close_event - > Signal ( ) ;
}
if ( connected_pids . find ( pid ) ! = connected_pids . end ( ) ) {
connected_pids . erase ( pid ) ;
close_result = ResultSuccess ;
} else {
close_result = ErrorNotConnected ;
}
if ( connected_pids . size ( ) = = 0 ) {
ac_connected = false ;
if ( disconnect_event ) {
disconnect_event - > Signal ( ) ;
}
// TODO(PabloMK7) Move shared page modification to NWM once it is implemented.
SharedPage : : Handler & shared_page = system . Kernel ( ) . GetSharedPageHandler ( ) ;
shared_page . SetWifiState ( SharedPage : : WifiState : : Enabled ) ;
shared_page . SetWifiLinkLevel ( SharedPage : : WifiLinkLevel : : Off ) ;
}
}
bool Module : : CanAccessInternet ( ) {
std : : shared_ptr < SOC : : SOC_U > socu_module = SOC : : GetService ( system ) ;
if ( socu_module ) {
return socu_module - > GetDefaultInterfaceInfo ( ) . has_value ( ) ;
}
return false ;
}
Module : : Interface : : Interface ( std : : shared_ptr < Module > ac , const char * name , u32 max_session )
: ServiceFramework ( name , max_session ) , ac ( std : : move ( ac ) ) { }
@ -202,6 +358,10 @@ void InstallInterfaces(Core::System& system) {
std : : make_shared < AC_U > ( ac ) - > InstallAsService ( service_manager ) ;
}
std : : shared_ptr < AC_U > GetService ( Core : : System & system ) {
return system . ServiceManager ( ) . GetService < AC_U > ( " ac:u " ) ;
}
Module : : Module ( Core : : System & system_ ) : system ( system_ ) { }
template < class Archive >
@ -210,6 +370,13 @@ void Module::serialize(Archive& ar, const unsigned int) {
ar & close_event ;
ar & connect_event ;
ar & disconnect_event ;
u32 connect_result_32 = connect_result . raw ;
ar & connect_result_32 ;
connect_result . raw = connect_result_32 ;
u32 close_result_32 = close_result . raw ;
ar & close_result_32 ;
close_result . raw = close_result_32 ;
ar & connected_pids ;
// default_config is never written to
}
SERIALIZE_IMPL ( Module )