mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Merge pull request #2831 from Subv/uds_auth
Services/UDS: Handle beacon frames and the basic AP connection sequence frames.
This commit is contained in:
		
						commit
						617b6974b9
					
				@ -145,6 +145,7 @@ set(SRCS
 | 
			
		||||
            hle/service/nwm/nwm_tst.cpp
 | 
			
		||||
            hle/service/nwm/nwm_uds.cpp
 | 
			
		||||
            hle/service/nwm/uds_beacon.cpp
 | 
			
		||||
            hle/service/nwm/uds_connection.cpp
 | 
			
		||||
            hle/service/nwm/uds_data.cpp
 | 
			
		||||
            hle/service/pm_app.cpp
 | 
			
		||||
            hle/service/ptm/ptm.cpp
 | 
			
		||||
@ -344,6 +345,7 @@ set(HEADERS
 | 
			
		||||
            hle/service/nwm/nwm_tst.h
 | 
			
		||||
            hle/service/nwm/nwm_uds.h
 | 
			
		||||
            hle/service/nwm/uds_beacon.h
 | 
			
		||||
            hle/service/nwm/uds_connection.h
 | 
			
		||||
            hle/service/nwm/uds_data.h
 | 
			
		||||
            hle/service/pm_app.h
 | 
			
		||||
            hle/service/ptm/ptm.h
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
@ -15,8 +16,10 @@
 | 
			
		||||
#include "core/hle/result.h"
 | 
			
		||||
#include "core/hle/service/nwm/nwm_uds.h"
 | 
			
		||||
#include "core/hle/service/nwm/uds_beacon.h"
 | 
			
		||||
#include "core/hle/service/nwm/uds_connection.h"
 | 
			
		||||
#include "core/hle/service/nwm/uds_data.h"
 | 
			
		||||
#include "core/memory.h"
 | 
			
		||||
#include "network/network.h"
 | 
			
		||||
 | 
			
		||||
namespace Service {
 | 
			
		||||
namespace NWM {
 | 
			
		||||
@ -51,6 +54,135 @@ static NetworkInfo network_info;
 | 
			
		||||
// Event that will generate and send the 802.11 beacon frames.
 | 
			
		||||
static int beacon_broadcast_event;
 | 
			
		||||
 | 
			
		||||
// Mutex to synchronize access to the list of received beacons between the emulation thread and the
 | 
			
		||||
// network thread.
 | 
			
		||||
static std::mutex beacon_mutex;
 | 
			
		||||
 | 
			
		||||
// Number of beacons to store before we start dropping the old ones.
 | 
			
		||||
// TODO(Subv): Find a more accurate value for this limit.
 | 
			
		||||
constexpr size_t MaxBeaconFrames = 15;
 | 
			
		||||
 | 
			
		||||
// List of the last <MaxBeaconFrames> beacons received from the network.
 | 
			
		||||
static std::deque<Network::WifiPacket> received_beacons;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a list of received 802.11 beacon frames from the specified sender since the last call.
 | 
			
		||||
 */
 | 
			
		||||
std::deque<Network::WifiPacket> GetReceivedBeacons(const MacAddress& sender) {
 | 
			
		||||
    std::lock_guard<std::mutex> lock(beacon_mutex);
 | 
			
		||||
    // TODO(Subv): Filter by sender.
 | 
			
		||||
    return std::move(received_beacons);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Sends a WifiPacket to the room we're currently connected to.
 | 
			
		||||
void SendPacket(Network::WifiPacket& packet) {
 | 
			
		||||
    // TODO(Subv): Implement.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Inserts the received beacon frame in the beacon queue and removes any older beacons if the size
 | 
			
		||||
// limit is exceeded.
 | 
			
		||||
void HandleBeaconFrame(const Network::WifiPacket& packet) {
 | 
			
		||||
    std::lock_guard<std::mutex> lock(beacon_mutex);
 | 
			
		||||
 | 
			
		||||
    received_beacons.emplace_back(packet);
 | 
			
		||||
 | 
			
		||||
    // Discard old beacons if the buffer is full.
 | 
			
		||||
    if (received_beacons.size() > MaxBeaconFrames)
 | 
			
		||||
        received_beacons.pop_front();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns an available index in the nodes array for the
 | 
			
		||||
 * currently-hosted UDS network.
 | 
			
		||||
 */
 | 
			
		||||
static u16 GetNextAvailableNodeId() {
 | 
			
		||||
    ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
 | 
			
		||||
               "Can not accept clients if we're not hosting a network");
 | 
			
		||||
 | 
			
		||||
    for (u16 index = 0; index < connection_status.max_nodes; ++index) {
 | 
			
		||||
        if ((connection_status.node_bitmask & (1 << index)) == 0)
 | 
			
		||||
            return index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Any connection attempts to an already full network should have been refused.
 | 
			
		||||
    ASSERT_MSG(false, "No available connection slots in the network");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Start a connection sequence with an UDS server. The sequence starts by sending an 802.11
 | 
			
		||||
 * authentication frame with SEQ1.
 | 
			
		||||
 */
 | 
			
		||||
void StartConnectionSequence(const MacAddress& server) {
 | 
			
		||||
    ASSERT(connection_status.status == static_cast<u32>(NetworkStatus::NotConnected));
 | 
			
		||||
 | 
			
		||||
    // TODO(Subv): Handle timeout.
 | 
			
		||||
 | 
			
		||||
    // Send an authentication frame with SEQ1
 | 
			
		||||
    using Network::WifiPacket;
 | 
			
		||||
    WifiPacket auth_request;
 | 
			
		||||
    auth_request.channel = network_channel;
 | 
			
		||||
    auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ1);
 | 
			
		||||
    auth_request.destination_address = server;
 | 
			
		||||
    auth_request.type = WifiPacket::PacketType::Authentication;
 | 
			
		||||
 | 
			
		||||
    SendPacket(auth_request);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Sends an Association Response frame to the specified mac address
 | 
			
		||||
void SendAssociationResponseFrame(const MacAddress& address) {
 | 
			
		||||
    ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost));
 | 
			
		||||
 | 
			
		||||
    using Network::WifiPacket;
 | 
			
		||||
    WifiPacket assoc_response;
 | 
			
		||||
    assoc_response.channel = network_channel;
 | 
			
		||||
    // TODO(Subv): This will cause multiple clients to end up with the same association id, but
 | 
			
		||||
    // we're not using that for anything.
 | 
			
		||||
    u16 association_id = 1;
 | 
			
		||||
    assoc_response.data = GenerateAssocResponseFrame(AssocStatus::Successful, association_id,
 | 
			
		||||
                                                     network_info.network_id);
 | 
			
		||||
    assoc_response.destination_address = address;
 | 
			
		||||
    assoc_response.type = WifiPacket::PacketType::AssociationResponse;
 | 
			
		||||
 | 
			
		||||
    SendPacket(assoc_response);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Handles the authentication request frame and sends the authentication response and association
 | 
			
		||||
 * response frames. Once an Authentication frame with SEQ1 is received by the server, it responds
 | 
			
		||||
 * with an Authentication frame containing SEQ2, and immediately sends an Association response frame
 | 
			
		||||
 * containing the details of the access point and the assigned association id for the new client.
 | 
			
		||||
 */
 | 
			
		||||
void HandleAuthenticationFrame(const Network::WifiPacket& packet) {
 | 
			
		||||
    // Only the SEQ1 auth frame is handled here, the SEQ2 frame doesn't need any special behavior
 | 
			
		||||
    if (GetAuthenticationSeqNumber(packet.data) == AuthenticationSeq::SEQ1) {
 | 
			
		||||
        ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost));
 | 
			
		||||
 | 
			
		||||
        // Respond with an authentication response frame with SEQ2
 | 
			
		||||
        using Network::WifiPacket;
 | 
			
		||||
        WifiPacket auth_request;
 | 
			
		||||
        auth_request.channel = network_channel;
 | 
			
		||||
        auth_request.data = GenerateAuthenticationFrame(AuthenticationSeq::SEQ2);
 | 
			
		||||
        auth_request.destination_address = packet.transmitter_address;
 | 
			
		||||
        auth_request.type = WifiPacket::PacketType::Authentication;
 | 
			
		||||
 | 
			
		||||
        SendPacket(auth_request);
 | 
			
		||||
 | 
			
		||||
        SendAssociationResponseFrame(packet.transmitter_address);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Callback to parse and handle a received wifi packet.
 | 
			
		||||
void OnWifiPacketReceived(const Network::WifiPacket& packet) {
 | 
			
		||||
    switch (packet.type) {
 | 
			
		||||
    case Network::WifiPacket::PacketType::Beacon:
 | 
			
		||||
        HandleBeaconFrame(packet);
 | 
			
		||||
        break;
 | 
			
		||||
    case Network::WifiPacket::PacketType::Authentication:
 | 
			
		||||
        HandleAuthenticationFrame(packet);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * NWM_UDS::Shutdown service function
 | 
			
		||||
 *  Inputs:
 | 
			
		||||
@ -111,8 +243,7 @@ static void RecvBeaconBroadcastData(Interface* self) {
 | 
			
		||||
    u32 total_size = sizeof(BeaconDataReplyHeader);
 | 
			
		||||
 | 
			
		||||
    // Retrieve all beacon frames that were received from the desired mac address.
 | 
			
		||||
    std::deque<WifiPacket> beacons =
 | 
			
		||||
        GetReceivedPackets(WifiPacket::PacketType::Beacon, mac_address);
 | 
			
		||||
    auto beacons = GetReceivedBeacons(mac_address);
 | 
			
		||||
 | 
			
		||||
    BeaconDataReplyHeader data_reply_header{};
 | 
			
		||||
    data_reply_header.total_entries = beacons.size();
 | 
			
		||||
@ -193,6 +324,9 @@ static void InitializeWithVersion(Interface* self) {
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.PushCopyHandles(Kernel::g_handle_table.Create(connection_status_event).Unwrap());
 | 
			
		||||
 | 
			
		||||
    // TODO(Subv): Connect the OnWifiPacketReceived function to the wifi packet received callback of
 | 
			
		||||
    // the room we're currently in.
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_NWM, "called sharedmem_size=0x%08X, version=0x%08X, sharedmem_handle=0x%08X",
 | 
			
		||||
              sharedmem_size, version, sharedmem_handle);
 | 
			
		||||
}
 | 
			
		||||
@ -610,31 +744,22 @@ static void BeaconBroadcastCallback(u64 userdata, int cycles_late) {
 | 
			
		||||
    if (connection_status.status != static_cast<u32>(NetworkStatus::ConnectedAsHost))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // TODO(Subv): Actually send the beacon.
 | 
			
		||||
    std::vector<u8> frame = GenerateBeaconFrame(network_info, node_info);
 | 
			
		||||
 | 
			
		||||
    using Network::WifiPacket;
 | 
			
		||||
    WifiPacket packet;
 | 
			
		||||
    packet.type = WifiPacket::PacketType::Beacon;
 | 
			
		||||
    packet.data = std::move(frame);
 | 
			
		||||
    packet.destination_address = Network::BroadcastMac;
 | 
			
		||||
    packet.channel = network_channel;
 | 
			
		||||
 | 
			
		||||
    SendPacket(packet);
 | 
			
		||||
 | 
			
		||||
    // Start broadcasting the network, send a beacon frame every 102.4ms.
 | 
			
		||||
    CoreTiming::ScheduleEvent(msToCycles(DefaultBeaconInterval * MillisecondsPerTU) - cycles_late,
 | 
			
		||||
                              beacon_broadcast_event, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns an available index in the nodes array for the
 | 
			
		||||
 * currently-hosted UDS network.
 | 
			
		||||
 */
 | 
			
		||||
static u32 GetNextAvailableNodeId() {
 | 
			
		||||
    ASSERT_MSG(connection_status.status == static_cast<u32>(NetworkStatus::ConnectedAsHost),
 | 
			
		||||
               "Can not accept clients if we're not hosting a network");
 | 
			
		||||
 | 
			
		||||
    for (unsigned index = 0; index < connection_status.max_nodes; ++index) {
 | 
			
		||||
        if ((connection_status.node_bitmask & (1 << index)) == 0)
 | 
			
		||||
            return index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Any connection attempts to an already full network should have been refused.
 | 
			
		||||
    ASSERT_MSG(false, "No available connection slots in the network");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Called when a client connects to an UDS network we're hosting,
 | 
			
		||||
 * updates the connection status and signals the update event.
 | 
			
		||||
 | 
			
		||||
@ -42,6 +42,7 @@ using NodeList = std::vector<NodeInfo>;
 | 
			
		||||
enum class NetworkStatus {
 | 
			
		||||
    NotConnected = 3,
 | 
			
		||||
    ConnectedAsHost = 6,
 | 
			
		||||
    Connecting = 7,
 | 
			
		||||
    ConnectedAsClient = 9,
 | 
			
		||||
    ConnectedAsSpectator = 10,
 | 
			
		||||
};
 | 
			
		||||
@ -85,6 +86,17 @@ static_assert(offsetof(NetworkInfo, oui_value) == 0xC, "oui_value is at the wron
 | 
			
		||||
static_assert(offsetof(NetworkInfo, wlan_comm_id) == 0x10, "wlancommid is at the wrong offset.");
 | 
			
		||||
static_assert(sizeof(NetworkInfo) == 0x108, "NetworkInfo has incorrect size.");
 | 
			
		||||
 | 
			
		||||
/// Additional block tag ids in the Beacon and Association Response frames
 | 
			
		||||
enum class TagId : u8 {
 | 
			
		||||
    SSID = 0,
 | 
			
		||||
    SupportedRates = 1,
 | 
			
		||||
    DSParameterSet = 2,
 | 
			
		||||
    TrafficIndicationMap = 5,
 | 
			
		||||
    CountryInformation = 7,
 | 
			
		||||
    ERPInformation = 42,
 | 
			
		||||
    VendorSpecific = 221
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class NWM_UDS final : public Interface {
 | 
			
		||||
public:
 | 
			
		||||
    NWM_UDS();
 | 
			
		||||
 | 
			
		||||
@ -325,8 +325,5 @@ std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeL
 | 
			
		||||
    return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::deque<WifiPacket> GetReceivedPackets(WifiPacket::PacketType type, const MacAddress& sender) {
 | 
			
		||||
    return {};
 | 
			
		||||
}
 | 
			
		||||
} // namespace NWM
 | 
			
		||||
} // namespace Service
 | 
			
		||||
 | 
			
		||||
@ -17,17 +17,6 @@ namespace NWM {
 | 
			
		||||
using MacAddress = std::array<u8, 6>;
 | 
			
		||||
constexpr std::array<u8, 3> NintendoOUI = {0x00, 0x1F, 0x32};
 | 
			
		||||
 | 
			
		||||
/// Additional block tag ids in the Beacon frames
 | 
			
		||||
enum class TagId : u8 {
 | 
			
		||||
    SSID = 0,
 | 
			
		||||
    SupportedRates = 1,
 | 
			
		||||
    DSParameterSet = 2,
 | 
			
		||||
    TrafficIndicationMap = 5,
 | 
			
		||||
    CountryInformation = 7,
 | 
			
		||||
    ERPInformation = 42,
 | 
			
		||||
    VendorSpecific = 221
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Internal vendor-specific tag ids as stored inside
 | 
			
		||||
 * VendorSpecific blocks in the Beacon frames.
 | 
			
		||||
@ -135,20 +124,6 @@ struct BeaconData {
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(BeaconData) == 0x12, "BeaconData has incorrect size.");
 | 
			
		||||
 | 
			
		||||
/// Information about a received WiFi packet.
 | 
			
		||||
/// Acts as our own 802.11 header.
 | 
			
		||||
struct WifiPacket {
 | 
			
		||||
    enum class PacketType { Beacon, Data };
 | 
			
		||||
 | 
			
		||||
    PacketType type; ///< The type of 802.11 frame, Beacon / Data.
 | 
			
		||||
 | 
			
		||||
    /// Raw 802.11 frame data, starting at the management frame header for management frames.
 | 
			
		||||
    std::vector<u8> data;
 | 
			
		||||
    MacAddress transmitter_address; ///< Mac address of the transmitter.
 | 
			
		||||
    MacAddress destination_address; ///< Mac address of the receiver.
 | 
			
		||||
    u8 channel;                     ///< WiFi channel where this frame was transmitted.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decrypts the beacon data buffer for the network described by `network_info`.
 | 
			
		||||
 */
 | 
			
		||||
@ -161,10 +136,5 @@ void DecryptBeaconData(const NetworkInfo& network_info, std::vector<u8>& buffer)
 | 
			
		||||
 */
 | 
			
		||||
std::vector<u8> GenerateBeaconFrame(const NetworkInfo& network_info, const NodeList& nodes);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns a list of received 802.11 frames from the specified sender
 | 
			
		||||
 * matching the type since the last call.
 | 
			
		||||
 */
 | 
			
		||||
std::deque<WifiPacket> GetReceivedPackets(WifiPacket::PacketType type, const MacAddress& sender);
 | 
			
		||||
} // namespace NWM
 | 
			
		||||
} // namespace Service
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										79
									
								
								src/core/hle/service/nwm/uds_connection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/core/hle/service/nwm/uds_connection.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
			
		||||
// Copyright 2017 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include "core/hle/service/nwm/nwm_uds.h"
 | 
			
		||||
#include "core/hle/service/nwm/uds_connection.h"
 | 
			
		||||
#include "fmt/format.h"
 | 
			
		||||
 | 
			
		||||
namespace Service {
 | 
			
		||||
namespace NWM {
 | 
			
		||||
 | 
			
		||||
// Note: These values were taken from a packet capture of an o3DS XL
 | 
			
		||||
// broadcasting a Super Smash Bros. 4 lobby.
 | 
			
		||||
constexpr u16 DefaultExtraCapabilities = 0x0431;
 | 
			
		||||
 | 
			
		||||
std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq) {
 | 
			
		||||
    AuthenticationFrame frame{};
 | 
			
		||||
    frame.auth_seq = static_cast<u16>(seq);
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> data(sizeof(frame));
 | 
			
		||||
    std::memcpy(data.data(), &frame, sizeof(frame));
 | 
			
		||||
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body) {
 | 
			
		||||
    AuthenticationFrame frame;
 | 
			
		||||
    std::memcpy(&frame, body.data(), sizeof(frame));
 | 
			
		||||
 | 
			
		||||
    return static_cast<AuthenticationSeq>(frame.auth_seq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generates an SSID tag of an 802.11 Beacon frame with an 8-byte character representation of the
 | 
			
		||||
 * specified network id as the SSID value.
 | 
			
		||||
 * @param network_id The network id to use.
 | 
			
		||||
 * @returns A buffer with the SSID tag.
 | 
			
		||||
 */
 | 
			
		||||
static std::vector<u8> GenerateSSIDTag(u32 network_id) {
 | 
			
		||||
    constexpr u8 SSIDSize = 8;
 | 
			
		||||
 | 
			
		||||
    struct {
 | 
			
		||||
        u8 id = static_cast<u8>(TagId::SSID);
 | 
			
		||||
        u8 size = SSIDSize;
 | 
			
		||||
    } tag_header;
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> buffer(sizeof(tag_header) + SSIDSize);
 | 
			
		||||
 | 
			
		||||
    std::memcpy(buffer.data(), &tag_header, sizeof(tag_header));
 | 
			
		||||
 | 
			
		||||
    std::string network_name = fmt::format("{0:08X}", network_id);
 | 
			
		||||
 | 
			
		||||
    std::memcpy(buffer.data() + sizeof(tag_header), network_name.c_str(), SSIDSize);
 | 
			
		||||
 | 
			
		||||
    return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id) {
 | 
			
		||||
    AssociationResponseFrame frame{};
 | 
			
		||||
    frame.capabilities = DefaultExtraCapabilities;
 | 
			
		||||
    frame.status_code = static_cast<u16>(status);
 | 
			
		||||
    // The association id is ORed with this magic value (0xC000)
 | 
			
		||||
    constexpr u16 AssociationIdMagic = 0xC000;
 | 
			
		||||
    frame.assoc_id = association_id | AssociationIdMagic;
 | 
			
		||||
 | 
			
		||||
    std::vector<u8> data(sizeof(frame));
 | 
			
		||||
    std::memcpy(data.data(), &frame, sizeof(frame));
 | 
			
		||||
 | 
			
		||||
    auto ssid_tag = GenerateSSIDTag(network_id);
 | 
			
		||||
    data.insert(data.end(), ssid_tag.begin(), ssid_tag.end());
 | 
			
		||||
 | 
			
		||||
    // TODO(Subv): Add the SupportedRates tag.
 | 
			
		||||
    // TODO(Subv): Add the DSParameterSet tag.
 | 
			
		||||
    // TODO(Subv): Add the ERPInformation tag.
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace NWM
 | 
			
		||||
} // namespace Service
 | 
			
		||||
							
								
								
									
										51
									
								
								src/core/hle/service/nwm/uds_connection.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/core/hle/service/nwm/uds_connection.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
// Copyright 2017 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/swap.h"
 | 
			
		||||
#include "core/hle/service/service.h"
 | 
			
		||||
 | 
			
		||||
namespace Service {
 | 
			
		||||
namespace NWM {
 | 
			
		||||
 | 
			
		||||
/// Sequence number of the 802.11 authentication frames.
 | 
			
		||||
enum class AuthenticationSeq : u16 { SEQ1 = 1, SEQ2 = 2 };
 | 
			
		||||
 | 
			
		||||
enum class AuthAlgorithm : u16 { OpenSystem = 0 };
 | 
			
		||||
 | 
			
		||||
enum class AuthStatus : u16 { Successful = 0 };
 | 
			
		||||
 | 
			
		||||
enum class AssocStatus : u16 { Successful = 0 };
 | 
			
		||||
 | 
			
		||||
struct AuthenticationFrame {
 | 
			
		||||
    u16_le auth_algorithm = static_cast<u16>(AuthAlgorithm::OpenSystem);
 | 
			
		||||
    u16_le auth_seq;
 | 
			
		||||
    u16_le status_code = static_cast<u16>(AuthStatus::Successful);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(AuthenticationFrame) == 6, "AuthenticationFrame has wrong size");
 | 
			
		||||
 | 
			
		||||
struct AssociationResponseFrame {
 | 
			
		||||
    u16_le capabilities;
 | 
			
		||||
    u16_le status_code;
 | 
			
		||||
    u16_le assoc_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(AssociationResponseFrame) == 6, "AssociationResponseFrame has wrong size");
 | 
			
		||||
 | 
			
		||||
/// Generates an 802.11 authentication frame, starting at the frame body.
 | 
			
		||||
std::vector<u8> GenerateAuthenticationFrame(AuthenticationSeq seq);
 | 
			
		||||
 | 
			
		||||
/// Returns the sequence number from the body of an Authentication frame.
 | 
			
		||||
AuthenticationSeq GetAuthenticationSeqNumber(const std::vector<u8>& body);
 | 
			
		||||
 | 
			
		||||
/// Generates an 802.11 association response frame with the specified status, association id and
 | 
			
		||||
/// network id, starting at the frame body.
 | 
			
		||||
std::vector<u8> GenerateAssocResponseFrame(AssocStatus status, u16 association_id, u32 network_id);
 | 
			
		||||
 | 
			
		||||
} // namespace NWM
 | 
			
		||||
} // namespace Service
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user