@ -5,19 +5,61 @@
# include "core/core.h"
# include "core/core.h"
# include "core/hle/ipc_helpers.h"
# include "core/hle/ipc_helpers.h"
# include "core/hle/kernel/event.h"
# include "core/hle/kernel/event.h"
# include "core/hle/lock.h"
# include "core/hle/service/nfc/nfc.h"
# include "core/hle/service/nfc/nfc.h"
# include "core/hle/service/nfc/nfc_m.h"
# include "core/hle/service/nfc/nfc_m.h"
# include "core/hle/service/nfc/nfc_u.h"
# include "core/hle/service/nfc/nfc_u.h"
namespace Service : : NFC {
namespace Service : : NFC {
struct TagInfo {
u16_le id_offset_size ;
u8 unk1 ;
u8 unk2 ;
std : : array < u8 , 7 > uuid ;
INSERT_PADDING_BYTES ( 0x20 ) ;
} ;
static_assert ( sizeof ( TagInfo ) = = 0x2C , " TagInfo is an invalid size " ) ;
struct AmiiboConfig {
u16_le lastwritedate_year ;
u8 lastwritedate_month ;
u8 lastwritedate_day ;
u16_le write_counter ;
std : : array < u8 , 3 > characterID ;
u16_le amiiboID ;
u8 type ;
u8 pagex4_byte3 ;
u16_le appdata_size ;
INSERT_PADDING_BYTES ( 0x30 ) ;
} ;
static_assert ( sizeof ( AmiiboConfig ) = = 0x40 , " AmiiboConfig is an invalid size " ) ;
struct IdentificationBlockReply {
u16_le char_id ;
u8 char_variant ;
u8 series ;
u16_le model_number ;
u8 figure_type ;
INSERT_PADDING_BYTES ( 0x2F ) ;
} ;
static_assert ( sizeof ( IdentificationBlockReply ) = = 0x36 ,
" IdentificationBlockReply is an invalid size " ) ;
void Module : : Interface : : Initialize ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : Initialize ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x01 , 1 , 0 ) ;
IPC : : RequestParser rp ( ctx , 0x01 , 1 , 0 ) ;
u8 param = rp . Pop < u8 > ( ) ;
u8 param = rp . Pop < u8 > ( ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : NotInitialized ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
nfc - > nfc_tag_state = TagState : : NotScanning ;
nfc - > nfc_tag_state = TagState : : NotScanning ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push ( RESULT_SUCCESS ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called, param={} " , param ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called, param={} " , param ) ;
}
}
@ -53,35 +95,83 @@ void Module::Interface::StartTagScanning(Kernel::HLERequestContext& ctx) {
IPC : : RequestParser rp ( ctx , 0x05 , 1 , 0 ) ; // 0x00050040
IPC : : RequestParser rp ( ctx , 0x05 , 1 , 0 ) ; // 0x00050040
u16 in_val = rp . Pop < u16 > ( ) ;
u16 in_val = rp . Pop < u16 > ( ) ;
ResultCode result = RESULT_SUCCESS ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : NotScanning & &
// TODO(shinyquagsire23): Implement NFC tag detection, for now stub result
nfc - > nfc_tag_state ! = TagState : : TagOutOfRange ) {
result = ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
if ( result = = RESULT_SUCCESS ) {
return ;
nfc - > nfc_tag_state = TagState : : TagInRange ;
nfc - > tag_in_range_event - > Signal ( ) ;
}
}
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
nfc - > nfc_tag_state = TagState : : Scanning ;
rb . Push ( result ) ;
rb . Push ( RESULT_SUCCESS ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called, in_val={:04x} " , in_val ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called, in_val={:04x} " , in_val ) ;
}
}
void Module : : Interface : : GetTagInfo ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x11 , 0 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : TagInRange & &
nfc - > nfc_tag_state ! = TagState : : TagDataLoaded & & nfc - > nfc_tag_state ! = TagState : : Unknown6 ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
TagInfo tag_info { } ;
tag_info . uuid = nfc - > amiibo_data . uuid ;
tag_info . id_offset_size = tag_info . uuid . size ( ) ;
tag_info . unk1 = 0x0 ;
tag_info . unk2 = 0x2 ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 12 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushRaw < TagInfo > ( tag_info ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called " ) ;
}
void Module : : Interface : : GetAmiiboConfig ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x18 , 0 , 0 ) ;
AmiiboConfig amiibo_config { } ;
amiibo_config . lastwritedate_year = 2017 ;
amiibo_config . lastwritedate_month = 10 ;
amiibo_config . lastwritedate_day = 10 ;
// TODO(FearlessTobi): Find the right values for the struct
IPC : : RequestBuilder rb = rp . MakeBuilder ( 17 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushRaw < AmiiboConfig > ( amiibo_config ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called " ) ;
}
void Module : : Interface : : StopTagScanning ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : StopTagScanning ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x06 , 0 , 0 ) ;
IPC : : RequestParser rp ( ctx , 0x06 , 0 , 0 ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
if ( nfc - > nfc_tag_state = = TagState : : NotInitialized | |
nfc - > nfc_tag_state = = TagState : : NotScanning ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
nfc - > nfc_tag_state = TagState : : NotScanning ;
nfc - > nfc_tag_state = TagState : : NotScanning ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push ( RESULT_SUCCESS ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called " ) ;
LOG_ DEBU G( Service_NFC , " called" ) ;
}
}
void Module : : Interface : : LoadAmiiboData ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : LoadAmiiboData ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x07 , 0 , 0 ) ;
IPC : : RequestParser rp ( ctx , 0x07 , 0 , 0 ) ;
// TODO(FearlessTobi): Add state checking when this function gets properly implemented
nfc - > nfc_tag_state = TagState : : TagDataLoaded ;
nfc - > nfc_tag_state = TagState : : TagDataLoaded ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
@ -92,29 +182,52 @@ void Module::Interface::LoadAmiiboData(Kernel::HLERequestContext& ctx) {
void Module : : Interface : : ResetTagScanState ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : ResetTagScanState ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x08 , 0 , 0 ) ;
IPC : : RequestParser rp ( ctx , 0x08 , 0 , 0 ) ;
nfc - > nfc_tag_state = TagState : : NotScanning ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : TagDataLoaded & & nfc - > nfc_tag_state ! = TagState : : Unknown6 ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
nfc - > nfc_tag_state = TagState : : TagInRange ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push ( RESULT_SUCCESS ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called " ) ;
LOG_ DEBU G( Service_NFC , " called" ) ;
}
}
void Module : : Interface : : GetTagInRangeEvent ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : GetTagInRangeEvent ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x0B , 0 , 0 ) ;
IPC : : RequestParser rp ( ctx , 0x0B , 0 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : NotScanning ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushCopyObjects ( nfc - > tag_in_range_event ) ;
rb . PushCopyObjects ( nfc - > tag_in_range_event ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called " ) ;
LOG_ DEBU G( Service_NFC , " called" ) ;
}
}
void Module : : Interface : : GetTagOutOfRangeEvent ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : GetTagOutOfRangeEvent ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x0C , 0 , 0 ) ;
IPC : : RequestParser rp ( ctx , 0x0C , 0 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : NotScanning ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 2 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushCopyObjects ( nfc - > tag_out_of_range_event ) ;
rb . PushCopyObjects ( nfc - > tag_out_of_range_event ) ;
LOG_WARNING ( Service_NFC , " (STUBBED) called " ) ;
LOG_ DEBU G( Service_NFC , " called" ) ;
}
}
void Module : : Interface : : GetTagState ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : GetTagState ( Kernel : : HLERequestContext & ctx ) {
@ -122,8 +235,8 @@ void Module::Interface::GetTagState(Kernel::HLERequestContext& ctx) {
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 2 , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushEnum ( nfc - > nfc_tag_state );
rb . PushEnum ( nfc - > nfc_tag_state .load ( ) );
LOG_DEBUG ( Service_NFC , " (STUBBED) called" ) ;
LOG_DEBUG ( Service_NFC , " called" ) ;
}
}
void Module : : Interface : : CommunicationGetStatus ( Kernel : : HLERequestContext & ctx ) {
void Module : : Interface : : CommunicationGetStatus ( Kernel : : HLERequestContext & ctx ) {
@ -135,6 +248,65 @@ void Module::Interface::CommunicationGetStatus(Kernel::HLERequestContext& ctx) {
LOG_DEBUG ( Service_NFC , " (STUBBED) called " ) ;
LOG_DEBUG ( Service_NFC , " (STUBBED) called " ) ;
}
}
void Module : : Interface : : Unknown0x1A ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x1A , 0 , 0 ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : TagInRange ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
nfc - > nfc_tag_state = TagState : : Unknown6 ;
rb . Push ( RESULT_SUCCESS ) ;
LOG_DEBUG ( Service_NFC , " called " ) ;
}
void Module : : Interface : : GetIdentificationBlock ( Kernel : : HLERequestContext & ctx ) {
IPC : : RequestParser rp ( ctx , 0x1B , 0 , 0 ) ;
if ( nfc - > nfc_tag_state ! = TagState : : TagDataLoaded & & nfc - > nfc_tag_state ! = TagState : : Unknown6 ) {
LOG_ERROR ( Service_NFC , " Invalid TagState {} " , static_cast < int > ( nfc - > nfc_tag_state . load ( ) ) ) ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 1 , 0 ) ;
rb . Push ( ResultCode ( ErrCodes : : CommandInvalidForState , ErrorModule : : NFC ,
ErrorSummary : : InvalidState , ErrorLevel : : Status ) ) ;
return ;
}
IdentificationBlockReply identification_block_reply { } ;
identification_block_reply . char_id = nfc - > amiibo_data . char_id ;
identification_block_reply . char_variant = nfc - > amiibo_data . char_variant ;
identification_block_reply . series = nfc - > amiibo_data . series ;
identification_block_reply . model_number = nfc - > amiibo_data . model_number ;
identification_block_reply . figure_type = nfc - > amiibo_data . figure_type ;
IPC : : RequestBuilder rb = rp . MakeBuilder ( 0x1F , 0 ) ;
rb . Push ( RESULT_SUCCESS ) ;
rb . PushRaw < IdentificationBlockReply > ( identification_block_reply ) ;
LOG_DEBUG ( Service_NFC , " called " ) ;
}
std : : shared_ptr < Module > Module : : Interface : : GetModule ( ) const {
return nfc ;
}
void Module : : Interface : : LoadAmiibo ( const AmiiboData & amiibo_data ) {
std : : lock_guard lock ( HLE : : g_hle_lock ) ;
nfc - > amiibo_data = amiibo_data ;
nfc - > nfc_tag_state = Service : : NFC : : TagState : : TagInRange ;
nfc - > tag_in_range_event - > Signal ( ) ;
}
void Module : : Interface : : RemoveAmiibo ( ) {
std : : lock_guard lock ( HLE : : g_hle_lock ) ;
nfc - > nfc_tag_state = Service : : NFC : : TagState : : TagOutOfRange ;
nfc - > tag_out_of_range_event - > Signal ( ) ;
nfc - > amiibo_data = { } ;
}
Module : : Interface : : Interface ( std : : shared_ptr < Module > nfc , const char * name , u32 max_session )
Module : : Interface : : Interface ( std : : shared_ptr < Module > nfc , const char * name , u32 max_session )
: ServiceFramework ( name , max_session ) , nfc ( std : : move ( nfc ) ) { }
: ServiceFramework ( name , max_session ) , nfc ( std : : move ( nfc ) ) { }