service/nwm_uds: Add NetworkStatusChangeReason (#5377)
fixes https://github.com/citra-emu/citra/issues/3975
This commit is contained in:
parent
06a9f69d88
commit
9d5ae8e1c2
@ -124,7 +124,7 @@ void NWM_UDS::BroadcastNodeMap() {
|
|||||||
|
|
||||||
void NWM_UDS::HandleNodeMapPacket(const Network::WifiPacket& packet) {
|
void NWM_UDS::HandleNodeMapPacket(const Network::WifiPacket& packet) {
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status == NetworkStatus::ConnectedAsHost) {
|
||||||
LOG_DEBUG(Service_NWM, "Ignored NodeMapPacket since connection_status is host");
|
LOG_DEBUG(Service_NWM, "Ignored NodeMapPacket since connection_status is host");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -170,10 +170,10 @@ void NWM_UDS::HandleAssociationResponseFrame(const Network::WifiPacket& packet)
|
|||||||
"Could not join network");
|
"Could not join network");
|
||||||
{
|
{
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::Connecting)) {
|
if (connection_status.status != NetworkStatus::Connecting) {
|
||||||
LOG_DEBUG(Service_NWM,
|
LOG_DEBUG(Service_NWM,
|
||||||
"Ignored AssociationResponseFrame because connection status is {}",
|
"Ignored AssociationResponseFrame because connection status is {}",
|
||||||
connection_status.status);
|
static_cast<u32>(connection_status.status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,9 +196,9 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
|
|||||||
std::lock(hle_lock, lock);
|
std::lock(hle_lock, lock);
|
||||||
|
|
||||||
if (GetEAPoLFrameType(packet.data) == EAPoLStartMagic) {
|
if (GetEAPoLFrameType(packet.data) == EAPoLStartMagic) {
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is {}",
|
LOG_DEBUG(Service_NWM, "Connection sequence aborted, because connection status is {}",
|
||||||
connection_status.status);
|
static_cast<u32>(connection_status.status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
|
|||||||
SendPacket(eapol_logoff);
|
SendPacket(eapol_logoff);
|
||||||
|
|
||||||
connection_status_event->Signal();
|
connection_status_event->Signal();
|
||||||
} else if (connection_status.status == static_cast<u32>(NetworkStatus::Connecting)) {
|
} else if (connection_status.status == NetworkStatus::Connecting) {
|
||||||
auto logoff = ParseEAPoLLogoffFrame(packet.data);
|
auto logoff = ParseEAPoLLogoffFrame(packet.data);
|
||||||
|
|
||||||
network_info.host_mac_address = packet.transmitter_address;
|
network_info.host_mac_address = packet.transmitter_address;
|
||||||
@ -282,14 +282,14 @@ void NWM_UDS::HandleEAPoLPacket(const Network::WifiPacket& packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We're now connected, signal the application
|
// We're now connected, signal the application
|
||||||
connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsClient);
|
connection_status.status = NetworkStatus::ConnectedAsClient;
|
||||||
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::Connected);
|
connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished;
|
||||||
// Some games require ConnectToNetwork to block, for now it doesn't
|
// Some games require ConnectToNetwork to block, for now it doesn't
|
||||||
// If blocking is implemented this lock needs to be changed,
|
// If blocking is implemented this lock needs to be changed,
|
||||||
// otherwise it might cause deadlocks
|
// otherwise it might cause deadlocks
|
||||||
connection_status_event->Signal();
|
connection_status_event->Signal();
|
||||||
connection_event->Signal();
|
connection_event->Signal();
|
||||||
} else if (connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsClient)) {
|
} else if (connection_status.status == NetworkStatus::ConnectedAsClient) {
|
||||||
// TODO(B3N30): Remove that section and send/receive a proper connection_status packet
|
// TODO(B3N30): Remove that section and send/receive a proper connection_status packet
|
||||||
// On a 3ds this packet wouldn't be addressed to already connected clients
|
// On a 3ds this packet wouldn't be addressed to already connected clients
|
||||||
// We use this information because in the current implementation the host
|
// We use this information because in the current implementation the host
|
||||||
@ -328,11 +328,11 @@ void NWM_UDS::HandleSecureDataPacket(const Network::WifiPacket& packet) {
|
|||||||
std::unique_lock lock(connection_status_mutex, std::defer_lock);
|
std::unique_lock lock(connection_status_mutex, std::defer_lock);
|
||||||
std::lock(hle_lock, lock);
|
std::lock(hle_lock, lock);
|
||||||
|
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost) &&
|
if (connection_status.status != NetworkStatus::ConnectedAsHost &&
|
||||||
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient)) {
|
connection_status.status != NetworkStatus::ConnectedAsClient) {
|
||||||
// TODO(B3N30): Handle spectators
|
// TODO(B3N30): Handle spectators
|
||||||
LOG_DEBUG(Service_NWM, "Ignored SecureDataPacket, because connection status is {}",
|
LOG_DEBUG(Service_NWM, "Ignored SecureDataPacket, because connection status is {}",
|
||||||
connection_status.status);
|
static_cast<u32>(connection_status.status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,12 +347,12 @@ void NWM_UDS::HandleSecureDataPacket(const Network::WifiPacket& packet) {
|
|||||||
// However, we might have received this packet due to a broadcast from the host, in that
|
// However, we might have received this packet due to a broadcast from the host, in that
|
||||||
// case just ignore it.
|
// case just ignore it.
|
||||||
if (packet.destination_address != Network::BroadcastMac &&
|
if (packet.destination_address != Network::BroadcastMac &&
|
||||||
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
LOG_ERROR(Service_NWM, "Received packet addressed to others but we're not a host");
|
LOG_ERROR(Service_NWM, "Received packet addressed to others but we're not a host");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost) &&
|
if (connection_status.status == NetworkStatus::ConnectedAsHost &&
|
||||||
secure_data.dest_node_id != BroadcastNetworkNodeId) {
|
secure_data.dest_node_id != BroadcastNetworkNodeId) {
|
||||||
// Broadcast the packet so the right receiver can get it.
|
// Broadcast the packet so the right receiver can get it.
|
||||||
// TODO(B3N30): Is there a flag that makes this kind of routing be unicast instead of
|
// TODO(B3N30): Is there a flag that makes this kind of routing be unicast instead of
|
||||||
@ -390,7 +390,7 @@ void NWM_UDS::StartConnectionSequence(const MacAddress& server) {
|
|||||||
WifiPacket auth_request;
|
WifiPacket auth_request;
|
||||||
{
|
{
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
connection_status.status = static_cast<u32>(NetworkStatus::Connecting);
|
connection_status.status = NetworkStatus::Connecting;
|
||||||
|
|
||||||
// TODO(Subv): Handle timeout.
|
// TODO(Subv): Handle timeout.
|
||||||
|
|
||||||
@ -410,9 +410,9 @@ void NWM_UDS::SendAssociationResponseFrame(const MacAddress& address) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is {}",
|
LOG_ERROR(Service_NWM, "Connection sequence aborted, because connection status is {}",
|
||||||
connection_status.status);
|
static_cast<u32>(connection_status.status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,10 +436,10 @@ void NWM_UDS::HandleAuthenticationFrame(const Network::WifiPacket& packet) {
|
|||||||
WifiPacket auth_request;
|
WifiPacket auth_request;
|
||||||
{
|
{
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
LOG_ERROR(Service_NWM,
|
LOG_ERROR(Service_NWM,
|
||||||
"Connection sequence aborted, because connection status is {}",
|
"Connection sequence aborted, because connection status is {}",
|
||||||
connection_status.status);
|
static_cast<u32>(connection_status.status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (node_map.find(packet.transmitter_address) != node_map.end()) {
|
if (node_map.find(packet.transmitter_address) != node_map.end()) {
|
||||||
@ -472,7 +472,7 @@ void NWM_UDS::HandleDeauthenticationFrame(const Network::WifiPacket& packet) {
|
|||||||
std::unique_lock hle_lock(HLE::g_hle_lock, std::defer_lock);
|
std::unique_lock hle_lock(HLE::g_hle_lock, std::defer_lock);
|
||||||
std::unique_lock lock(connection_status_mutex, std::defer_lock);
|
std::unique_lock lock(connection_status_mutex, std::defer_lock);
|
||||||
std::lock(hle_lock, lock);
|
std::lock(hle_lock, lock);
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
LOG_ERROR(Service_NWM, "Got deauthentication frame but we are not the host");
|
LOG_ERROR(Service_NWM, "Got deauthentication frame but we are not the host");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -667,8 +667,7 @@ ResultVal<std::shared_ptr<Kernel::Event>> NWM_UDS::Initialize(
|
|||||||
// Reset the connection status, it contains all zeros after initialization,
|
// Reset the connection status, it contains all zeros after initialization,
|
||||||
// except for the actual status value.
|
// except for the actual status value.
|
||||||
connection_status = {};
|
connection_status = {};
|
||||||
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::NotConnected);
|
connection_status.status = NetworkStatus::NotConnected;
|
||||||
connection_status.status = static_cast<u32>(NetworkStatus::NotConnected);
|
|
||||||
node_info.clear();
|
node_info.clear();
|
||||||
node_info.push_back(current_node);
|
node_info.push_back(current_node);
|
||||||
channel_data.clear();
|
channel_data.clear();
|
||||||
@ -856,8 +855,8 @@ ResultCode NWM_UDS::BeginHostingNetwork(const u8* network_info_buffer,
|
|||||||
// The real UDS module throws a fatal error if this assert fails.
|
// The real UDS module throws a fatal error if this assert fails.
|
||||||
ASSERT_MSG(network_info.max_nodes > 1, "Trying to host a network of only one member.");
|
ASSERT_MSG(network_info.max_nodes > 1, "Trying to host a network of only one member.");
|
||||||
|
|
||||||
connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsHost);
|
connection_status.status = NetworkStatus::ConnectedAsHost;
|
||||||
connection_status.disconnect_reason = static_cast<u32>(DisconnectStatus::Connected);
|
connection_status.status_change_reason = NetworkStatusChangeReason::ConnectionEstablished;
|
||||||
|
|
||||||
// Ensure the application data size is less than the maximum value.
|
// Ensure the application data size is less than the maximum value.
|
||||||
ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize,
|
ASSERT_MSG(network_info.application_data_size <= ApplicationDataSize,
|
||||||
@ -965,7 +964,7 @@ void NWM_UDS::EjectClient(Kernel::HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status != static_cast<u8>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
// Only the host can kick people.
|
// Only the host can kick people.
|
||||||
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
|
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Usage));
|
ErrorSummary::InvalidState, ErrorLevel::Usage));
|
||||||
@ -1016,11 +1015,12 @@ void NWM_UDS::DestroyNetwork(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
// Only a host can destroy
|
// Only a host can destroy
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status != static_cast<u8>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultCode(ErrCodes::WrongStatus, ErrorModule::UDS, ErrorSummary::InvalidState,
|
rb.Push(ResultCode(ErrCodes::WrongStatus, ErrorModule::UDS, ErrorSummary::InvalidState,
|
||||||
ErrorLevel::Status));
|
ErrorLevel::Status));
|
||||||
LOG_WARNING(Service_NWM, "called with status {}", connection_status.status);
|
LOG_WARNING(Service_NWM, "called with status {}",
|
||||||
|
static_cast<u32>(connection_status.status));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1028,7 +1028,7 @@ void NWM_UDS::DestroyNetwork(Kernel::HLERequestContext& ctx) {
|
|||||||
|
|
||||||
u16_le tmp_node_id = connection_status.network_node_id;
|
u16_le tmp_node_id = connection_status.network_node_id;
|
||||||
connection_status = {};
|
connection_status = {};
|
||||||
connection_status.status = static_cast<u32>(NetworkStatus::NotConnected);
|
connection_status.status = NetworkStatus::NotConnected;
|
||||||
connection_status.network_node_id = tmp_node_id;
|
connection_status.network_node_id = tmp_node_id;
|
||||||
node_map.clear();
|
node_map.clear();
|
||||||
connection_status_event->Signal();
|
connection_status_event->Signal();
|
||||||
@ -1053,11 +1053,11 @@ void NWM_UDS::DisconnectNetwork(Kernel::HLERequestContext& ctx) {
|
|||||||
WifiPacket deauth;
|
WifiPacket deauth;
|
||||||
{
|
{
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
if (connection_status.status == NetworkStatus::ConnectedAsHost) {
|
||||||
// A real 3ds makes strange things here. We do the same
|
// A real 3ds makes strange things here. We do the same
|
||||||
u16_le tmp_node_id = connection_status.network_node_id;
|
u16_le tmp_node_id = connection_status.network_node_id;
|
||||||
connection_status = {};
|
connection_status = {};
|
||||||
connection_status.status = static_cast<u32>(NetworkStatus::ConnectedAsHost);
|
connection_status.status = NetworkStatus::ConnectedAsHost;
|
||||||
connection_status.network_node_id = tmp_node_id;
|
connection_status.network_node_id = tmp_node_id;
|
||||||
node_map.clear();
|
node_map.clear();
|
||||||
LOG_DEBUG(Service_NWM, "called as a host");
|
LOG_DEBUG(Service_NWM, "called as a host");
|
||||||
@ -1067,7 +1067,7 @@ void NWM_UDS::DisconnectNetwork(Kernel::HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
u16_le tmp_node_id = connection_status.network_node_id;
|
u16_le tmp_node_id = connection_status.network_node_id;
|
||||||
connection_status = {};
|
connection_status = {};
|
||||||
connection_status.status = static_cast<u32>(NetworkStatus::NotConnected);
|
connection_status.status = NetworkStatus::NotConnected;
|
||||||
connection_status.network_node_id = tmp_node_id;
|
connection_status.network_node_id = tmp_node_id;
|
||||||
node_map.clear();
|
node_map.clear();
|
||||||
connection_status_event->Signal();
|
connection_status_event->Signal();
|
||||||
@ -1107,8 +1107,8 @@ void NWM_UDS::SendTo(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient) &&
|
if (connection_status.status != NetworkStatus::ConnectedAsClient &&
|
||||||
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost)) {
|
connection_status.status != NetworkStatus::ConnectedAsHost) {
|
||||||
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
|
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
return;
|
return;
|
||||||
@ -1179,9 +1179,9 @@ void NWM_UDS::PullPacket(Kernel::HLERequestContext& ctx) {
|
|||||||
u32 buff_size = std::min<u32>(max_out_buff_size_aligned, 0x172) << 2;
|
u32 buff_size = std::min<u32>(max_out_buff_size_aligned, 0x172) << 2;
|
||||||
|
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost) &&
|
if (connection_status.status != NetworkStatus::ConnectedAsHost &&
|
||||||
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsClient) &&
|
connection_status.status != NetworkStatus::ConnectedAsClient &&
|
||||||
connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsSpectator)) {
|
connection_status.status != NetworkStatus::ConnectedAsSpectator) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
|
rb.Push(ResultCode(ErrorDescription::NotAuthorized, ErrorModule::UDS,
|
||||||
ErrorSummary::InvalidState, ErrorLevel::Status));
|
ErrorSummary::InvalidState, ErrorLevel::Status));
|
||||||
@ -1242,7 +1242,7 @@ void NWM_UDS::GetChannel(Kernel::HLERequestContext& ctx) {
|
|||||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
|
|
||||||
std::lock_guard lock(connection_status_mutex);
|
std::lock_guard lock(connection_status_mutex);
|
||||||
bool is_connected = connection_status.status != static_cast<u32>(NetworkStatus::NotConnected);
|
bool is_connected = connection_status.status != NetworkStatus::NotConnected;
|
||||||
|
|
||||||
u8 channel = is_connected ? network_channel : 0;
|
u8 channel = is_connected ? network_channel : 0;
|
||||||
|
|
||||||
@ -1445,7 +1445,7 @@ void NWM_UDS::DecryptBeaconData(Kernel::HLERequestContext& ctx) {
|
|||||||
// Sends a 802.11 beacon frame with information about the current network.
|
// Sends a 802.11 beacon frame with information about the current network.
|
||||||
void NWM_UDS::BeaconBroadcastCallback(std::uintptr_t user_data, s64 cycles_late) {
|
void NWM_UDS::BeaconBroadcastCallback(std::uintptr_t user_data, s64 cycles_late) {
|
||||||
// Don't do anything if we're not actually hosting a network
|
// Don't do anything if we're not actually hosting a network
|
||||||
if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost))
|
if (connection_status.status != NetworkStatus::ConnectedAsHost)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info);
|
std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info);
|
||||||
|
@ -65,7 +65,7 @@ static_assert(sizeof(NodeInfo) == 40, "NodeInfo has incorrect size.");
|
|||||||
|
|
||||||
using NodeList = std::vector<NodeInfo>;
|
using NodeList = std::vector<NodeInfo>;
|
||||||
|
|
||||||
enum class NetworkStatus {
|
enum class NetworkStatus : u32 {
|
||||||
NotConnected = 3,
|
NotConnected = 3,
|
||||||
ConnectedAsHost = 6,
|
ConnectedAsHost = 6,
|
||||||
Connecting = 7,
|
Connecting = 7,
|
||||||
@ -73,15 +73,15 @@ enum class NetworkStatus {
|
|||||||
ConnectedAsSpectator = 10,
|
ConnectedAsSpectator = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DisconnectStatus {
|
enum class NetworkStatusChangeReason : u32 {
|
||||||
Connected = 1,
|
None = 0,
|
||||||
NotConnected = 2,
|
ConnectionEstablished = 1,
|
||||||
// TODO(B3N30): Figure out the other values
|
ConnectionLost = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionStatus {
|
struct ConnectionStatus {
|
||||||
u32_le status;
|
enum_le<NetworkStatus> status;
|
||||||
u32_le disconnect_reason;
|
enum_le<NetworkStatusChangeReason> status_change_reason;
|
||||||
u16_le network_node_id;
|
u16_le network_node_id;
|
||||||
u16_le changed_nodes;
|
u16_le changed_nodes;
|
||||||
u16_le nodes[UDSMaxNodes];
|
u16_le nodes[UDSMaxNodes];
|
||||||
|
Loading…
Reference in New Issue
Block a user