summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/nwm_uds.cpp
blob: 80081aae2d75643be709c6ce711e1d61f183a871 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/nwm_uds.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace NWM_UDS

namespace NWM_UDS {

static Kernel::SharedPtr<Kernel::Event> handle_event;

/**
 * NWM_UDS::Shutdown service function
 *  Inputs:
 *      1 : None
 *  Outputs:
 *      0 : Return header
 *      1 : Result of function, 0 on success, otherwise error code
 */
static void Shutdown(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();

    // TODO(purpasmart): Verify return header on HW

    cmd_buff[1] = RESULT_SUCCESS.raw;

    LOG_WARNING(Service_NWM, "(STUBBED) called");
}

/**
 * NWM_UDS::RecvBeaconBroadcastData service function
 *  Inputs:
 *      1 : Output buffer max size
 *      2 : Unknown
 *      3 : Unknown
 *      4 : MAC address?
 *   6-14 : Unknown, usually zero / uninitialized?
 *     15 : WLan Comm ID
 *     16 : This is the ID also located at offset 0xE in the CTR-generation structure.
 *     17 : Value 0
 *     18 : Input handle
 *     19 : (Size<<4) | 12
 *     20 : Output buffer ptr
 *  Outputs:
 *      0 : Return header
 *      1 : Result of function, 0 on success, otherwise error code
 */
static void RecvBeaconBroadcastData(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();
    u32 out_buffer_size = cmd_buff[1];
    u32 unk1 = cmd_buff[2];
    u32 unk2 = cmd_buff[3];
    u32 mac_address = cmd_buff[4];

    u32 unk3 = cmd_buff[6];

    u32 wlan_comm_id = cmd_buff[15];
    u32 ctr_gen_id = cmd_buff[16];
    u32 value = cmd_buff[17];
    u32 input_handle = cmd_buff[18];
    u32 new_buffer_size = cmd_buff[19];
    u32 out_buffer_ptr = cmd_buff[20];

    cmd_buff[1] = RESULT_SUCCESS.raw;

    LOG_WARNING(Service_NWM,
                "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X,"
                "mac_address=0x%08X, unk3=0x%08X, wlan_comm_id=0x%08X, ctr_gen_id=0x%08X,"
                "value=%u, input_handle=0x%08X, new_buffer_size=0x%08X, out_buffer_ptr=0x%08X",
                out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value,
                input_handle, new_buffer_size, out_buffer_ptr);
}

/**
 * NWM_UDS::Initialize service function
 *  Inputs:
 *      1 : Unknown
 *   2-11 : Input Structure
 *     12 : Unknown u16
 *     13 : Value 0
 *     14 : Handle
 *  Outputs:
 *      0 : Return header
 *      1 : Result of function, 0 on success, otherwise error code
 *      2 : Value 0
 *      3 : Output handle
 */
static void Initialize(Service::Interface* self) {
    u32* cmd_buff = Kernel::GetCommandBuffer();
    u32 unk1 = cmd_buff[1];
    u32 unk2 = cmd_buff[12];
    u32 value = cmd_buff[13];
    u32 handle = cmd_buff[14];

    // Because NWM service is not implemented at all, we stub the Initialize function with an error
    // code instead of success to prevent games from using the service and from causing more issues.
    // The error code is from a real 3DS with wifi off, thus believed to be "network disabled".
    /*
    cmd_buff[1] = RESULT_SUCCESS.raw;
    cmd_buff[2] = 0;
    cmd_buff[3] = Kernel::g_handle_table.Create(handle_event)
                      .MoveFrom(); // TODO(purpasmart): Verify if this is a event handle
    */
    cmd_buff[0] = IPC::MakeHeader(0x1B, 1, 2);
    cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(2), ErrorModule::UDS,
                             ErrorSummary::StatusChanged, ErrorLevel::Status)
                      .raw;
    cmd_buff[2] = 0;
    cmd_buff[3] = 0;

    LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X",
                unk1, unk2, value, handle);
}

const Interface::FunctionInfo FunctionTable[] = {
    {0x00020000, nullptr, "Scrap"},
    {0x00030000, Shutdown, "Shutdown"},
    {0x00040402, nullptr, "CreateNetwork"},
    {0x00050040, nullptr, "EjectClient"},
    {0x00060000, nullptr, "EjectSpectator"},
    {0x00070080, nullptr, "UpdateNetworkAttribute"},
    {0x00080000, nullptr, "DestroyNetwork"},
    {0x000A0000, nullptr, "DisconnectNetwork"},
    {0x000B0000, nullptr, "GetConnectionStatus"},
    {0x000D0040, nullptr, "GetNodeInformation"},
    {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"},
    {0x00100042, nullptr, "SetBeaconAdditionalData"},
    {0x00110040, nullptr, "GetApplicationData"},
    {0x00120100, nullptr, "Bind"},
    {0x00130040, nullptr, "Unbind"},
    {0x001400C0, nullptr, "RecvBroadcastDataFrame"},
    {0x00150080, nullptr, "SetMaxSendDelay"},
    {0x00170182, nullptr, "SendTo"},
    {0x001A0000, nullptr, "GetChannel"},
    {0x001B0302, Initialize, "Initialize"},
    {0x001D0044, nullptr, "BeginHostingNetwork"},
    {0x001E0084, nullptr, "ConnectToNetwork"},
    {0x001F0006, nullptr, "DecryptBeaconData"},
    {0x00200040, nullptr, "Flush"},
    {0x00210080, nullptr, "SetProbeResponseParam"},
    {0x00220402, nullptr, "ScanOnConnection"},
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Interface class

Interface::Interface() {
    handle_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "NWM_UDS::handle_event");

    Register(FunctionTable);
}

Interface::~Interface() {
    handle_event = nullptr;
}

} // namespace