Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions network/wlan/WIFICX/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
page_type: sample
description: "Demonstrates how to use WIFICX for control flow and NetAdapterCx for data flow."
languages:
- cpp
products:
- windows
- windows-wdk
---

# WIFICX and NetAdapterCx Samples

This sample illustrates how to leverage **WIFICX** for control flow and **NetAdapterCx** for data flow. It supports both **KMDF** and **UMDF(In Preview Stage)** drivers.

## How to Build
1. Mount the EWDK ISO from a local drive (network share paths are not supported).
2. Run `LaunchBuildEnv.cmd`.
3. In the environment created in step 2, type `SetupVSEnv` and press **Enter**.
4. Navigate to the current folder and open the solution file, for example:
`X:\Windows-driver-samples\network\wlan\WIFICX\wificxsampleclient.sln`
5. Build the solution from the Visual Studio UI.

## Interfaces and Abstraction
The sample interacts with three OS components:

- **WDF**
`driver.cpp`, `device.cpp`, and `adapter.cpp` demonstrate proper registration for PnP and power event callbacks. WDF manages system PnP and power requests (e.g., power IRPs), so IHV drivers should follow the flow triggered through these callbacks.

- **WDF Wi-Fi Class Extension (WIFICX)**
`wifixxxxx.cpp` files implement the **control path**, handling commands sent to Wi-Fi firmware (e.g., scan access points, connect, disconnect).

- **WDF NetAdapter Class Extension (NetAdapterCx)**
`netvxxxx` files and classes implement the **data path**, managing network buffers and synchronizing with the control path for transfer start/stop operations.

## Data Buffers from Firmware
The control path uses hardcoded data since this sample does not target real hardware. The data path uses **Emulated Network Link (ENL)**, which connects two virtual network adapters directly. Packets sent over one adapter are delivered to the other and vice versa.

## Supported Scenarios
- [x] Scan access points and report BSS entries to the Windows UI.
- [x] Connect to an open access point from the Windows UI.
- [x] Disconnect from the connected access point.
- [ ] Transfer data between two Wi-Fi device instances (e.g., ping and throughput test).
16 changes: 16 additions & 0 deletions network/wlan/WIFICX/drivercode/SharedTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
#pragma once

//
// SharedTypes.h
// Central header for global definitions, macros, and shared structures.
//
#include "precomp.h"
#include <initguid.h> // for GUID defination

// =============================
// GUIDs or Constants
// =============================
// {bb67559a-06f6-4eb0-81e9-21fdc3b60efb}
DEFINE_GUID(GUID_WIFICX_SAMPLE_CLIENT_INTERFACE, 0xbb67559a, 0x06f6, 0x4eb0, 0x81, 0xe9, 0x21, 0xfd, 0xc3, 0xb6, 0x0e, 0xfb);
#define WIFI_DRIVER_DEFAULT_POOL_TAG 'shiW' // WIFI IHV Sample Driver
63 changes: 63 additions & 0 deletions network/wlan/WIFICX/drivercode/adapter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "precomp.h"

#include "device.h"

#include "adapter.h"
#include "adapter.tmh"

_Use_decl_annotations_
NTSTATUS WifiIhvInitAdapterContext(_In_ WDFDEVICE Device, _In_ NETADAPTER NetAdapter)
{
PWIFI_IHV_DEVICE_CONTEXT deviceContext = WifiGetIhvDeviceContext(Device);
PWIFI_IHV_NETADAPTER_CONTEXT netAdapterContext = WifiGetIhvNetAdapterContext(NetAdapter);

if (deviceContext->primaryStaAdapter == WDF_NO_HANDLE)
{
deviceContext->primaryStaAdapter = NetAdapter;
}

netAdapterContext->WifiDeviceContext = deviceContext;

return STATUS_SUCCESS;
}

_Use_decl_annotations_
NTSTATUS WifiIhvAdapterStart(NETADAPTER netAdapter)
{
TraceEntry();

static WDI_MAC_ADDRESS STAAddress = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05};
NET_ADAPTER_LINK_LAYER_ADDRESS permanentLinkLayerAddress;
NET_ADAPTER_LINK_LAYER_ADDRESS_INIT(&permanentLinkLayerAddress, sizeof(WDI_MAC_ADDRESS), STAAddress.Address);
NetAdapterSetCurrentLinkLayerAddress(netAdapter, &permanentLinkLayerAddress);
NetAdapterSetPermanentLinkLayerAddress(netAdapter, &permanentLinkLayerAddress);

// Sample Phase 1 has no datapath support, so setting those values to the default one.
NET_ADAPTER_TX_CAPABILITIES txCaps;
NET_ADAPTER_RX_CAPABILITIES rxCaps;
NET_ADAPTER_LINK_LAYER_CAPABILITIES linkLayerCaps;

NET_ADAPTER_TX_CAPABILITIES_INIT(&txCaps, 1);
NET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED(&rxCaps, 1514, 1);
NET_ADAPTER_LINK_LAYER_CAPABILITIES_INIT(&linkLayerCaps, 0, 0);

NetAdapterSetLinkLayerMtuSize(netAdapter, 1500);
NetAdapterSetLinkLayerCapabilities(netAdapter, &linkLayerCaps);
NetAdapterSetDataPathCapabilities(netAdapter, &txCaps, &rxCaps);

WIFI_ADAPTER_WAKE_CAPABILITIES wakeCap{};
WIFI_ADAPTER_WAKE_CAPABILITIES_INIT(&wakeCap);
if (WIFI_IS_FIELD_AVAILABLE(WIFI_ADAPTER_WAKE_CAPABILITIES, ClientDriverDiagnostic))
{
wakeCap.ClientDriverDiagnostic = true;
}
WifiAdapterSetWakeCapabilities(netAdapter, &wakeCap);

NTSTATUS status = NetAdapterStart(netAdapter);
ASSERT(STATUS_SUCCESS == status);

TraceExit(status);

return status;
}
23 changes: 23 additions & 0 deletions network/wlan/WIFICX/drivercode/adapter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
#pragma once

#include "device.h"

// packet and header sizes
#define WIFI_MAX_PACKET_SIZE (1514)

// maximum link speed for send and recv in bps
#define WIFI_MEDIA_MAX_SPEED 1'000'000'000

NTSTATUS WifiIhvInitAdapterContext(_In_ WDFDEVICE Device, _In_ NETADAPTER NetAdapter);
NTSTATUS WifiIhvAdapterStart(_In_ NETADAPTER netAdapter);

// Context for each "Wdi Port"[NetAdapter] instance.
// Each NetAdapter instance corresponds to an IP interface
typedef struct _WIFI_IHV_NETADAPTER_CONTEXT
{
PWIFI_IHV_DEVICE_CONTEXT WifiDeviceContext; // Wdf Ihv device context
NETADAPTER NetAdapter; // NetAdapter object
} WIFI_IHV_NETADAPTER_CONTEXT, * PWIFI_IHV_NETADAPTER_CONTEXT;

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WIFI_IHV_NETADAPTER_CONTEXT, WifiGetIhvNetAdapterContext);
78 changes: 78 additions & 0 deletions network/wlan/WIFICX/drivercode/device.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation. All rights reserved.

#include "precomp.h"

#include "adapter.h"
#include "device.h"
#include "device.tmh"

_Use_decl_annotations_
NTSTATUS EvtDevicePrepareHardware(WDFDEVICE device, WDFCMRESLIST resourcesRaw, WDFCMRESLIST resourcesTranslated)
{
UNREFERENCED_PARAMETER(resourcesRaw);
UNREFERENCED_PARAMETER(resourcesTranslated);

WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
WifiHAL::_Create(device),
"WifiHAL::_Create failed");

WFCInfo("Device=0x%p", device);
return STATUS_SUCCESS;
}

_Use_decl_annotations_
NTSTATUS EvtDeviceReleaseHardware(WDFDEVICE device, WDFCMRESLIST resourcesTranslated)
{
UNREFERENCED_PARAMETER(resourcesTranslated);

WFCInfo("Device=0x%p", device);

return STATUS_SUCCESS;
}

_Use_decl_annotations_
NTSTATUS EvtWifiDeviceCreateAdapter(WDFDEVICE Device, NETADAPTER_INIT* AdapterInit)
{

//NET_ADAPTER_DATAPATH_CALLBACKS datapathCallbacks;
//NET_ADAPTER_DATAPATH_CALLBACKS_INIT(&datapathCallbacks, EvtAdapterCreateTxQueue, EvtAdapterCreateRxQueue);

//NetAdapterInitSetDatapathCallbacks(AdapterInit, &datapathCallbacks);

WDF_OBJECT_ATTRIBUTES adapterAttributes;
WDF_OBJECT_ATTRIBUTES_INIT(&adapterAttributes);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&adapterAttributes, WIFI_IHV_NETADAPTER_CONTEXT);
adapterAttributes.EvtCleanupCallback = EvtAdapterCleanup;

NETADAPTER netAdapter{};
WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
NetAdapterCreate(AdapterInit, &adapterAttributes, &netAdapter), "Failed to create NetAdapter");

WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
WifiAdapterInitialize(netAdapter), "Failed to initialize WifiAdapter");

WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
WifiIhvInitAdapterContext(Device, netAdapter), "Failed to initialize WifiAdapterContext");

WX_RETURN_NTSTATUS_IF_NOT_NT_SUCCESS_MSG(
WifiIhvAdapterStart(netAdapter), "Failed to start WifiIhvAdapter");

return STATUS_SUCCESS;
}

_Use_decl_annotations_
NTSTATUS EvtWifiDeviceCreateWifiDirectDevice(WDFDEVICE, WIFIDIRECT_DEVICE_INIT*)
{
NTSTATUS status = STATUS_SUCCESS;
TraceEntry();
TraceExit(status);
return status;
}

_Use_decl_annotations_
void EvtAdapterCleanup(_In_ WDFOBJECT NetAdapter)
{
UNREFERENCED_PARAMETER(NetAdapter);
TraceEntry();
TraceExit(STATUS_SUCCESS);
}
26 changes: 26 additions & 0 deletions network/wlan/WIFICX/drivercode/device.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
#pragma once
#include "wifiHAL.h"
EVT_WDF_DEVICE_PREPARE_HARDWARE EvtDevicePrepareHardware;
EVT_WDF_DEVICE_RELEASE_HARDWARE EvtDeviceReleaseHardware;

EVT_WIFI_DEVICE_CREATE_ADAPTER EvtWifiDeviceCreateAdapter;
EVT_WIFI_DEVICE_CREATE_WIFIDIRECTDEVICE EvtWifiDeviceCreateWifiDirectDevice;
EVT_WIFI_DEVICE_SEND_COMMAND EvtWifiDeviceSendCommand;
EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtAdapterCleanup;

typedef struct _WIFI_IHV_DEVICE_CONTEXT
{
//
// Do not add field variable before WdfTriageInfoPtr.
// NetAdapterCx carving code requires the first field of WDF context
// to be a pointer to WDF_TRIAGE_INFO.
//
void* WdfTriageInfoPtr;
WDFDEVICE WdfDevice;
TLV_CONTEXT TlvContext;
NETADAPTER primaryStaAdapter;
} WIFI_IHV_DEVICE_CONTEXT, * PWIFI_IHV_DEVICE_CONTEXT;

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WIFI_IHV_DEVICE_CONTEXT, WifiGetIhvDeviceContext);
static_assert(FIELD_OFFSET(WIFI_IHV_DEVICE_CONTEXT, WdfTriageInfoPtr) == 0);
Loading
Loading