From 3bc0670b910c4d638dfff81da67e5a95009183cb Mon Sep 17 00:00:00 2001 From: Max Roncace Date: Tue, 3 Feb 2026 02:17:29 -0500 Subject: [PATCH] Revolution WUD work (mostly matching) (#3080) * WUD mostly matching for Wii Mostly copied from Petari with small modifications, Shield match is still pretty bad. * Implement WUDHidHost * Fix WUD regressions in Shield/ShieldD --- config/DZDE01/splits.txt | 4 +- config/DZDE01/symbols.txt | 10 +- config/RZDE01_00/splits.txt | 4 +- config/RZDE01_00/symbols.txt | 10 +- config/RZDE01_02/splits.txt | 4 +- config/RZDE01_02/symbols.txt | 10 +- config/RZDJ01/splits.txt | 4 +- config/RZDJ01/symbols.txt | 10 +- config/RZDP01/splits.txt | 4 +- config/RZDP01/symbols.txt | 10 +- configure.py | 4 +- include/revolution/os.h | 1 + include/revolution/sc.h | 59 + include/revolution/wpad.h | 2 +- include/revolution/wpad/bte.h | 55 +- include/revolution/wud.h | 150 ++ include/revolution/wud/WUD.h | 256 --- include/revolution/wud/debug_msg.h | 14 - src/revolution/wpad/WPAD.c | 22 +- src/revolution/wpad/__wpad.h | 72 +- src/revolution/wud/WUD.c | 2883 +++++++++++++++++++++++++++- src/revolution/wud/WUDHidHost.c | 261 +++ src/revolution/wud/__wud.h | 258 ++- src/revolution/wud/debug_msg.c | 6 +- 24 files changed, 3644 insertions(+), 469 deletions(-) create mode 100644 include/revolution/wud.h delete mode 100644 include/revolution/wud/WUD.h delete mode 100644 include/revolution/wud/debug_msg.h create mode 100644 src/revolution/wud/WUDHidHost.c diff --git a/config/DZDE01/splits.txt b/config/DZDE01/splits.txt index 949f92ebbd..c8bd90d424 100644 --- a/config/DZDE01/splits.txt +++ b/config/DZDE01/splits.txt @@ -3411,7 +3411,7 @@ revolution/wud/WUD.c: .data start:0x80403678 end:0x80404440 .bss start:0x804BE680 end:0x804C03E0 .sdata start:0x804FA7E8 end:0x804FA7F0 - .sbss start:0x804FBA38 end:0x804FBA5C + .sbss start:0x804FBA38 end:0x804FBA58 .sdata2 start:0x805005B8 end:0x805005C0 revolution/wud/WUDHidHost.c: @@ -3444,7 +3444,7 @@ revolution/bte/uusb_ppc.c: .data start:0x80404878 end:0x804055C0 .bss start:0x804E8F00 end:0x804EAF60 .sdata start:0x804FA7F0 end:0x804FA810 - .sbss start:0x804FBA5C end:0x804FBA70 + .sbss start:0x804FBA58 end:0x804FBA70 revolution/bte/bta_dm_cfg.c: .rodata start:0x803BB9B0 end:0x803BBA40 diff --git a/config/DZDE01/symbols.txt b/config/DZDE01/symbols.txt index e915d532a5..9a4d18524e 100644 --- a/config/DZDE01/symbols.txt +++ b/config/DZDE01/symbols.txt @@ -27888,15 +27888,15 @@ lo = .sbss:0x804FBA28; // type:object size:0x4 scope:global align:4 data:4byte hi = .sbss:0x804FBA2C; // type:object size:0x4 scope:global align:4 data:4byte lbl_804FBA30 = .sbss:0x804FBA30; // type:object size:0x1 data:byte _initialized = .sbss:0x804FBA38; // type:object size:0x4 scope:global align:4 data:4byte -lbl_804FBA3C = .sbss:0x804FBA3C; // type:object size:0x1 data:byte +__bte_trace_level = .sbss:0x804FBA3C; // type:object size:0x1 data:byte remove_patch = .sbss:0x804FBA40; // type:object size:0x1 scope:global align:4 -lbl_804FBA41 = .sbss:0x804FBA41; // type:object size:0x1 data:byte -lbl_804FBA42 = .sbss:0x804FBA42; // type:object size:0x1 data:byte +install_num = .sbss:0x804FBA41; // type:object size:0x1 data:byte +patch_num = .sbss:0x804FBA42; // type:object size:0x1 data:byte addr = .sbss:0x804FBA44; // type:object size:0x4 scope:global align:4 data:4byte offset = .sbss:0x804FBA48; // type:object size:0x4 scope:global align:4 data:4byte size = .sbss:0x804FBA4C; // type:object size:0x4 scope:global align:4 data:4byte -lbl_804FBA50 = .sbss:0x804FBA50; // type:object size:0x1 data:byte -lbl_804FBA51 = .sbss:0x804FBA51; // type:object size:0x7 data:byte +_discRssi = .sbss:0x804FBA50; // type:object size:0x1 data:byte +_discNumResps = .sbss:0x804FBA51; // type:object size:0x7 data:byte lbl_804FBA58 = .sbss:0x804FBA58; // type:object size:0x1 data:byte lbl_804FBA59 = .sbss:0x804FBA59; // type:object size:0x1 data:byte __ntd_ohci = .sbss:0x804FBA5C; // type:object size:0x4 scope:global align:4 data:4byte diff --git a/config/RZDE01_00/splits.txt b/config/RZDE01_00/splits.txt index 9de906be2f..188ccb5d1c 100644 --- a/config/RZDE01_00/splits.txt +++ b/config/RZDE01_00/splits.txt @@ -3663,7 +3663,7 @@ revolution/wud/WUD.c: .data start:0x80441D20 end:0x80442AE8 .bss start:0x804FE3E0 end:0x80500140 .sdata start:0x8053A630 end:0x8053A638 - .sbss start:0x8053B910 end:0x8053B934 + .sbss start:0x8053B910 end:0x8053B930 .sdata2 start:0x80540648 end:0x80540650 revolution/wud/WUDHidHost.c: @@ -3696,7 +3696,7 @@ revolution/bte/uusb_ppc.c: .data start:0x80442F20 end:0x80443C68 .bss start:0x80528C60 end:0x8052ACC0 .sdata start:0x8053A638 end:0x8053A658 - .sbss start:0x8053B934 end:0x8053B948 + .sbss start:0x8053B930 end:0x8053B948 revolution/bte/bta_dm_cfg.c: .rodata start:0x803F3F50 end:0x803F3FE0 diff --git a/config/RZDE01_00/symbols.txt b/config/RZDE01_00/symbols.txt index b8c6c157e3..9af50ee377 100644 --- a/config/RZDE01_00/symbols.txt +++ b/config/RZDE01_00/symbols.txt @@ -29071,15 +29071,15 @@ lo = .sbss:0x8053B900; // type:object size:0x4 scope:global align:4 data:4byte hi = .sbss:0x8053B904; // type:object size:0x4 scope:global align:4 data:4byte lbl_8053B908 = .sbss:0x8053B908; // type:object size:0x1 data:byte _initialized = .sbss:0x8053B910; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8053B914 = .sbss:0x8053B914; // type:object size:0x1 data:byte +__bte_trace_level = .sbss:0x8053B914; // type:object size:0x1 data:byte remove_patch = .sbss:0x8053B918; // type:object size:0x1 scope:global align:4 -lbl_8053B919 = .sbss:0x8053B919; // type:object size:0x1 data:byte -lbl_8053B91A = .sbss:0x8053B91A; // type:object size:0x1 data:byte +install_num = .sbss:0x8053B919; // type:object size:0x1 data:byte +patch_num = .sbss:0x8053B91A; // type:object size:0x1 data:byte addr = .sbss:0x8053B91C; // type:object size:0x4 scope:global align:4 data:4byte offset = .sbss:0x8053B920; // type:object size:0x4 scope:global align:4 data:4byte size = .sbss:0x8053B924; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8053B928 = .sbss:0x8053B928; // type:object size:0x1 data:byte -lbl_8053B929 = .sbss:0x8053B929; // type:object size:0x7 data:byte +_discRssi = .sbss:0x8053B928; // type:object size:0x1 data:byte +_discNumResps = .sbss:0x8053B929; // type:object size:0x7 data:byte lbl_8053B930 = .sbss:0x8053B930; // type:object size:0x1 data:byte lbl_8053B931 = .sbss:0x8053B931; // type:object size:0x1 data:byte __ntd_ohci = .sbss:0x8053B934; // type:object size:0x4 scope:global align:4 data:4byte diff --git a/config/RZDE01_02/splits.txt b/config/RZDE01_02/splits.txt index 84de438bfd..546ef54cb5 100644 --- a/config/RZDE01_02/splits.txt +++ b/config/RZDE01_02/splits.txt @@ -3622,7 +3622,7 @@ revolution/wud/WUD.c: .data start:0x80429200 end:0x80429FC8 .bss start:0x804E4460 end:0x804E61C0 .sdata start:0x80520640 end:0x80520648 - .sbss start:0x80521908 end:0x8052192C + .sbss start:0x80521908 end:0x80521928 .sdata2 start:0x805266C8 end:0x805266D0 revolution/wud/WUDHidHost.c: @@ -3655,7 +3655,7 @@ revolution/bte/uusb_ppc.c: .data start:0x8042A400 end:0x8042B148 .bss start:0x8050ECE0 end:0x80510D40 .sdata start:0x80520648 end:0x80520668 - .sbss start:0x8052192C end:0x80521940 + .sbss start:0x80521928 end:0x80521940 revolution/bte/bta_dm_cfg.c: .rodata start:0x803DF2BC end:0x803DF340 diff --git a/config/RZDE01_02/symbols.txt b/config/RZDE01_02/symbols.txt index 32d5938dd8..04368a54f4 100644 --- a/config/RZDE01_02/symbols.txt +++ b/config/RZDE01_02/symbols.txt @@ -28591,15 +28591,15 @@ lo = .sbss:0x805218F8; // type:object size:0x4 scope:global align:4 data:4byte hi = .sbss:0x805218FC; // type:object size:0x4 scope:global align:4 data:4byte lbl_80521900 = .sbss:0x80521900; // type:object size:0x1 data:byte _initialized = .sbss:0x80521908; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8052190C = .sbss:0x8052190C; // type:object size:0x1 data:byte +__bte_trace_level = .sbss:0x8052190C; // type:object size:0x1 data:byte remove_patch = .sbss:0x80521910; // type:object size:0x1 scope:global align:4 -lbl_80521911 = .sbss:0x80521911; // type:object size:0x1 data:byte -lbl_80521912 = .sbss:0x80521912; // type:object size:0x1 data:byte +install_num = .sbss:0x80521911; // type:object size:0x1 data:byte +patch_num = .sbss:0x80521912; // type:object size:0x1 data:byte addr = .sbss:0x80521914; // type:object size:0x4 scope:global align:4 data:4byte offset = .sbss:0x80521918; // type:object size:0x4 scope:global align:4 data:4byte size = .sbss:0x8052191C; // type:object size:0x4 scope:global align:4 data:4byte -lbl_80521920 = .sbss:0x80521920; // type:object size:0x1 data:byte -lbl_80521921 = .sbss:0x80521921; // type:object size:0x7 data:byte +_discRssi = .sbss:0x80521920; // type:object size:0x1 data:byte +_discNumResps = .sbss:0x80521921; // type:object size:0x1 data:byte lbl_80521928 = .sbss:0x80521928; // type:object size:0x1 data:byte lbl_80521929 = .sbss:0x80521929; // type:object size:0x1 data:byte __ntd_ohci = .sbss:0x8052192C; // type:object size:0x4 scope:global align:4 data:4byte diff --git a/config/RZDJ01/splits.txt b/config/RZDJ01/splits.txt index 6849b350e9..40868be17e 100644 --- a/config/RZDJ01/splits.txt +++ b/config/RZDJ01/splits.txt @@ -3618,7 +3618,7 @@ revolution/wud/WUD.c: .data start:0x80427080 end:0x80427E48 .bss start:0x804E22E0 end:0x804E4040 .sdata start:0x8051E4B0 end:0x8051E4B8 - .sbss start:0x8051F778 end:0x8051F79C + .sbss start:0x8051F778 end:0x8051F798 .sdata2 start:0x80524520 end:0x80524528 revolution/wud/WUDHidHost.c: @@ -3651,7 +3651,7 @@ revolution/bte/uusb_ppc.c: .data start:0x80428280 end:0x80428FC8 .bss start:0x8050CB60 end:0x8050EBC0 .sdata start:0x8051E4B8 end:0x8051E4D8 - .sbss start:0x8051F79C end:0x8051F7B0 + .sbss start:0x8051F798 end:0x8051F7B0 revolution/bte/bta_dm_cfg.c: .rodata start:0x803DD270 end:0x803DD300 diff --git a/config/RZDJ01/symbols.txt b/config/RZDJ01/symbols.txt index 6ed5b5431e..320529aea7 100644 --- a/config/RZDJ01/symbols.txt +++ b/config/RZDJ01/symbols.txt @@ -28595,15 +28595,15 @@ lo = .sbss:0x8051F768; // type:object size:0x4 scope:global align:4 data:4byte hi = .sbss:0x8051F76C; // type:object size:0x4 scope:global align:4 data:4byte lbl_8051F770 = .sbss:0x8051F770; // type:object size:0x1 data:byte _initialized = .sbss:0x8051F778; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8051F77C = .sbss:0x8051F77C; // type:object size:0x1 data:byte +__bte_trace_level = .sbss:0x8051F77C; // type:object size:0x1 data:byte remove_patch = .sbss:0x8051F780; // type:object size:0x1 scope:global align:4 -lbl_8051F781 = .sbss:0x8051F781; // type:object size:0x1 data:byte -lbl_8051F782 = .sbss:0x8051F782; // type:object size:0x1 data:byte +install_num = .sbss:0x8051F781; // type:object size:0x1 data:byte +patch_num = .sbss:0x8051F782; // type:object size:0x1 data:byte addr = .sbss:0x8051F784; // type:object size:0x4 scope:global align:4 data:4byte offset = .sbss:0x8051F788; // type:object size:0x4 scope:global align:4 data:4byte size = .sbss:0x8051F78C; // type:object size:0x4 scope:global align:4 data:4byte -lbl_8051F790 = .sbss:0x8051F790; // type:object size:0x1 data:byte -lbl_8051F791 = .sbss:0x8051F791; // type:object size:0x7 data:byte +_discRssi = .sbss:0x8051F790; // type:object size:0x1 data:byte +_discNumResps = .sbss:0x8051F791; // type:object size:0x7 data:byte lbl_8051F798 = .sbss:0x8051F798; // type:object size:0x1 data:byte lbl_8051F799 = .sbss:0x8051F799; // type:object size:0x1 data:byte __ntd_ohci = .sbss:0x8051F79C; // type:object size:0x4 scope:global align:4 data:4byte diff --git a/config/RZDP01/splits.txt b/config/RZDP01/splits.txt index 286cab9f6a..667c869a2e 100644 --- a/config/RZDP01/splits.txt +++ b/config/RZDP01/splits.txt @@ -3618,7 +3618,7 @@ revolution/wud/WUD.c: .data start:0x80429B00 end:0x8042A8C8 .bss start:0x804E4D60 end:0x804E6AC0 .sdata start:0x80520DE8 end:0x80520DF0 - .sbss start:0x805220C8 end:0x805220EC + .sbss start:0x805220C8 end:0x805220E8 .sdata2 start:0x80526E98 end:0x80526EA0 revolution/wud/WUDHidHost.c: @@ -3651,7 +3651,7 @@ revolution/bte/uusb_ppc.c: .data start:0x8042AD00 end:0x8042BA48 .bss start:0x8050F5E0 end:0x80511640 .sdata start:0x80520DF0 end:0x80520E10 - .sbss start:0x805220EC end:0x80522100 + .sbss start:0x805220E8 end:0x80522100 revolution/bte/bta_dm_cfg.c: .rodata start:0x803DFFD0 end:0x803E0060 diff --git a/config/RZDP01/symbols.txt b/config/RZDP01/symbols.txt index 21623bcd87..91e6c28bd6 100644 --- a/config/RZDP01/symbols.txt +++ b/config/RZDP01/symbols.txt @@ -28482,15 +28482,15 @@ lo = .sbss:0x805220B8; // type:object size:0x4 scope:global align:4 data:4byte hi = .sbss:0x805220BC; // type:object size:0x4 scope:global align:4 data:4byte lbl_805220C0 = .sbss:0x805220C0; // type:object size:0x1 data:byte _initialized = .sbss:0x805220C8; // type:object size:0x4 scope:global align:4 data:4byte -lbl_805220CC = .sbss:0x805220CC; // type:object size:0x1 data:byte +__bte_trace_level = .sbss:0x805220CC; // type:object size:0x1 data:byte remove_patch = .sbss:0x805220D0; // type:object size:0x1 scope:global align:4 -lbl_805220D1 = .sbss:0x805220D1; // type:object size:0x1 data:byte -lbl_805220D2 = .sbss:0x805220D2; // type:object size:0x1 data:byte +install_num = .sbss:0x805220D1; // type:object size:0x1 data:byte +patch_num = .sbss:0x805220D2; // type:object size:0x1 data:byte addr = .sbss:0x805220D4; // type:object size:0x4 scope:global align:4 data:4byte offset = .sbss:0x805220D8; // type:object size:0x4 scope:global align:4 data:4byte size = .sbss:0x805220DC; // type:object size:0x4 scope:global align:4 data:4byte -lbl_805220E0 = .sbss:0x805220E0; // type:object size:0x1 data:byte -lbl_805220E1 = .sbss:0x805220E1; // type:object size:0x7 data:byte +_discRssi = .sbss:0x805220E0; // type:object size:0x1 data:byte +_discNumResps = .sbss:0x805220E1; // type:object size:0x7 data:byte lbl_805220E8 = .sbss:0x805220E8; // type:object size:0x1 data:byte lbl_805220E9 = .sbss:0x805220E9; // type:object size:0x1 data:byte __ntd_ohci = .sbss:0x805220EC; // type:object size:0x4 scope:global align:4 data:4byte diff --git a/configure.py b/configure.py index 7e1e12f274..b8ffadbb32 100755 --- a/configure.py +++ b/configure.py @@ -1863,8 +1863,8 @@ config.libs = [ "wud", [ Object(NonMatching, "revolution/wud/WUD.c"), - Object(NonMatching, "revolution/wud/WUDHidHost.c"), - Object(NonMatching, "revolution/wud/debug_msg.c"), + Object(MatchingFor(ALL_WII), "revolution/wud/WUDHidHost.c"), + Object(MatchingFor(ALL_WII), "revolution/wud/debug_msg.c"), ], ), RevolutionLib( diff --git a/include/revolution/os.h b/include/revolution/os.h index 7fcffb8f5f..f896dd5144 100644 --- a/include/revolution/os.h +++ b/include/revolution/os.h @@ -105,6 +105,7 @@ u8 __gUnknown800030E3 AT_ADDRESS(OS_BASE_CACHED | 0x30E3); #define OSMillisecondsToTicks(msec) ((msec) * (OS_TIMER_CLOCK / 1000)) #define OSNanosecondsToTicks(nsec) (((nsec) * (OS_TIMER_CLOCK / 125000)) / 8000) #define OSMicrosecondsToTicks(usec) (((usec) * (OS_TIMER_CLOCK / 125000)) / 8) +#define OSTicksDelta(x, y) ((s32)x, (s32)y) u32 OSGetConsoleType(void); void OSInit(void); diff --git a/include/revolution/sc.h b/include/revolution/sc.h index 89b205cec4..88ecad9660 100644 --- a/include/revolution/sc.h +++ b/include/revolution/sc.h @@ -11,6 +11,13 @@ extern "C" { typedef u8 SCType; +typedef enum { + SC_STATUS_OK, + SC_STATUS_BUSY, + SC_STATUS_FATAL, + SC_STATUS_PARSE, +} SCStatus; + typedef struct { u8 mode; u8 led; @@ -108,6 +115,57 @@ typedef struct { u32 flushSize; } SCControl; +#define SC_MAX_DEV_ENTRY_FOR_STD 10 +#define SC_MAX_DEV_ENTRY_FOR_SMP 6 +#define SC_MAX_DEV_ENTRY (SC_MAX_DEV_ENTRY_FOR_STD + SC_MAX_DEV_ENTRY_FOR_SMP) + +typedef struct { + BD_ADDR bd_addr; + u8 bd_name[64]; + u8 link_key[16]; +} SCBtCmpDevInfoSingle; + +typedef struct { + BD_ADDR bd_addr; + u8 bd_name[64]; +} SCBtDeviceInfoSingle; + +typedef struct { + u8 num; + SCBtCmpDevInfoSingle info[6]; +} SCBtCmpDevInfoArray; + +typedef struct SCDevInfo { + char devName[20]; // at 0x0 + char at_0x14[1]; + char UNK_0x15[0xB]; + LINK_KEY linkKey; // at 0x20 + char UNK_0x30[0x10]; +} SCDevInfo; + +typedef struct SCBtDeviceInfo { + BD_ADDR addr; // at 0x0 + SCDevInfo info; // at 0x6 +} SCBtDeviceInfo; + +typedef struct SCBtDeviceInfoArray { + /* 0x000 */ u8 num; + + union { + struct { +#if SDK_AUG2010 + /* 0x001 */ SCBtDeviceInfo regist[SC_MAX_DEV_ENTRY_FOR_STD]; + /* 0x2BD */ SCBtDeviceInfo active[SC_MAX_DEV_ENTRY_FOR_SMP]; +#else + /* 0x001 */ SCBtDeviceInfo regist[SC_MAX_DEV_ENTRY]; +#endif + }; + }; +#if SDK_AUG2010 + SCBtDeviceInfoSingle info[16]; +#endif +} SCBtDeviceInfoArray; + #define SC_LANG_JAPANESE 0u #define SC_LANG_ENGLISH 1u #define SC_LANG_GERMAN 2u @@ -152,6 +210,7 @@ BOOL SCFindS8Item(s8* data, SCItemID id); BOOL SCFindU32Item(u32* data, SCItemID id); BOOL SCReplaceU8Item(u8 data, SCItemID id); void SCFlushAsync(SCFlushCallback callback); +BOOL SCGetBtDeviceInfoArray(SCBtDeviceInfoArray*); BOOL SCSetBtDeviceInfoArray(const SCBtDeviceInfoArray*); u32 SCCheckStatus(void); s32 SCReloadConfFileAsync(u8* bufp, u32 bufSize, SCReloadConfFileCallback callback); diff --git a/include/revolution/wpad.h b/include/revolution/wpad.h index c2b23c436a..09881c6551 100644 --- a/include/revolution/wpad.h +++ b/include/revolution/wpad.h @@ -135,7 +135,7 @@ typedef void (*WPADInitFunc)(void); typedef void (*WPADCallback)(s32 chan, s32 result); typedef void (*WPADExtensionCallback)(s32 chan, s32 devType); typedef void* (*WPADAlloc)(u32 size); -typedef u8 (*WPADFree)(void* ptr); +typedef BOOL (*WPADFree)(void* ptr); typedef void (*WPADSyncDeviceCallback)(s32 result, s32 num); typedef void (*WPADSamplingCallback)(s32 chan); typedef void (*WPADConnectCallback)(s32 chan, s32 result); diff --git a/include/revolution/wpad/bte.h b/include/revolution/wpad/bte.h index a09000a254..8f936a6b54 100644 --- a/include/revolution/wpad/bte.h +++ b/include/revolution/wpad/bte.h @@ -596,13 +596,19 @@ typedef union typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data); /* Search callback events */ -#define BTA_DM_INQ_RES_EVT 0 /* Inquiry result for a peer device. */ -#define BTA_DM_INQ_CMPL_EVT 1 /* Inquiry complete. */ -#define BTA_DM_DISC_RES_EVT 2 /* Discovery result for a peer device. */ -#define BTA_DM_DISC_BLE_RES_EVT 3 /* Discovery result for BLE GATT based service on a peer device. */ -#define BTA_DM_DISC_CMPL_EVT 4 /* Discovery complete. */ -#define BTA_DM_DI_DISC_CMPL_EVT 5 /* Discovery complete. */ -#define BTA_DM_SEARCH_CANCEL_CMPL_EVT 6 /* Search cancelled */ +enum BTA_DM_State_e { + BTA_DM_INQ_RES_EVT, /* Inquiry result for a peer device. */ + BTA_DM_INQ_CMPL_EVT, /* Inquiry complete. */ + BTA_DM_DISC_RES_EVT, /* Discovery result for a peer device. */ +#if SDK_AUG2010 + BTA_DM_DISC_BLE_RES_EVT, /* Discovery result for BLE GATT based service on a peer device. */ +#endif + BTA_DM_DISC_CMPL_EVT, /* Discovery complete. */ +#if SDK_AUG2010 + BTA_DM_DI_DISC_CMPL_EVT, /* Discovery complete. */ +#endif + BTA_DM_SEARCH_CANCEL_CMPL_EVT, /* Search cancelled */ +}; typedef UINT8 tBTA_DM_SEARCH_EVT; @@ -1028,39 +1034,4 @@ void BTA_HhGetAclQueueInfo(void); void BTA_Init(void); void BTA_CleanUp(void (*p_cb)(tBTA_STATUS status)); // probably -// --- -/* muff1n: I wrote this definition myself - * TODO: would this be part of BLE or WUD? - */ - -struct small_dev_info -{ - char devName[20]; // size 0x14? offset 0x00 // might be 0x13? - char at_0x14[1]; // size 0x??, offset 0x14? - char __pad0[0x20 - (0x14 + 0x01)]; - LINK_KEY linkKey; // size 0x10, offset 0x20 - char __pad1[0x10]; -}; // size 0x40 - -typedef struct { - BD_ADDR bd_addr; - u8 bd_name[64]; - u8 link_key[16]; -} SCBtCmpDevInfoSingle; - -typedef struct { - BD_ADDR bd_addr; - u8 bd_name[64]; -} SCBtDeviceInfoSingle; - -typedef struct { - u8 num; - SCBtCmpDevInfoSingle info[6]; -} SCBtCmpDevInfoArray; - -typedef struct { - u8 num; - SCBtDeviceInfoSingle info[16]; -} SCBtDeviceInfoArray; - #endif // CONTEXT_BTE_H diff --git a/include/revolution/wud.h b/include/revolution/wud.h new file mode 100644 index 0000000000..292c7c50aa --- /dev/null +++ b/include/revolution/wud.h @@ -0,0 +1,150 @@ +#ifndef RVL_SDK_WUD_H +#define RVL_SDK_WUD_H + + +#include +#include + +#include "types.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define WUD_MAX_DEV_ENTRY_FOR_STD SC_MAX_DEV_ENTRY_FOR_STD +#define WUD_MAX_DEV_ENTRY_FOR_SMP SC_MAX_DEV_ENTRY_FOR_SMP +#define WUD_MAX_DEV_ENTRY SC_MAX_DEV_ENTRY +#define WUD_DEV_HANDLE_INVALID (-1) +#define WUD_ADDR_LEN BD_ADDR_LEN + +// Forward declarations +typedef struct WUDDevInfo WUDDevInfo; + +typedef enum { + WUD_LIB_STATUS_0, + WUD_LIB_STATUS_1, + WUD_LIB_STATUS_2, + WUD_LIB_STATUS_3, + WUD_LIB_STATUS_4, + WUD_LIB_STATUS_5, +} WUDLibStatus; + +typedef enum { + WUD_CHAN0, + WUD_CHAN1, + WUD_CHAN2, + WUD_CHAN3, + + WUD_MAX_CHANNELS, + WUD_CHAN_INVALID = -1 +} WUDChannel; + +typedef enum { + WUD_SYNC_TYPE_STANDARD, + WUD_SYNC_TYPE_SIMPLE, +} WUDSyncType; + +typedef enum { + WUD_RESULT_SYNC_BUSY = -1, + WUD_RESULT_SYNC_WAITING, + WUD_RESULT_SYNC_DONE, +} WUDSyncResult; + +typedef void* (*WUDAllocFunc)(u32 size); +typedef BOOL (*WUDFreeFunc)(void* pBlock); + +typedef void (*WUDSyncDeviceCallback)(s32 result, s32 num); +typedef void (*WUDClearDeviceCallback)(s32 result); + +typedef void (*WUDHidConnCallback)(u8, u8); +typedef void (*WUDHidRecvCallback)(UINT8 devHandle, UINT8* pReport, UINT16 len); + +typedef struct WUDDevInfo { + SCDevInfo conf; // at 0x0 + BD_ADDR devAddr; // at 0x40 + LINK_KEY linkKey; // at 0x46 + UINT8 devHandle; // at 0x56 + UINT8 subclass; // at 0x57 + UINT8 appID; // at 0x58 + u8 status; // at 0x59 + s8 UNK_0x5A; // at 0x5A + u8 sync_type; // at 0x5B + u8 UNK_0x5C; // at 0x5C + u8 UNK_0x5D[1]; + tBTA_HH_ATTR_MASK hhAttrMask; // at 0x5E +} WUDDevInfo; + +BOOL WUDInit(void); +BOOL WUDIsBusy(void); +void WUDRegisterAllocator(WUDAllocFunc pAllocFunc, WUDFreeFunc pFreeFunc); +u32 WUDGetAllocatedMemSize(void); +void WUDShutdown(void); + +WUDLibStatus WUDGetStatus(void); +u8 WUDGetBufferStatus(void); + +void WUDSetSniffMode(BD_ADDR addr, s32 interval); + +// clang-format off +WUDSyncDeviceCallback +WUDSetSyncSimpleCallback(WUDSyncDeviceCallback pCallback); + +WUDClearDeviceCallback +WUDSetClearDeviceCallback(WUDClearDeviceCallback pCallback); +// clang-format on + +BOOL WUDStartSyncDevice(void); +BOOL WUDStartFastSyncSimple(void); +BOOL WUDStartSyncSimple(void); +BOOL WUDStopSyncSimple(void); +BOOL WUDCancelSyncDevice(void); + +BOOL WUDStartClearDevice(void); +BOOL WUDSetDisableChannel(s8 afhChannel); + +WUDHidRecvCallback WUDSetHidRecvCallback(WUDHidRecvCallback pCallback); +WUDHidConnCallback WUDSetHidConnCallback(WUDHidConnCallback pCallback); + +void WUDSetVisibility(u8 disc, u8 conn); +u8 WUDGetConnectable(void); + +void WUDiGetFirmwareVersion(void); +void WUDiInitSub(void); + +void WUDiEnableStack(void); +void WUDiAutoSync(void); +void WUDiDeleteAllLinkKeys(void); + +void WUDiRegisterDevice(BD_ADDR addr); +void WUDiRemoveDevice(BD_ADDR addr); + +WUDDevInfo* WUDiGetDevInfo(BD_ADDR addr); +WUDDevInfo* WUDiGetDevInfoIndex(int idx); +WUDDevInfo* WUDiGetNewDevInfo(void); +void WUDiRemoveDevInfo(BD_ADDR addr); +void WUDiClearDevice(void); + +u8 WUDiGetDevNumber(void); +u8 WUDiGetDevSmpNumber(void); +u8 WUDiGetConnNumber(void); +u8 WUDiGetLinkNum(void); + +void WUDiMoveTopSmpDevInfoPtr(WUDDevInfo* pInfo); +void WUDiMoveBottomSmpDevInfoPtr(WUDDevInfo* pInfo); +WUDDevInfo* WUDiGetRemoveSmpDevice(void); +void WUDiMoveTopOfDisconnectedSmpDevice(WUDDevInfo* pInfo); + +void WUDiMoveTopStdDevInfoPtr(WUDDevInfo* pInfo); +void WUDiMoveBottomStdDevInfoPtr(WUDDevInfo* pInfo); +WUDDevInfo* WUDiGetRemoveStdDevice(void); +void WUDiMoveTopOfDisconnectedStdDevice(WUDDevInfo* pInfo); + +BD_ADDR_PTR _WUDGetDevAddr(UINT8 handle); +u16 _WUDGetQueuedSize(s8 dev_handle); +u16 _WUDGetNotAckedSize(s8 dev_handle); +u8 _WUDGetLinkNumber(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/revolution/wud/WUD.h b/include/revolution/wud/WUD.h deleted file mode 100644 index 138733f1f0..0000000000 --- a/include/revolution/wud/WUD.h +++ /dev/null @@ -1,256 +0,0 @@ -#ifndef _REVOLUTION_WUD_WUD_H_ -#define _REVOLUTION_WUD_WUD_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define WUD_CHAN0 0 -#define WUD_CHAN1 1 -#define WUD_CHAN2 2 -#define WUD_CHAN3 3 -#define WUD_MAX_CHANNELS 4 - -#define WUD_CHAN_INVALID -1 - -typedef void* WUDAllocFunc(u32 size); -typedef int WUDFreeFunc(void* ptr); // signature from petari. not sure what the int is, though - -typedef struct WUDDevInfo { - /* 0x00 */ struct small_dev_info small; - /* 0x40 */ BD_ADDR devAddr; - /* 0x46 */ LINK_KEY linkKey; - /* 0x56 */ u8 devHandle; - /* 0x57 */ u8 subclass; - /* 0x58 */ u8 appID; - /* 0x59 */ u8 at_0x59; - /* 0x5a */ u8 at_0x5a; /* unknown */ - /* 0x5b */ u8 at_0x5b; - /* 0x5c */ u8 at_0x5c; - u8 at_0x5d[1]; // padding? - /* 0x5e */ tBTA_HH_ATTR_MASK hhAttrMask; -} WUDDevInfo; // size 0x60 - -typedef void WUDHidConnectCallback(WUDDevInfo* devInfo, u8 isOpenEvent); -typedef void WUDHidReceiveCallback(u8 dev_handle, u8* p_rpt, u16 len); - -u8 WUDGetBufferStatus(void); -u8 _WUDGetLinkNumber(void); -u16 _WUDGetQueuedSize(s8 dev_handle); -u16 _WUDGetNotAckedSize(s8 dev_handle); - -typedef u8 BTD_NAME[64]; -typedef u8 BTD_ADDR[6]; -typedef u8 LINKKEY[16]; - -typedef enum { - WUD_STATE_SYNC_START = 0, - WUD_STATE_SYNC_PREPARE_SEARCH = 1, - WUD_STATE_SYNC_START_SEARCH = 2, - WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT = 3, - WUD_STATE_SYNC_CHECK_SEARCH_RESULT = 4, - WUD_STATE_SYNC_IS_EXISTED_DEVICE = 5, - WUD_STATE_SYNC_6 = 6, - WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM = 7, - WUD_STATE_SYNC_WAIT_FOR_STORING = 8, - WUD_STATE_SYNC_WAIT_FOR_READING = 10, - WUD_STATE_SYNC_11 = 11, - WUD_STATE_SYNC_12 = 12, - WUD_STATE_SYNC_13 = 13, - WUD_STATE_SYNC_DONE = 14, - WUD_STATE_SYNC_TRY_CONNECT = 15, - WUD_STATE_SYNC_PREPARE_FOR_EXISTED_DEVICE = 16, - WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE = 17, - WUD_STATE_SYNC_REGISTER_DEVICE = 18, - WUD_STATE_SYNC_VIRGIN_SIMPLE = 19, - WUD_STATE_SYNC_VIRGIN_STANDARD = 20, - WUD_STATE_SYNC_CHANGE_SIMPLE_TO_STANDARD = 21, - WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND = 22, - WUD_STATE_SYNC_COMPLETE = 23, - WUD_STATE_SYNC_WAIT_FOR_INCOMING = 24, - WUD_STATE_SYNC_SC_FLUSH = 25, - WUD_STATE_SYNC_CANCEL_SEARCH = 26, - WUD_STATE_SYNC_WAIT_FOR_START_SEARCH = 29, - WUD_STATE_SYNC_ERROR = 255, -} WUDSyncState; - -typedef enum { - WUD_STATE_DELETE_START = 0, - WUD_STATE_DELETE_DISALLOW_INCOMING = 1, - WUD_STATE_DELETE_DISCONNECT_ALL = 2, - WUD_STATE_DELETE_CLEANUP_DATABASE = 3, - WUD_STATE_DELETE_CLEANUP_SETTING = 5, - WUD_STATE_DELETE_6 = 6, - WUD_STATE_DELETE_7 = 7, - WUD_STATE_DELETE_DONE = 8 -} WUDDeleteState; - -typedef enum { - WUD_RESULT_DELETE_BUSY = -1, - WUD_RESULT_DELETE_WAITING, - WUD_RESULT_DELETE_COMPLETE, -} WUDDeleteResult; - -typedef enum { - WUD_STATE_LINK_KEY_START = 0, - WUD_STATE_LINK_KEY_READING = 1, - WUD_STATE_LINK_KEY_WRITING = 2, - WUD_STATE_LINK_KEY_DELETING = 3, - WUD_STATE_LINK_KEY_ERROR = 255, -} WUDLinkKeyState; - -typedef enum { - WUD_STATE_STACK_START = 0, - WUD_STATE_STACK_GET_STORED_LINK_KEY = 1, - WUD_STATE_STACK_CHECK_DEVICE_INFO = 2, - WUD_STATE_STACK_DONE = 3, - WUD_STATE_STACK_INITIALIZED = 4, - WUD_STATE_STACK_ERROR = 255, -} WUDStackState; - -typedef enum { - WUD_STATE_INIT_START = 0, - WUD_STATE_INIT_WAIT_FOR_INITIALIZATION = 1, - WUD_STATE_INIT_GET_DEV_INFO = 2, - WUD_STATE_INIT_DONE = 3, - WUD_STATE_INIT_INITIALIZED = 4, - WUD_STATE_INIT_ERROR = 255, -} WUDInitState; - -typedef enum { - WUD_STATE_SHUTDOWN_START = 0, - WUD_STATE_SHUTDOWN_STORE_SETTINGS = 1, - WUD_STATE_SHUTDOWN_FLUSH_SETTINGS = 2, - WUD_STATE_SHUTDOWN_DONE = 3, - WUD_STATE_SHUTDOWN_ERROR = 255, -} WUDShutdownState; - -typedef enum { - WUD_VSE_INITIATE_PAIRING = 8, - WUD_VSE_DELETE_ALL_KEYS, - WUD_VSE_SI_PORT_STATUS, - WUD_VSE_WATCH_DOG_RESET_HW = 16, -} WUDVendorSpecificEvent; - -typedef struct WUDDeviceInfo { - BTD_NAME bd_name; - BTD_ADDR bd_addr; - LINKKEY link_key; - u8 handle; - u8 sub_class; - u8 app_id; - u8 status; - u8 overwrite; - u8 sync_type; - u8 reg; - u16 attr_mask; -} WUDDeviceInfo; - -typedef void* (*WUDAlloc)(u32); -typedef u8 (*WUDFree)(void*); -typedef void (*WUDSyncDeviceCallback)(s32 result, s32 num); // what is result? -typedef void (*WUDClearDeviceCallback)(s32); -typedef void (*WUDHidRecvCallback)(u8, u8*, u16); -typedef void (*WUDHidConnCallback)(u8, u8); -typedef void (*WUDStoredCallback)(void*); - -typedef struct DeviceList { - WUDDeviceInfo* info; - void* prev; - void* next; -} DeviceList; - -typedef struct WUDControlBlock { - WUDSyncDeviceCallback syncCallback; - WUDSyncDeviceCallback syncSmpCallback; - WUDClearDeviceCallback clearCallback; - u8 syncStatus; - u8 delStatus; - u8 keyStatus; - u8 profStatus; - u8 initStatus; - u8 shutStatus; - u8 devNums; - u8 devSmpNums; - DeviceList* smpListHead; - DeviceList* smpListTail; - DeviceList smpList[6]; - DeviceList* stdListHead; - DeviceList* stdListTail; - DeviceList stdList[10]; - WUDDeviceInfo devInfo[10]; - WUDDeviceInfo devSmpInfo[6]; - u8 connNums; - u8 linkNums; - u8 pairNums; - u8 syncFast; - s8 syncLoop; - u8 syncMode; - u8 connectable; - u8 discoverable; - WUDHidRecvCallback hidRecvCallback; - WUDHidConnCallback hidConnCallback; - WUDAlloc alloc; - WUDFree free; - BTD_ADDR lastAddr; - BTD_ADDR hostAddr; - s8 status; - u8 siStatus; - u8 pmId; - s8 rssi; - OSAlarm evtAlarm; - u32 profileMask; - u16 aclAvailBufSize; - u16 aclMaxBufSize; - s16 delayCnt; - s16 incomeCnt; -} WUDControlBlock; - -BOOL WUDInit(); -BOOL WUDStartSyncSimple(void); -BOOL WUDStartFastSyncSimple(void); -u32 WUDGetAllocatedMemSize(void); -WUDSyncDeviceCallback WUDSetSyncSimpleCallback(WUDSyncDeviceCallback); -void WUDiMoveTopSmpDevInfoPtr(WUDDeviceInfo*); -void WUDiMoveTopStdDevInfoPtr(WUDDeviceInfo*); -void WUDSetSniffMode(BTD_ADDR, s32); -void WUDiRemoveDevice(BTD_ADDR); -void WUDiMoveBottomSmpDevInfoPtr(WUDDeviceInfo*); -void WUDiMoveTopSmpDevInfoPtr(WUDDeviceInfo*); -void WUDiMoveBottomStdDevInfoPtr(WUDDeviceInfo*); -void WUDiMoveTopOfDisconnectedSmpDevice(WUDDeviceInfo*); -void WUDiMoveTopOfDisconnectedStdDevice(WUDDeviceInfo*); -WUDDeviceInfo* WUDiGetDevInfo(BTD_ADDR); - -BOOL WUDCancelSyncDevice(void); -BOOL WUDStopSyncSimple(void); -s32 WUDGetStatus(void); -void WUDShutdown(); -void WUDSetVisibility(u8, u8); -u8 WUDGetConnectable(void); -BOOL WUDIsBusy(void); -WUDHidRecvCallback WUDSetHidRecvCallback(WUDHidRecvCallback); -WUDHidConnCallback WUDSetHidConnCallback(WUDHidConnCallback); -void WUDRegisterAllocator(WUDAlloc, WUDFree); -u8* _WUDGetDevAddr(u8); -BOOL WUDSetDisableChannel(s8); -u8 WUDGetBufferStatus(void); -u8 _WUDGetLinkNumber(void); -u16 _WUDGetQueuedSize(s8); -u16 _WUDGetNotAckedSize(s8); - -extern WUDControlBlock _wcb; -extern WUDDeviceInfo _work; -extern u8* _dev_handle_to_bda[16]; -extern u16 _dev_handle_queue_size[16]; -extern u16 _dev_handle_notack_num[16]; -extern SCBtDeviceInfoArray _scArray; - -#ifdef __cplusplus -} -#endif - -#endif /* _REVOLUTION_WUD_WUD_H_ */ diff --git a/include/revolution/wud/debug_msg.h b/include/revolution/wud/debug_msg.h deleted file mode 100644 index 550bf9a0ba..0000000000 --- a/include/revolution/wud/debug_msg.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _REVOLUTION_WUD_DEBUG_MSG_H_ -#define _REVOLUTION_WUD_DEBUG_MSG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void WUD_DEBUGPrint(const char*, ...); - -#ifdef __cplusplus -} -#endif - -#endif /* _REVOLUTION_WUD_DEBUG_MSG_H_ */ diff --git a/src/revolution/wpad/WPAD.c b/src/revolution/wpad/WPAD.c index 6f01d6e459..9bdbe70b04 100644 --- a/src/revolution/wpad/WPAD.c +++ b/src/revolution/wpad/WPAD.c @@ -1,11 +1,12 @@ #include #include -#include +#include #include #include #include #include +#include #include #include @@ -14,7 +15,11 @@ extern volatile BOOL __OSIsReturnToIdle; //TODO: this apparently should be aligned to 32 bytes, but // adding ATTRIBUTE_ALIGN breaks codegen in WPADInit WPADControlBlock _wpd[WPAD_MAX_CONTROLLERS]; +#if SDK_AUG2010 +WPADControlBlock* __rvl_p_wpadcb[WPAD_MAX_CONTROLLERS]; +#else WPADControlBlock* _wpdcb[WPAD_MAX_CONTROLLERS]; +#endif u8 _sleepTime; u8 _dpdSensitivity; @@ -89,7 +94,7 @@ BOOL OnShutdown(BOOL final, u32 event) { _shutdown = TRUE; WUDSetVisibility(0, 0); for (i = 10; i < 14; i++) { - memset(&_scArray.info[i], 0, sizeof(_scArray.info[i])); + memset(&_scArray.regist[i], 0, sizeof(_scArray.regist[i])); } OSCancelAlarm(&_managerAlarm); WUDSetHidRecvCallback(NULL); @@ -1030,7 +1035,7 @@ s32 WPADiRetrieveChannel(u8 dev_handle) { devAddr = _WUDGetDevAddr(dev_handle); for (i = 0; i < WPAD_MAX_CONTROLLERS; i++) { - if (!memcmp(_scArray.info[i + 10].bd_addr, devAddr, 6)) { + if (!memcmp(_scArray.regist[i + 10].addr, devAddr, 6)) { if (_chan_active_state[i] == 0) { _chan_active_state[i] = 1; return i; @@ -1040,7 +1045,7 @@ s32 WPADiRetrieveChannel(u8 dev_handle) { for (i = 0; i < WPAD_MAX_CONTROLLERS; i++) { if (_chan_active_state[i] == 0) { _chan_active_state[i] = 1; - memcpy(_scArray.info[i + 10].bd_addr, devAddr, 6); + memcpy(_scArray.regist[i + 10].addr, devAddr, 6); _scFlush = 1; return i; } @@ -1319,8 +1324,7 @@ u8 WPADGetSensorBarPosition() { } void WPADDisconnect(s32 chan) { - WPADControlBlock* p_wpd = _wpdcb[chan]; - memset(&_scArray.info[chan + 10], 0, sizeof(SCBtDeviceInfoSingle)); + memset(&_scArray.regist[chan + 10], 0, sizeof(SCBtDeviceInfo)); _scFlush = 1; WPADiDisconnect(chan, TRUE); } @@ -2523,17 +2527,17 @@ void __WPADShutdown() { WUDSetVisibility(0, 0); for (i = 10; i < 14; i++) { - memset(&_scArray.info[i], 0, sizeof(SCBtDeviceInfoSingle)); + memset(&_scArray.regist[i], 0, sizeof(SCBtDeviceInfo)); } WPADiShutdown(FALSE); OSRestoreInterrupts(enable); } -void WPADiShutdown(BOOL exec) { +void WPADiShutdown() { OSCancelAlarm(&_managerAlarm); WUDSetHidRecvCallback(NULL); - WUDShutdown(exec); + WUDShutdown(); } BOOL WPADCancelSyncDevice() { diff --git a/src/revolution/wpad/__wpad.h b/src/revolution/wpad/__wpad.h index 2c5329a221..500183cfae 100644 --- a/src/revolution/wpad/__wpad.h +++ b/src/revolution/wpad/__wpad.h @@ -380,7 +380,9 @@ typedef struct WPADDevConfig { /* 0x26 */ WPADAcc acc_1g; /* 0x2C */ u8 motor; /* 0x2D */ u8 volume; +#if SDK_AUG2010 /* 0x2E */ u8 unk_0x2e[0x30 - 0x2e]; +#endif } WPADDevConfig; typedef struct WPADStick { @@ -419,7 +421,11 @@ typedef struct WPADExtConfig { /* 0x00 */ union { WPADFsConfig fs; WPADClConfig cl; +#if SDK_AUG2010 u8 bytes[0x1c]; +#else + u8 bytes[0x18]; +#endif }; #if SDK_AUG2010 struct WPADMplsConfig { @@ -533,36 +539,40 @@ typedef struct WPADControlBlock { /* 0x8C4 */ u16 packetCnt; /* 0x8C6 */ u8 disconnect; /* 0x8C7 */ u8 lastReportId; - /* 0xb80 */ WPADCallback getInfoCB; - /* 0xb84 */ u8 getInfoBusy; - /* 0xb85 */ u8 extState; - /* 0xb86 */ u8 savePower; - /* 0xb87 */ u8 blcBattery; - /* 0xb88 */ u8 savedDevType; // maybe? - /* 0xb89 */ u8 extWasDisconnected; - /* 0xb8a */ s16 reconnectExtMs; - /* 0xb8c */ WPADMemBlock memBlock; - /* 0xba0 */ WPADCallback controlMplsCB; - /* 0xba4 */ u8 parseMPBuf; - /* 0xba5 */ u8 certProbeByte; - /* 0xba6 */ u8 dpdBusy; - /* 0xba7 */ u8 interleaveFlags; - /* 0xba8 */ u32 mplsCBReadAddress; - /* 0xbac */ u8 mplsCBState; - /* 0xbad */ u8 mplsUptimeMs; - /* 0xbae */ s8 certMayVerifyByCalibBlock; - /* 0xbaf */ u8 unk_0xbaf[0xbb1 - 0xbaf]; /* unknown (can't be alignment) */ - /* 0xbb1 */ u8 certProbeStartingValue; - /* 0xbb2 */ u16 lastMplsCalibID; - /* 0xbb4 */ u32 lastMplsCalibCRC; - /* 0xbb8 */ u8 noParseExtCount; - /* 0xbb9 */ s8 extErr; - /* 0xbba */ u8 extDataLength; - /* 0xbbb */ u8 extDevType; - /* 0xbbc */ u8 currPwmDuty; - /* 0xbbd */ u8 pendingPwmDuty; - /* 0xbbe */ u8 unk_0xbbe[0xbc0 - 0xbbe]; /* unknown (can't be alignment) */ - /* 0xbc0 */ u8 extDataBuf[32]; +#if SDK_AUG2010 + /* 0xB80 */ WPADCallback getInfoCB; + /* 0xB84 */ u8 getInfoBusy; + /* 0xB85 */ u8 extState; + /* 0xB86 */ u8 savePower; + /* 0xB87 */ u8 blcBattery; + /* 0xB88 */ u8 savedDevType; // maybe? + /* 0xB89 */ u8 extWasDisconnected; + /* 0xB8A */ s16 reconnectExtMs; + /* 0xB8C */ WPADMemBlock memBlock; + /* 0xBA0 */ WPADCallback controlMplsCB; + /* 0xBA4 */ u8 parseMPBuf; + /* 0xBA5 */ u8 certProbeByte; + /* 0xBA6 */ u8 dpdBusy; + /* 0xBA7 */ u8 interleaveFlags; + /* 0xBA8 */ u32 mplsCBReadAddress; + /* 0xBAC */ u8 mplsCBState; + /* 0xBAD */ u8 mplsUptimeMs; + /* 0xBAE */ s8 certMayVerifyByCalibBlock; + /* 0xBAF */ u8 unk_0xbaf[0xbb1 - 0xbaf]; /* unknown (can't be alignment) */ + /* 0xBB1 */ u8 certProbeStartingValue; + /* 0xBB2 */ u16 lastMplsCalibID; + /* 0xBB4 */ u32 lastMplsCalibCRC; + /* 0xBB8 */ u8 noParseExtCount; + /* 0xBB9 */ s8 extErr; + /* 0xBBA */ u8 extDataLength; + /* 0xBBB */ u8 extDevType; + /* 0xBBC */ u8 currPwmDuty; + /* 0xBBD */ u8 pendingPwmDuty; + /* 0xBBE */ u8 unk_0xbbe[0xbc0 - 0xbbe]; /* unknown (can't be alignment) */ + /* 0xBC0 */ u8 extDataBuf[32]; +#else + /* 0x8C8 */ u8 extDataBuf[0x8e0 - 0x8c8]; +#endif } WPADControlBlock; typedef struct WPADMEMControlBlock { @@ -609,7 +619,7 @@ u32 WPADGetLatestIndexInBuf(s32 chan, void* buf); void WPADiExcludeButton(s32 chan); s32 WPADiGetStatus(s32 chan); -void WPADiShutdown(BOOL exec); +void WPADiShutdown(); void WPADiDisconnect(s32 chan, BOOL polite); BOOL WPADiSendSetPort(WPADCmdQueue* queue, u8 pattern, WPADCallback callback); diff --git a/src/revolution/wud/WUD.c b/src/revolution/wud/WUD.c index 9c38c36731..b6f7073699 100644 --- a/src/revolution/wud/WUD.c +++ b/src/revolution/wud/WUD.c @@ -1,34 +1,2844 @@ -#include +#include +#include +#include +#include +#include +#include #include -#include -#include "__wud.h" -#include "types.h" +#include +#include +#include -wud_cb_st __rvl_wudcb; +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define CLAMP(val, min, max) ((val) > (max) ? (max) : (val) < (min) ? (min) : (val)) -static u16 _dev_handle_queue_size[WUD_MAX_DEV_ENTRY]; -static u16 _dev_handle_notack_num[WUD_MAX_DEV_ENTRY]; +#define DEBUGPrint WUD_DEBUGPrint + +#define BT_VSC_NINTENDO_INSTALL_PATCH 0xFC4F +#define BT_VSC_NINTENDO_WRITE_PATCH 0xFC4C + +void WUDSecurityCallback(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* pData); +void WUDSearchCallback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* pData); +void WUDVendorSpecificCallback(UINT8 len, UINT8* pData); +void WUDDeviceStatusCallback(tBTM_DEV_STATUS status); +void WUDStoredLinkKeyCallback(void* p1); +void WUDPowerManagerCallback(BD_ADDR addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hciStatus); + +//static void InitCore(void); + +static void WUDiRemovePatch(void); +static void WUDiWritePatch(void); +static void WUDiInstallPatch(void); + +#if SDK_AUG2010 +WUDControlBlock __rvl_wudcb; +#else +WUDControlBlock _wcb; +#endif +WUDDevInfo _work; +static WUDDiscResp _discResp; +SCBtDeviceInfoArray _scArray; +u8 __WUDHandlerStack[0x1000] ATTRIBUTE_ALIGN(32); + +extern u8 _scFlush; + +BD_ADDR_PTR _dev_handle_to_bda[WUD_MAX_DEV_ENTRY]; +u16 _dev_handle_queue_size[WUD_MAX_DEV_ENTRY]; +u16 _dev_handle_notack_num[WUD_MAX_DEV_ENTRY]; + +static BOOL _initialized = FALSE; +static u8 __bte_trace_level = 0; + +static OSAlarm _arm; + +static u8 _discNumResps; +static s8 _discRssi; + +// clang-format off +static u8 descriptor[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, // Usage (Game Pad) + + 0xA1, 0x01, // Collection (Application) + + 0x85, 0x10, // Report ID (16) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x11, // Report ID (17) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x12, // Report ID (18) + 0x95, 0x02, // Report Count (2) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x13, // Report ID (19) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x14, // Report ID (20) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x15, // Report ID (21) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x16, // Report ID (22) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x17, // Report ID (23) + 0x95, 0x06, // Report Count (6) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x18, // Report ID (24) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x19, // Report ID (25) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x1A, // Report ID (26) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x00, // Output (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + + 0x85, 0x20, // Report ID (32) + 0x95, 0x06, // Report Count (6) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x21, // Report ID (33) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x22, // Report ID (34) + 0x95, 0x04, // Report Count (4) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x30, // Report ID (48) + 0x95, 0x02, // Report Count (2) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x31, // Report ID (49) + 0x95, 0x05, // Report Count (5) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x32, // Report ID (50) + 0x95, 0x0A, // Report Count (10) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x33, // Report ID (51) + 0x95, 0x11, // Report Count (17) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x34, // Report ID (52) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x35, // Report ID (53) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x36, // Report ID (54) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x37, // Report ID (55) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x3D, // Report ID (61) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x3E, // Report ID (62) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0x85, 0x3F, // Report ID (63) + 0x95, 0x15, // Report Count (21) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) + + 0xC0, // End Collection +}; +// clang-format on + +void* App_MEMalloc(u32 size) { + DEBUGPrint("App_MEMalloc\n"); + return _wcb.allocFunc(size); +} + +BOOL App_MEMfree(void* pBlock) { + DEBUGPrint("App_MEMfree\n"); + return _wcb.freeFunc(pBlock); +} + +static void ReverseAddr(BD_ADDR_PTR pDst, BD_ADDR src) { + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + + for (i = 0; i < BD_ADDR_LEN; i++) { + pDst[i] = src[BD_ADDR_LEN - 1 - i]; + } + + OSRestoreInterrupts(enabled); +} + +static void SyncFlushCallback(u32 status) { + WUDControlBlock* p = &_wcb; + + DEBUGPrint("SyncFlushCallback() : %d, Sync: %d\n", status, _wcb.syncState); + + if (p->syncState == WUD_STATE_SYNC_START) { + return; + } + + if (status == SC_STATUS_OK) { + p->syncState = WUD_STATE_SYNC_COMPLETE; + } else { + p->syncState = WUD_STATE_SYNC_ERROR; + } +} + +static void DeleteFlushCallback(u32 status) { + WUDControlBlock* p = &_wcb; + + DEBUGPrint("DeleteFlushCallback() : %d, Delete: %d\n", status, _wcb.deleteState); + + if (p->deleteState == WUD_STATE_DELETE_START) { + return; + } + + if (status == SC_STATUS_OK) { + p->deleteState = WUD_STATE_DELETE_DONE; + } else { + p->deleteState = WUD_STATE_DELETE_DONE; + } +} + +static void ShutFlushCallback(u32 status) { + WUDControlBlock* p = &_wcb; + + DEBUGPrint("ShutFlushCallback() : %d, Shutdown: %d\n", status, _wcb.shutdownState); + + OSCancelAlarm(&_wcb.alarm); + p->shutdownState = WUD_STATE_SHUTDOWN_DONE; + BTA_DisableBluetooth(); +} + +static void ClearDiscoverResult(void) { + _discNumResps = 0; + memset(&_discResp, 0, sizeof(WUDDiscResp)); +} + +static void _resumeSmpSync(OSAlarm* pAlarm, OSContext* pContext) { +#pragma unused(pAlarm) +#pragma unused(pContext) + + _wcb.syncState = WUD_STATE_SYNC_PREPARE_SEARCH; +} + +static void WUDiWaitForIncomingConnection(void) { + u32 waitSec = WUDiGetLinkNum() == WUD_MAX_CHANNELS - 1 ? 4 : 2; + + if (WUDiGetLinkNum() == WUD_MAX_CHANNELS && WUDiGetConnNumber() == WUD_MAX_CHANNELS) { + _wcb.syncState = WUD_STATE_SYNC_DONE; + } + + OSCreateAlarm(&_arm); + OSSetAlarm(&_arm, OSSecondsToTicks(waitSec), _resumeSmpSync); +} + +static u8 WUDiIsSyncDisabled(void) { + WUDControlBlock* p = &_wcb; + int i; + WUDDevInfo* pInfo; + u8 waitSecs; + + if (p->syncLoopNum == 0) { + return WUD_STATE_SYNC_DONE; + } + + if (WUDiGetLinkNum() == WUD_MAX_CHANNELS && WUDiGetConnNumber() == WUD_MAX_CHANNELS) { + return WUD_STATE_SYNC_DONE; + } + + if (p->syncSkipChecks) { + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) { + pInfo = WUDiGetDevInfoIndex(i); + + if (pInfo->status == 9) { + WUDSetSniffMode(pInfo->devAddr, 0); + return WUD_STATE_SYNC_PREPARE_SEARCH; + } + } + } + + if (p->syncLoopNum > 0) { + p->syncLoopNum--; + } + + if (p->syncLoopNum == -1) { + p->syncLoopNum = -2; + waitSecs = WUDiGetLinkNum() == 3 ? 4 : 2; + + if (WUDiGetLinkNum() == 4 && WUDiGetConnNumber() == 4) { + _wcb.syncState = WUD_STATE_SYNC_DONE; + } + + OSCreateAlarm(&_arm); + OSSetAlarm(&_arm, OSSecondsToTicks(waitSecs), _resumeSmpSync); + return 0x18U; + } + + return WUD_STATE_SYNC_START_SEARCH; +} + +static u8 WUDiStartSearch(void) { + WUDControlBlock* p = &_wcb; + tBTA_DM_INQ dm_inq; + + dm_inq.mode = BTM_LIMITED_INQUIRY; + dm_inq.max_resps = 1; + dm_inq.report_dup = FALSE; + + if (p->syncSkipChecks) { + dm_inq.duration = 5 - 2; + } else if (p->syncType == WUD_SYNC_TYPE_STANDARD) { + dm_inq.duration = WUDiGetLinkNum() == WUD_MAX_CHANNELS - 1 ? 10 : 5; + dm_inq.duration -= p->syncLoopNum; + } else { + dm_inq.duration = WUDiGetLinkNum() == WUD_MAX_CHANNELS - 1 ? 10 - 2 : 5 - 2; + } + + ClearDiscoverResult(); + BTA_DmSearch(&dm_inq, 0, &WUDSearchCallback); + + return WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT; +} + +static u8 WUDiWaitForSearchResult(void) { + if (WUDiGetLinkNum() == WUD_MAX_CHANNELS && WUDiGetConnNumber() == WUD_MAX_CHANNELS) { + DEBUGPrint("Cancel searching because 4 connections exist.\n"); + BTA_DmSearchCancel(); + + return WUD_STATE_SYNC_CANCEL_SEARCH; + } + + return WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT; +} + +static u8 WUDiNextStepBySearchResult(void) { + WUDControlBlock* p = &_wcb; + WUDSyncState nextState = WUD_STATE_SYNC_PREPARE_SEARCH; + + if (_discNumResps > 0) { + if (WUD_DEV_NAME_IS_CNT(_discResp.devName)) { + if (_discRssi > p->syncRssi) { + nextState = WUD_STATE_SYNC_IS_EXISTED_DEVICE; + } + } + } else { + WUDiWaitForIncomingConnection(); + nextState = WUD_STATE_SYNC_WAIT_FOR_INCOMING; + } + + return nextState; +} + +static u8 WUDiCheckDeviceDataBase(void) { + WUDDevInfo* pInfo; + WUDSyncState nextState = WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE; + + pInfo = WUDiGetDevInfo(_discResp.devAddr); + + if (pInfo != NULL) { + memcpy(&_work, pInfo, sizeof(WUDDevInfo)); + nextState = WUD_STATE_SYNC_PREPARE_FOR_EXISTED_DEVICE; + } + + return nextState; +} + +static u8 WUDiExistedDevice(void) { + WUDDevInfo* pWork = &_work; + + pWork->status = 1; + + switch (pWork->sync_type) { + case 0: + case 2: + case 4: + case 5: { + if (_wcb.syncType == WUD_SYNC_TYPE_STANDARD) { + WUDiRemoveDevice(pWork->devAddr); + return WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE; + } else { + pWork->sync_type = 4; + } + + break; + } + + case 1: + case 3: { + WUDiMoveBottomSmpDevInfoPtr(pWork); + WUDiRemoveDevice(_wcb.smpListTail->devInfo->devAddr); + return WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE; + } + } + + return WUD_STATE_SYNC_TRY_CONNECT; +} + +static u8 WUDiUnknownDevice(void) { + WUDDevInfo* pWork = &_work; + + pWork->status = 1; + pWork->sync_type = _wcb.syncType == WUD_SYNC_TYPE_STANDARD ? 0 : 1; + + WUD_BDCPY(pWork->devAddr, _discResp.devAddr); + memcpy(pWork->conf.devName, _discResp.devName, sizeof(_discResp.devName)); + memset(pWork->linkKey, 0, LINK_KEY_LEN); + + return WUD_STATE_SYNC_TRY_CONNECT; +} + +static u8 WUDiTryConnecting(void) { + WUDSyncState nextState = WUD_STATE_SYNC_ERROR; + + if (WUD_DEV_NAME_IS_CNT(_discResp.devName)) { + _work.status = 2; + BTA_HhOpen(_work.devAddr, BTA_HH_PROTO_RPT_MODE, BTA_SEC_AUTHENTICATE); + nextState = WUD_STATE_SYNC_6; + } + + return nextState; +} + +static int WUDiSetPinCode(BD_ADDR addr) { + BD_ADDR pin; + BD_ADDR_PTR pAddr; + + pAddr = _wcb.syncType == WUD_SYNC_TYPE_STANDARD ? _wcb.hostAddr : addr; + + _work.UNK_0x5A = 1; + + ReverseAddr(pin, pAddr); + BTA_DmPinReply(addr, TRUE, BD_ADDR_LEN, pin); + + return 0; +} + +static BOOL WUDiIsFinishLinkKeyCmd(void) { + return _wcb.linkKeyState == WUD_STATE_LINK_KEY_START ? TRUE : FALSE; +} + +static BOOL WUDiIsFinishScCmd(void) { + return SCCheckStatus() != SC_STATUS_BUSY ? TRUE : FALSE; +} + +static WUDDevInfo* WUDiGetDevInfoFromIndex(s32 index) { + WUDDevInfo* result; + BOOL irq_enabled; + + irq_enabled = OSDisableInterrupts(); + + if (index >= 0 && index < WUD_MAX_DEV_ENTRY_FOR_STD) { + result = &_wcb.stdDevs[index]; + } else { + result = &_wcb.smpDevs[index - WUD_MAX_DEV_ENTRY_FOR_STD]; + } + + OSRestoreInterrupts(irq_enabled); + + return result; +} + +static u8 WUDiSaveDeviceToNand(void) { + WUDSyncState nextState = WUD_STATE_SYNC_COMPLETE; + WUDDevInfoList* pIt; + WUDDevInfo* devInfo; + u8 i; + u8 storedCount; + + if (!WUDiIsFinishScCmd()) { + return WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND; + } + + memset(&_scArray.regist, 0, sizeof(SCBtDeviceInfo) * WUD_MAX_DEV_ENTRY_FOR_STD); + + _scArray.num = WUDiGetDevNumber(); + + for (i = 0, storedCount = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + devInfo = WUDiGetDevInfoFromIndex(i); + if (devInfo->status != 0) { + if (devInfo->sync_type == 0 || devInfo->sync_type == 2 || devInfo->sync_type == 4) { + memcpy(&_scArray.regist[storedCount].addr, devInfo->devAddr, sizeof(BD_ADDR)); + memcpy(&_scArray.regist[storedCount].info, devInfo->conf.devName, sizeof(SCDevInfo)); + storedCount++; + } + } + } + + DEBUGPrint("%d devices is stored into SC.\n", storedCount); + + if (!SCSetBtDeviceInfoArray(&_scArray)) { + nextState = WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND; + } else { + nextState = WUD_STATE_SYNC_SC_FLUSH; + } + + return nextState; +} + +static void WUDiSaveFlush(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + + enabled = OSDisableInterrupts(); + p->syncState = WUD_STATE_SYNC_13; + OSRestoreInterrupts(enabled); + + SCFlushAsync(SyncFlushCallback); +} + +static u8 WUDiVirginSimpleSync(void) { + WUDDevInfo* pInfo; + + if (WUDiGetDevSmpNumber() == WUD_MAX_DEV_ENTRY_FOR_SMP) { + pInfo = WUDiGetRemoveSmpDevice(); + WUDiRemoveDevice(pInfo->devAddr); + } + + pInfo = WUDiGetNewDevInfo(); + memcpy(pInfo, &_work, sizeof(WUDDevInfo)); + + WUDiRegisterDevice(pInfo->devAddr); + WUDiMoveTopSmpDevInfoPtr(pInfo); + + _dev_handle_to_bda[pInfo->devHandle] = pInfo->devAddr; + + return WUD_STATE_SYNC_COMPLETE; +} + +static u8 WUDiVirginStandardSync(void) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + + if (WUDiGetDevNumber() == WUD_MAX_DEV_ENTRY_FOR_STD) { + p->linkKeyState = 1; + BTM_ReadStoredLinkKey(0, WUDStoredLinkKeyCallback); + + return WUD_STATE_SYNC_WAIT_FOR_READING; + } else { + pInfo = WUDiGetNewDevInfo(); + memcpy(pInfo, &_work, sizeof(WUDDevInfo)); + + WUDiRegisterDevice(pInfo->devAddr); + + _dev_handle_to_bda[pInfo->devHandle] = pInfo->devAddr; + + return WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; + } + +} + +static u8 WUDiChangeSimpleToStandard(void) { + WUDiMoveBottomSmpDevInfoPtr(&_work); + WUDiRemoveDevice(_wcb.smpListTail->devInfo->devAddr); + return WUDiVirginStandardSync(); +} + +static u8 WUDiRegisterSyncDevice(void) { + WUDSyncState nextState; + + switch (_work.sync_type) { + case 1: { + nextState = WUD_STATE_SYNC_VIRGIN_SIMPLE; + break; + } + + case 0: { + nextState = WUD_STATE_SYNC_VIRGIN_STANDARD; + break; + } + + case 5: { + nextState = WUD_STATE_SYNC_CHANGE_SIMPLE_TO_STANDARD; + break; + } + + case 3: { + nextState = WUD_STATE_SYNC_COMPLETE; + break; + } + + case 4: { + nextState = WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; + break; + } + + case 2: { + nextState = WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; + break; + } + + default: { + // UB + break; + } + } + + return nextState; +} + +static u8 WUDiStoredLinkKey(void) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + + if (!WUDiIsFinishLinkKeyCmd()) { + return WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM; + } + + pInfo = WUDiGetDevInfo(_work.devAddr); + + // clang-format off + DEBUGPrint("write stored link key\n"); + + DEBUGPrint("addr : %02x:%02x:%02x:%02x:%02x:%02x\n", + pInfo->devAddr[0], pInfo->devAddr[1], pInfo->devAddr[2], + pInfo->devAddr[3], pInfo->devAddr[4], pInfo->devAddr[5]); + + DEBUGPrint("key : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pInfo->linkKey[0], pInfo->linkKey[1], pInfo->linkKey[2], pInfo->linkKey[3], + pInfo->linkKey[4], pInfo->linkKey[5], pInfo->linkKey[6], pInfo->linkKey[7], + pInfo->linkKey[8], pInfo->linkKey[9], pInfo->linkKey[10], pInfo->linkKey[11], + pInfo->linkKey[12], pInfo->linkKey[13], pInfo->linkKey[14], pInfo->linkKey[15]); + // clang-format on + + p->linkKeyState = WUD_STATE_LINK_KEY_WRITING; + + BTM_WriteStoredLinkKey(1, &pInfo->devAddr, &pInfo->linkKey, WUDStoredLinkKeyCallback); + + return WUD_STATE_SYNC_WAIT_FOR_STORING; +} + +static u8 WUDiWaitFinishStoring(void) { + return WUDiIsFinishLinkKeyCmd() ? WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND : WUD_STATE_SYNC_WAIT_FOR_STORING; +} + +static u8 WUDiWaitFinishReading(void) { + WUDSyncState nextState = WUD_STATE_SYNC_WAIT_FOR_READING; + + if (WUDiIsFinishLinkKeyCmd()) { + nextState = WUD_STATE_SYNC_VIRGIN_STANDARD; + WUDiRemoveDevice(_wcb.pairAddr); + } + + return nextState; +} + +static u8 WUDiSyncComplete(void) { + _wcb.syncedNum++; + + memset(&_work, 0, sizeof(WUDDevInfo)); + + return _wcb.syncType == WUD_SYNC_TYPE_STANDARD ? WUD_STATE_SYNC_DONE : WUD_STATE_SYNC_PREPARE_SEARCH; +} + +static u8 WUDiSyncError(void) { + memset(&_work, 0, sizeof(WUDDevInfo)); + + return _wcb.syncType == WUD_SYNC_TYPE_STANDARD ? WUD_STATE_SYNC_DONE : WUD_STATE_SYNC_PREPARE_SEARCH; +} + +static u8 WUDiSyncDone(void) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + int i; + WUDSyncDeviceCallback pSyncCallback; + + if (p->syncSkipChecks) { + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) { + pInfo = WUDiGetDevInfoIndex(i); + + if (pInfo->status == 8) { + WUDSetSniffMode(pInfo->devAddr, 8); + return WUD_STATE_SYNC_DONE; + } + } + } + + OSCancelAlarm(&p->alarm); + + pSyncCallback = p->syncType == WUD_SYNC_TYPE_STANDARD ? p->syncStdCB : p->syncSmpCB; + + if (pSyncCallback != NULL) { + pSyncCallback(WUD_RESULT_SYNC_DONE, p->syncedNum); + } + + DEBUGPrint("Pairing Done\n"); + return WUD_STATE_SYNC_START; +} + +static void SyncHandler(void) { + WUDControlBlock* p = &_wcb; + + switch (p->syncState) { + case WUD_STATE_SYNC_PREPARE_SEARCH: { + p->syncState = WUDiIsSyncDisabled(); + break; + } + + case WUD_STATE_SYNC_START_SEARCH: { + p->syncState = WUDiStartSearch(); + break; + } + + case WUD_STATE_SYNC_CHECK_SEARCH_RESULT: { + p->syncState = WUDiNextStepBySearchResult(); + break; + } + + case WUD_STATE_SYNC_IS_EXISTED_DEVICE: { + p->syncState = WUDiCheckDeviceDataBase(); + break; + } + + case WUD_STATE_SYNC_PREPARE_FOR_EXISTED_DEVICE: { + p->syncState = WUDiExistedDevice(); + break; + } + + case WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE: { + p->syncState = WUDiUnknownDevice(); + break; + } + + case WUD_STATE_SYNC_TRY_CONNECT: { + p->syncState = WUDiTryConnecting(); + break; + } + + case WUD_STATE_SYNC_REGISTER_DEVICE: { + p->syncState = WUDiRegisterSyncDevice(); + break; + } + + case WUD_STATE_SYNC_VIRGIN_SIMPLE: { + p->syncState = WUDiVirginSimpleSync(); + break; + } + + case WUD_STATE_SYNC_VIRGIN_STANDARD: { + p->syncState = WUDiVirginStandardSync(); + break; + } + + case WUD_STATE_SYNC_CHANGE_SIMPLE_TO_STANDARD: { + p->syncState = WUDiChangeSimpleToStandard(); + break; + } + + case WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM: { + p->syncState = WUDiStoredLinkKey(); + break; + } + + case WUD_STATE_SYNC_WAIT_FOR_STORING: { + p->syncState = WUDiWaitFinishStoring(); + break; + } + + case WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND: { + p->syncState = WUDiSaveDeviceToNand(); + break; + } + + case WUD_STATE_SYNC_SC_FLUSH: { + WUDiSaveFlush(); + break; + } + + case WUD_STATE_SYNC_WAIT_FOR_READING: { + p->syncState = WUDiWaitFinishReading(); + break; + } + + case WUD_STATE_SYNC_COMPLETE: { + p->syncState = WUDiSyncComplete(); + break; + } + + case WUD_STATE_SYNC_ERROR: { + p->syncState = WUDiSyncError(); + break; + } + + case WUD_STATE_SYNC_DONE: { + p->syncState = WUDiSyncDone(); + break; + } + + case WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT: { + p->syncState = WUDiWaitForSearchResult(); + break; + } + + case WUD_STATE_SYNC_6: + case WUD_STATE_SYNC_13: + case WUD_STATE_SYNC_WAIT_FOR_INCOMING: + case WUD_STATE_SYNC_CANCEL_SEARCH: { + break; + } + + case WUD_STATE_SYNC_11: + case WUD_STATE_SYNC_12: + default: { + DEBUGPrint("WARNING: Illigal status\n"); + break; + } + } +} + +static void SyncHandler0(OSAlarm* pAlarm, OSContext* pContext) { + OSSwitchFiberEx((u32)pAlarm, (u32)pContext, 0, 0, (u32)SyncHandler, (u32)__WUDHandlerStack + sizeof(__WUDHandlerStack)); +} + +static WUDDeleteState WUDiDisallowIncoming(void) { + BTA_DmSetVisibility(FALSE, FALSE); + return WUD_STATE_DELETE_DISCONNECT_ALL; +} + +static WUDDeleteState WUDiTerminateDevice(void) { + int i; + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + pInfo = &p->stdDevs[i]; + + if (pInfo->status > 1) { + btm_remove_acl(pInfo->devAddr); + } + } + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + pInfo = &p->smpDevs[i]; + + if (pInfo->status > 1) { + btm_remove_acl(pInfo->devAddr); + } + } + + return WUD_STATE_DELETE_CLEANUP_DATABASE; +} + +static WUDDeleteState WUDiDeleteDevice(void) { + int i; + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + + if (WUDiGetLinkNum() > 0) { + return WUD_STATE_DELETE_CLEANUP_DATABASE; + } + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + pInfo = &p->stdDevs[i]; + + if (pInfo->status == 1) { + WUDiRemoveDevice(pInfo->devAddr); + } + } + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + pInfo = &p->smpDevs[i]; + + if (pInfo->status == 1) { + WUDiRemoveDevice(pInfo->devAddr); + } + } + + return WUD_STATE_DELETE_CLEANUP_SETTING; +} + +static void WUDiCleanUp(void) { + WUDControlBlock* p = &_wcb; + BOOL success = FALSE; + + if (SCCheckStatus() != SC_STATUS_OK) { + return; + } + + memset(&_scArray, 0, sizeof(SCBtDeviceInfoArray)); + success |= SCSetBtDeviceInfoArray(&_scArray); + + if (success) { + p->deleteState = WUD_STATE_DELETE_6; + SCFlushAsync(DeleteFlushCallback); + } +} + +static WUDDeleteState WUDiDeleteAllComplete(void) { + WUDControlBlock* p = &_wcb; + + WUDSetVisibility(FALSE, WUDGetConnectable()); + + OSCancelAlarm(&p->alarm); + p->deleteState = WUD_STATE_DELETE_START; + + if (p->clearDevCB != NULL) { + p->clearDevCB(WUD_RESULT_DELETE_COMPLETE); + } + + return WUD_STATE_DELETE_START; +} + +static void DeleteAllHandler(void) { + WUDControlBlock* p = &_wcb; + + p->syncState = WUD_STATE_SYNC_START; + + switch (p->deleteState) { + case WUD_STATE_DELETE_DISALLOW_INCOMING: { + p->deleteState = WUDiDisallowIncoming(); + break; + } + + case WUD_STATE_DELETE_DISCONNECT_ALL: { + p->deleteState = WUDiTerminateDevice(); + break; + } + + case WUD_STATE_DELETE_CLEANUP_DATABASE: { + p->deleteState = WUDiDeleteDevice(); + break; + } + + case WUD_STATE_DELETE_CLEANUP_SETTING: { + WUDiCleanUp(); + break; + } + + case WUD_STATE_DELETE_DONE: { + p->deleteState = WUDiDeleteAllComplete(); + break; + } + + case WUD_STATE_DELETE_7: { + break; + } + } +} + +static void DeleteAllHandler0(OSAlarm* pAlarm, OSContext* pContext) { + OSSwitchFiberEx((u32)pAlarm, (u32)pContext, 0, 0, (u32)DeleteAllHandler, (u32)__WUDHandlerStack + sizeof(__WUDHandlerStack)); +} + +static WUDStackState WUDiCheckRegisteredDeviceInfo(void) { + WUDControlBlock* p = &_wcb; + + // Set by BTA_HH_ENABLE_EVT + if (p->hhFlags == 1) { + p->linkKeyState = WUD_STATE_LINK_KEY_READING; + BTM_ReadStoredLinkKey(NULL, WUDStoredLinkKeyCallback); + } + + return WUD_STATE_STACK_CHECK_DEVICE_INFO; +} + +static WUDStackState WUDiClearUnregisteredDevice(void) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + int i; + + if (p->linkKeyState == WUD_STATE_LINK_KEY_START) { + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) { + pInfo = WUDiGetDevInfoIndex(i); + if (pInfo->status == 0) { + continue; + } + + if (pInfo->UNK_0x5C == 1) { + p->linkKeyState = WUD_STATE_LINK_KEY_DELETING; + BTM_DeleteStoredLinkKey(pInfo->devAddr, WUDStoredLinkKeyCallback); + + pInfo->UNK_0x5C = 0; + return WUD_STATE_STACK_CHECK_DEVICE_INFO; + } + + if (pInfo->UNK_0x5C != 3) { + WUDiRemoveDevInfo(pInfo->devAddr); + } + } + + return WUD_STATE_STACK_DONE; + } + + return WUD_STATE_STACK_CHECK_DEVICE_INFO; +} + +static WUDStackState WUDiStackSetupComplete(void) { + WUDControlBlock* p = &_wcb; + + if (p->linkKeyState == WUD_STATE_LINK_KEY_START) { + OSCancelAlarm(&p->alarm); + WUDiGetFirmwareVersion(); + return WUD_STATE_STACK_INITIALIZED; + } + + return WUD_STATE_STACK_CHECK_DEVICE_INFO; +} + +static void EnableStackHandler(void) { + WUDControlBlock* p = &_wcb; + + switch (p->stackState) { + case WUD_STATE_STACK_GET_STORED_LINK_KEY: { + p->stackState = WUDiCheckRegisteredDeviceInfo(); + break; + } + + case WUD_STATE_STACK_CHECK_DEVICE_INFO: { + p->stackState = WUDiClearUnregisteredDevice(); + break; + } + + case WUD_STATE_STACK_DONE: { + p->stackState = WUDiStackSetupComplete(); + break; + } + } +} + +static void EnableStackHandler0(OSAlarm* pAlarm, OSContext* pContext) { + OSSwitchFiberEx((u32)pAlarm, (u32)pContext, 0, 0, (u32)EnableStackHandler, (u32)__WUDHandlerStack + sizeof(__WUDHandlerStack)); +} + +static WUDInitState WUDiWaitSCSetup(void) { + //TODO: probably a fakematch + return (SCCheckStatus() == SC_STATUS_OK) + 1; +} + +static WUDInitState WUDiGetRegisteredDevice(void) { + int i; + WUDDevInfo* pInfo; + + memset(&_scArray, 0, sizeof _scArray); + SCGetBtDeviceInfoArray(&_scArray); + + for (i = 0; i < _scArray.num; i++) { + pInfo = WUDiGetNewDevInfo(); + + WUD_BDCPY(pInfo->devAddr, _scArray.regist[i].addr); + + memcpy(&pInfo->conf, &_scArray.regist[i].info, sizeof(SCDevInfo)); + + pInfo->status = 1; + pInfo->sync_type = 0; + pInfo->UNK_0x5C = 2; + + if (WUD_DEV_NAME_IS_CNT_01(pInfo->conf.devName)) { + pInfo->subclass = 2; // subclass 2 is marked as reserved + + pInfo->hhAttrMask = BTA_HH_SEC_REQUIRED | BTA_HH_BATTERY_POWER | BTA_HH_REMOTE_WAKE | BTA_HH_SUP_TOUT_AVLBL | BTA_HH_RECONN_INIT; + + pInfo->appID = 3; + } + + DEBUGPrint("addr : %02x:%02x:%02x:%02x:%02x:%02x\n", pInfo->devAddr[0], pInfo->devAddr[1], pInfo->devAddr[2], pInfo->devAddr[3], + pInfo->devAddr[4], pInfo->devAddr[5]); + + DEBUGPrint("name : %s\n", pInfo->conf.devName); + } + + return WUD_STATE_INIT_DONE; +} + +static WUDInitState WUDiInitComplete(void) { + WUDControlBlock* p = &_wcb; + + OSCancelAlarm(&p->alarm); + p->libStatus = WUD_LIB_STATUS_1; + + BTA_EnableBluetooth(WUDSecurityCallback); + return WUD_STATE_INIT_INITIALIZED; +} + +static void InitHandler(void) { + WUDControlBlock* p = &_wcb; + + switch (p->initState) { + case WUD_STATE_INIT_WAIT_FOR_INITIALIZATION: { + p->initState = WUDiWaitSCSetup(); + break; + } + + case WUD_STATE_INIT_GET_DEV_INFO: { + p->initState = WUDiGetRegisteredDevice(); + break; + } + + case WUD_STATE_INIT_DONE: { + p->initState = WUDiInitComplete(); + break; + } + } +} + +static void InitHandler0(OSAlarm* pAlarm, OSContext* pContext) { + OSSwitchFiberEx((u32)pAlarm, (u32)pContext, 0, 0, (u32)InitHandler, (u32)__WUDHandlerStack + sizeof(__WUDHandlerStack)); +} + +static void WUDiContMapTableFlush(void) { + WUDControlBlock* p = &_wcb; + u8 nextState; + + if (SCCheckStatus() == SC_STATUS_OK && SCSetBtDeviceInfoArray(&_scArray)) { + SCFlushAsync(ShutFlushCallback); + nextState = WUD_STATE_SHUTDOWN_FLUSH_SETTINGS; + } else { + nextState = WUD_STATE_SHUTDOWN_STORE_SETTINGS; + } + + p->shutdownState = nextState; +} + +static void ShutdownHandler(void) { + WUDControlBlock* p = &_wcb; + + switch (p->shutdownState) { + case WUD_STATE_SHUTDOWN_STORE_SETTINGS: { + WUDiContMapTableFlush(); + break; + } + + case WUD_STATE_SHUTDOWN_FLUSH_SETTINGS: { + break; + } + } +} + +static void ShutdownHandler0(OSAlarm* pAlarm, OSContext* pContext) { + OSSwitchFiberEx((u32)pAlarm, (u32)pContext, 0, 0, (u32)ShutdownHandler, (u32)__WUDHandlerStack + sizeof(__WUDHandlerStack)); +} + +BOOL WUDInit(void) { + WUDControlBlock* p = &_wcb; + BOOL irqEnabled; + int i; + + if (_initialized) { + return FALSE; + } + + irqEnabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY; i++) { + _dev_handle_to_bda[i] = NULL; + _dev_handle_queue_size[i] = 0; + _dev_handle_notack_num[i] = 0; + } + + p->smpListTail = &p->smpList[WUD_MAX_DEV_ENTRY_FOR_SMP - 1]; + p->smpListHead = &p->smpList[0]; + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + p->smpList[i].devInfo = &p->smpDevs[WUD_MAX_DEV_ENTRY_FOR_SMP - 1 - i]; + p->smpList[i].prev = i == 0 ? NULL : &p->smpList[i - 1]; + p->smpList[i].next = i == WUD_MAX_DEV_ENTRY_FOR_SMP - 1 ? NULL : &p->smpList[i + 1]; + } + + p->syncStdCB = NULL; + p->syncSmpCB = NULL; + p->clearDevCB = NULL; + p->hidConnCB = NULL; + p->hidRecvCB = NULL; + + p->syncState = WUD_STATE_SYNC_START; + p->linkKeyState = WUD_STATE_LINK_KEY_START; + p->deleteState = WUD_STATE_DELETE_START; + p->stackState = WUD_STATE_STACK_START; + p->initState = WUD_STATE_INIT_START; + p->shutdownState = WUD_STATE_SHUTDOWN_START; + + p->syncSkipChecks = FALSE; + p->syncType = WUD_SYNC_TYPE_STANDARD; + p->syncLoopNum = 1; + + p->connectable = FALSE; + p->discoverable = FALSE; + + p->libStatus = WUD_LIB_STATUS_0; + p->pmID = 0; + p->syncRssi = -65; + + memset(p->hostAddr, 0, BD_ADDR_LEN); + memset(p->pairAddr, 0, BD_ADDR_LEN); + + p->bufferStatus0 = 0; + p->bufferStatus1 = 10; + + WUDiClearDevice(); + + p->initState = WUD_STATE_INIT_WAIT_FOR_INITIALIZATION; + + OSRestoreInterrupts(irqEnabled); + + DEBUGPrint("BTA_Init() is started\n"); + + BTA_Init(); + bta_sys_set_trace_level(__bte_trace_level); + L2CA_SetTraceLevel(__bte_trace_level); + SDP_SetTraceLevel(__bte_trace_level); + + DEBUGPrint("BTA_Init() is done\n"); + + SCInit(); + + OSCreateAlarm(&p->alarm); + OSSetPeriodicAlarm(&p->alarm, __OSGetSystemTime(), OSMillisecondsToTicks(10), InitHandler0); + + _initialized = TRUE; + return TRUE; +} + +void WUDRegisterAllocator(WUDAllocFunc pAllocFunc, WUDFreeFunc pFreeFunc) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + p->allocFunc = pAllocFunc; + p->freeFunc = pFreeFunc; + + OSRestoreInterrupts(enabled); +} + +extern u32 __ntd_get_allocated_mem_size(void); + +u32 WUDGetAllocatedMemSize(void) { + return __ntd_get_allocated_mem_size(); +} + +void WUDShutdown(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + int i; + WUDDevInfoList* pIt; + + DEBUGPrint("WUDShutdown()\n"); + + WUDSetVisibility(FALSE, FALSE); + + enabled = OSDisableInterrupts(); + + if (WUDIsBusy()) { + OSCancelAlarm(&p->alarm); + } + + p->shutdownState = WUD_STATE_SHUTDOWN_STORE_SETTINGS; + + OSCreateAlarm(&p->alarm); + OSSetPeriodicAlarm(&p->alarm, __OSGetSystemTime(), OSMillisecondsToTicks(10), ShutdownHandler0); + + p->libStatus = WUD_LIB_STATUS_4; + + OSRestoreInterrupts(enabled); +} + +WUDLibStatus WUDGetStatus(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled = OSDisableInterrupts(); + + s8 libStatus = p->libStatus; + + OSRestoreInterrupts(enabled); + return libStatus; +} u8 WUDGetBufferStatus(void) { - wud_cb_st* p_wcb = &__rvl_wudcb; - u8 ret; - BOOL intrStatus = OSDisableInterrupts(); + WUDControlBlock* p = &_wcb; + u8 status; + BOOL enabled = OSDisableInterrupts(); - ret = p_wcb->bufferStatus1 - p_wcb->bufferStatus0; + status = p->bufferStatus1 - p->bufferStatus0; - OSRestoreInterrupts(intrStatus); - return ret; + OSRestoreInterrupts(enabled); + return status; +} + +void WUDSetSniffMode(BD_ADDR addr, s32 interval) { + WUDControlBlock* p = &_wcb; + tBTM_PM_PWR_MD block; + + if (interval > 0) { + block.mode = BTM_PM_MD_SNIFF; + } else { + block.mode = BTM_PM_MD_ACTIVE; + } + + block.max = interval; + block.min = interval; + block.attempt = 1; + block.timeout = 0; + + BTM_SetPowerMode(p->pmID, addr, &block); +} + +WUDSyncDeviceCallback WUDSetSyncSimpleCallback(WUDSyncDeviceCallback pCallback) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + WUDSyncDeviceCallback pOldCallback; + + DEBUGPrint("WUDSetSyncDeviceCallback\n"); + + enabled = OSDisableInterrupts(); + + pOldCallback = p->syncSmpCB; + p->syncSmpCB = pCallback; + + OSRestoreInterrupts(enabled); + return pOldCallback; +} + +WUDClearDeviceCallback WUDSetClearDeviceCallback(WUDClearDeviceCallback pCallback) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + WUDClearDeviceCallback pOldCallback; + + DEBUGPrint("WUDSetClearDeviceCallback\n"); + + enabled = OSDisableInterrupts(); + + pOldCallback = p->clearDevCB; + p->clearDevCB = pCallback; + + OSRestoreInterrupts(enabled); + return pOldCallback; +} + +static BOOL StartSyncDevice(u8 syncType, s8 syncLoopNum, BOOL syncSkipChecks) { + WUDControlBlock* p = &_wcb; + BOOL success = FALSE; + BOOL enabled; + u32 libStatus; + + enabled = OSDisableInterrupts(); + libStatus = p->libStatus; + OSRestoreInterrupts(enabled); + + if (libStatus == WUD_LIB_STATUS_3 && !WUDIsBusy()) { + enabled = OSDisableInterrupts(); + + p->syncState = WUD_STATE_SYNC_PREPARE_SEARCH; + p->syncLoopNum = syncLoopNum; + p->syncType = syncType; + p->syncSkipChecks = syncSkipChecks ? TRUE : FALSE; + p->syncedNum = 0; + + OSCreateAlarm(&p->alarm); + OSSetPeriodicAlarm(&p->alarm, __OSGetSystemTime(), OSMillisecondsToTicks(20), SyncHandler0); + + OSRestoreInterrupts(enabled); + + success = TRUE; + } + + return success; +} + +static BOOL StartSyncStandard(BOOL syncSkipChecks) { + return StartSyncDevice(WUD_SYNC_TYPE_STANDARD, 3, syncSkipChecks); +} + +BOOL WUDStartSyncDevice(void) { + WUDControlBlock* p = &_wcb; + BOOL success; + BOOL enabled; + WUDSyncDeviceCallback pSyncCallback; + + DEBUGPrint("WUDStartSyncDevice()\n"); + success = StartSyncStandard(FALSE); + + enabled = OSDisableInterrupts(); + pSyncCallback = p->syncStdCB; + OSRestoreInterrupts(enabled); + + if (!success && pSyncCallback != NULL) { + pSyncCallback(WUD_RESULT_SYNC_BUSY, 0); + } + + return success; +} + +static BOOL StartSyncSimple(BOOL syncSkipChecks) { + return StartSyncDevice(WUD_SYNC_TYPE_SIMPLE, -1, syncSkipChecks); +} + +BOOL WUDStartFastSyncSimple(void) { + WUDControlBlock* p = &_wcb; + BOOL success; + BOOL enabled; + WUDSyncDeviceCallback pSyncCallback; + + DEBUGPrint("WUDStartSyncSimple()\n"); + success = StartSyncSimple(TRUE); + + enabled = OSDisableInterrupts(); + pSyncCallback = p->syncSmpCB; + OSRestoreInterrupts(enabled); + + if (!success && pSyncCallback != NULL) { + pSyncCallback(WUD_RESULT_SYNC_BUSY, 0); + } + + return success; +} + +BOOL WUDStartSyncSimple(void) { + WUDControlBlock* p = &_wcb; + BOOL success; + BOOL enabled; + WUDSyncDeviceCallback pSyncCallback; + + DEBUGPrint("WUDStartSyncSimple()\n"); + success = StartSyncSimple(FALSE); + + enabled = OSDisableInterrupts(); + pSyncCallback = p->syncSmpCB; + OSRestoreInterrupts(enabled); + + if (!success && pSyncCallback != NULL) { + pSyncCallback(WUD_RESULT_SYNC_BUSY, 0); + } + + return success; +} + +BOOL WUDCancelSyncDevice(void) { + DEBUGPrint("WUDCancelSyncDevice()\n"); +} + +static BOOL StopSync(void) { + WUDControlBlock* p; + BOOL success; + BOOL enabled; + + DEBUGPrint("WUDStopSyncSimple()\n"); + + p = &_wcb; + success = FALSE; + enabled = OSDisableInterrupts(); + + if (p->libStatus == WUD_LIB_STATUS_3) { + if (p->syncState == WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT) { + BTA_DmSearchCancel(); + } + + p->syncLoopNum = 0; + + success = TRUE; + } + + OSRestoreInterrupts(enabled); + return success; +} + +BOOL WUDStopSyncSimple(void) { + return StopSync(); +} + +BOOL WUDStartClearDevice(void) { + WUDControlBlock* p = &_wcb; + BOOL success; + BOOL enabled; + u32 libStatus; + + success = FALSE; + DEBUGPrint("WUDStartClearDevice()\n"); + + enabled = OSDisableInterrupts(); + libStatus = p->libStatus; + + OSRestoreInterrupts(enabled); + + if (libStatus == WUD_LIB_STATUS_3 && !WUDIsBusy()) { + enabled = OSDisableInterrupts(); + + p->deleteState = WUD_STATE_DELETE_DISALLOW_INCOMING; + + OSCreateAlarm(&p->alarm); + OSSetPeriodicAlarm(&p->alarm, __OSGetSystemTime(), OSMillisecondsToTicks(20), DeleteAllHandler0); + + OSRestoreInterrupts(enabled); + + success = TRUE; + } + + return success; +} + +BOOL WUDSetDisableChannel(s8 afhChannel) { + int first = 0; + int last = 0; + BOOL success = FALSE; + WUDControlBlock* p = &_wcb; + BOOL enabled; + u32 libStatus; + tBTM_STATUS status; + + DEBUGPrint("WUDSetDisableChannel()\n"); + + if (afhChannel < 0 || 13 < afhChannel) { + return FALSE; + } + + enabled = OSDisableInterrupts(); + libStatus = p->libStatus; + OSRestoreInterrupts(enabled); + + if (libStatus == WUD_LIB_STATUS_3) { + if (!afhChannel) { + first = 0xFF; + last = 0xFF; + } else { + first = (afhChannel + 1) * 5 - 14; + last = (afhChannel + 1) * 5 + 14; + + if (first < 0) { + first = 0; + } + + if (last > 78) { + last = 78; + } + } + + status = BTM_SetAfhChannels(first, last); + DEBUGPrint("BTM_SetAfhChannels() : %d\n", status); + + success = TRUE; + } + + return success; +} + +WUDHidRecvCallback WUDSetHidRecvCallback(WUDHidRecvCallback pCallback) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + WUDHidRecvCallback pOldCallback; + + DEBUGPrint("WUDSetHidRecvCallback()\n"); + + enabled = OSDisableInterrupts(); + + pOldCallback = p->hidRecvCB; + p->hidRecvCB = pCallback; + + OSRestoreInterrupts(enabled); + return pOldCallback; +} + +WUDHidConnCallback WUDSetHidConnCallback(WUDHidConnCallback pCallback) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + WUDHidConnCallback pOldCallback; + + DEBUGPrint("WUDSetHidConnCallback()\n"); + + enabled = OSDisableInterrupts(); + + pOldCallback = p->hidConnCB; + p->hidConnCB = pCallback; + + OSRestoreInterrupts(enabled); + return pOldCallback; +} + +void WUDSetVisibility(u8 disc, u8 conn) { + WUDControlBlock* p = &_wcb; + BOOL enabled = OSDisableInterrupts(); + + p->discoverable = disc; + p->connectable = conn; + + OSRestoreInterrupts(enabled); + BTA_DmSetVisibility(disc, conn); +} + +u8 WUDGetConnectable(void) { + WUDControlBlock* p = &_wcb; + u8 connectable; + BOOL enabled = OSDisableInterrupts(); + + connectable = p->connectable; + + OSRestoreInterrupts(enabled); + return connectable; +} + +void reset_again_cb(void* p1) { +#pragma unused(p1) + + WUDiInitSub(); +} + +void reset_again(void) { + BTM_DeviceReset(reset_again_cb); +} + +// clang-format off +static u8 patch_binary[] = { + 0x70, 0x99, 0x08, 0x00, // address (little-endian) + 0x38, 0x00, 0x00, 0x00, // size (little-endian) + + // patch data + 0x88, 0x43, 0xD1, 0x07, + 0x09, 0x0C, 0x08, 0x43, + 0xA0, 0x62, 0x19, 0x23, + 0xDB, 0x01, 0x33, 0x80, + 0x7C, 0xF7, 0x88, 0xF8, + 0x28, 0x76, 0x80, 0xF7, + 0x17, 0xFF, 0x43, 0x78, + 0xEB, 0x70, 0x19, 0x23, + 0xDB, 0x01, 0x33, 0x87, + 0x7C, 0xF7, 0xBC, 0xFB, + 0x0B, 0x60, 0xA3, 0x7B, + 0x01, 0x49, 0x0B, 0x60, + 0x90, 0xF7, 0x96, 0xFB, + 0xD8, 0x1D, 0x08, 0x00, +}; +// clang-format on + +// clang-format off +static WUDPatchList patch_install = { + 5, + { + {0x20, 0xBC, 0x65, 0x01, 0x00, 0x84, 0x42, 0x09, 0xD2, 0x84, 0x42, 0x09, 0xD1}, + {0x21, 0x84, 0x5A, 0x00, 0x00, 0x83, 0xF0, 0x74, 0xFF, 0x09, 0x0C, 0x08, 0x43}, + {0x22, 0x00, 0x61, 0x00, 0x00, 0x83, 0xF0, 0x40, 0xFC, 0x00, 0x00, 0x00, 0x00}, + {0x23, 0xCC, 0x9F, 0x01, 0x00, 0x6F, 0xF0, 0xE4, 0xFC, 0x03, 0x28, 0x7D, 0xD1}, + {0x24, 0x3C, 0x62, 0x01, 0x00, 0x28, 0x20, 0x00, 0xE0, 0x60, 0x8D, 0x23, 0x68}, + } +}; +// clang-format on + +static u8 remove_patch[] = {0x00}; + +static u8 install_num = 0; +static u8 patch_num = 0; + +static u32 addr = 0; +static s32 offset = 0; +static u32 size = 0; + +static void remove_patch_cb(tBTM_VSC_CMPL* p1) { + if (p1 == NULL) { + WUDiInitSub(); + } else { + offset = 0; + WUDiWritePatch(); + } +} + +static void WUDiRemovePatch(void) { + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_INSTALL_PATCH, sizeof(remove_patch), remove_patch, remove_patch_cb); +} + +static void write_patch_cb(tBTM_VSC_CMPL* p1) { + if (p1 != NULL) { + if (size == (u32)offset) { + install_num = 0; + patch_num = patch_install.num; + WUDiInstallPatch(); + } else { + WUDiWritePatch(); + } + } else { + WUDiInitSub(); + } +} + +static void WUDiWritePatch(void) { + u8 buf[WUD_PATCH_BUFFER_SIZE]; + u8 length; + int i; + + length = MIN(size - offset, WUD_PATCH_BUFFER_SIZE - sizeof(u32)); + + for (i = 0; i < (s32)sizeof(u32); i++) { + buf[i] = (addr + offset) >> i * 8; + } + + for (i = 0; i < (s32)length; i++) { + buf[(s32)sizeof(u32) + i] = patch_binary[sizeof(size) + sizeof(offset) + offset + i]; + } + + offset += length; + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_WRITE_PATCH, (s32)sizeof(u32) + length, buf, write_patch_cb); +} + +static void install_patch_cb(tBTM_VSC_CMPL* p1) { + if (p1 != NULL) { + if (patch_num == install_num) { + WUDiInitSub(); + } else { + WUDiInstallPatch(); + } + } else { + WUDiInitSub(); + } +} + +static void WUDiInstallPatch(void) { + u8 buf[WUD_PATCH_BUFFER_SIZE]; + u8 num; + + num = MIN(patch_num - install_num, WUD_MAX_PATCHES); + buf[offsetof(WUDPatchList, num)] = num; + + memcpy(&buf[offsetof(WUDPatchList, cmds)], patch_install.cmds[install_num].data, num * sizeof(WUDPatchCmd)); + + install_num += num; + BTM_VendorSpecificCommand(BT_VSC_NINTENDO_INSTALL_PATCH, sizeof(num) + num * sizeof(WUDPatchCmd), buf, install_patch_cb); +} + +static void WUDiAppendRuntimePatch(void) { + int i; + + DEBUGPrint("WUDiAppendRuntimePatch()\n"); + + size = 0; + addr = 0; + + for (i = 0; i < (int)sizeof(u32); i++) { + addr <<= 8; + addr += patch_binary[3 - i]; + + size <<= 8; + size += patch_binary[7 - i]; + } + + WUDiRemovePatch(); +} + +void WUDiGetFirmwareVersion(void) { + tBTM_VERSION_INFO version; + BTM_ReadLocalVersion(&version); + + DEBUGPrint("hci_version : %02x\n", version.hci_version); + DEBUGPrint("hci_revision : %04x\n", version.hci_revision); + + DEBUGPrint("lmp_version : %02x\n", version.lmp_version); + DEBUGPrint("lmp_subversion: %04x\n", version.lmp_subversion); + + DEBUGPrint("manufacturer : %04x\n", version.manufacturer); + + DEBUGPrint(" ==> 2045 firmware ver.002.003.014.%d\n", version.hci_revision & 0xFFF); + + if ((version.hci_revision & 0xFFF) == 167) { + WUDiAppendRuntimePatch(); + } else { + WUDiInitSub(); + } +} + +void WUDiInitSub(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + int i; + + char devName[] = "Wii"; + DEV_CLASS devClass = { + 0x00, // No designated Major Service Classes + 0x04, // Major Device Class 4 (Audio/Video) + 0x48 // Minor Device Class 18 (Audio/Video -> Gaming/Toy) + }; + + DEBUGPrint("start WUDiInitSub()\n"); + + BTA_DmSetDeviceName(devName); + BTM_SetDeviceClass(devClass); + + BTM_RegisterForVSEvents(&WUDVendorSpecificCallback); + BTM_RegisterForDeviceStatusNotif(&WUDDeviceStatusCallback); + BTM_PmRegister(BTM_PM_REG_SET | BTM_PM_REG_NOTIF, &p->pmID, &WUDPowerManagerCallback); + + BTM_WritePageTimeout(32768); + BTM_SetDefaultLinkPolicy(HCI_ENABLE_MASTER_SLAVE_SWITCH | HCI_ENABLE_SNIFF_MODE); + BTM_SetDefaultLinkSuperTout(3200); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + if (p->stdDevs[i].status == 1) { + WUDiRegisterDevice(p->stdDevs[i].devAddr); + } + } + + enabled = OSDisableInterrupts(); + p->libStatus = WUD_LIB_STATUS_3; + OSRestoreInterrupts(enabled); + + WUDSetVisibility(FALSE, TRUE); +} + +void WUDiEnableStack(void) { + WUDControlBlock* p = &_wcb; + + BTA_HhEnable(BTA_SEC_AUTHENTICATE, WUDHidHostCallback); + + p->stackState = WUD_STATE_STACK_GET_STORED_LINK_KEY; + + OSCreateAlarm(&p->alarm); + OSSetPeriodicAlarm(&p->alarm, __OSGetSystemTime(), OSMillisecondsToTicks(10), EnableStackHandler0); +} + +void WUDiAutoSync(void) { + WUDControlBlock* p = &_wcb; + WUDSyncDeviceCallback pSyncCallback; + s32 result; + BOOL enabled; + + DEBUGPrint("WUDiAutoSync()\n"); + enabled = OSDisableInterrupts(); + + pSyncCallback = p->syncStdCB; + result = WUDIsBusy() ? -1 /* WUD_RESULT_DELETE_BUSY */ + : + WUD_RESULT_DELETE_WAITING; + + OSRestoreInterrupts(enabled); + + if (pSyncCallback != NULL) { + pSyncCallback(result, 0); + } else { + WUDStartSyncDevice(); + } +} + +void WUDiCancelSync() { + DEBUGPrint("WUDiCancelSync()\n"); +} + +void WUDiDeleteAllLinkKeys(void) { + WUDControlBlock* p = &_wcb; + WUDClearDeviceCallback pClearCallback; + s32 result; + BOOL enabled; + + DEBUGPrint("WUDiDeleteAllLinkKeys()\n"); + enabled = OSDisableInterrupts(); + + pClearCallback = p->clearDevCB; + result = WUDIsBusy() ? -1 /* WUD_RESULT_DELETE_BUSY */ + : + WUD_RESULT_DELETE_WAITING; + + OSRestoreInterrupts(enabled); + + if (pClearCallback != NULL) { + pClearCallback(result); + } else { + WUDStartClearDevice(); + } +} + +void WUDiRegisterDevice(BD_ADDR addr) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + tBTA_STATUS status; + BOOL enabled; + + pInfo = WUDiGetDevInfo(addr); + + status = BTA_DmAddDevice(pInfo->devAddr, pInfo->linkKey, 0, FALSE); + DEBUGPrint("BTA_DmAddDevice(): %d\n", status); + + if (WUD_DEV_NAME_IS_CNT(pInfo->conf.devName)) { + tBTA_HH_DEV_DESCR desc; + desc.dl_len = sizeof(descriptor); + desc.dsc_list = descriptor; + + DEBUGPrint("BTA_HhAddDev()\n"); + BTA_HhAddDev(pInfo->devAddr, pInfo->hhAttrMask, pInfo->subclass, pInfo->appID, desc); + } + + enabled = OSDisableInterrupts(); + + if (pInfo->sync_type == 0 || pInfo->sync_type == 4 || pInfo->sync_type == 2 || pInfo->sync_type == 5) { + p->devNums++; + } else { + p->devSmpNums++; + } + + OSRestoreInterrupts(enabled); +} + +void WUDiRemoveDevice(BD_ADDR addr) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + tBTM_STATUS status; + BOOL enabled = OSDisableInterrupts(); + + DEBUGPrint("WUDiRemoveDevice : \n"); + + pInfo = WUDiGetDevInfo(addr); + + if (pInfo != NULL) { + DEBUGPrint(" handle : %d, addr : %02x:%02x:%02x:%02x:%02x:%02x\n", pInfo->devHandle, pInfo->devAddr[0], pInfo->devAddr[1], pInfo->devAddr[2], + pInfo->devAddr[3], pInfo->devAddr[4], pInfo->devAddr[5]); + + DEBUGPrint("remove device info from database.\n"); + + if (WUD_DEV_NAME_IS_CNT(pInfo->conf.devName)) { + DEBUGPrint("BTA_HhRemoveDev()\n"); + DEBUGPrint(" handle : %d\n", pInfo->devHandle); + BTA_HhRemoveDev(pInfo->devHandle); + } + + status = BTA_DmRemoveDevice(pInfo->devAddr); + DEBUGPrint("BTA_DmRemoveDevice(): %d\n", status); + + if (pInfo->sync_type == 0) { + p->devNums--; + } else { + p->devSmpNums--; + } + + memset(pInfo, 0, sizeof *pInfo); + } + + OSRestoreInterrupts(enabled); +} + +WUDDevInfo* WUDiGetDevInfo(BD_ADDR addr) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + BOOL enabled; + int i; + + pInfo = NULL; + enabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + if (WUD_BDCMP(p->stdDevs[i].devAddr, addr) == 0) { + pInfo = &p->stdDevs[i]; + break; + } + } + + if (pInfo == NULL) { + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + if (WUD_BDCMP(p->smpDevs[i].devAddr, addr) == 0) { + pInfo = &p->smpDevs[i]; + break; + } + } + } + + OSRestoreInterrupts(enabled); + return pInfo; +} + +WUDDevInfo* WUDiGetDevInfoIndex(int idx) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + if (0 <= idx && idx < WUD_MAX_DEV_ENTRY_FOR_STD) { + pInfo = &p->stdDevs[idx]; + } else { + pInfo = &p->smpDevs[idx - WUD_MAX_DEV_ENTRY_FOR_STD]; + } + + OSRestoreInterrupts(enabled); + return pInfo; +} + +WUDDevInfo* WUDiGetNewDevInfo(void) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + BOOL enabled; + int i; + + pInfo = NULL; + enabled = OSDisableInterrupts(); + + if (p->syncType == WUD_SYNC_TYPE_STANDARD) { + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + if (p->stdDevs[i].status == 0) { + DEBUGPrint("new entry index is %d\n", i); + pInfo = &p->stdDevs[i]; + break; + } + } + } else { + pInfo = p->smpListTail->devInfo; + } + + OSRestoreInterrupts(enabled); + return pInfo; +} + +void WUDiRemoveDevInfo(BD_ADDR addr) { + WUDDevInfo* pInfo; + BOOL enabled; + + pInfo = WUDiGetDevInfo(addr); + if (pInfo == NULL) { + return; + } + + enabled = OSDisableInterrupts(); + memset(pInfo, 0, sizeof(WUDDevInfo)); + OSRestoreInterrupts(enabled); +} + +void WUDiClearDevice(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + memset(p->stdDevs, 0, sizeof(WUDDevInfo) * WUD_MAX_DEV_ENTRY_FOR_STD); + memset(p->smpDevs, 0, sizeof(WUDDevInfo) * WUD_MAX_DEV_ENTRY_FOR_SMP); + + p->devNums = 0; + p->devSmpNums = 0; + + p->connectedNum = 0; + p->linkedNum = 0; + p->syncedNum = 0; + + OSRestoreInterrupts(enabled); +} + +u8 WUDiGetDevNumber(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled = OSDisableInterrupts(); + + u8 num = p->devNums; + + OSRestoreInterrupts(enabled); + return num; +} + +u8 WUDiGetDevSmpNumber(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled = OSDisableInterrupts(); + + u8 num = p->devSmpNums; + + OSRestoreInterrupts(enabled); + return num; +} + +u8 WUDiGetConnNumber(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled = OSDisableInterrupts(); + + u8 num = p->connectedNum; + + OSRestoreInterrupts(enabled); + return num; +} + +u8 WUDiGetLinkNum(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled = OSDisableInterrupts(); + + u8 num = p->linkedNum; + + OSRestoreInterrupts(enabled); + return num; +} + +void WUDiMoveTopSmpDevInfoPtr(WUDDevInfo* pInfo) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + if (WUD_BDCMP(p->smpList[i].devInfo->devAddr, pInfo->devAddr) != 0) { + continue; + } + + if (WUD_BDCMP(p->smpListHead->devInfo->devAddr, p->smpList[i].devInfo->devAddr) == 0) { + break; + } + + p->smpList[i].prev->next = p->smpList[i].next; + + if (WUD_BDCMP(p->smpListTail->devInfo->devAddr, p->smpList[i].devInfo->devAddr) == 0) { + p->smpListTail = p->smpList[i].prev; + } else { + p->smpList[i].next->prev = p->smpList[i].prev; + } + + p->smpList[i].next = p->smpListHead; + p->smpListHead->prev = &p->smpList[i]; + p->smpListHead = &p->smpList[i]; + + p->smpList[i].prev = NULL; + + break; + } + + OSRestoreInterrupts(enabled); +} + +void WUDiMoveBottomSmpDevInfoPtr(WUDDevInfo* pInfo) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + if (WUD_BDCMP(p->smpList[i].devInfo->devAddr, pInfo->devAddr) != 0) { + continue; + } + + if (WUD_BDCMP(p->smpListTail->devInfo->devAddr, p->smpList[i].devInfo->devAddr) == 0) { + break; + } + + p->smpList[i].next->prev = p->smpList[i].prev; + + if (WUD_BDCMP(p->smpListHead->devInfo->devAddr, p->smpList[i].devInfo->devAddr) == 0) { + p->smpListHead = p->smpList[i].next; + } else { + p->smpList[i].prev->next = p->smpList[i].next; + } + + p->smpList[i].prev = p->smpListTail; + p->smpListTail->next = &p->smpList[i]; + p->smpListTail = &p->smpList[i]; + + p->smpList[i].next = NULL; + + break; + } + + OSRestoreInterrupts(enabled); +} + +WUDDevInfo* WUDiGetRemoveSmpDevice(void) { + return _wcb.smpListTail->devInfo; +} + +void WUDiMoveTopOfDisconnectedSmpDevice(WUDDevInfo* pInfo) { + WUDControlBlock* p = &_wcb; + int i; + BOOL enabled; + WUDDevInfoList* pIt; + + enabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + if (WUD_BDCMP(p->smpList[i].devInfo->devAddr, pInfo->devAddr) != 0) { + continue; + } + + for (pIt = p->smpListHead; pIt; pIt = pIt->next) { + if (WUD_BDCMP(pIt->devInfo->devAddr, pInfo->devAddr) == 0) { + continue; + } + + if (pIt->devInfo->status > 1) { + continue; + } + + if (WUD_BDCMP(p->smpListHead->devInfo->devAddr, p->smpList[i].devInfo->devAddr) == 0) { + if (pIt == p->smpListHead->next) { + break; + } + + p->smpListHead = p->smpList[i].next; + } else { + p->smpList[i].prev->next = p->smpList[i].next; + } + + p->smpList[i].next->prev = p->smpList[i].prev; + + if (pIt != p->smpListHead) { + p->smpList[i].prev = pIt->prev; + p->smpList[i].next = pIt; + + pIt->prev->next = &p->smpList[i]; + pIt->prev = &p->smpList[i]; + } else { + p->smpList[i].prev = pIt; + p->smpList[i].next = pIt->next; + + pIt->next->prev = &p->smpList[i]; + pIt->next = &p->smpList[i]; + } + + break; + } + } + + OSRestoreInterrupts(enabled); +} + +#if SDK_AUG2010 +void WUDiMoveTopStdDevInfoPtr(WUDDevInfo* pInfo) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + if (WUD_BDCMP(p->stdList[i].devInfo->devAddr, pInfo->devAddr) != 0) { + continue; + } + + if (WUD_BDCMP(p->stdListHead->devInfo->devAddr, p->stdList[i].devInfo->devAddr) == 0) { + break; + } + + p->stdList[i].prev->next = p->stdList[i].next; + + if (WUD_BDCMP(p->stdListTail->devInfo->devAddr, p->stdList[i].devInfo->devAddr) == 0) { + p->stdListTail = p->stdList[i].prev; + } else { + p->stdList[i].next->prev = p->stdList[i].prev; + } + + p->stdList[i].next = p->stdListHead; + p->stdListHead->prev = &p->stdList[i]; + p->stdListHead = &p->stdList[i]; + + p->stdList[i].prev = NULL; + + break; + } + + OSRestoreInterrupts(enabled); +} + +void WUDiMoveBottomStdDevInfoPtr(WUDDevInfo* pInfo) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + int i; + + enabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + if (WUD_BDCMP(p->stdList[i].devInfo->devAddr, pInfo->devAddr) != 0) { + continue; + } + + if (WUD_BDCMP(p->stdListTail->devInfo->devAddr, p->stdList[i].devInfo->devAddr) == 0) { + break; + } + + p->stdList[i].next->prev = p->stdList[i].prev; + + if (WUD_BDCMP(p->stdListHead->devInfo->devAddr, p->stdList[i].devInfo->devAddr) == 0) { + p->stdListHead = p->stdList[i].next; + } else { + p->stdList[i].prev->next = p->stdList[i].next; + } + + p->stdList[i].prev = p->stdListTail; + p->stdListTail->next = &p->stdList[i]; + p->stdListTail = &p->stdList[i]; + + p->stdList[i].next = NULL; + + break; + } + + OSRestoreInterrupts(enabled); +} + +WUDDevInfo* WUDiGetRemoveStdDevice(void) { + return _wcb.stdListTail->devInfo; +} + +void WUDiMoveTopOfDisconnectedStdDevice(WUDDevInfo* pInfo) { + WUDControlBlock* p = &_wcb; + int i; + BOOL enabled; + WUDDevInfoList* pIt; + + enabled = OSDisableInterrupts(); + + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_STD; i++) { + if (WUD_BDCMP(p->stdList[i].devInfo->devAddr, pInfo->devAddr) != 0) { + continue; + } + + for (pIt = p->stdListHead; pIt; pIt = pIt->next) { + if (WUD_BDCMP(pIt->devInfo->devAddr, pInfo->devAddr) == 0) { + continue; + } + + if (pIt->devInfo->status > 1) { + continue; + } + + if (WUD_BDCMP(p->stdListHead->devInfo->devAddr, p->stdList[i].devInfo->devAddr) == 0) { + if (pIt == p->stdListHead->next) + break; + + p->stdListHead = p->stdList[i].next; + } else { + p->stdList[i].prev->next = p->stdList[i].next; + } + + p->stdList[i].next->prev = p->stdList[i].prev; + + if (pIt != p->stdListHead) { + p->stdList[i].prev = pIt->prev; + p->stdList[i].next = pIt; + + pIt->prev->next = &p->stdList[i]; + pIt->prev = &p->stdList[i]; + } else { + p->stdList[i].prev = pIt; + p->stdList[i].next = pIt->next; + + pIt->next->prev = &p->stdList[i]; + pIt->next = &p->stdList[i]; + } + + break; + } + } + + OSRestoreInterrupts(enabled); +} +#endif + +BOOL WUDIsBusy(void) { + WUDControlBlock* p = &_wcb; + BOOL enabled; + + enabled = OSDisableInterrupts(); + + if (p->syncState == WUD_STATE_SYNC_START && + p->deleteState == WUD_STATE_DELETE_START && + p->stackState == WUD_STATE_STACK_INITIALIZED && + p->initState == 4) { + OSRestoreInterrupts(enabled); + return FALSE; + } + + OSRestoreInterrupts(enabled); + return TRUE; +} + +static void CleanupCallback(tBTA_STATUS status) { + WUDControlBlock* p = &_wcb; + + if (status == BTA_SUCCESS) { + _initialized = FALSE; + p->libStatus = WUD_LIB_STATUS_0; + return; + } + + DEBUGPrint("WARNING: USB_CLOSE_FAILURE!\n"); +} + +void WUDSecurityCallback(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* pData) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + u8 i; + + tBTA_DM_ENABLE* pEnable; + tBTA_DM_LINK_UP* pLinkUp; + tBTA_DM_LINK_DOWN* pLinkDown; + tBTA_DM_PIN_REQ* pPinReq; + tBTA_DM_AUTH_CMPL* pAuthCmpl; + + DEBUGPrint("WUDSecurityCallback: "); + + switch (event) { + case BTA_DM_ENABLE_EVT: { + pEnable = &pData->enable; + WUD_BDCPY(p->hostAddr, pEnable->bd_addr); + + DEBUGPrint("BTA_ENABLE_EVT\n"); + DEBUGPrint("host : %02x:%02x:%02x:%02x:%02x:%02x\n", p->hostAddr[0], p->hostAddr[1], p->hostAddr[2], p->hostAddr[3], p->hostAddr[4], + p->hostAddr[5]); + + WUDiEnableStack(); + p->libStatus = WUD_LIB_STATUS_2; + break; + } + + case BTA_DM_DISABLE_EVT: { + DEBUGPrint("BTA_DISABLE_EVT\n"); + + BTA_CleanUp(CleanupCallback); + break; + } + + case BTA_DM_PIN_REQ_EVT: { + pPinReq = &pData->pin_req; + + DEBUGPrint("BTA_DM_PIN_REQ_EVT\n"); + + WUDiSetPinCode(pPinReq->bd_addr); + break; + } + + case BTA_DM_AUTH_CMPL_EVT: { + pAuthCmpl = &pData->auth_cmpl; + + DEBUGPrint("BTA_DM_AUTH_CMPL_EVT\n"); + + DEBUGPrint(" addr : %02x:%02x:%02x:%02x:%02x:%02x\n", pAuthCmpl->bd_addr[0], pAuthCmpl->bd_addr[1], pAuthCmpl->bd_addr[2], + pAuthCmpl->bd_addr[3], pAuthCmpl->bd_addr[4], pAuthCmpl->bd_addr[5]); + + // clang-format off + DEBUGPrint(" key : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pAuthCmpl->key[0], pAuthCmpl->key[1], pAuthCmpl->key[2], pAuthCmpl->key[3], + pAuthCmpl->key[4], pAuthCmpl->key[5], pAuthCmpl->key[6], pAuthCmpl->key[7], + pAuthCmpl->key[8], pAuthCmpl->key[9], pAuthCmpl->key[10], pAuthCmpl->key[11], + pAuthCmpl->key[12], pAuthCmpl->key[13], pAuthCmpl->key[14], pAuthCmpl->key[15]); + // clang-format on + + DEBUGPrint(" result = %d\n", pAuthCmpl->key_type); + + if (pAuthCmpl->key_type == HCI_LKEY_TYPE_COMBINATION) { + break; + } + + pInfo = WUDiGetDevInfo(pAuthCmpl->bd_addr); + + if (WUD_BDCMP(_work.devAddr, pAuthCmpl->bd_addr) == 0) { + _work.status = 12; + + if (pInfo == NULL) { + pInfo = &_work; + } + } + + memcpy(pInfo->linkKey, pAuthCmpl->key, LINK_KEY_LEN); + break; + } + + case BTA_DM_AUTHORIZE_EVT: { + DEBUGPrint("BTA_DM_AUTHORIZE_EVT\n"); + break; + } + + case BTA_DM_LINK_UP_EVT: { + pLinkUp = &pData->link_up; + + DEBUGPrint("BTA_DM_LINK_UP_EVT\n"); + + DEBUGPrint(" addr : %02x:%02x:%02x:%02x:%02x:%02x\n", pLinkUp->bd_addr[0], pLinkUp->bd_addr[1], pLinkUp->bd_addr[2], pLinkUp->bd_addr[3], + pLinkUp->bd_addr[4], pLinkUp->bd_addr[5]); + + pInfo = WUDiGetDevInfo(pLinkUp->bd_addr); + if (pInfo == NULL && WUD_BDCMP(pLinkUp->bd_addr, _work.devAddr) == 0) { + pInfo = &_work; + } + + if (pInfo == NULL || WUDiGetLinkNum() == WUD_MAX_CHANNELS) { + btm_remove_acl(pLinkUp->bd_addr); + + DEBUGPrint("%s --> %02x:%02x:%02x:%02x:%02x:%02x\n", pInfo == NULL ? "not paired" : "4 links exist", pLinkUp->bd_addr[0], + pLinkUp->bd_addr[1], pLinkUp->bd_addr[2], pLinkUp->bd_addr[3], pLinkUp->bd_addr[4], pLinkUp->bd_addr[5]); + break; + } + + pInfo->status = pInfo->status == 2 ? 12 : 3; + p->linkedNum++; + break; + } + + case BTA_DM_LINK_DOWN_EVT: { + pLinkDown = &pData->link_down; + + DEBUGPrint("BTA_DM_LINK_DOWN_EVT\n"); + + DEBUGPrint(" addr : %02x:%02x:%02x:%02x:%02x:%02x\n", pLinkDown->bd_addr[0], pLinkDown->bd_addr[1], pLinkDown->bd_addr[2], + pLinkDown->bd_addr[3], pLinkDown->bd_addr[4], pLinkDown->bd_addr[5]); + + DEBUGPrint("result: %d\n", pLinkDown->status); + + pInfo = WUDiGetDevInfo(pLinkDown->bd_addr); + if (pInfo != NULL) { + pInfo->status = 1; + p->linkedNum--; + + if (WUD_BDCMP(_work.devAddr, pLinkDown->bd_addr) == 0) { + p->syncState = WUD_STATE_SYNC_ERROR; + } + + if (pLinkDown->status == HCI_ERR_PEER_POWER_OFF) { + for (i = 0; i < WUD_MAX_CHANNELS; i++) { + if (WUD_BDCMP(_scArray.regist[WUD_MAX_DEV_ENTRY_FOR_STD + i].addr, pLinkDown->bd_addr) == 0) { + memset(&_scArray.regist[WUD_MAX_DEV_ENTRY_FOR_STD + i], 0, sizeof(SCBtDeviceInfo)); + + _scFlush = TRUE; + } + } + } + } else if (WUD_BDCMP(_work.devAddr, pLinkDown->bd_addr) == 0) { + p->syncState = WUD_STATE_SYNC_ERROR; + p->linkedNum--; + } else { + DEBUGPrint("this device in not paired\n"); + } + + if (p->linkedNum <= 255 && p->linkedNum >= 250) { + OSReport("WARNING: link num count is reset.\n"); + p->linkedNum = 0; + } + break; + } + + case BTA_DM_SIG_STRENGTH_EVT: { + DEBUGPrint("BTA_DM_SIG_STRENGTH_EVT\n"); + break; + } + + case BTA_DM_BUSY_LEVEL_EVT: { + DEBUGPrint("BTA_DM_BUSY_LEVEL_EVT\n"); + break; + } + } +} + +void WUDSearchCallback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH* pData) { + s32 timeout; + + switch (event) { + case BTA_DM_INQ_RES_EVT: { + tBTA_DM_INQ_RES* pResp = &pData->inq_res; + + // clang-format off + DEBUGPrint("INQUIRY RESULT: %02x:%02x:%02x:%02x:%02x:%02x %02x%02x%02x %d\n", + pResp->bd_addr[0], pResp->bd_addr[1], pResp->bd_addr[2], + pResp->bd_addr[3], pResp->bd_addr[4], pResp->bd_addr[5], + pResp->dev_class[0], pResp->dev_class[1], pResp->dev_class[2], + pResp->rssi); + // clang-format on + + _discRssi = pResp->rssi; + + if (_wcb.syncSkipChecks == TRUE || (_wcb.syncSkipChecks == FALSE && WUDiGetLinkNum() < WUD_MAX_CHANNELS - 1)) { + timeout = 4800; + } else { + timeout = 32768; + } + + BTM_WritePageTimeout(timeout); + break; + } + + case BTA_DM_INQ_CMPL_EVT: { + DEBUGPrint("INQUIRY_COMPLETED\n"); + break; + } + + case BTA_DM_DISC_RES_EVT: { + tBTA_DM_DISC_RES* dmDiscRes = &pData->disc_res; + + WUD_BDCPY(_discResp.devAddr, dmDiscRes->bd_addr); + memcpy(_discResp.devName, dmDiscRes->bd_name, sizeof(_discResp.devName)); + + _discResp.services = dmDiscRes->services; + _discNumResps++; + + // clang-format off + DEBUGPrint("DISCOVER RESULT: %02x:%02x:%02x:%02x:%02x:%02x %s (%04x)\n", + _discResp.devAddr[0], _discResp.devAddr[1], _discResp.devAddr[2], + _discResp.devAddr[3], _discResp.devAddr[4], _discResp.devAddr[5], + _discResp.devName, _discResp.services); + // clang-format on + break; + } + + case BTA_DM_DISC_CMPL_EVT: { + DEBUGPrint("DISCOVER COMPLETED\n"); + + _wcb.syncState = WUD_STATE_SYNC_CHECK_SEARCH_RESULT; + break; + } + + case BTA_DM_SEARCH_CANCEL_CMPL_EVT: { + DEBUGPrint("SEARCH CANCEL\n\n"); + + _discNumResps = 0; + memset(&_discResp, 0, sizeof(WUDDiscResp)); + + _wcb.syncState = WUD_STATE_SYNC_CHECK_SEARCH_RESULT; + break; + } + + default: { + DEBUGPrint("Warning: Search Callback returns invalid event\n"); + break; + } + } +} + +void WUDVendorSpecificCallback(UINT8 len, UINT8* pData) { +#pragma unused(len) + + u8 event = pData[0]; + WUDControlBlock* p = &_wcb; + + switch (event) { + case WUD_VSE_INITIATE_PAIRING: { + DEBUGPrint("VSE:- INITIATE_PAIRING\n"); + WUDiAutoSync(); + break; + } + + case WUD_VSE_DELETE_ALL_KEYS: { + DEBUGPrint("VSE:- DELETE_ALL_KEYS\n"); + WUDiDeleteAllLinkKeys(); + break; + } + + case WUD_VSE_SI_PORT_STATUS: { + DEBUGPrint("VSE:- SI_PORT_STATUS status = %d\n", pData[1]); + p->serialPortStatus = pData[1]; + break; + } + + case WUD_VSE_WATCH_DOG_RESET_HW: { + DEBUGPrint("VSE:- WATCH_DOG_RESET HW error = %d\n", pData[1]); + + // clang-format off + OSPanic(__FILE__, 3484, "MODULE FATAL ERROR\n"); + // clang-format on + break; + } + } +} + +void WUDDeviceStatusCallback(tBTM_DEV_STATUS status) { + DEBUGPrint("WUDDeviceStatusCallback\n"); + + if (status == BTM_DEV_STATUS_CMD_TOUT) { + OSReport("---- WARNING: USB FATAL ERROR! ----\n"); + } +} + +void WUDStoredLinkKeyCallback(void* p1) { + tBTM_BD_ADDR_LINK_KEY_PAIR* pPair; + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + int i; + + tBTM_STORED_LINK_KEYS_EVT* pData = p1; + tBTM_READ_STORED_LINK_KEY_COMPLETE* pRead; + tBTM_WRITE_STORED_LINK_KEY_COMPLETE* pWrite; + tBTM_DELETE_STORED_LINK_KEY_COMPLETE* pDelete; + tBTM_RETURN_LINK_KEYS_EVT* pReturn; + + switch (pData->event) { + case BTM_CB_EVT_RETURN_LINK_KEYS: { + pReturn = p1; + + DEBUGPrint("BTM_CB_EVT_RETURN_LINK_KEYS\n"); + + pPair = (tBTM_BD_ADDR_LINK_KEY_PAIR*)(pReturn + 1); + i = 0; + + while (i < pReturn->num_keys) { + pInfo = WUDiGetDevInfo(pPair->bd_addr); + + DEBUGPrint("BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", pPair->bd_addr[0], pPair->bd_addr[1], pPair->bd_addr[2], pPair->bd_addr[3], + pPair->bd_addr[4], pPair->bd_addr[5]); + + // clang-format off + DEBUGPrint("LINKKEY: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pPair->link_key[0], pPair->link_key[1], pPair->link_key[2], pPair->link_key[3], + pPair->link_key[4], pPair->link_key[5], pPair->link_key[6], pPair->link_key[7], + pPair->link_key[8], pPair->link_key[9], pPair->link_key[10], pPair->link_key[11], + pPair->link_key[12], pPair->link_key[13], pPair->link_key[14], pPair->link_key[15]); + // clang-format on + + if (pInfo == NULL) { + DEBUGPrint("this device is not stored in NAND\n"); + + pInfo = WUDiGetNewDevInfo(); + + if (pInfo == NULL) { + for (i = 0; i < WUD_MAX_DEV_ENTRY_FOR_SMP; i++) { + if (p->smpDevs[i].status == 0) { + pInfo = &p->smpDevs[i]; + break; + } + } + } + + if (pInfo) { + pInfo->UNK_0x5C = 1; + pInfo->status = 1; + + WUD_BDCPY(pInfo->devAddr, pPair->bd_addr); + memcpy(pInfo->linkKey, pPair->link_key, LINK_KEY_LEN); + } + } else { + WUD_BDCPY(pInfo->devAddr, pPair->bd_addr); + memcpy(pInfo->linkKey, pPair->link_key, LINK_KEY_LEN); + + if (pInfo->UNK_0x5C == 2) { + pInfo->UNK_0x5C = 3; + } + + WUD_BDCPY(p->pairAddr, pPair->bd_addr); + DEBUGPrint(" LAST: %02x:%02x:%02x:%02x:%02x:%02x\n", p->pairAddr[0], p->pairAddr[1], p->pairAddr[2], p->pairAddr[3], p->pairAddr[4], + p->pairAddr[5]); + } + + pPair++; + i++; + } + + break; + } + + case BTM_CB_EVT_READ_STORED_LINK_KEYS: { + pRead = p1; + + DEBUGPrint("BTM_CB_EVT_READ_STORED_LINK_KEYS\n"); + DEBUGPrint(" status: %d max_keys: %d num_keys: %d\n", pRead->status, pRead->max_keys, pRead->read_keys); + + p->linkKeyState = WUD_STATE_LINK_KEY_START; + break; + } + + case BTM_CB_EVT_WRITE_STORED_LINK_KEYS: { + pWrite = p1; + + DEBUGPrint("BTM_CB_EVT_WRITE_STORED_LINK_KEYS\n"); + DEBUGPrint(" status: %d num_keys: %d\n", pWrite->status, pWrite->num_keys); + + p->linkKeyState = WUD_STATE_LINK_KEY_START; + break; + } + + case BTM_CB_EVT_DELETE_STORED_LINK_KEYS: { + pDelete = p1; + + DEBUGPrint("BTM_CB_EVT_DELETE_STORED_LINK_KEYS\n"); + DEBUGPrint(" status: %d num_keys: %d\n", pDelete->status, pDelete->num_keys); + + if (pDelete->num_keys == 0) { + DEBUGPrint("WARNING: no entry is deleted\n"); + } + + p->linkKeyState = WUD_STATE_LINK_KEY_START; + break; + } + + default: { + // clang-format off + OSPanic(__FILE__, 3636, "Unknown event\n"); + // clang-format on + } + } +} + +void WUDPowerManagerCallback(BD_ADDR addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hciStatus) { +#pragma unused(value) + + WUDDevInfo* pInfo; + + DEBUGPrint("WUDPowerManagerCallback\n"); + DEBUGPrint("hci_status = %d", hciStatus); + + pInfo = WUDiGetDevInfo(addr); + if (pInfo == NULL) { + if (WUD_BDCMP(_work.devAddr, addr) == 0) { + pInfo = &_work; + } + } + + switch (status) { + case BTM_PM_STS_ACTIVE: { + pInfo->status = 8; + break; + } + + case BTM_PM_STS_SNIFF: { + pInfo->status = 9; + break; + } + } + + DEBUGPrint(" addr = %02x:%02x:%02x:%02x:%02x:%02x, status = %d\n", pInfo->devAddr[0], pInfo->devAddr[1], pInfo->devAddr[2], pInfo->devAddr[3], + pInfo->devAddr[4], pInfo->devAddr[5], pInfo->status); +} + +BD_ADDR_PTR _WUDGetDevAddr(UINT8 handle) { + BD_ADDR_PTR pAddr; + BOOL enabled = OSDisableInterrupts(); + + if (handle < WUD_MAX_DEV_ENTRY) { + pAddr = _dev_handle_to_bda[handle]; + + } else { + pAddr = NULL; + } + + OSRestoreInterrupts(enabled); + return pAddr; } u16 _WUDGetQueuedSize(s8 dev_handle) { u16 queuedSize; BOOL intrStatus = OSDisableInterrupts(); - if (dev_handle >= 0 && dev_handle < WUD_MAX_DEV_ENTRY) + if (dev_handle >= 0 && dev_handle < WUD_MAX_DEV_ENTRY) { queuedSize = WUDiGetQueueSizeForHandle(dev_handle); - else + } else { queuedSize = 0; + } OSRestoreInterrupts(intrStatus); return queuedSize; @@ -38,36 +2848,53 @@ u16 _WUDGetNotAckedSize(s8 dev_handle) { u16 notAckedSize; BOOL intrStatus = OSDisableInterrupts(); - if (dev_handle >= 0 && dev_handle < WUD_MAX_DEV_ENTRY) + if (dev_handle >= 0 && dev_handle < WUD_MAX_DEV_ENTRY) { notAckedSize = WUDiGetNotAckNumForHandle(dev_handle); - else + } else { notAckedSize = 0; + } OSRestoreInterrupts(intrStatus); return notAckedSize; } u8 _WUDGetLinkNumber(void) { - wud_cb_st* p_wcb = &__rvl_wudcb; - BOOL intrStatus = OSDisableInterrupts(); - u8 linkedNum = p_wcb->linkedNum; + WUDControlBlock* p = &_wcb; + BOOL enabled = OSDisableInterrupts(); - OSRestoreInterrupts(intrStatus); - return linkedNum; + u8 num = p->linkedNum; + + OSRestoreInterrupts(enabled); + return num; } -u16 WUDiGetQueueSizeForHandle(u8 dev_handle) { +// not sure if this is a fakematch or an actual version difference of some kind +#if SDK_AUG2010 +inline u16 WUDiGetQueueSizeForHandle(u8 dev_handle) { +#else +inline u16 WUDiGetQueueSizeForHandle(u32 dev_handle) { +#endif return _dev_handle_queue_size[dev_handle]; } -u16 WUDiGetNotAckNumForHandle(u8 dev_handle) { +// see comment for WUDiGetQueueSizeForHandle +#if SDK_AUG2010 +inline u16 WUDiGetNotAckNumForHandle(u8 dev_handle) { +#else +inline u16 WUDiGetNotAckNumForHandle(u32 dev_handle) { +#endif return _dev_handle_notack_num[dev_handle]; } -BOOL WUDStartSyncSimple(void) { - // NONMATCHING +void _WUDEnableTestMode() { + DEBUGPrint("_WUDEnableTestMode\n"); } -BOOL WUDStartFastSyncSimple(void) { - // NONMATCHING +void _WUDStartSyncDevice() { + DEBUGPrint("_WUDStartSyncDevice()\n"); +} + +void _WUDDeleteStoreDevice() { + DEBUGPrint("_WUDDeleteStoreDevice()\n"); + DEBUGPrint("dev number = %d\n", 0); } diff --git a/src/revolution/wud/WUDHidHost.c b/src/revolution/wud/WUDHidHost.c new file mode 100644 index 0000000000..aaae4d0aa2 --- /dev/null +++ b/src/revolution/wud/WUDHidHost.c @@ -0,0 +1,261 @@ +#include +#include +#include +#include +#include + +#define DEBUGPrint WUD_DEBUGPrint + +// TODO(kiwi) Is this from BTA? +#define WUD_HH_CUSTOM_EVT 15 + +typedef struct WUD_HH_EVT15 { + /* 0x00 */ u16 status0; + /* 0x02 */ u16 status1; + /* 0x04 */ u16 linkedNum; + + /* 0x06 */ struct { + /* 0x00 */ UINT8 handle; + /* 0x02 */ UINT16 queueSize; + /* 0x04 */ UINT16 notAckNum; + } devices[]; +} WUD_HH_EVT15; + +void WUDHidHostCallback(tBTA_HH_EVT event, tBTA_HH* pData) { + WUDControlBlock* p = &_wcb; + WUDDevInfo* pInfo; + tBTA_HH_CONN* pConn; + tBTA_HH_CBDATA* pCbData; + WUD_HH_EVT15* pEvt15; + int i; + + switch (event) { + case BTA_HH_ENABLE_EVT: { + DEBUGPrint("BTA_HH_ENABLE_EVT\n"); + + p->hhFlags |= 1; + break; + } + + case BTA_HH_DISABLE_EVT: { + DEBUGPrint("BTA_HH_DISABLE_EVT\n"); + break; + } + + case BTA_HH_OPEN_EVT: { + pConn = &pData->conn; + + DEBUGPrint("BTA_HH_OPEN_EVT\n"); + + DEBUGPrint("handle: %d, addr: %02x:%02x:%02x:%02x:%02x:%02x\n", pConn->handle, pConn->bda[0], pConn->bda[1], pConn->bda[2], pConn->bda[3], + pConn->bda[4], pConn->bda[5]); + + if (pConn->status == BTA_HH_OK) { + pInfo = &_work; + + if (WUD_BDCMP(pInfo->devAddr, pConn->bda) != 0) { + pInfo = WUDiGetDevInfo(pConn->bda); + } + + switch (pInfo->status) { + case 12: { + p->syncState = WUD_STATE_SYNC_REGISTER_DEVICE; + break; + } + + case 2: { + p->syncState = WUD_STATE_SYNC_COMPLETE; + break; + } + } + + pInfo->status = 8; + pInfo->devHandle = pConn->handle; + p->connectedNum++; + + pInfo = WUDiGetDevInfo(pConn->bda); + if (pInfo == NULL) { + pInfo = &_work; + } + + _dev_handle_to_bda[pConn->handle] = pInfo->devAddr; + _dev_handle_queue_size[pConn->handle] = 0; + _dev_handle_notack_num[pConn->handle] = 0; + + if (pInfo->sync_type == 3 || pInfo->sync_type == 1) { + WUDiMoveTopSmpDevInfoPtr(pInfo); + } + + WUDSetSniffMode(pInfo->devAddr, 8); + + if (p->hidConnCB != NULL) { + p->hidConnCB(pConn->handle, TRUE); + } + } else { + DEBUGPrint("error code: %d\n", pConn->status); + + if (!memcmp(pConn->bda, _work.devAddr, 6)) { + if (p->syncState != 0) { + if (_work.status == 2) { + if (WUDiGetDevInfo(pConn->bda) && pConn->status == 12) { + WUDiRemoveDevice(pConn->bda); + p->linkedNum--; + } + + p->syncState = 255; + } + } + } + } + } + + break; + case BTA_HH_CLOSE_EVT: { + pCbData = &pData->dev_status; + + DEBUGPrint("BTA_HH_CLOSE_EVT\n"); + + p->connectedNum--; + + DEBUGPrint("device handle : %d status = %d\n", pCbData->handle, pCbData->status); + + _dev_handle_to_bda[pCbData->handle] = NULL; + _dev_handle_queue_size[pCbData->handle] = 0; + _dev_handle_notack_num[pCbData->handle] = 0; + + if (p->hidConnCB != NULL) { + p->hidConnCB(pCbData->handle, FALSE); + } + break; + } + + case BTA_HH_SET_RPT_EVT: { + DEBUGPrint("BTA_HH_SET_RPT_EVT\n"); + break; + } + case BTA_HH_GET_RPT_EVT: { + DEBUGPrint("BTA_HH_GET_RPT_EVT\n"); + break; + } + + case BTA_HH_SET_PROTO_EVT: { + DEBUGPrint("BTA_HH_SET_PROTO_EVT\n"); + break; + } + case BTA_HH_GET_PROTO_EVT: { + DEBUGPrint("BTA_HH_GET_PROTO_EVT\n"); + break; + } + + case BTA_HH_SET_IDLE_EVT: { + DEBUGPrint("BTA_HH_SET_IDLE_EVT\n"); + break; + } + case BTA_HH_GET_IDLE_EVT: { + DEBUGPrint("BTA_HH_GET_IDLE_EVT\n"); + break; + } + + case BTA_HH_GET_DSCP_EVT: { + DEBUGPrint("BTA_HH_GET_DCSP_EVT\n"); + break; + } + + case BTA_HH_ADD_DEV_EVT: { + pConn = &pData->dev_info; + + DEBUGPrint("BTA_HH_ADD_DEV_EVT\n"); + + // clang-format off + DEBUGPrint("result: %d, handle: %d, addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + pConn->status, pConn->handle, + pConn->bda[0], pConn->bda[1], pConn->bda[2], + pConn->bda[3], pConn->bda[4], pConn->bda[5]); + // clang-format on + + pInfo = WUDiGetDevInfo(pConn->bda); + pInfo->devHandle = pConn->handle; + break; + } + + case BTA_HH_RMV_DEV_EVT: { + pConn = &pData->dev_info; + + DEBUGPrint("BTA_HH_RMV_DEV_EVT\n"); + + // clang-format off + DEBUGPrint("result: %d, handle: %d, addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + pConn->status, pConn->handle, + pConn->bda[0], pConn->bda[1], pConn->bda[2], + pConn->bda[3], pConn->bda[4], pConn->bda[5]); + // clang-format on + break; + } + + case BTA_HH_VC_UNPLUG_EVT: { + DEBUGPrint("BTA_HH_VS_UNPLUG_EVT\n"); + break; + } + + case WUD_HH_CUSTOM_EVT: { + pEvt15 = (WUD_HH_EVT15*)pData; + + p->bufferStatus0 = pEvt15->status0; + p->bufferStatus1 = pEvt15->status1; + + if (p->linkedNum < pEvt15->linkedNum) { + OSReport("WARNING: link num count is modified.\n"); + p->linkedNum = pEvt15->linkedNum; + } + + for (i = 0; i < pEvt15->linkedNum; i++) { + if (pEvt15->devices[i].handle < WUD_MAX_DEV_ENTRY) { + _dev_handle_queue_size[pEvt15->devices[i].handle] = pEvt15->devices[i].queueSize; + + _dev_handle_notack_num[pEvt15->devices[i].handle] = pEvt15->devices[i].notAckNum; + } + } + + break; + } + } +} + +void bta_hh_co_data(UINT8 handle, UINT8* pReport, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 subClass, UINT8 appId) { +#pragma unused(mode) +#pragma unused(subClass) + + WUDControlBlock* p = &_wcb; + + if (appId == 3) { + if (p->hidRecvCB != NULL) { + p->hidRecvCB(handle, pReport, len); + } + } else { + DEBUGPrint("Invalid app_id [%d]\n", appId); + } +} + +void bta_hh_co_open(UINT8 handle, UINT8 subClass, UINT16 attrMask, UINT8 appId) { +#pragma unused(handle) +#pragma unused(subClass) +#pragma unused(attrMask) +#pragma unused(appId) + + DEBUGPrint("bta_hh_co_open()\n"); +} + +void bta_hh_co_close(UINT8 handle, UINT8 appId) { +#pragma unused(handle) +#pragma unused(appId) + + DEBUGPrint("bta_hh_co_close()\n"); +} + +BOOL bta_dm_co_get_compress_memory(tBTA_SYS_ID id, UINT8** ppMemory, UINT32* memorySize) { +#pragma unused(id) +#pragma unused(ppMemory) +#pragma unused(memorySize) + + return FALSE; +} diff --git a/src/revolution/wud/__wud.h b/src/revolution/wud/__wud.h index dace1a2f71..9a7149dbca 100644 --- a/src/revolution/wud/__wud.h +++ b/src/revolution/wud/__wud.h @@ -2,77 +2,237 @@ #define _REVOLUTION_WUD_PRIVATE_H_ #include +#include #include +#include #ifdef __cplusplus extern "C" { #endif -#define WUD_MAX_DEV_ENTRY_FOR_STD 10 -#define WUD_MAX_DEV_ENTRY_FOR_SMP 6 +#define WUD_BDCMP(LHS, RHS) memcmp(LHS, RHS, BD_ADDR_LEN) +#define WUD_BDCPY(DST, SRC) memcpy(DST, SRC, BD_ADDR_LEN) -#define WUD_MAX_DEV_ENTRY 16 +// clang-format off +#define WUD_DEV_NAME_IS(NAME, VALUE) \ + (memcmp(NAME, VALUE, sizeof(VALUE) - 1) == 0) -#define WUD_DEV_HANDLE_INVALID (-1) +#define WUD_DEV_NAME_IS_CNT(NAME) \ + WUD_DEV_NAME_IS(NAME, "Nintendo RVL-CNT") -struct WUDDevInfoList { +#define WUD_DEV_NAME_IS_CNT_01(NAME) \ + WUD_DEV_NAME_IS(NAME, "Nintendo RVL-CNT-01") +// clang-format on + +typedef enum { + WUD_STATE_SYNC_START = 0, + WUD_STATE_SYNC_PREPARE_SEARCH = 1, + WUD_STATE_SYNC_START_SEARCH = 2, + WUD_STATE_SYNC_WAIT_FOR_SEARCH_RESULT = 3, + WUD_STATE_SYNC_CHECK_SEARCH_RESULT = 4, + WUD_STATE_SYNC_IS_EXISTED_DEVICE = 5, + WUD_STATE_SYNC_6 = 6, + WUD_STATE_SYNC_STORED_LINK_KEY_TO_EEPROM = 7, + WUD_STATE_SYNC_WAIT_FOR_STORING = 8, + WUD_STATE_SYNC_WAIT_FOR_READING = 10, + WUD_STATE_SYNC_11 = 11, + WUD_STATE_SYNC_12 = 12, + WUD_STATE_SYNC_13 = 13, + WUD_STATE_SYNC_DONE = 14, + WUD_STATE_SYNC_TRY_CONNECT = 15, + WUD_STATE_SYNC_PREPARE_FOR_EXISTED_DEVICE = 16, + WUD_STATE_SYNC_PREPARE_FOR_UNKNOWN_DEVICE = 17, + WUD_STATE_SYNC_REGISTER_DEVICE = 18, + WUD_STATE_SYNC_VIRGIN_SIMPLE = 19, + WUD_STATE_SYNC_VIRGIN_STANDARD = 20, + WUD_STATE_SYNC_CHANGE_SIMPLE_TO_STANDARD = 21, + WUD_STATE_SYNC_STORED_DEV_INFO_TO_NAND = 22, + WUD_STATE_SYNC_COMPLETE = 23, + WUD_STATE_SYNC_WAIT_FOR_INCOMING = 24, + WUD_STATE_SYNC_SC_FLUSH = 25, + WUD_STATE_SYNC_CANCEL_SEARCH = 26, + WUD_STATE_SYNC_WAIT_FOR_START_SEARCH = 29, + WUD_STATE_SYNC_ERROR = 255, +} WUDSyncState; + +typedef enum { + WUD_STATE_DELETE_START = 0, + WUD_STATE_DELETE_DISALLOW_INCOMING = 1, + WUD_STATE_DELETE_DISCONNECT_ALL = 2, + WUD_STATE_DELETE_CLEANUP_DATABASE = 3, + WUD_STATE_DELETE_CLEANUP_SETTING = 5, + WUD_STATE_DELETE_6 = 6, + WUD_STATE_DELETE_7 = 7, + WUD_STATE_DELETE_DONE = 8 +} WUDDeleteState; + +typedef enum { + WUD_RESULT_DELETE_BUSY = -1, + WUD_RESULT_DELETE_WAITING, + WUD_RESULT_DELETE_COMPLETE, +} WUDDeleteResult; + +typedef enum { + WUD_STATE_LINK_KEY_START = 0, + WUD_STATE_LINK_KEY_READING = 1, + WUD_STATE_LINK_KEY_WRITING = 2, + WUD_STATE_LINK_KEY_DELETING = 3, + WUD_STATE_LINK_KEY_ERROR = 255, +} WUDLinkKeyState; + +typedef enum { + WUD_STATE_STACK_START = 0, + WUD_STATE_STACK_GET_STORED_LINK_KEY = 1, + WUD_STATE_STACK_CHECK_DEVICE_INFO = 2, + WUD_STATE_STACK_DONE = 3, + WUD_STATE_STACK_INITIALIZED = 4, + WUD_STATE_STACK_ERROR = 255, +} WUDStackState; + +typedef enum { + WUD_STATE_INIT_START = 0, + WUD_STATE_INIT_WAIT_FOR_INITIALIZATION = 1, + WUD_STATE_INIT_GET_DEV_INFO = 2, + WUD_STATE_INIT_DONE = 3, + WUD_STATE_INIT_INITIALIZED = 4, + WUD_STATE_INIT_ERROR = 255, +} WUDInitState; + +typedef enum { + WUD_STATE_SHUTDOWN_START = 0, + WUD_STATE_SHUTDOWN_STORE_SETTINGS = 1, + WUD_STATE_SHUTDOWN_FLUSH_SETTINGS = 2, + WUD_STATE_SHUTDOWN_DONE = 3, + WUD_STATE_SHUTDOWN_ERROR = 255, +} WUDShutdownState; + +typedef enum { + WUD_VSE_INITIATE_PAIRING = 8, + WUD_VSE_DELETE_ALL_KEYS, + WUD_VSE_SI_PORT_STATUS, + WUD_VSE_WATCH_DOG_RESET_HW = 16, +} WUDVendorSpecificEvent; + +typedef struct WUDDevInfoList { /* 0x00 */ WUDDevInfo* devInfo; /* 0x04 */ struct WUDDevInfoList* prev; /* 0x08 */ struct WUDDevInfoList* next; -}; // size 0x0c +} WUDDevInfoList; -typedef struct /* possibly untagged, like kpad */ { - /* 0x000 */ WUDSyncDeviceCallback* syncStdCB; - /* 0x004 */ WUDSyncDeviceCallback* syncSmpCB; - /* 0x008 */ WUDClearDeviceCallback* clearDevCB; - /* 0x00c */ u8 syncState; - /* 0x00d */ u8 deleteState; - /* 0x00e */ u8 linkKeyState; - /* 0x00f */ u8 stackState; +typedef struct WUDDiscResp { + /* 0x000 */ BD_ADDR devAddr; + /* 0x006 */ char devName[64]; + /* 0x046 */ u8 unk_0x46[0x100 - 0x46]; + /* 0x100 */ tBTA_SERVICE_MASK services; + /* 0x104 */ u8 unk_0x104[0x104 - 0x100]; +} WUDDiscResp; + +typedef struct WUDPatchCmd { + /* 0x00 */ u8 data[13]; +} WUDPatchCmd; + +typedef struct WUDPatchList { + /* 0x00 */ u8 num; + /* 0x01 */ WUDPatchCmd cmds[]; +} WUDPatchList; + +#define WUD_PATCH_BUFFER_SIZE 0xFF +#define WUD_MAX_PATCHES (WUD_PATCH_BUFFER_SIZE / (s32)sizeof(WUDPatchCmd)) + +typedef struct WUDCB { + /* 0x000 */ WUDSyncDeviceCallback syncStdCB; + /* 0x004 */ WUDSyncDeviceCallback syncSmpCB; + /* 0x008 */ WUDClearDeviceCallback clearDevCB; + + /* 0x00C */ u8 syncState; + /* 0x00D */ u8 deleteState; + /* 0x00E */ u8 linkKeyState; + /* 0x00F */ u8 stackState; /* 0x010 */ u8 initState; /* 0x011 */ u8 shutdownState; + /* 0x012 */ u8 devNums; /* 0x013 */ u8 devSmpNums; - /* 0x014 */ struct WUDDevInfoList* smpListHead; - /* 0x018 */ struct WUDDevInfoList* smpListTail; - /* 0x01c */ struct WUDDevInfoList smpList[WUD_MAX_DEV_ENTRY_FOR_SMP]; - /* 0x064 */ struct WUDDevInfoList* stdListHead; - /* 0x068 */ struct WUDDevInfoList* stdListTail; - /* 0x06c */ struct WUDDevInfoList stdList[WUD_MAX_DEV_ENTRY_FOR_STD]; - /* 0x0e4 */ WUDDevInfo stdDevs[WUD_MAX_DEV_ENTRY_FOR_STD]; - /* 0x4a4 */ WUDDevInfo smpDevs[WUD_MAX_DEV_ENTRY_FOR_SMP]; - /* 0x6e4 */ u8 connectedNum; - /* 0x6e5 */ u8 linkedNum; - /* 0x6e6 */ u8 syncedNum; - /* 0x6e7 */ u8 syncSkipChecks; - /* 0x6e8 */ s8 syncLoopNum; - /* 0x6e9 */ u8 syncType; - /* 0x6ea */ u8 connectable; - /* 0x6eb */ u8 discoverable; - /* 0x6ec */ WUDHidReceiveCallback* hidRecvCB; - /* 0x6f0 */ WUDHidConnectCallback* hidConnCB; - /* 0x6f4 */ WUDAllocFunc* allocFunc; - /* 0x6f8 */ WUDFreeFunc* freeFunc; - /* 0x6fc */ BD_ADDR pairAddr; - /* 0x702 */ BD_ADDR hostAddr; - /* 0x708 */ s8 libStatus; - /* 0x709 */ u8 siPortStatus; - /* 0x70a */ u8 pmID; - /* 0x70b */ s8 syncRssi; - /* 0x710 */ OSAlarm alarm; - /* 0x740 */ u32 hhFlags; // some flags maybe? - /* 0x744 */ u16 bufferStatus0; - /* 0x746 */ u16 bufferStatus1; - /* 0x748 */ s8 initWaitDeviceUpFrames; - /* 0x749 */ s8 waitStartSearchFrames; - /* 0x74a */ s16 waitIncomingFrames; -} wud_cb_st; // size 0x750 + /* 0x014 */ WUDDevInfoList* smpListHead; + /* 0x018 */ WUDDevInfoList* smpListTail; + /* 0x01C */ WUDDevInfoList smpList[WUD_MAX_DEV_ENTRY_FOR_SMP]; + +#if SDK_AUG2010 + /* 0x064 */ WUDDevInfoList* stdListHead; + /* 0x068 */ WUDDevInfoList* stdListTail; + /* 0x06C */ WUDDevInfoList stdList[WUD_MAX_DEV_ENTRY_FOR_STD]; +#endif + + /* 0x064 */ WUDDevInfo stdDevs[WUD_MAX_DEV_ENTRY_FOR_STD]; + /* 0x424 */ WUDDevInfo smpDevs[WUD_MAX_DEV_ENTRY_FOR_SMP]; + + /* 0x664 */ u8 connectedNum; + /* 0x665 */ u8 linkedNum; + /* 0x666 */ u8 syncedNum; + + /* 0x667 */ u8 syncSkipChecks; + /* 0x668 */ s8 syncLoopNum; + /* 0x669 */ u8 syncType; + + /* 0x66A */ u8 connectable; + /* 0x66B */ u8 discoverable; + + /* 0x66C */ WUDHidRecvCallback hidRecvCB; + /* 0x670 */ WUDHidConnCallback hidConnCB; + + /* 0x674 */ WUDAllocFunc allocFunc; + /* 0x678 */ WUDFreeFunc freeFunc; + + /* 0x67C */ BD_ADDR pairAddr; + /* 0x682 */ BD_ADDR hostAddr; + + /* 0x688 */ s8 libStatus; + + /* 0x689 */ u8 serialPortStatus; + /* 0x68A */ UINT8 pmID; + /* 0x68B */ s8 syncRssi; + /* 0x670 */ OSAlarm alarm; + /* 0x6C0 */ u32 hhFlags; + + /* 0x6C4 */ u16 bufferStatus0; + /* 0x6C6 */ u16 bufferStatus1; +#if SDK_AUG2010 + /* 0x748 */ u8 unk_0x748[0x750 - 0x748]; +#endif +} WUDControlBlock; + +#if SDK_AUG2010 +extern WUDControlBlock __rvl_wudcb; +#define _wcb __rvl_wudcb +#else +extern WUDControlBlock _wcb; +#endif +extern WUDDevInfo _work; + +extern SCBtDeviceInfoArray _scArray; + +extern BD_ADDR_PTR _dev_handle_to_bda[WUD_MAX_DEV_ENTRY]; +extern u16 _dev_handle_queue_size[WUD_MAX_DEV_ENTRY]; +extern u16 _dev_handle_notack_num[WUD_MAX_DEV_ENTRY]; + +#if SDK_AUG2010 u16 WUDiGetQueueSizeForHandle(u8 dev_handle); u16 WUDiGetNotAckNumForHandle(u8 dev_handle); +#else +u16 WUDiGetQueueSizeForHandle(u32 dev_handle); +u16 WUDiGetNotAckNumForHandle(u32 dev_handle); +#endif + +/* wud/WUDHidHost.c */ +void WUDHidHostCallback(tBTA_HH_EVT event, tBTA_HH *p_data); + +/* wud/debug_msg.c */ + +void WUD_DEBUGPrint(const char* fmt, ...); #ifdef __cplusplus } #endif -#endif // _REVOLUTION_WUD_PRIVATE_H_ +#endif /* _REVOLUTION_WUD_PRIVATE_H_ */ diff --git a/src/revolution/wud/debug_msg.c b/src/revolution/wud/debug_msg.c index 43ab011cb5..8e05cc0499 100644 --- a/src/revolution/wud/debug_msg.c +++ b/src/revolution/wud/debug_msg.c @@ -1,6 +1,8 @@ -#include +#include + +#include void WUD_DEBUGPrint(const char* msg, ...) { - // NONMATCHING + va_list list; }