summaryrefslogtreecommitdiff
path: root/network
diff options
context:
space:
mode:
authortaj0207 <[email protected]>2022-11-09 11:31:14 -0800
committerGitHub <[email protected]>2022-11-09 11:31:14 -0800
commit82537c2a1da27908ffbc5d98a7ad77e6af0956c8 (patch)
treeaf74ee90abbbe0eacc15c28873f35a0ca46cec7c /network
parent96e23c8f1172e227122de5c66390e8e5b4028831 (diff)
Add mobile broadband mbbcx client driver sample code (#797)
Diffstat (limited to 'network')
-rw-r--r--network/wwan/cxwmbclass/README.md14
-rw-r--r--network/wwan/cxwmbclass/adapter.cpp197
-rw-r--r--network/wwan/cxwmbclass/businit.cpp1906
-rw-r--r--network/wwan/cxwmbclass/cxwmbclass.rc20
-rw-r--r--network/wwan/cxwmbclass/cxwmbclass.sln35
-rw-r--r--network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.inf119
-rw-r--r--network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj176
-rw-r--r--network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj.filters107
-rw-r--r--network/wwan/cxwmbclass/datapipe.cpp998
-rw-r--r--network/wwan/cxwmbclass/device.cpp381
-rw-r--r--network/wwan/cxwmbclass/driver.cpp120
-rw-r--r--network/wwan/cxwmbclass/inc/BusInterface.h573
-rw-r--r--network/wwan/cxwmbclass/inc/MbbLibrary.h175
-rw-r--r--network/wwan/cxwmbclass/inc/adapter.h53
-rw-r--r--network/wwan/cxwmbclass/inc/align.h168
-rw-r--r--network/wwan/cxwmbclass/inc/data.h185
-rw-r--r--network/wwan/cxwmbclass/inc/device.h45
-rw-r--r--network/wwan/cxwmbclass/inc/mbbmessages.h3273
-rw-r--r--network/wwan/cxwmbclass/inc/mbbncm.h431
-rw-r--r--network/wwan/cxwmbclass/inc/power.h11
-rw-r--r--network/wwan/cxwmbclass/inc/precomp.h53
-rw-r--r--network/wwan/cxwmbclass/inc/rxqueue.h26
-rw-r--r--network/wwan/cxwmbclass/inc/txqueue.h22
-rw-r--r--network/wwan/cxwmbclass/inc/usbbus.h235
-rw-r--r--network/wwan/cxwmbclass/inc/util.h42
-rw-r--r--network/wwan/cxwmbclass/inc/utils.h61
-rw-r--r--network/wwan/cxwmbclass/power.cpp116
-rw-r--r--network/wwan/cxwmbclass/rxqueue.cpp602
-rw-r--r--network/wwan/cxwmbclass/sources.inc12
-rw-r--r--network/wwan/cxwmbclass/txqueue.cpp988
-rw-r--r--network/wwan/cxwmbclass/util.cpp326
-rw-r--r--network/wwan/cxwmbclass/utils.cpp588
32 files changed, 12058 insertions, 0 deletions
diff --git a/network/wwan/cxwmbclass/README.md b/network/wwan/cxwmbclass/README.md
new file mode 100644
index 00000000..d0b04978
--- /dev/null
+++ b/network/wwan/cxwmbclass/README.md
@@ -0,0 +1,14 @@
+---
+page_type: sample
+description: "Demonstrates use of the cxwmbclass driver."
+languages:
+- c
+products:
+- windows
+- windows-wdk
+---
+
+# cxwmbclass samples
+
+This sample demonstrates use of the cxwmbclass.
+
diff --git a/network/wwan/cxwmbclass/adapter.cpp b/network/wwan/cxwmbclass/adapter.cpp
new file mode 100644
index 00000000..ed60b427
--- /dev/null
+++ b/network/wwan/cxwmbclass/adapter.cpp
@@ -0,0 +1,197 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+#include "device.h"
+#include "txqueue.h"
+#include "rxqueue.h"
+
+_Use_decl_annotations_ NTSTATUS WmbClassAdapterStart(NETADAPTER netAdapter)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = WmbClassGetNetAdapterContext(netAdapter);
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = netAdapterContext->WmbDeviceContext;
+
+ ULONG64 maxXmitLinkSpeed = MBB_MEDIA_MAX_SPEED;
+ ULONG64 maxRcvLinkSpeed = MBB_MEDIA_MAX_SPEED;
+ DWORD maxPowerFilterSize = 0;
+
+ NET_ADAPTER_LINK_LAYER_CAPABILITIES linkLayerCapabilities;
+ NET_ADAPTER_LINK_LAYER_CAPABILITIES_INIT(&linkLayerCapabilities, maxXmitLinkSpeed, maxRcvLinkSpeed);
+
+ NetAdapterSetLinkLayerCapabilities(netAdapter, &linkLayerCapabilities);
+
+ if (deviceContext->BusParams.IsErrataDevice)
+ {
+ NetAdapterSetLinkLayerMtuSize(netAdapter, deviceContext->BusParams.MTU);
+ }
+ else
+ {
+ NetAdapterSetLinkLayerMtuSize(netAdapter, deviceContext->BusParams.MaxSegmentSize);
+ }
+
+ if (deviceContext->BusParams.PowerFiltersSupported > 0)
+ {
+ NET_ADAPTER_WAKE_BITMAP_CAPABILITIES bitmapCapabilities;
+ NET_ADAPTER_WAKE_BITMAP_CAPABILITIES_INIT(&bitmapCapabilities);
+
+ bitmapCapabilities.BitmapPattern = TRUE;
+ bitmapCapabilities.MaximumPatternCount = deviceContext->BusParams.PowerFiltersSupported;
+
+ if (deviceContext->BusParams.IsErrataDevice)
+ {
+ // For errata devices we will report the device specific max pattern size.
+ // 192 bytes is the maximum power filter size as per the MBIM spec.
+ // If a device reports more than 192 bytes as the power filter size, we
+ // normalize it here to 192 bytes. This will prevent erroneous devices
+ // from indicating arbitrary pattern size. This needs to change with any
+ // MBIM spec revision.
+
+ if (deviceContext->BusParams.MaxPowerFilterSize > WMBCLASS_MAX_MBIM_WOL_PATTERN)
+ {
+ maxPowerFilterSize = WMBCLASS_MAX_MBIM_WOL_PATTERN;
+ }
+ else
+ {
+ maxPowerFilterSize = deviceContext->BusParams.MaxPowerFilterSize;
+ }
+ }
+ else
+ {
+ // To maintain backward compatibility with Win8 devices, we continue
+ // reporting 256 bytes as the wake pattern size.
+ maxPowerFilterSize = WMBCLASS_MAX_WOL_PATTERN;
+ }
+
+ bitmapCapabilities.MaximumPatternSize = maxPowerFilterSize;
+
+ NetAdapterWakeSetBitmapCapabilities(netAdapter, &bitmapCapabilities);
+ }
+
+ NET_ADAPTER_WAKE_MEDIA_CHANGE_CAPABILITIES wakeMediaChangeCapabilities;
+ NET_ADAPTER_WAKE_MEDIA_CHANGE_CAPABILITIES_INIT(&wakeMediaChangeCapabilities);
+
+ wakeMediaChangeCapabilities.MediaConnect = TRUE;
+ wakeMediaChangeCapabilities.MediaDisconnect = TRUE;
+
+ NetAdapterWakeSetMediaChangeCapabilities(netAdapter, &wakeMediaChangeCapabilities);
+
+ if (deviceContext->BusParams.SelectiveSuspendSupported)
+ {
+ NET_ADAPTER_WAKE_PACKET_FILTER_CAPABILITIES wakePacketFilterCapabilities;
+ NET_ADAPTER_WAKE_PACKET_FILTER_CAPABILITIES_INIT(&wakePacketFilterCapabilities);
+ wakePacketFilterCapabilities.PacketFilterMatch = TRUE;
+
+ NetAdapterWakeSetPacketFilterCapabilities(netAdapter, &wakePacketFilterCapabilities);
+ }
+
+ NET_ADAPTER_TX_CAPABILITIES txCapabilities;
+ NET_ADAPTER_TX_CAPABILITIES_INIT(&txCapabilities, 1);
+ NET_ADAPTER_RX_CAPABILITIES rxCapabilities;
+ NET_ADAPTER_RX_CAPABILITIES_INIT_DRIVER_MANAGED(&rxCapabilities, EvtAdapterReturnRxBuffer, MBB_MAX_PACKET_SIZE, 1);
+
+ NetAdapterSetDataPathCapabilities(netAdapter, &txCapabilities, &rxCapabilities);
+
+ status = NetAdapterStart(netAdapter);
+
+ return status;
+}
+
+NTSTATUS
+EvtAdapterCreateTxQueue(_In_ NETADAPTER netAdapter, _Inout_ NETTXQUEUE_INIT* txQueueInit)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PMBB_TXQUEUE_CONTEXT txQueueContext = NULL;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = WmbClassGetNetAdapterContext(netAdapter);
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = netAdapterContext->WmbDeviceContext;
+ WDF_OBJECT_ATTRIBUTES txAttributes;
+ NET_EXTENSION_QUERY extension;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&txAttributes);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&txAttributes, MBB_TXQUEUE_CONTEXT);
+
+ txAttributes.EvtDestroyCallback = EvtTxQueueDestroy;
+
+ NET_PACKET_QUEUE_CONFIG queueConfig;
+ NET_PACKET_QUEUE_CONFIG_INIT(&queueConfig, EvtTxQueueAdvance, EvtTxQueueSetNotificationEnabled, EvtTxQueueCancel);
+
+ NETPACKETQUEUE txQueue;
+ status = NetTxQueueCreate(txQueueInit, &txAttributes, &queueConfig, &txQueue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+
+ txQueueContext = MbbGetTxQueueContext(txQueue);
+
+
+ txQueueContext->NetAdapterContext = netAdapterContext;
+ txQueueContext->DatapathDescriptor = NetTxQueueGetRingCollection(txQueue);
+
+ // Try to use MaxOutDatagrams parameter as the tx completion batch size, but limit to half of the packet ring buffer
+ auto maxBatchSize = NetRingCollectionGetPacketRing(txQueueContext->DatapathDescriptor)->NumberOfElements / 2;
+ txQueueContext->CompletionBatchSize = min(deviceContext->BusParams.MaxOutDatagrams, maxBatchSize);
+
+ NET_EXTENSION_QUERY_INIT(&extension, NET_FRAGMENT_EXTENSION_MDL_NAME, NET_FRAGMENT_EXTENSION_MDL_VERSION_1, NetExtensionTypeFragment);
+
+ NetTxQueueGetExtension(txQueue, &extension, &txQueueContext->MdlExtension);
+
+ netAdapterContext->TxQueue = txQueue;
+Exit:
+ return status;
+}
+
+void EvtRxQueueStart(_In_ NETPACKETQUEUE rxQueue)
+{
+ MbbGetRxQueueContext(rxQueue)->NetAdapterContext->AllowRxTraffic = TRUE;
+}
+
+NTSTATUS
+EvtAdapterCreateRxQueue(_In_ NETADAPTER netAdapter, _Inout_ NETRXQUEUE_INIT* rxQueueInit)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = NULL;
+ WDF_OBJECT_ATTRIBUTES rxAttributes;
+ NET_EXTENSION_QUERY extension;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = WmbClassGetNetAdapterContext(netAdapter);
+
+ NET_PACKET_QUEUE_CONFIG rxConfig;
+ NET_PACKET_QUEUE_CONFIG_INIT(&rxConfig, EvtRxQueueAdvance, EvtRxQueueSetNotificationEnabled, EvtRxQueueCancel);
+ rxConfig.EvtStart = EvtRxQueueStart;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&rxAttributes);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&rxAttributes, MBB_RXQUEUE_CONTEXT);
+ rxAttributes.EvtDestroyCallback = EvtRxQueueDestroy;
+
+ NETPACKETQUEUE rxQueue;
+ status = NetRxQueueCreate(rxQueueInit, &rxAttributes, &rxConfig, &rxQueue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+
+ rxQueueContext = MbbGetRxQueueContext(rxQueue);
+
+ NET_EXTENSION_QUERY_INIT(&extension, NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_NAME, NET_FRAGMENT_EXTENSION_VIRTUAL_ADDRESS_VERSION_1, NetExtensionTypeFragment);
+
+ NetRxQueueGetExtension(rxQueue, &extension, &rxQueueContext->VirtualAddressExtension);
+
+ rxQueueContext->NetAdapterContext = netAdapterContext;
+ rxQueueContext->DatapathDescriptor = NetRxQueueGetRingCollection(rxQueue);
+
+ NET_EXTENSION_QUERY_INIT(&extension, NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_NAME, NET_FRAGMENT_EXTENSION_RETURN_CONTEXT_VERSION_1, NetExtensionTypeFragment);
+
+ NetRxQueueGetExtension(rxQueue, &extension, &rxQueueContext->ReturnContextExtension);
+
+ // Set netAdapterContext->RxQueue to mean EvtAdapterCreateRxQueue completed successfully
+ netAdapterContext->RxQueue = rxQueue;
+
+Exit:
+
+ return status;
+}
diff --git a/network/wwan/cxwmbclass/businit.cpp b/network/wwan/cxwmbclass/businit.cpp
new file mode 100644
index 00000000..a4109ada
--- /dev/null
+++ b/network/wwan/cxwmbclass/businit.cpp
@@ -0,0 +1,1906 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include <precomp.h>
+
+#pragma pack(push, 1)
+
+typedef struct _USB_DESCRIPTOR_HEADER
+{
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+
+} USB_DESCRIPTOR_HEADER, * PUSB_DESCRIPTOR_HEADER;
+
+#pragma pack(pop)
+
+NTSTATUS
+MbbParseConfigDescriptor(
+ WDFUSBDEVICE WdfUsbDevice,
+ PUSHORT MaxSegmentSize,
+ PUCHAR NcmCaps,
+ PUCHAR PowerFiltersSupported,
+ PUCHAR MaxPowerFilterSize,
+ PUCHAR CommunicationClassInterface,
+ PUCHAR DataClassInterface,
+ PUSHORT MaxControlMessage,
+ PUCHAR AltCommunicationClassSetting,
+ PUCHAR AltDataClassSetting,
+ PUSHORT BulkInDataClassPacketSize,
+ PUSHORT MTU,
+ PUSHORT MbimVersion,
+ PUSHORT MbimExtendedVersion);
+
+NTSTATUS
+GetNtbParameters(WDFUSBDEVICE WdfUsbDevice, PNCM_NTB_PARAMETER NcmNtb);
+
+NTSTATUS
+GetDeviceString(__in WDFUSBDEVICE UsbDevice, __in UCHAR Index, __out PWSTR* String);
+
+VOID FreeBusObject(_In_ __drv_freesMem(Mem) PBUS_OBJECT BusObject);
+
+NTSTATUS
+SetActivityIdForRequest(__in WDFREQUEST Request, __in LPGUID ActivityId);
+
+void ResetDataPipeWorkItem(_In_ WDFWORKITEM WorkItem);
+
+EVT_WDF_USB_READER_COMPLETION_ROUTINE InterruptPipeReadComplete;
+EVT_WDF_USB_READERS_FAILED InterruptPipeReadError;
+
+NTSTATUS
+MbbBusInitializeByWdf(
+ _In_ WDFDEVICE WdfDevice,
+ _In_ MBB_BUS_RESPONSE_AVAILABLE_CALLBACK ResponseAvailableCallback,
+ _In_ MBB_BUS_DATA_RECEIVE_CALLBACK ReceiveDataCallback,
+ _In_ MBB_BUS_SS_IDLE_CONFIRM_CALLBACK IdleConfirmCallback,
+ _In_ MBB_BUS_SS_IDLE_NOTIFICATION_COMPLETE_CALLBACK IdleNotificationComplete,
+ _In_ MBB_PROTOCOL_HANDLE ProtocolHandle,
+ _Outptr_ MBB_BUS_HANDLE* BusHandle,
+ _Inout_opt_ MBB_BUS_HANDLE preAllocatedBusObject)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDF_OBJECT_ATTRIBUTES attributes;
+
+ WDF_USB_DEVICE_SELECT_CONFIG_PARAMS configParams;
+ PWDF_USB_INTERFACE_SETTING_PAIR settingPairs = NULL;
+ WDF_USB_INTERFACE_SELECT_SETTING_PARAMS SettingParams;
+ WDFUSBPIPE pipe;
+ WDF_USB_PIPE_INFORMATION pipeInfo;
+ WDFUSBINTERFACE UsbInterface = NULL;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+ USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ WDF_USB_DEVICE_CREATE_CONFIG Config;
+
+ WDF_WORKITEM_CONFIG workitemConfig;
+ WDF_OBJECT_ATTRIBUTES workitemAttributes;
+
+ UCHAR numInterfaces;
+ UCHAR interfaceIndex;
+ UCHAR i;
+ USHORT DescriptorSize = 0;
+ UCHAR CurrentSetting;
+ USHORT BulkInPacketSize = 0;
+ WDF_USB_CONTINUOUS_READER_CONFIG ReaderConfig;
+
+ PIRP UsbSsIrp = NULL;
+
+ PBUS_OBJECT BusObject = NULL;
+
+ USB_CAP_DEVICE_INFO usbCapDeviceInfo = { USB_CAP_DEVICE_TYPE_MAXIMUM, 0, 0, 0 };
+ ULONG capResultLength = 0;
+
+ WDF_USB_DEVICE_INFORMATION deviceInformation;
+
+ *BusHandle = NULL;
+
+ if (preAllocatedBusObject == NULL)
+ {
+
+ BusObject = (PBUS_OBJECT)ALLOCATE_NONPAGED_POOL(sizeof(BUS_OBJECT));
+
+ if (BusObject == NULL)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ RtlZeroMemory(BusObject, sizeof(*BusObject));
+
+ BusObject->Fdo = WdfDeviceWdmGetDeviceObject(WdfDevice);
+
+ INITIALIZE_PASSIVE_LOCK(&BusObject->Lock);
+ BusObject->State = BUS_STATE_CLOSED;
+
+ BusObject->ProtocolHandle = ProtocolHandle;
+ BusObject->ResponseAvailableCallback = ResponseAvailableCallback;
+ BusObject->ReceiveDataCallback = ReceiveDataCallback;
+ BusObject->IdleConfirmCallback = IdleConfirmCallback;
+ BusObject->IdleNotificationComplete = IdleNotificationComplete;
+
+ }
+ else
+ {
+ BusObject = (PBUS_OBJECT)preAllocatedBusObject;
+ }
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, USB_DEVICE_CONTEXT);
+
+ WDF_USB_DEVICE_CREATE_CONFIG_INIT(&Config, USBD_CLIENT_CONTRACT_VERSION_602);
+
+ Status = WdfUsbTargetDeviceCreateWithParameters(WdfDevice, &Config, &attributes, &BusObject->WdfUsbDevice);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ usbDeviceContext->BulkPipeResetFlag = FALSE;
+ usbDeviceContext->BulkPipeResetWorkitem = NULL;
+
+ //
+ // create a work item to reset data pipe
+ //
+ ExInitializeRundownProtection(&usbDeviceContext->BulkPipeResetRundown);
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&workitemAttributes);
+ workitemAttributes.ParentObject = BusObject->WdfUsbDevice;
+ WDF_WORKITEM_CONFIG_INIT(&workitemConfig, ResetDataPipeWorkItem);
+
+ Status = WdfWorkItemCreate(&workitemConfig, &workitemAttributes, &usbDeviceContext->BulkPipeResetWorkitem);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ //
+ // create a lock
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = BusObject->WdfUsbDevice;
+
+ Status = WdfWaitLockCreate(&attributes, &usbDeviceContext->PipeStateLock);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = BusObject->WdfUsbDevice;
+
+ Status = WdfCollectionCreate(&attributes, &usbDeviceContext->WriteRequestCollection);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = BusObject->WdfUsbDevice;
+
+ Status = WdfSpinLockCreate(&attributes, &usbDeviceContext->WriteCollectionLock);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ //
+ // see if the bus driver supports chained mdl's
+ //
+ Status = WdfUsbTargetDeviceQueryUsbCapability(BusObject->WdfUsbDevice, (PGUID)&GUID_USB_CAPABILITY_CHAINED_MDLS, 0, NULL, NULL);
+
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // request work, the stack supports chained mdl's
+ //
+ BusObject->ChainedMdlsSupported = TRUE;
+ }
+ else
+ {
+ }
+
+ // see what USB device type the bus driver is supporting
+ //
+ Status = WdfUsbTargetDeviceQueryUsbCapability(
+ BusObject->WdfUsbDevice, (PGUID)&GUID_USB_CAPABILITY_DEVICE_TYPE, sizeof(USB_CAP_DEVICE_INFO), (PVOID)&usbCapDeviceInfo, &capResultLength);
+
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // request work, the stack returns USB device type
+ //
+ if (IsUsbCapDeviceInfoValid(usbCapDeviceInfo, capResultLength))
+ {
+ BusObject->UsbCapDeviceInfo = usbCapDeviceInfo;
+ }
+ }
+
+ WdfUsbTargetDeviceGetDeviceDescriptor(BusObject->WdfUsbDevice, &DeviceDescriptor);
+
+ Status = GetDeviceString(BusObject->WdfUsbDevice, DeviceDescriptor.iManufacturer, &BusObject->Manufacturer);
+
+ Status = GetDeviceString(BusObject->WdfUsbDevice, DeviceDescriptor.iProduct, &BusObject->Model);
+
+ WDF_USB_DEVICE_INFORMATION_INIT(&deviceInformation);
+ Status = WdfUsbTargetDeviceRetrieveInformation(BusObject->WdfUsbDevice, &deviceInformation);
+ if (NT_SUCCESS(Status))
+ {
+ BusObject->RemoteWakeCapable = IS_USB_DEVICE_REMOTE_WAKE_CAPABLE(deviceInformation);
+ }
+
+ Status = MbbParseConfigDescriptor(
+ BusObject->WdfUsbDevice,
+ &BusObject->MaxSegmentSize,
+ &BusObject->NcmParams,
+ &BusObject->PowerFiltersSupported,
+ &BusObject->MaxPowerFilterSize,
+ &usbDeviceContext->UsbCommunicationInterfaceIndex,
+ &usbDeviceContext->UsbDataInterfaceIndex,
+ &BusObject->MaxControlChannelSize,
+ &usbDeviceContext->UsbCommunicationInterfaceSetting,
+ &usbDeviceContext->UsbDataInterfaceSetting,
+ &BulkInPacketSize,
+ &BusObject->MTU,
+ &BusObject->MbimVersion,
+ &BusObject->MbimExtendedVersion);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ if (BusObject->MaxControlChannelSize < MIN_CONTROL_MESSAGE_SIZE)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ if (BulkInPacketSize == 0)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ numInterfaces = WdfUsbTargetDeviceGetNumInterfaces(BusObject->WdfUsbDevice);
+
+ settingPairs = (PWDF_USB_INTERFACE_SETTING_PAIR)ALLOCATE_NONPAGED_POOL(sizeof(WDF_USB_INTERFACE_SETTING_PAIR) * numInterfaces);
+
+ if (settingPairs == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ for (interfaceIndex = 0; interfaceIndex < numInterfaces; interfaceIndex++)
+ {
+ settingPairs[interfaceIndex].UsbInterface = WdfUsbTargetDeviceGetInterface(BusObject->WdfUsbDevice, interfaceIndex);
+
+ //
+ // Select alternate setting zero on all interfaces.
+ //
+ settingPairs[interfaceIndex].SettingIndex = 0;
+ }
+
+ WDF_USB_DEVICE_SELECT_CONFIG_PARAMS_INIT_MULTIPLE_INTERFACES(&configParams, numInterfaces, settingPairs);
+
+ Status = WdfUsbTargetDeviceSelectConfig(BusObject->WdfUsbDevice, NULL, &configParams);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ if (configParams.Types.MultiInterface.NumberOfConfiguredInterfaces < 2)
+ {
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto Cleanup;
+ }
+
+
+ usbDeviceContext->WdfCommunicationInterfaceIndex = 0xff;
+ usbDeviceContext->WdfDataInterfaceIndex = 0xff;
+
+ for (i = 0; i < configParams.Types.MultiInterface.NumberOfConfiguredInterfaces; i++)
+ {
+ UsbInterface = WdfUsbTargetDeviceGetInterface(BusObject->WdfUsbDevice, i);
+ CurrentSetting = WdfUsbInterfaceGetConfiguredSettingIndex(UsbInterface);
+ WdfUsbInterfaceGetDescriptor(UsbInterface, CurrentSetting, &InterfaceDescriptor);
+ if ((InterfaceDescriptor.bInterfaceNumber == usbDeviceContext->UsbCommunicationInterfaceIndex))
+ {
+ if (usbDeviceContext->WdfCommunicationInterfaceIndex == 0xff)
+ {
+ usbDeviceContext->WdfCommunicationInterfaceIndex = i;
+ }
+ }
+
+ if ((InterfaceDescriptor.bInterfaceNumber == usbDeviceContext->UsbDataInterfaceIndex))
+ {
+ if (usbDeviceContext->WdfDataInterfaceIndex == 0xff)
+ {
+ usbDeviceContext->WdfDataInterfaceIndex = i;
+ }
+ }
+ }
+
+ if ((usbDeviceContext->WdfCommunicationInterfaceIndex == 0xff) || (usbDeviceContext->WdfDataInterfaceIndex == 0xff))
+ {
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto Cleanup;
+ }
+
+ //
+ // get interrupt pipe handles
+ //
+ {
+ BYTE ConfiguredPipes = 0;
+ UsbInterface = WdfUsbTargetDeviceGetInterface(BusObject->WdfUsbDevice, usbDeviceContext->WdfCommunicationInterfaceIndex);
+
+ WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&SettingParams, usbDeviceContext->UsbCommunicationInterfaceSetting);
+
+ Status = WdfUsbInterfaceSelectSetting(UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &SettingParams);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ ConfiguredPipes = WdfUsbInterfaceGetNumConfiguredPipes(UsbInterface);
+
+ if (ConfiguredPipes != 1)
+ {
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto Cleanup;
+ }
+
+ WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
+
+ pipe = WdfUsbInterfaceGetConfiguredPipe(
+ UsbInterface,
+ 0, // index 0
+ &pipeInfo);
+
+ if (WdfUsbPipeTypeInterrupt == pipeInfo.PipeType)
+ {
+ usbDeviceContext->InterruptPipe = pipe;
+ usbDeviceContext->InterruptPipeIoTarget = WdfUsbTargetPipeGetIoTarget(pipe);
+
+ usbDeviceContext->InterruptPipeMaxPacket = pipeInfo.MaximumPacketSize;
+ }
+ else
+ {
+ Status = STATUS_NO_SUCH_DEVICE;
+ goto Cleanup;
+ }
+ }
+
+ BusObject->SyncInterruptReadBuffer = (PUCHAR)ALLOCATE_NONPAGED_POOL(usbDeviceContext->InterruptPipeMaxPacket);
+
+ if (BusObject->SyncInterruptReadBuffer == NULL)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ //
+ // Configure the continous reader now
+ //
+
+ WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&ReaderConfig, InterruptPipeReadComplete, BusObject, usbDeviceContext->InterruptPipeMaxPacket);
+
+ ReaderConfig.NumPendingReads = 1;
+ ReaderConfig.EvtUsbTargetPipeReadersFailed = InterruptPipeReadError;
+
+ Status = WdfUsbTargetPipeConfigContinuousReader(usbDeviceContext->InterruptPipe, &ReaderConfig);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = GetNtbParameters(BusObject->WdfUsbDevice, &BusObject->NtbParam);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ if (!BusObject->ChainedMdlsSupported)
+ {
+ //
+ // chained mdl's not supported, create a lookaside list to hold the buffers
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = BusObject->WdfUsbDevice;
+ //
+ // TODO : For testing
+ //
+ // BusObject->NtbParam.dwNtbOutMaxSize = 512;
+
+ Status = WdfLookasideListCreate(
+ &attributes, BusObject->NtbParam.dwNtbOutMaxSize, NonPagedPoolNx, WDF_NO_OBJECT_ATTRIBUTES, 'CBMW', &usbDeviceContext->LookasideList);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+ }
+
+ if (BusObject->UsbCapDeviceInfo.DeviceInfoHeader.DeviceType == USB_CAP_DEVICE_TYPE_UDE_MBIM)
+ {
+ BusObject->MaxBulkInTransfer = BusObject->NtbParam.dwNtbInMaxSize < MAX_HOST_NTB_SIZE_FOR_UDE_MBIM
+ ? BusObject->NtbParam.dwNtbInMaxSize
+ : MAX_HOST_NTB_SIZE_FOR_UDE_MBIM;
+ }
+ else
+ {
+ BusObject->MaxBulkInTransfer =
+ BusObject->NtbParam.dwNtbInMaxSize < MAX_HOST_NTB_SIZE ? BusObject->NtbParam.dwNtbInMaxSize : MAX_HOST_NTB_SIZE;
+ }
+
+ //
+ // round down the transfer size so it is a multiple of maxpacket size for the builk in pipe
+ //
+ BusObject->MaxBulkInTransfer = (BusObject->MaxBulkInTransfer / BulkInPacketSize) * BulkInPacketSize;
+
+ BusObject->BulkInHeaderSize =
+ ROUND_UP_COUNT((ULONG)MmSizeOfMdl(NULL, ROUND_UP_COUNT(BusObject->MaxBulkInTransfer + PAGE_SIZE, ALIGN_QUAD)), ALIGN_QUAD);
+
+ if ((BusObject->NtbParam.bmNtbFormatSupported & NCM_NTB_FORMAT_32_BIT) == NCM_NTB_FORMAT_32_BIT)
+ {
+ //
+ // device supports 32 bit mode
+ //
+ if ((BusObject->NtbParam.dwNtbInMaxSize > 0xffff) || (BusObject->NtbParam.dwNtbOutMaxSize > 0xffff))
+ {
+ //
+ // the device can actually handle a transfer larger than 16bit, change to 32 bit
+ //
+ BusObject->NtbFormat32Bit = TRUE;
+ }
+ }
+
+ //
+ // put the device back into a known state
+ //
+ Status = MbbBusResetDeviceAndSetParms(BusObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ *BusHandle = BusObject;
+ usbDeviceContext->BusObject = BusObject;
+ BusObject = NULL;
+
+Cleanup:
+
+ if (settingPairs != NULL)
+ {
+ FREE_POOL(settingPairs);
+ settingPairs = NULL;
+ }
+
+ if (BusObject != NULL && preAllocatedBusObject == NULL)
+ {
+ FreeBusObject(BusObject);
+ BusObject = NULL;
+ }
+
+ return Status;
+}
+
+VOID FreeBusObject(_In_ __drv_freesMem(Mem) PBUS_OBJECT BusObject)
+
+{
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+ if (BusObject->WdfUsbDevice != NULL)
+ {
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ if (usbDeviceContext->InterruptPipeIoTarget != NULL)
+ {
+ WdfIoTargetStop(usbDeviceContext->InterruptPipeIoTarget, WdfIoTargetCancelSentIo);
+ }
+
+ usbDeviceContext->BusObject = NULL;
+ }
+
+ if (BusObject->Manufacturer != NULL)
+ {
+ FREE_POOL(BusObject->Manufacturer);
+ BusObject->Manufacturer = NULL;
+ }
+
+ if (BusObject->Model != NULL)
+ {
+ FREE_POOL(BusObject->Model);
+ BusObject->Model = NULL;
+ }
+
+ if (BusObject->WdfDevice != NULL)
+ {
+ WdfObjectDelete(BusObject->WdfDevice);
+ }
+
+ if (BusObject->UsbSsIrp != NULL)
+ {
+ IoCancelIrp(BusObject->UsbSsIrp);
+
+
+ KeWaitForSingleObject(&BusObject->UsbSsIrpComplete, Executive, KernelMode, FALSE, NULL);
+
+
+ IoFreeIrp(BusObject->UsbSsIrp);
+ BusObject->UsbSsIrp = NULL;
+ }
+
+ if (BusObject->SyncInterruptReadBuffer != NULL)
+ {
+ FREE_POOL(BusObject->SyncInterruptReadBuffer);
+ BusObject->SyncInterruptReadBuffer = NULL;
+ }
+
+ FREE_POOL(BusObject);
+ BusObject = NULL;
+
+ return;
+}
+
+VOID MbbBusCleanup(__in MBB_BUS_HANDLE BusHandle)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+
+ FreeBusObject(BusObject);
+ BusObject = NULL;
+
+ return;
+}
+
+NTSTATUS
+MbbParseConfigDescriptor(
+ WDFUSBDEVICE WdfUsbDevice,
+ PUSHORT MaxSegmentSize,
+ PUCHAR NcmCaps,
+ PUCHAR PowerFiltersSupported,
+ PUCHAR MaxPowerFilterSize,
+ PUCHAR CommunicationClassInterface,
+ PUCHAR DataClassInterface,
+ PUSHORT MaxControlMessage,
+ PUCHAR AltCommunicationClassSetting,
+ PUCHAR AltDataClassSetting,
+ PUSHORT BulkInDataClassPacketSize,
+ PUSHORT MTU,
+ PUSHORT MbimVersion,
+ PUSHORT MbimExtendedVersion)
+
+{
+
+ NTSTATUS Status;
+
+ BYTE* ConfigDescriptorBuffer = NULL;
+ PUSB_CONFIGURATION_DESCRIPTOR ConfigDescriptor = NULL;
+ PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor = NULL;
+ PUSB_ENDPOINT_DESCRIPTOR EndpointDescriptor = NULL;
+ PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR IadDescriptor = NULL;
+ PUSB_CS_DESCRIPTOR CsDescriptor = NULL;
+ PUSB_CS_ECM_DESCRIPTOR EcmDescriptor = NULL;
+ PUSB_CS_NCM_DESCRIPTOR NcmDescriptor = NULL;
+ PUSB_CS_MBB_DESCRIPTOR MbbDescriptor = NULL;
+ PUSB_CS_MBB_DESCRIPTOR_EXTENDED MbbDescriptorExtended = NULL;
+ PUSB_CS_CDC_DESCRIPTOR CdcDescriptor = NULL;
+
+ BYTE* Current = NULL;
+ USHORT DescriptorSize = 0;
+
+ BOOLEAN GotEcmDesc = FALSE;
+ BOOLEAN GotNcmDesc = FALSE;
+ BOOLEAN GotMbbDesc = FALSE;
+ BYTE CurrentInterface = 0;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+ *CommunicationClassInterface = 0xff;
+ *DataClassInterface = 0xff;
+ *AltCommunicationClassSetting = 0;
+ *AltDataClassSetting = 0;
+ *BulkInDataClassPacketSize = 0;
+ *MTU = 0;
+ *MbimVersion = 0x0100; // Default to MBIM 1.0 Version
+ *MbimExtendedVersion = 0x0100;
+
+ usbDeviceContext = GetUsbDeviceContext(WdfUsbDevice);
+
+ Status = WdfUsbTargetDeviceRetrieveConfigDescriptor(WdfUsbDevice, NULL, &DescriptorSize);
+
+ if (Status != STATUS_BUFFER_TOO_SMALL)
+ {
+
+ goto Cleanup;
+ }
+
+ ConfigDescriptorBuffer = (BYTE*)ALLOCATE_NONPAGED_POOL(DescriptorSize);
+
+ if (ConfigDescriptorBuffer == NULL)
+ {
+ Status = STATUS_NO_MEMORY;
+ goto Cleanup;
+ }
+
+ Status = WdfUsbTargetDeviceRetrieveConfigDescriptor(WdfUsbDevice, ConfigDescriptorBuffer, &DescriptorSize);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ Current = ConfigDescriptorBuffer;
+
+ while (Current + sizeof(USB_DESCRIPTOR_HEADER) <= ConfigDescriptorBuffer + DescriptorSize)
+ {
+ PUSB_DESCRIPTOR_HEADER Header = (PUSB_DESCRIPTOR_HEADER)Current;
+
+ if (Current + Header->bLength > ConfigDescriptorBuffer + DescriptorSize)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+ switch (Header->bDescriptorType)
+ {
+ case USB_CONFIGURATION_DESCRIPTOR_TYPE:
+
+ ConfigDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Current;
+
+ break;
+
+ case USB_INTERFACE_DESCRIPTOR_TYPE:
+
+ InterfaceDescriptor = (PUSB_INTERFACE_DESCRIPTOR)Current;
+
+ CurrentInterface = InterfaceDescriptor->bInterfaceNumber;
+
+ if ((InterfaceDescriptor->bInterfaceClass == MBIM_CC_INTERFACE_CLASS) &&
+ ((InterfaceDescriptor->bInterfaceSubClass == MBIM_CC_INTERFACE_SUBCLASS)) &&
+ (InterfaceDescriptor->bInterfaceProtocol == MBIM_CC_INTERFACE_PROTOCOL ||
+ InterfaceDescriptor->bInterfaceProtocol == MBIM_CC_INTERFACE_NBL_PROTOCOL ||
+ InterfaceDescriptor->bInterfaceProtocol == MBIM_CC_INTERFACE_NETPACKET_PROTOCOL))
+ {
+
+ *CommunicationClassInterface = InterfaceDescriptor->bInterfaceNumber;
+ *AltCommunicationClassSetting = InterfaceDescriptor->bAlternateSetting;
+ }
+
+ if ((InterfaceDescriptor->bInterfaceClass == MBIM_DC_INTERFACE_CLASS) &&
+ (InterfaceDescriptor->bInterfaceSubClass == MBIM_DC_INTERFACE_SUBCLASS) &&
+ (InterfaceDescriptor->bInterfaceProtocol == MBIM_DC_INTERFACE_PROTOCOL))
+ {
+ *DataClassInterface = InterfaceDescriptor->bInterfaceNumber;
+ *AltDataClassSetting = InterfaceDescriptor->bAlternateSetting;
+ }
+
+ break;
+
+ case USB_ENDPOINT_DESCRIPTOR_TYPE:
+
+ if ((Header->bLength != sizeof(*EndpointDescriptor)))
+ {
+
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+ EndpointDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)Current;
+
+
+ if (CurrentInterface == *DataClassInterface)
+ {
+ //
+ // this endpoint is for the data interface
+ //
+ if (USB_ENDPOINT_DIRECTION_IN(EndpointDescriptor->bEndpointAddress) && (EndpointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_BULK))
+ {
+ //
+ // bulk in endpoint
+ //
+ *BulkInDataClassPacketSize = EndpointDescriptor->wMaxPacketSize & 0x7ff;
+
+ }
+ }
+
+ break;
+
+ case USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE:
+
+
+ break;
+
+ case USB_CDC_CS_DESCRIPTOR_TYPE:
+
+ CsDescriptor = (PUSB_CS_DESCRIPTOR)Current;
+
+ switch (CsDescriptor->bSubType)
+ {
+ case USB_CDC_CS_ECM_DESCRIPTOR_SUBTYPE:
+
+ EcmDescriptor = (PUSB_CS_ECM_DESCRIPTOR)Current;
+
+
+ break;
+
+ case USB_CDC_CS_NCM_DESCRIPTOR_SUBTYPE:
+
+ NcmDescriptor = (PUSB_CS_NCM_DESCRIPTOR)Current;
+
+ break;
+
+ case USB_CDC_CS_DESCRIPTOR_SUBTYPE:
+
+ if ((CsDescriptor->bLength != sizeof(*CdcDescriptor)))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+ CdcDescriptor = (PUSB_CS_CDC_DESCRIPTOR)Current;
+
+ break;
+
+ case USB_CDC_CS_MBB_DESCRIPTOR_SUBTYPE:
+
+ if ((CsDescriptor->bLength != sizeof(*MbbDescriptor)))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+ MbbDescriptor = (PUSB_CS_MBB_DESCRIPTOR)Current;
+
+ if (MbbDescriptor->wMbbVersion < MBIM_MBB_FUNCDESC_MIN_VERSION)
+ {
+
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ if (MbbDescriptor->wMaxSegmentSize < MBIM_MIN_SEGMENT_SIZE)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ if (MbbDescriptor->bMaxFilterSize > MBIM_MAX_PACKET_FILTER_SIZE)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+ if (MbbDescriptor->bNumberPowerFilters < MBIM_MIN_NUMBER_OF_PACKET_FILTERS)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+ *MaxSegmentSize = MbbDescriptor->wMaxSegmentSize;
+ *PowerFiltersSupported = MbbDescriptor->bNumberPowerFilters;
+ *MaxPowerFilterSize = MbbDescriptor->bMaxFilterSize;
+ *NcmCaps = MbbDescriptor->bmNetworkCapabilities;
+ *MaxControlMessage = MbbDescriptor->wMaxControlMessage;
+ GotMbbDesc = TRUE;
+ *MbimVersion = MbbDescriptor->wMbbVersion;
+
+ break;
+
+ case USB_CDC_CS_MBB_DESCRIPTOR_EXTENDED_SUBTYPE:
+
+ // MBIM 1.0 - 6.5: If MBIM Extended Functional Descriptor is provided, it must appear after MBIM Functional Descriptor.
+ if (!GotMbbDesc)
+ {
+ Status = STATUS_UNRECOGNIZED_MEDIA;
+
+ goto Cleanup;
+ }
+
+ if ((CsDescriptor->bLength != sizeof(*MbbDescriptorExtended)))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+ MbbDescriptorExtended = (PUSB_CS_MBB_DESCRIPTOR_EXTENDED)Current;
+
+ if (MbbDescriptorExtended->wMbbVersion < MBIM_MBB_FUNCDESC_EXTENDED_MIN_VERSION)
+ {
+
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ if (MbbDescriptorExtended->wMTU < MBIM_MIN_MTU_SIZE)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ // If the Extended MTU comes in as larger than the MaxSegmentSize, we set the MTU to MaxSegmentSize
+ if (MbbDescriptorExtended->wMTU > *MaxSegmentSize)
+ {
+ // Check if the MaxSegmentSize is not less than the Minimum MTU size, if it is then bail
+ if (*MaxSegmentSize < MBIM_MIN_MTU_SIZE)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+ else
+ {
+ MbbDescriptorExtended->wMTU = *MaxSegmentSize;
+ }
+ }
+
+ *MTU = MbbDescriptorExtended->wMTU;
+ *MbimExtendedVersion = MbbDescriptorExtended->wMbbVersion;
+
+ break;
+
+ default:
+
+
+ break;
+ }
+
+ break;
+
+ default:
+
+
+ break;
+ }
+
+ Current += Header->bLength;
+ }
+
+ Status = STATUS_SUCCESS;
+
+Cleanup:
+
+ if (ConfigDescriptorBuffer != NULL)
+ {
+ FREE_POOL(ConfigDescriptorBuffer);
+ ConfigDescriptorBuffer = NULL;
+ }
+
+ if (!(GotMbbDesc))
+ {
+
+ Status = STATUS_UNRECOGNIZED_MEDIA;
+ }
+
+ if ((*CommunicationClassInterface == 0xff) || (*DataClassInterface == 0xff))
+ {
+
+ Status = STATUS_UNRECOGNIZED_MEDIA;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+GetNtbParameters(WDFUSBDEVICE WdfUsbDevice, PNCM_NTB_PARAMETER NcmNtb)
+
+{
+
+ NTSTATUS Status;
+ ULONG BytesTransfered = 0;
+
+ Status = SendSyncControlCommand(
+ WdfUsbDevice, BmRequestDeviceToHost, BmRequestToInterface, GET_NTB_PARAMETERS, 0, (PUCHAR)NcmNtb, sizeof(*NcmNtb), &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (BytesTransfered < sizeof(*NcmNtb))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+ }
+ else
+ {
+ goto Cleanup;
+ }
+
+ if ((NcmNtb->bmNtbFormatSupported & NCM_NTB_FORMAT_16_BIT) != NCM_NTB_FORMAT_16_BIT)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ if (NcmNtb->wNdpInPayloadRemainder >= NcmNtb->wNdpInDivisor)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ if ((NcmNtb->wNdpInPayloadRemainder > NcmNtb->dwNtbInMaxSize) || (NcmNtb->wNdpInDivisor > NcmNtb->dwNtbInMaxSize))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ if ((NcmNtb->wNdpInAlignment < 4) || (NcmNtb->wNdpInAlignment > NcmNtb->dwNtbInMaxSize) ||
+ ((NcmNtb->wNdpInAlignment - 1) & NcmNtb->wNdpInAlignment) != 0)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ if (NcmNtb->wNdpOutPayloadRemainder >= NcmNtb->wNdpOutDivisor)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ if ((NcmNtb->wNdpOutPayloadRemainder > NcmNtb->dwNtbOutMaxSize) || (NcmNtb->wNdpOutDivisor > NcmNtb->dwNtbOutMaxSize))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ if ((NcmNtb->wNdpOutAlignment < 4) || (NcmNtb->wNdpOutAlignment > NcmNtb->dwNtbOutMaxSize) ||
+ ((NcmNtb->wNdpOutAlignment - 1) & NcmNtb->wNdpOutAlignment) != 0)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+Cleanup:
+
+ return Status;
+}
+
+NTSTATUS
+SetActivityIdForRequest(__in WDFREQUEST Request, __in LPGUID ActivityId)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ PIRP Irp = NULL;
+
+ do
+ {
+ GUID zeroGuid = { 0 };
+
+ if (ActivityId == NULL || IsEqualGUID(*ActivityId, zeroGuid))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ Irp = WdfRequestWdmGetIrp(Request);
+
+ if (Irp == NULL)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ // set the activity id of the IRP
+ Status = IoSetActivityIdIrp(Irp, ActivityId);
+ } while (FALSE);
+
+ return Status;
+}
+
+EVT_WDF_REQUEST_COMPLETION_ROUTINE SendCompletionRoutine;
+
+VOID SendCompletionRoutine(__in WDFREQUEST Request, __in WDFIOTARGET Target, __in PWDF_REQUEST_COMPLETION_PARAMS Params, __in WDFCONTEXT Context)
+
+{
+ PREQUEST_CONTEXT ReqContext = NULL;
+
+ ReqContext = GetRequestContext(Request);
+
+ (ReqContext->Callback.Send)(ReqContext->ProtocolHandle, ReqContext->CallbackContext, Params->IoStatus.Status);
+
+ WdfObjectDelete(Request);
+}
+
+NTSTATUS
+MbbBusSendMessageFragment(
+ __in MBB_BUS_HANDLE BusHandle,
+ __in MBB_REQUEST_HANDLE RequestHandle,
+ __in PVOID MessageFragment,
+ __in ULONG FragmentLength,
+ __in LPGUID ActivityId,
+ __in MBB_BUS_SEND_COMPLETION_CALLBACK SendCompletionCallback)
+
+ /*
+ Description
+ The protocol layer call this routine to request the bus layer to
+ send a message fragment. Fragmentation / Reassembly is handled by
+ the protocol layer and it will only handle fragments that are within
+ the maximum transfer size of the bus.
+
+ This routine is asynchronous and returns immediately after queueing
+ the transfer. The caller is notified of the completion through the
+ callback.
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ __in MBB_REQUEST_HANDLE RequestHandle,
+ Identifies the request.
+
+ __in PVOID MessageFragment,
+ The data payload that needs to be sent.
+
+ __in ULONG FragmentLength,
+ Length of the data payload. This will not be greater than the
+ maximum transfer size supported by the bus.
+
+ __in LPGUID ActivityId,
+ The activity Id to be associated with this fragment transfer.
+ This activity Id will also be used by USB for logging USB events.
+
+ __in MBB_BUS_SEND_COMPLETION_CALLBACK SendCompletionCallback
+ The completion callback routine that will be called by the bus
+ when the transfer is complete.
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ The transfer has completed successfully. SendCompletionCallback will NOT be called.
+
+ NTSTATUS_PENDING
+ The transfer was queued. SendCompletionCallback will be called on completion.
+
+ Other failure code
+ The transfer could not be queued. SendCompletionCallback will NOT be called.
+ */
+
+{
+
+ WDF_USB_CONTROL_SETUP_PACKET packet;
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDFMEMORY memHandle = NULL;
+ WDFREQUEST request = NULL;
+ BOOLEAN SentToDevice = FALSE;
+ PREQUEST_CONTEXT Context = NULL;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);
+ attributes.ParentObject = BusObject->WdfUsbDevice;
+
+ status = WdfRequestCreate(&attributes, WdfUsbTargetDeviceGetIoTarget(BusObject->WdfUsbDevice), &request);
+
+ if (!NT_SUCCESS(status))
+ {
+
+ goto Cleanup;
+ }
+
+ Context = GetRequestContext(request);
+
+ Context->CallbackContext = RequestHandle;
+ Context->Callback.Send = SendCompletionCallback;
+ Context->ProtocolHandle = BusObject->ProtocolHandle;
+ Context->UsbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = request;
+
+ status = WdfMemoryCreatePreallocated(&attributes, MessageFragment, FragmentLength, &memHandle);
+
+ if (!NT_SUCCESS(status))
+ {
+
+ goto Cleanup;
+ }
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_CLASS(
+ &packet, BmRequestHostToDevice, BmRequestToInterface, SEND_ENCAPSULATE_COMMAND, 0, Context->UsbDeviceContext->UsbCommunicationInterfaceIndex);
+
+ status = WdfUsbTargetDeviceFormatRequestForControlTransfer(BusObject->WdfUsbDevice, request, &packet, memHandle, NULL);
+
+ if (!NT_SUCCESS(status))
+ {
+
+ goto Cleanup;
+ }
+
+ WdfRequestSetCompletionRoutine(request, SendCompletionRoutine, NULL);
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, 0);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(10));
+
+ // Set the activity Id of the IRP associated with the request.
+ // Ignore any failures
+ SetActivityIdForRequest(request, ActivityId);
+
+ if (FragmentLength >= sizeof(MBB_COMMAND_HEADER))
+ {
+ PMBB_COMMAND_HEADER CommandHeader = (PMBB_COMMAND_HEADER)MessageFragment;
+ }
+
+ SentToDevice = WdfRequestSend(request, WdfUsbTargetDeviceGetIoTarget(BusObject->WdfUsbDevice), &SendOptions);
+
+ status = STATUS_PENDING;
+
+ if (!SentToDevice)
+ {
+
+ status = WdfRequestGetStatus(request);
+
+ }
+
+Cleanup:
+
+ if (!NT_SUCCESS(status))
+ {
+ if (request != NULL)
+ {
+ WdfObjectDelete(request);
+ request = NULL;
+ }
+ }
+
+ return status;
+}
+
+EVT_WDF_REQUEST_COMPLETION_ROUTINE ReceiveCompletionRoutine;
+
+VOID ReceiveCompletionRoutine(__in WDFREQUEST Request, __in WDFIOTARGET Target, __in PWDF_REQUEST_COMPLETION_PARAMS Params, __in WDFCONTEXT Context)
+
+{
+ PREQUEST_CONTEXT ReqContext = NULL;
+ GUID ActivityId = { 0 };
+ PIRP Irp = NULL;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ ReqContext = GetRequestContext(Request);
+
+ // Get the IRP
+ Irp = WdfRequestWdmGetIrp(Request);
+
+ if (Irp != NULL)
+ {
+ // Get the activity Id
+ Status = IoGetActivityIdIrp(Irp, &ActivityId);
+ }
+
+ if (NT_SUCCESS(Params->IoStatus.Status) && (Params->IoStatus.Information >= sizeof(MBB_COMMAND_DONE_HEADER)))
+ {
+
+ PMBB_COMMAND_DONE_HEADER CommandHeader = (PMBB_COMMAND_DONE_HEADER)ReqContext->Buffer;
+ }
+
+ (*ReqContext->Callback.Receive)(
+ ReqContext->ProtocolHandle, ReqContext->CallbackContext, Params->IoStatus.Status, (ULONG)Params->IoStatus.Information);
+
+ WdfObjectDelete(Request);
+}
+
+NTSTATUS
+MbbBusReceiveMessageFragment(
+ _In_ MBB_BUS_HANDLE BusHandle,
+ _In_ MBB_REQUEST_HANDLE RequestHandle,
+ _In_ __drv_aliasesMem PVOID MessageFragment,
+ _In_ ULONG FragmentLength,
+ _In_ LPGUID ActivityId,
+ _In_ MBB_BUS_RECEIVE_COMPLETION_CALLBACK ReceiveCompletionCallback)
+ /*
+ Description
+
+ Parameters
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Initialization was successful.
+
+ Other failure code
+ */
+ /*
+ Description
+ The protocol layer call this routine to request the bus layer to
+ receive data from the device. Reassembly is handled by the protocol layer.
+
+ This routine is asynchronous and returns immediately after queueing
+ the transfer. The caller is notified of the completion through the
+ callback.
+
+ Parameters
+ _In_ MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ _In_ MBB_REQUEST_HANDLE RequestHandle,
+ Identifies the request.
+
+ _In_ __drv_aliasesMem PVOID MessageFragment,
+ The data buffer that would be filled with the received data.
+
+ _In_ ULONG FragmentLength,
+ Length of the data requested from the device. This will not be
+ greater than the maximum transfer size supported by the bus.
+
+ _In_ LPGUID ActivityId,
+ The activity Id to be associated with this fragment transfer.
+ This activity Id will also be used by USB for logging USB events.
+
+ _In_ MBB_BUS_RECEIVE_COMPLETION_CALLBACK ReceiveCompletionCallback
+ The completion callback routine that will be called by the bus
+ when the transfer is complete.
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ The transfer has completed successfully. ReceiveCompletionCallback will NOT be called.
+
+ NTSTATUS_PENDING
+ The transfer was queued. ReceiveCompletionCallback will be called on completion.
+
+ Other failure code
+ The transfer could not be queued. ReceiveCompletionCallback will NOT be called.
+ */
+
+{
+ WDF_USB_CONTROL_SETUP_PACKET packet;
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDFMEMORY memHandle = NULL;
+ WDFREQUEST request = NULL;
+ BOOLEAN SentToDevice = FALSE;
+ PREQUEST_CONTEXT Context = NULL;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+ PIRP Irp = NULL;
+
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT);
+
+ attributes.ParentObject = BusObject->WdfUsbDevice;
+
+ status = WdfRequestCreate(&attributes, WdfUsbTargetDeviceGetIoTarget(BusObject->WdfUsbDevice), &request);
+
+ if (!NT_SUCCESS(status))
+ {
+
+ goto Cleanup;
+ }
+
+ Context = GetRequestContext(request);
+
+ Context->CallbackContext = RequestHandle;
+ Context->Callback.Receive = ReceiveCompletionCallback;
+ Context->ProtocolHandle = BusObject->ProtocolHandle;
+ Context->UsbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ Context->Buffer = MessageFragment;
+ Context->BufferLength = FragmentLength;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = request;
+
+ status = WdfMemoryCreatePreallocated(&attributes, MessageFragment, FragmentLength, &memHandle);
+
+ if (!NT_SUCCESS(status))
+ {
+
+ goto Cleanup;
+ }
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_CLASS(
+ &packet, BmRequestDeviceToHost, BmRequestToInterface, GET_ENCAPSULATE_RESPONSE, 0, Context->UsbDeviceContext->UsbCommunicationInterfaceIndex);
+
+ status = WdfUsbTargetDeviceFormatRequestForControlTransfer(BusObject->WdfUsbDevice, request, &packet, memHandle, NULL);
+
+ if (!NT_SUCCESS(status))
+ {
+
+ goto Cleanup;
+ }
+
+ WdfRequestSetCompletionRoutine(request, ReceiveCompletionRoutine, NULL);
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, 0);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(10));
+
+ // Set the activity Id of the IRP associated with the request.
+ // Ignore any failures
+ SetActivityIdForRequest(request, ActivityId);
+
+ SentToDevice = WdfRequestSend(request, WdfUsbTargetDeviceGetIoTarget(BusObject->WdfUsbDevice), &SendOptions);
+
+ status = STATUS_PENDING;
+
+ if (!SentToDevice)
+ {
+
+ status = WdfRequestGetStatus(request);
+
+ }
+
+Cleanup:
+
+ if (!NT_SUCCESS(status))
+ {
+ if (request != NULL)
+ {
+ WdfObjectDelete(request);
+ request = NULL;
+ }
+ }
+
+ return status;
+}
+
+VOID InterruptPipeReadComplete(__in WDFUSBPIPE Pipe, __in WDFMEMORY Memory, __in size_t NumBytesTransfered, __in WDFCONTEXT Context)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)Context;
+ PVOID Buffer = NULL;
+ PUSB_CDC_NOTIFICATION CdcNotification = NULL;
+ PUSB_CDC_NOTIFICATION_SPEED_CHANGE CdcSpeedChangeNotification = NULL;
+ ULONG TempBytesTransfered = (ULONG)NumBytesTransfered;
+ UCHAR IndicateBuffer[INTERRUPT_REASSEMBLY_BUFFER_SIZE];
+ ULONG BufferLength = 0;
+
+
+ Buffer = WdfMemoryGetBuffer(Memory, NULL);
+
+ //
+ // process this fragment, the function will return a non-zero value if a complete message is returned.
+ //
+ BufferLength = ProcessInterruptPipeRead(BusObject, (PCUCHAR)Buffer, NumBytesTransfered, IndicateBuffer, sizeof(IndicateBuffer));
+
+ if (BufferLength >= sizeof(*CdcNotification))
+ {
+ CdcNotification = (PUSB_CDC_NOTIFICATION)&IndicateBuffer[0];
+
+ switch (CdcNotification->bNotificationCode)
+ {
+ case USB_CDC_NOTIFICATION_RESPONSE_AVAILABLE: (BusObject->ResponseAvailableCallback)(BusObject->ProtocolHandle); break;
+
+ case USB_CDC_NOTIFICATION_NETWORK_CONNECTION:
+ case USB_CDC_NOTIFICATION_CONNECTION_SPEED_CHANGE:
+ default: break;
+ }
+ }
+
+ return;
+}
+
+BOOLEAN
+InterruptPipeReadError(__in WDFUSBPIPE Pipe, __in NTSTATUS Status, __in USBD_STATUS UsbdStatus)
+
+{
+ return TRUE;
+}
+
+NTSTATUS
+MbbBusQueryBusParameters(__in MBB_BUS_HANDLE BusHandle, __out PMBB_BUS_PARAMETERS BusParameters)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+
+ RtlZeroMemory(BusParameters, sizeof(*BusParameters));
+
+ BusParameters->FragmentSize = BusObject->MaxControlChannelSize;
+
+ BusParameters->MaxSegmentSize = BusObject->MaxSegmentSize;
+
+ BusParameters->Ntb32BitSupported = (BusObject->NtbParam.bmNtbFormatSupported & NCM_NTB_FORMAT_32_BIT) == NCM_NTB_FORMAT_32_BIT;
+ BusParameters->MaxOutNtb = BusObject->NtbParam.dwNtbOutMaxSize;
+
+ if ((BusObject->NtbParam.wNtbOutMaxDatagrams == 0) || (BusObject->NtbParam.wNtbOutMaxDatagrams > MAX_OUT_DATAGRAMS))
+ {
+ //
+ // Zero means unlimited, impose a limit so the driver can preallocated the contexts it needs
+ //
+ BusParameters->MaxOutDatagrams = MAX_OUT_DATAGRAMS;
+ }
+ else
+ {
+ BusParameters->MaxOutDatagrams = BusObject->NtbParam.wNtbOutMaxDatagrams;
+ }
+
+ BusParameters->NdpOutDivisor = BusObject->NtbParam.wNdpOutDivisor;
+ BusParameters->NdpOutRemainder = BusObject->NtbParam.wNdpOutPayloadRemainder;
+ BusParameters->NdpOutAlignment = BusObject->NtbParam.wNdpOutAlignment;
+ //
+ // TODO: Read the current value from the bus object when SetNtb is implemented
+ //
+ BusParameters->CurrentMode32Bit = BusObject->NtbFormat32Bit;
+ BusParameters->SelectiveSuspendSupported = TRUE;
+
+ BusParameters->PowerFiltersSupported = BusObject->PowerFiltersSupported;
+ BusParameters->MaxPowerFilterSize = BusObject->MaxPowerFilterSize;
+ BusParameters->RemoteWakeCapable = BusObject->RemoteWakeCapable;
+
+ if (BusObject->Manufacturer != NULL)
+ {
+ RtlStringCbCopyW(BusParameters->Manufacturer, sizeof(BusParameters->Manufacturer), BusObject->Manufacturer);
+ }
+
+ if (BusObject->Model != NULL)
+ {
+ RtlStringCbCopyW(BusParameters->Model, sizeof(BusParameters->Model), BusObject->Model);
+ }
+
+ BusParameters->MTU = BusObject->MTU;
+ if (BusObject->MTU != 0)
+ {
+ BusParameters->IsErrataDevice = TRUE;
+ }
+ else
+ {
+ BusParameters->IsErrataDevice = FALSE;
+ }
+
+ BusParameters->MbimVersion = BusObject->MbimVersion;
+ BusParameters->MbimExtendedVersion = BusObject->MbimExtendedVersion;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS MbbBusHandshake(_In_ PBUS_OBJECT BusObject, _In_ ULONG TransactionId, _In_opt_ PVOID FastIOSendNetBufferListsComplete, _In_opt_ PVOID FastIOIndicateReceiveNetBufferLists)
+{
+ NTSTATUS Status;
+ ULONG BytesTransferred = 0;
+ UCHAR ReadBuffer[256];
+ ULONG RetryCount = 0;
+ MBB_OPEN_MESSAGE OpenMessage;
+ PMBB_OPEN_DONE OpenDoneMessage = NULL;
+ MBB_OPEN_MESSAGE_FASTIO OpenMessageFastIO;
+ PMBB_OPEN_DONE_FASTIO OpenDoneMessageFastIO = NULL;
+
+ RtlZeroMemory(&OpenMessage, sizeof(OpenMessage));
+
+ OpenMessage.MessageHeader.MessageType = MBB_MESSAGE_TYPE_OPEN;
+ OpenMessage.MessageHeader.MessageLength = sizeof(OpenMessage);
+ OpenMessage.MessageHeader.MessageTransactionId = TransactionId;
+ OpenMessage.MaximumControlTransfer =
+ BusObject->MaxControlChannelSize < MAX_CONTROL_MESSAGE_SIZE ? BusObject->MaxControlChannelSize : MAX_CONTROL_MESSAGE_SIZE;
+
+ do
+ {
+ RetryCount++;
+
+ Status = TransactControlChannel(
+ BusObject, RetryCount * INITIAL_OPEN_TIMEOUT, (PUCHAR)&OpenMessage, sizeof(OpenMessage), (PUCHAR)&ReadBuffer[0], sizeof(ReadBuffer), &BytesTransferred);
+ } while ((Status == STATUS_IO_TIMEOUT) && (RetryCount < MAX_OPEN_RETRY_ATTEMPTS));
+
+ if (NT_SUCCESS(Status))
+ {
+ if (BytesTransferred < sizeof(*OpenDoneMessage))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ OpenDoneMessage = (PMBB_OPEN_DONE)&ReadBuffer[0];
+
+ if ((OpenDoneMessage->MessageHeader.MessageType != MBB_MESSAGE_TYPE_OPEN_DONE) ||
+ (OpenDoneMessage->MessageHeader.MessageLength < sizeof(*OpenDoneMessage)) ||
+ (OpenDoneMessage->MessageHeader.MessageTransactionId != OpenMessage.MessageHeader.MessageTransactionId))
+ {
+ Status = STATUS_NDIS_INVALID_DATA;
+ }
+ else if (OpenDoneMessage->MbbStatus != STATUS_SUCCESS)
+ {
+ Status = STATUS_OPEN_FAILED;
+ }
+ }
+ return Status;
+}
+
+NTSTATUS
+MbbBusStart(_In_ MBB_BUS_HANDLE BusHandle)
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ BOOLEAN FailOpen = FALSE;
+
+ BOOLEAN AltSettingSet = FALSE;
+
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ if (BusObject->State != BUS_STATE_CLOSED)
+ {
+ FailOpen = TRUE;
+ }
+ else
+ {
+ BusObject->State = BUS_STATE_OPENING;
+ }
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+
+ if (FailOpen)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto Cleanup;
+ }
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ Status = MbbBusResetDeviceAndSetParms(BusObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = MbbBusSelectDataAltSetting(BusObject, ALT_DATA_SETTING_1);
+
+ if (NT_ERROR(Status))
+ {
+ goto Cleanup;
+ }
+
+ AltSettingSet = TRUE;
+
+ //
+ // start the continouse reader now
+ //
+ Status = WdfIoTargetStart(usbDeviceContext->InterruptPipeIoTarget);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ Status = STATUS_SUCCESS;
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ BusObject->State = BUS_STATE_OPENED;
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+
+Cleanup:
+
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // stop the pipe reader
+ //
+ WdfIoTargetStop(usbDeviceContext->InterruptPipeIoTarget, WdfIoTargetCancelSentIo);
+
+ //
+ // set the data pipes back to alt seeting 0
+ //
+ if (AltSettingSet)
+ {
+ MbbBusSelectDataAltSetting(BusObject, ALT_DATA_SETTING_0);
+ }
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ BusObject->State = BUS_STATE_CLOSED;
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusStop(__in MBB_BUS_HANDLE BusHandle)
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ //
+ // stop the interrupt pipe so the continuous reader will stop and we can do sync reads
+ //
+ WdfIoTargetStop(usbDeviceContext->InterruptPipeIoTarget, WdfIoTargetCancelSentIo);
+
+ Status = STATUS_SUCCESS;
+
+ MbbBusSelectDataAltSetting(BusObject, ALT_DATA_SETTING_0);
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ BusObject->State = BUS_STATE_CLOSED;
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+
+
+ return Status;
+}
+
+BOOLEAN
+MbbBusIsStoped(_In_ MBB_BUS_HANDLE BusHandle)
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ return BusObject->State == BUS_STATE_CLOSED;
+}
+
+NTSTATUS
+MbbBusOpen(_In_ MBB_BUS_HANDLE BusHandle, _In_ ULONG TransactionId, _In_opt_ PVOID FastIOSendNetBufferListsComplete, _In_opt_ PVOID FastIOIndicateReceiveNetBufferLists)
+/*
+ Description
+
+ Opens the session with the device
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ BOOLEAN FailOpen = FALSE;
+
+ PUSB_CDC_NOTIFICATION Notification = NULL;
+ BOOLEAN AltSettingSet = FALSE;
+
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ if (BusObject->State != BUS_STATE_CLOSED)
+ {
+ FailOpen = TRUE;
+ }
+ else
+ {
+ BusObject->State = BUS_STATE_OPENING;
+ }
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+
+ if (FailOpen)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+
+
+ goto Cleanup;
+ }
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+
+ Status = MbbBusResetDeviceAndSetParms(BusObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = MbbBusSelectDataAltSetting(BusObject, ALT_DATA_SETTING_1);
+
+ if (NT_ERROR(Status))
+ {
+ goto Cleanup;
+ }
+
+ AltSettingSet = TRUE;
+
+ Status = MbbBusHandshake(BusObject, TransactionId, FastIOSendNetBufferListsComplete, FastIOIndicateReceiveNetBufferLists);
+ if (NT_ERROR(Status))
+ {
+ goto Cleanup;
+ }
+
+ //
+ // start the continouse reader now
+ //
+ Status = WdfIoTargetStart(usbDeviceContext->InterruptPipeIoTarget);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = STATUS_SUCCESS;
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ BusObject->State = BUS_STATE_OPENED;
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+
+Cleanup:
+
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // stop the pipe reader
+ //
+ WdfIoTargetStop(usbDeviceContext->InterruptPipeIoTarget, WdfIoTargetCancelSentIo);
+
+ //
+ // set the data pipes back to alt seeting 0
+ //
+ if (AltSettingSet)
+ {
+ MbbBusSelectDataAltSetting(BusObject, ALT_DATA_SETTING_0);
+ }
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ BusObject->State = BUS_STATE_CLOSED;
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusClose(__in MBB_BUS_HANDLE BusHandle, __in ULONG TransactionId, __in BOOLEAN ForceClose)
+/*
+ Description
+
+ Opens the session with the device
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ BOOLEAN FailClose = FALSE;
+
+ ULONG BytesTransfered = 0;
+ PUSB_CDC_NOTIFICATION Notification = NULL;
+ MBB_CLOSE_MESSAGE CloseMessage;
+ PMBB_CLOSE_DONE CloseDoneMessage = NULL;
+ UCHAR ReadBuffer[256];
+
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ if (!ForceClose)
+ {
+ if (BusObject->State != BUS_STATE_OPENED)
+ {
+ FailClose = TRUE;
+ }
+ }
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+
+ if (FailClose)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto Cleanup;
+ }
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ //
+ // stop the interrupt pipe so the continuous reader will stop and we can do sync reads
+ //
+ WdfIoTargetStop(usbDeviceContext->InterruptPipeIoTarget, WdfIoTargetCancelSentIo);
+
+ RtlZeroMemory(&CloseMessage, sizeof(CloseMessage));
+
+ CloseMessage.MessageHeader.MessageType = MBB_MESSAGE_TYPE_CLOSE;
+ CloseMessage.MessageHeader.MessageLength = sizeof(CloseMessage);
+ CloseMessage.MessageHeader.MessageTransactionId = TransactionId;
+
+ Status = TransactControlChannel(
+ BusObject, DEFAULT_IO_TIMEOUT, (PUCHAR)&CloseMessage, sizeof(CloseMessage), (PUCHAR)&ReadBuffer[0], sizeof(ReadBuffer), &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (BytesTransfered < sizeof(*CloseDoneMessage))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ CloseDoneMessage = (PMBB_CLOSE_DONE)&ReadBuffer[0];
+
+ if ((CloseDoneMessage->MessageHeader.MessageType != MBB_MESSAGE_TYPE_CLOSE_DONE) ||
+ (CloseDoneMessage->MessageHeader.MessageLength < sizeof(*CloseDoneMessage)) ||
+ (CloseDoneMessage->MessageHeader.MessageTransactionId != CloseMessage.MessageHeader.MessageTransactionId))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+
+ goto Cleanup;
+ }
+
+Cleanup:
+
+ Status = STATUS_SUCCESS;
+
+ MbbBusSelectDataAltSetting(BusObject, ALT_DATA_SETTING_0);
+
+ ACQUIRE_PASSIVE_LOCK(&BusObject->Lock);
+
+ BusObject->State = BUS_STATE_CLOSED;
+
+ RELEASE_PASSIVE_LOCK(&BusObject->Lock);
+
+ return Status;
+}
+
+VOID MbbBusSetNotificationState(__in MBB_BUS_HANDLE BusHandle, __in BOOLEAN Enabled)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ if (!Enabled)
+ {
+ WdfIoTargetStop(usbDeviceContext->InterruptPipeIoTarget, WdfIoTargetCancelSentIo);
+ }
+ else
+ {
+ (void)WdfIoTargetStart(usbDeviceContext->InterruptPipeIoTarget);
+ }
+
+ return;
+} \ No newline at end of file
diff --git a/network/wwan/cxwmbclass/cxwmbclass.rc b/network/wwan/cxwmbclass/cxwmbclass.rc
new file mode 100644
index 00000000..6df53fd8
--- /dev/null
+++ b/network/wwan/cxwmbclass/cxwmbclass.rc
@@ -0,0 +1,20 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#include "windows.h"
+#include "ntverp.h"
+
+/*-----------------------------------------------*/
+/* the following lines are specific to this file */
+/*-----------------------------------------------*/
+
+#define VER_FILETYPE VFT_DRV
+
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+
+#define VER_FILEDESCRIPTION_STR "Windows Mobile Broadband Class Driver"
+
+#define VER_INTERNALNAME_STR "cxwmbclass.sys"
+#define VER_ORIGINALFILENAME_STR "cxwmbclass.sys"
+
+#include "common.ver"
diff --git a/network/wwan/cxwmbclass/cxwmbclass.sln b/network/wwan/cxwmbclass/cxwmbclass.sln
new file mode 100644
index 00000000..249990f1
--- /dev/null
+++ b/network/wwan/cxwmbclass/cxwmbclass.sln
@@ -0,0 +1,35 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32929.385
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cxwmbclass", "cxwmbclass\cxwmbclass.vcxproj", "{11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Debug|x64.ActiveCfg = Debug|x64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Debug|x64.Build.0 = Debug|x64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Debug|x64.Deploy.0 = Debug|x64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Release|ARM64.Build.0 = Release|ARM64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Release|ARM64.Deploy.0 = Release|ARM64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Release|x64.ActiveCfg = Release|x64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Release|x64.Build.0 = Release|x64
+ {11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}.Release|x64.Deploy.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3DEAC1E8-F245-49DC-AD26-8A3694201775}
+ EndGlobalSection
+EndGlobal
diff --git a/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.inf b/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.inf
new file mode 100644
index 00000000..69055bfb
--- /dev/null
+++ b/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.inf
@@ -0,0 +1,119 @@
+;-------------------------------------------------------------------------------
+; netwmbclass.inf
+;
+; Copyright (c) Microsoft Corporation. All rights reserved.
+
+[version]
+Signature = "$Windows NT$"
+Class = Net
+ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318}
+Provider = %ManufacturerName%
+CatalogFile=cxwmbclass.cat
+DriverVer = ; will be filled in at build time by StampInf
+PnpLockdown = 1
+
+[SourceDisksNames]
+3426=windows cd
+
+[SourceDisksFiles]
+cxwmbclass.sys = 3426
+
+[DestinationDirs]
+DefaultDestDir=13
+
+[Manufacturer]
+%ManufacturerName% = Msft,NT$ARCH$
+
+[Msft.NT$ARCH$]
+ ; DisplayName Section DeviceID
+ ; ----------- ------- --------
+;%wmbclass.DeviceDesc% = wmbclass.ndi, USB\MS_COMP_MBIM
+;%wmbclass.DeviceDesc% = wmbclass.ndi, USB\class_02&subclass_0e&prot_00
+%wmbclass.DeviceDesc% = wmbclass.ndi, USB\VID_1199&PID_9071&MI_0C ;Sierra Wireless EM7430 Qualcomm Snapdragon X7 LTE-A
+
+;-------------------------------------------------------------------------------
+; Adapter DDInstall and Services section
+; for NetAdapter drivers
+[wmbclass.ndi]
+AddReg = wmbclass.Reg
+CopyFiles = wmbclassCopyFiles
+Characteristics = 0x4 ; NCF_PHYSICAL
+BusType = 15
+*IfType = 243; IF_TYPE_WWANPP
+*MediaType = 9; NdisMediumWirelessWan
+*PhysicalMediaType = 8; NdisPhysicalMediumWirelessWan
+EnableDhcp = 0; Disable DHCP
+
+[wmbclassCopyFiles]
+cxwmbclass.sys,,,0x0100
+
+[wmbclass.ndi.HW]
+Include = pci.inf
+Needs = PciD3ColdSupported.HW
+AddReg = wmbclass.ndi.AddReg.HW
+
+[wmbclass.ndi.AddReg.HW]
+HKR,,"AllowIdleIrpInD3",0x00010001,0x1
+
+[wmbclass.ndi.Services]
+AddService = %ServiceName%, 2, wmbclass.Service, wmbclass.EventLog
+
+; For mobile broadband drivers
+[wmbclass.Reg]
+HKR, Ndi, Service, 0, %ServiceName%
+HKR, Ndi\Interfaces, UpperRange, 0, "flpp4, flpp6"
+HKR, Ndi\Interfaces, LowerRange, 0, "ppip"
+HKR, , AllowDriverToOverrideDeviceName, 0x00010001, 1
+
+; standard INF keywords for NetAdapter drivers
+; using AddReg directive so they will work when this INF being Includes/Needs
+
+HKR, NetworkInterface, *IfConnectorPresent, 0x00010001, 1
+HKR, NetworkInterface, *ConnectionType, 0x00010001, 1
+HKR, NetworkInterface, *DirectionType, 0x00010001, 0
+HKR, NetworkInterface, *AccessType, 0x00010001, 2
+HKR, NetworkInterface, *HardwareLoopback, 0x00010001, 0
+HKR, , NumberOfNetworkInterfaces, 0x00010001, 17
+
+; Selective Suspend
+HKR,Ndi\params\*SelectiveSuspend,ParamDesc,,%SelectiveSuspend%
+HKR,Ndi\params\*SelectiveSuspend,default,,"1"
+HKR,Ndi\params\*SelectiveSuspend,type,,"enum"
+HKR,Ndi\params\*SelectiveSuspend\enum,0,,%Disabled%
+HKR,Ndi\params\*SelectiveSuspend\enum,1,,%Enabled%
+
+;-----------------------------------------------------------------------------
+; Driver and Service Section
+;
+
+; For wmbclass.x drivers
+[wmbclass.Service]
+DisplayName = %wmbclass.Service.DispName%
+ServiceType = 1 ;%SERVICE_KERNEL_DRIVER%
+StartType = 3 ;%SERVICE_DEMAND_START%
+ErrorControl = 1 ;%SERVICE_ERROR_NORMAL%
+ServiceBinary = %13%\cxwmbclass.sys
+LoadOrderGroup = NDIS
+
+[wmbclass.EventLog]
+AddReg = wmbclass.AddEventLog.Reg
+
+[wmbclass.AddEventLog.Reg]
+HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll"
+HKR, , TypesSupported, 0x00010001, 7
+
+;-----------------------------------------------------------------------------
+; Non-localizable Strings
+;
+[Strings]
+ServiceName = "cxwmbclass"
+
+;-----------------------------------------------------------------------------
+; Localizable Strings
+;
+ManufacturerName = "Sample Code"
+wmbclass.DeviceDesc = "Generic Mobile Broadband Adapter"
+wmbclass.Service.DispName = "USB Mobile Broadband Adapter Driver"
+Disabled = "Disabled"
+Enabled = "Enabled"
+SelectiveSuspend = "Selective Suspend"
diff --git a/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj b/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj
new file mode 100644
index 00000000..9d7d5b16
--- /dev/null
+++ b/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{11CC63F7-F6D0-4CED-99BA-C5FDAE88D29C}</ProjectGuid>
+ <TemplateGuid>{1bc93793-694f-48fe-9372-81e2b05556fd}</TemplateGuid>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <Configuration>Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">x64</Platform>
+ <RootNamespace>cxwmbclass</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <IncludePath>$(SolutionDir)\inc;$(IncludePath)</IncludePath>
+ <ExternalIncludePath>$(KIT_SHARED_INC_PATH_WDK)\netcx\shared\1.0;$(KM_IncludePath)\mbbcx\1.0;$(KIT_SHARED_INC_PATH_WDK);$(KM_IncludePath)\netcx\kmdf\adapter\2.3;$(ExternalIncludePath)</ExternalIncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <IncludePath>$(SolutionDir)\inc;$(IncludePath)</IncludePath>
+ <ExternalIncludePath>$(KIT_SHARED_INC_PATH_WDK)\netcx\shared\1.0;$(KM_IncludePath)\mbbcx\1.0;$(KIT_SHARED_INC_PATH_WDK);$(KM_IncludePath)\netcx\kmdf\adapter\2.3;$(ExternalIncludePath)</ExternalIncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <IncludePath>$(SolutionDir)\inc;$(IncludePath)</IncludePath>
+ <ExternalIncludePath>$(KIT_SHARED_INC_PATH_WDK)\netcx\shared\1.0;$(KM_IncludePath)\mbbcx\1.0;$(KIT_SHARED_INC_PATH_WDK);$(KM_IncludePath)\netcx\kmdf\adapter\2.3;$(ExternalIncludePath)</ExternalIncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ <IncludePath>$(SolutionDir)\inc;$(IncludePath)</IncludePath>
+ <ExternalIncludePath>$(KIT_SHARED_INC_PATH_WDK)\netcx\shared\1.0;$(KM_IncludePath)\mbbcx\1.0;$(KIT_SHARED_INC_PATH_WDK);$(KM_IncludePath)\netcx\kmdf\adapter\2.3;$(ExternalIncludePath)</ExternalIncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ <ClCompile>
+ <DisableSpecificWarnings>4748;%(DisableSpecificWarnings);4101;4189;4100;4267</DisableSpecificWarnings>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>$(WindowsDDK_LibraryPath)\x64\ndis.lib;$(WindowsDDK_LibraryPath)\x64\netio.lib;$(WindowsDDK_LibraryPath)\x64\usbd.lib;$(WindowsDDK_LibraryPath)\x64\usbdex.lib;$(WindowsDDK_LibraryPath)\x64\wdmguid.lib;$(WindowsDDK_LibraryPath)\x64\netcx\kmdf\adapter\2.3\netadaptercxstub.lib;$(WindowsDDK_LibraryPath)\x64\mbbcx\1.0\mbbcxstub.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>$(WindowsDDK_LibraryPath)\x64\ndis.lib;$(WindowsDDK_LibraryPath)\x64\netio.lib;$(WindowsDDK_LibraryPath)\x64\usbd.lib;$(WindowsDDK_LibraryPath)\x64\usbdex.lib;$(WindowsDDK_LibraryPath)\x64\wdmguid.lib;$(WindowsDDK_LibraryPath)\x64\netcx\kmdf\adapter\2.3\netadaptercxstub.lib;$(WindowsDDK_LibraryPath)\x64\mbbcx\1.0\mbbcxstub.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>$(WindowsDDK_LibraryPath)\arm64\ndis.lib;$(WindowsDDK_LibraryPath)\arm64\netio.lib;$(WindowsDDK_LibraryPath)\arm64\usbd.lib;$(WindowsDDK_LibraryPath)\arm64\usbdex.lib;$(WindowsDDK_LibraryPath)\arm64\wdmguid.lib;$(WindowsDDK_LibraryPath)\arm64\netcx\kmdf\adapter\2.3\netadaptercxstub.lib;$(WindowsDDK_LibraryPath)\arm64\mbbcx\1.0\mbbcxstub.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>$(WindowsDDK_LibraryPath)\arm64\ndis.lib;$(WindowsDDK_LibraryPath)\arm64\netio.lib;$(WindowsDDK_LibraryPath)\arm64\usbd.lib;$(WindowsDDK_LibraryPath)\arm64\usbdex.lib;$(WindowsDDK_LibraryPath)\arm64\wdmguid.lib;$(WindowsDDK_LibraryPath)\arm64\netcx\kmdf\adapter\2.3\netadaptercxstub.lib;$(WindowsDDK_LibraryPath)\arm64\mbbcx\1.0\mbbcxstub.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Inf Include="cxwmbclass.inf" />
+ </ItemGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\adapter.cpp" />
+ <ClCompile Include="..\businit.cpp" />
+ <ClCompile Include="..\datapipe.cpp" />
+ <ClCompile Include="..\device.cpp" />
+ <ClCompile Include="..\driver.cpp" />
+ <ClCompile Include="..\power.cpp" />
+ <ClCompile Include="..\rxqueue.cpp" />
+ <ClCompile Include="..\txqueue.cpp" />
+ <ClCompile Include="..\util.cpp" />
+ <ClCompile Include="..\utils.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\inc\adapter.h" />
+ <ClInclude Include="..\inc\align.h" />
+ <ClInclude Include="..\inc\BusInterface.h" />
+ <ClInclude Include="..\inc\data.h" />
+ <ClInclude Include="..\inc\device.h" />
+ <ClInclude Include="..\inc\mbbmessages.h" />
+ <ClInclude Include="..\inc\mbbncm.h" />
+ <ClInclude Include="..\inc\power.h" />
+ <ClInclude Include="..\inc\precomp.h" />
+ <ClInclude Include="..\inc\rxqueue.h" />
+ <ClInclude Include="..\inc\txqueue.h" />
+ <ClInclude Include="..\inc\usbbus.h" />
+ <ClInclude Include="..\inc\util.h" />
+ <ClInclude Include="..\inc\utils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\cxwmbclass.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj.filters b/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj.filters
new file mode 100644
index 00000000..7136df25
--- /dev/null
+++ b/network/wwan/cxwmbclass/cxwmbclass/cxwmbclass.vcxproj.filters
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Driver Files">
+ <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="cxwmbclass.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\adapter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\businit.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\datapipe.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\device.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\power.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\rxqueue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\txqueue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\inc\adapter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\align.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\BusInterface.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\data.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\device.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\mbbmessages.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\mbbncm.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\power.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\precomp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\rxqueue.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\txqueue.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\usbbus.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\inc\utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\cxwmbclass.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/network/wwan/cxwmbclass/datapipe.cpp b/network/wwan/cxwmbclass/datapipe.cpp
new file mode 100644
index 00000000..4452b761
--- /dev/null
+++ b/network/wwan/cxwmbclass/datapipe.cpp
@@ -0,0 +1,998 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+typedef struct _USB_WRITE_REQ_CONTEXT
+{
+ WDFMEMORY UrbMemory;
+ PURB Urb;
+ PMDL Mdl;
+ WDFMEMORY LookasideBuffer;
+ PBUS_OBJECT BusObject;
+ MBB_BUS_SEND_DATA_COMPLETION_CALLBACK Callback;
+ MBB_REQUEST_HANDLE RequestHandle;
+
+} USB_WRITE_REQ_CONTEXT, *PUSB_WRITE_REQ_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(USB_WRITE_REQ_CONTEXT, GetWriteRequestContext)
+
+EVT_WDF_USB_READER_COMPLETION_ROUTINE BulkInReadComplete;
+
+EVT_WDF_USB_READERS_FAILED BulkInReadError;
+
+NTSTATUS
+GetWriteRequests(WDFUSBDEVICE UsbDevice, WDFREQUEST* ReturnedWriteRequest);
+
+VOID FreeWriteRequest(WDFUSBDEVICE UsbDevice, WDFREQUEST WriteRequest);
+
+NTSTATUS
+MbbBusSelectDataAltSetting(__in MBB_BUS_HANDLE BusHandle, __in UCHAR AltSetting)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ WDF_USB_INTERFACE_SELECT_SETTING_PARAMS SettingParams;
+ WDFUSBINTERFACE UsbInterface = NULL;
+ WDF_USB_PIPE_INFORMATION pipeInfo;
+ WDFUSBPIPE pipe;
+ UCHAR ConfiguredPipes = 0;
+ UCHAR index = 0;
+ NTSTATUS Status;
+ NTSTATUS TempStatus;
+ WDF_USB_CONTINUOUS_READER_CONFIG ReaderConfig;
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ WdfWaitLockAcquire(usbDeviceContext->PipeStateLock, NULL);
+
+ UsbInterface = WdfUsbTargetDeviceGetInterface(BusObject->WdfUsbDevice, usbDeviceContext->WdfDataInterfaceIndex);
+
+ WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&SettingParams, AltSetting == 0 ? 0 : usbDeviceContext->UsbDataInterfaceSetting);
+
+ Status = WdfUsbInterfaceSelectSetting(UsbInterface, NULL, &SettingParams);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ ConfiguredPipes = WdfUsbInterfaceGetNumConfiguredPipes(UsbInterface);
+
+ if (((AltSetting == ALT_DATA_SETTING_0) && (ConfiguredPipes != ALT_DATA_SETTING_0_PIPES)) ||
+ ((AltSetting == ALT_DATA_SETTING_1) && (ConfiguredPipes != ALT_DATA_SETTING_1_PIPES)))
+ {
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto Cleanup;
+ }
+
+ if (AltSetting == ALT_DATA_SETTING_1)
+ {
+ for (index = 0; index < ConfiguredPipes; index++)
+ {
+
+ WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
+
+ pipe = WdfUsbInterfaceGetConfiguredPipe(
+ UsbInterface,
+ index, // PipeIndex,
+ &pipeInfo);
+
+ if (WdfUsbPipeTypeBulk == pipeInfo.PipeType)
+ {
+
+ if (WdfUsbTargetPipeIsInEndpoint(pipe))
+ {
+ usbDeviceContext->BulkInputPipeConfigured = TRUE;
+ usbDeviceContext->BulkInputPipe = pipe;
+ usbDeviceContext->BulkInputPipeMaxPacket = pipeInfo.MaximumPacketSize;
+ }
+ else
+ {
+ usbDeviceContext->BulkOutputPipeConfigured = TRUE;
+ usbDeviceContext->BulkOutputPipe = pipe;
+ usbDeviceContext->BulkOutputPipeMaxPacket = pipeInfo.MaximumPacketSize;
+ }
+ }
+ else
+ {
+
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto Cleanup;
+ }
+ }
+
+ if (!(usbDeviceContext->BulkInputPipeConfigured && usbDeviceContext->BulkOutputPipeConfigured))
+ {
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto Cleanup;
+ }
+
+ //
+ // configure the continous reader on the bulk pipe now, since this can only be done once on a given pipe
+ // unless it is unselected
+ //
+ WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&ReaderConfig, BulkInReadComplete, BusObject, BusObject->MaxBulkInTransfer);
+
+ if (BusObject->UsbCapDeviceInfo.DeviceInfoHeader.DeviceType == USB_CAP_DEVICE_TYPE_UDE_MBIM)
+ {
+ ReaderConfig.NumPendingReads = PENDING_BULK_IN_READS_FOR_UDE_MBIM;
+ }
+ else
+ {
+ ReaderConfig.NumPendingReads = PENDING_BULK_IN_READS;
+ }
+ ReaderConfig.HeaderLength = BusObject->BulkInHeaderSize;
+ ReaderConfig.EvtUsbTargetPipeReadersFailed = BulkInReadError;
+
+ Status = WdfUsbTargetPipeConfigContinuousReader(usbDeviceContext->BulkInputPipe, &ReaderConfig);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ //
+ // call this now that the pipe is configured
+ //
+ PreAllocateWriteRequests(BusObject->WdfUsbDevice);
+ }
+ else
+ {
+ //
+ // selecting the setting causes the frame work to delete the pipe
+ //
+ WDFREQUEST WriteRequest = NULL;
+
+ usbDeviceContext->BulkInputPipeConfigured = FALSE;
+ usbDeviceContext->BulkInputPipe = NULL;
+
+ usbDeviceContext->BulkOutputPipeConfigured = FALSE;
+ usbDeviceContext->BulkOutputPipe = NULL;
+
+ WdfSpinLockAcquire(usbDeviceContext->WriteCollectionLock);
+
+ WriteRequest = (WDFREQUEST)WdfCollectionGetLastItem(usbDeviceContext->WriteRequestCollection);
+
+ //
+ // delete the write request because they are associated with a pipe object
+ //
+ while (WriteRequest != NULL)
+ {
+ WdfCollectionRemove(usbDeviceContext->WriteRequestCollection, WriteRequest);
+
+ WdfObjectDelete(WriteRequest);
+ WriteRequest = (WDFREQUEST)WdfCollectionGetLastItem(usbDeviceContext->WriteRequestCollection);
+ }
+
+ WdfSpinLockRelease(usbDeviceContext->WriteCollectionLock);
+ }
+
+Cleanup:
+
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to configure the pipes, set back to alt setting 0
+ //
+ WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&SettingParams, 0);
+
+ TempStatus = WdfUsbInterfaceSelectSetting(UsbInterface, NULL, &SettingParams);
+
+ usbDeviceContext->BulkInputPipeConfigured = FALSE;
+ usbDeviceContext->BulkInputPipe = NULL;
+
+ usbDeviceContext->BulkOutputPipeConfigured = FALSE;
+ usbDeviceContext->BulkOutputPipe = NULL;
+ }
+
+ WdfWaitLockRelease(usbDeviceContext->PipeStateLock);
+
+ return Status;
+}
+
+NTSTATUS
+MbbUsbDeviceStartDataPipes(__in PUSB_DEVICE_CONTEXT usbDeviceContext)
+{
+ NTSTATUS Status;
+
+ WdfWaitLockAcquire(usbDeviceContext->PipeStateLock, NULL);
+
+ if (!(usbDeviceContext->BulkInputPipeConfigured && usbDeviceContext->BulkOutputPipeConfigured))
+ {
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto Cleanup;
+ }
+
+ Status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkInputPipe));
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ usbDeviceContext->BulkInputPipeStarted = TRUE;
+
+ Status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkOutputPipe));
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ usbDeviceContext->BulkOutputPipeStarted = TRUE;
+
+Cleanup:
+
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // failed to configure the pipes, set back to alt setting 0
+ //
+ if (usbDeviceContext->BulkInputPipeStarted)
+ {
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkInputPipe), WdfIoTargetCancelSentIo);
+ }
+
+ if (usbDeviceContext->BulkOutputPipeStarted)
+ {
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkOutputPipe), WdfIoTargetCancelSentIo);
+ }
+
+ usbDeviceContext->BulkInputPipeStarted = FALSE;
+ usbDeviceContext->BulkOutputPipeStarted = FALSE;
+ }
+
+ WdfWaitLockRelease(usbDeviceContext->PipeStateLock);
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusStartDataPipes(__in MBB_BUS_HANDLE BusHandle)
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ return MbbUsbDeviceStartDataPipes(GetUsbDeviceContext(BusObject->WdfUsbDevice));
+}
+
+VOID MbbUsbDeviceStopDataPipes(__in PUSB_DEVICE_CONTEXT usbDeviceContext)
+{
+ WDFUSBINTERFACE UsbInterface = NULL;
+
+ WdfWaitLockAcquire(usbDeviceContext->PipeStateLock, NULL);
+
+ if (usbDeviceContext->BulkInputPipeConfigured)
+ {
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkInputPipe), WdfIoTargetCancelSentIo);
+ }
+ if (usbDeviceContext->BulkOutputPipeConfigured)
+ {
+ WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkOutputPipe), WdfIoTargetCancelSentIo);
+ }
+
+ usbDeviceContext->BulkInputPipeStarted = FALSE;
+
+ usbDeviceContext->BulkOutputPipeStarted = FALSE;
+
+ WdfWaitLockRelease(usbDeviceContext->PipeStateLock);
+
+ return;
+}
+
+VOID MbbBusStopDataPipes(__in MBB_BUS_HANDLE BusHandle)
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ WdfWorkItemFlush(usbDeviceContext->BulkPipeResetWorkitem);
+
+ MbbUsbDeviceStopDataPipes(GetUsbDeviceContext(BusObject->WdfUsbDevice));
+}
+
+NTSTATUS
+MbbUsbDeviceResetBulkPipe(__in PUSB_DEVICE_CONTEXT usbDeviceContext, __in BOOLEAN Out)
+
+{
+ WDFUSBPIPE Pipe = NULL;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+ NTSTATUS StatusToReturn = STATUS_SUCCESS;
+ NTSTATUS Status;
+
+ WdfWaitLockAcquire(usbDeviceContext->PipeStateLock, NULL);
+
+ if (Out ? usbDeviceContext->BulkOutputPipeConfigured : usbDeviceContext->BulkInputPipeConfigured)
+ {
+
+ Pipe = Out ? usbDeviceContext->BulkOutputPipe : usbDeviceContext->BulkInputPipe;
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(30));
+
+ Status = WdfUsbTargetPipeAbortSynchronously(Pipe, NULL, &SendOptions);
+
+ if (!NT_SUCCESS(Status))
+ {
+ if (StatusToReturn == STATUS_SUCCESS)
+ {
+ StatusToReturn = Status;
+ }
+ }
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(30));
+
+ Status = WdfUsbTargetPipeResetSynchronously(Pipe, NULL, &SendOptions);
+
+ if (!NT_SUCCESS(Status))
+ {
+ if (StatusToReturn == STATUS_SUCCESS)
+ {
+ StatusToReturn = Status;
+ }
+ }
+ }
+ WdfWaitLockRelease(usbDeviceContext->PipeStateLock);
+
+ return StatusToReturn;
+}
+
+NTSTATUS
+MbbBusResetBulkPipe(__in MBB_BUS_HANDLE BusHandle, __in BOOLEAN Out)
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ return MbbUsbDeviceResetBulkPipe(GetUsbDeviceContext(BusObject->WdfUsbDevice), Out);
+}
+
+EVT_WDF_REQUEST_COMPLETION_ROUTINE WriteCompletionRoutine;
+
+void WriteCompletionRoutine(__in WDFREQUEST Request, __in WDFIOTARGET Target, __in PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, __in WDFCONTEXT Context)
+/*++
+
+Routine Description
+
+ Request - Handle to the WDFREQUEST which was used to send data to the USB target.
+ Target - Handle to the Iotarget to which teh Request was sent. COnceptually this
+ is the BULK USB __out pipe(on of Data or beacon)
+ CompletionParams - In case of USB this contains the USB status and amount of bytes transferred
+
+
+ Context - This is the COntext we set in WdfRequestSend
+
+
+Arguments:
+
+
+
+Return Value:
+
+
+
+--*/
+
+{
+ PUSB_WRITE_REQ_CONTEXT WriteContext;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(Target);
+ WriteContext = (PUSB_WRITE_REQ_CONTEXT)Context;
+
+ Status = CompletionParams->IoStatus.Status;
+
+ //
+ // For usb devices, we should look at the Usb.Completion param.
+ //
+
+ if (WriteContext->Callback != NULL)
+ {
+ (*WriteContext->Callback)(WriteContext->BusObject->ProtocolHandle, WriteContext->RequestHandle, Status, WriteContext->Mdl);
+ }
+
+ if (WriteContext->LookasideBuffer != NULL)
+ {
+
+ WdfObjectDelete(WriteContext->LookasideBuffer);
+ }
+
+ if (WriteContext->UrbMemory != NULL)
+ {
+ WdfObjectDelete(WriteContext->UrbMemory);
+ }
+
+ FreeWriteRequest(WriteContext->BusObject->WdfUsbDevice, Request);
+}
+
+NTSTATUS
+MbbBusWriteData(__in MBB_BUS_HANDLE BusHandle, __in MBB_REQUEST_HANDLE RequestHandle, __in PMDL Mdl, __in MBB_BUS_SEND_DATA_COMPLETION_CALLBACK Callback)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ PMDL TempMdl = NULL;
+ ULONGLONG TotalTransferLength = 0;
+ NTSTATUS Status;
+ WDFMEMORY urbMemory = NULL;
+ WDF_OBJECT_ATTRIBUTES objectAttribs;
+ PURB urbBuffer = NULL;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+ WDFREQUEST WriteRequest = NULL;
+ USBD_PIPE_HANDLE usbdPipeHandle = NULL;
+ PUSB_WRITE_REQ_CONTEXT writeContext = NULL;
+ BOOLEAN SentToDevice = FALSE;
+ WDFMEMORY BufferMemoryObject = NULL;
+ WDFREQUEST WriteRequestZLP = NULL;
+ PUSB_WRITE_REQ_CONTEXT writeContextZLP = NULL;
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ if (!ExAcquireRundownProtection(&usbDeviceContext->BulkPipeResetRundown))
+ {
+ return STATUS_NDIS_ADAPTER_NOT_READY;
+ }
+
+ //
+ // make sure the length is not too big
+ //
+ TempMdl = Mdl;
+
+ while (TempMdl != NULL)
+ {
+ TotalTransferLength += MmGetMdlByteCount(TempMdl);
+
+ TempMdl = TempMdl->Next;
+ }
+
+ if (TotalTransferLength > BusObject->NtbParam.dwNtbOutMaxSize)
+ {
+ //
+ // too big
+ //
+ Status = STATUS_UNSUCCESSFUL;
+
+ goto Cleanup;
+ }
+
+ if ((TotalTransferLength < BusObject->NtbParam.dwNtbOutMaxSize) && (TotalTransferLength % usbDeviceContext->BulkOutputPipeMaxPacket == 0))
+ {
+ //
+ // The transfer length is less than the max out transfer size, and transfer length is a multiple of MaxPacket size.
+ // Need to send a ZLP to the device stack to terminated the transfer.
+
+ Status = GetWriteRequests(BusObject->WdfUsbDevice, &WriteRequestZLP);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ writeContextZLP = GetWriteRequestContext(WriteRequestZLP);
+
+ writeContextZLP->BusObject = BusObject;
+ writeContextZLP->Callback = NULL;
+ }
+
+ Status = GetWriteRequests(BusObject->WdfUsbDevice, &WriteRequest);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ writeContext = GetWriteRequestContext(WriteRequest);
+
+ if (usbDeviceContext->LookasideList == NULL)
+ {
+
+ //
+ // allocate the URB, request is the parent
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
+ objectAttribs.ParentObject = WriteRequest;
+
+ Status = WdfUsbTargetDeviceCreateUrb(BusObject->WdfUsbDevice, &objectAttribs, &urbMemory, &urbBuffer);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ //
+ // get the USBD pipe handle, to build the URB
+ //
+ usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(usbDeviceContext->BulkOutputPipe);
+
+ //
+ // NOTE : call UsbBuildInterruptOrBulkTransferRequest otherwise
+ // WdfUsbTargetPipeFormatRequestForUrb will assert
+ // with *** Assertion failed: Urb->UrbHeader.Length >= sizeof(_URB_HEADER)
+ //
+ UsbBuildInterruptOrBulkTransferRequest(
+ urbBuffer,
+ sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
+ usbdPipeHandle,
+ NULL,
+ Mdl,
+ (ULONG)TotalTransferLength,
+ USBD_TRANSFER_DIRECTION_OUT | USBD_SHORT_TRANSFER_OK,
+ NULL);
+
+ //
+ // By calling WdfUsbTargetPipeFormatRequestForUrb the frameworks allocate a lot of resources
+ // like the underlying IRP for the request and hence it is better to do it at initilization
+ // to prevent an avoidable failure later.
+ //
+ Status = WdfUsbTargetPipeFormatRequestForUrb(usbDeviceContext->BulkOutputPipe, WriteRequest, urbMemory, NULL);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ writeContext->UrbMemory = urbMemory;
+ writeContext->Urb = (PURB)urbBuffer;
+ }
+ else
+ {
+ //
+ // usb stack does not support chained mdl's, double buffer the transfer
+ //
+ PUCHAR DestBuffer = NULL;
+ PUCHAR SourceAddress = NULL;
+ size_t BufferSize = 0;
+ ULONG SourceLength = 0;
+ WDFMEMORY_OFFSET MemoryOffset;
+
+ Status = WdfMemoryCreateFromLookaside(usbDeviceContext->LookasideList, &BufferMemoryObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ DestBuffer = (PUCHAR)WdfMemoryGetBuffer(BufferMemoryObject, &BufferSize);
+
+ TempMdl = Mdl;
+ TotalTransferLength = 0;
+ while (TempMdl != NULL)
+ {
+ SourceLength = MmGetMdlByteCount(TempMdl);
+
+ SourceAddress = (PUCHAR)MmGetSystemAddressForMdlSafe(TempMdl, NormalPagePriority | MdlMappingNoExecute);
+
+ if (SourceAddress == NULL)
+ {
+
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+
+ goto Cleanup;
+ }
+
+ RtlCopyMemory(DestBuffer, SourceAddress, SourceLength);
+
+ DestBuffer += SourceLength;
+
+ TotalTransferLength += SourceLength;
+
+ ASSERT(TotalTransferLength <= BufferSize);
+
+ TempMdl = TempMdl->Next;
+ }
+
+ MemoryOffset.BufferOffset = 0;
+ MemoryOffset.BufferLength = (ULONG)TotalTransferLength;
+
+ Status = WdfUsbTargetPipeFormatRequestForWrite(usbDeviceContext->BulkOutputPipe, WriteRequest, BufferMemoryObject, &MemoryOffset);
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ writeContext->LookasideBuffer = BufferMemoryObject;
+ BufferMemoryObject = NULL;
+ }
+
+ //
+ // set REQUEST_CONTEXT parameters.
+ //
+
+ writeContext->Mdl = Mdl;
+ writeContext->BusObject = BusObject;
+ writeContext->Callback = Callback;
+ writeContext->RequestHandle = RequestHandle;
+
+ WdfRequestSetCompletionRoutine(WriteRequest, WriteCompletionRoutine, writeContext);
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, 0);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(30));
+
+ SentToDevice = WdfRequestSend(WriteRequest, WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkOutputPipe), &SendOptions);
+
+ Status = STATUS_PENDING;
+
+ if (!SentToDevice)
+ {
+ Status = WdfRequestGetStatus(WriteRequest);
+ }
+ else
+ {
+ WriteRequest = NULL;
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+
+ //
+ // actual data write worked, see if we need to send the zlp
+ //
+
+ if (WriteRequestZLP != NULL)
+ {
+
+ NTSTATUS ZlpStatus;
+
+ Status = WdfUsbTargetPipeFormatRequestForWrite(usbDeviceContext->BulkOutputPipe, WriteRequestZLP, NULL, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ WdfRequestSetCompletionRoutine(WriteRequestZLP, WriteCompletionRoutine, writeContextZLP);
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, 0);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(30));
+
+ SentToDevice = WdfRequestSend(WriteRequestZLP, WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkOutputPipe), &SendOptions);
+
+ ZlpStatus = STATUS_PENDING;
+
+ if (!SentToDevice)
+ {
+
+ ZlpStatus = WdfRequestGetStatus(WriteRequestZLP);
+ }
+ else
+ {
+ WriteRequestZLP = NULL;
+ }
+ }
+ }
+
+Cleanup:
+
+ ExReleaseRundownProtection(&usbDeviceContext->BulkPipeResetRundown);
+
+ if (WriteRequest != NULL)
+ {
+ if (NULL != writeContext)
+ {
+ if (NULL != writeContext->LookasideBuffer)
+ {
+ WdfObjectDelete(writeContext->LookasideBuffer);
+ }
+ if (NULL != writeContext->UrbMemory)
+ {
+ WdfObjectDelete(writeContext->UrbMemory);
+ }
+ }
+
+ FreeWriteRequest(BusObject->WdfUsbDevice, WriteRequest);
+ WriteRequest = NULL;
+ }
+
+ if (WriteRequestZLP != NULL)
+ {
+ FreeWriteRequest(BusObject->WdfUsbDevice, WriteRequestZLP);
+ WriteRequestZLP = NULL;
+ }
+
+ return Status;
+}
+
+VOID BulkInReadComplete(__in WDFUSBPIPE Pipe, __in WDFMEMORY Memory, __in size_t NumBytesTransferred, __in WDFCONTEXT Context)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)Context;
+ PUCHAR Buffer = NULL;
+ PMDL Mdl = NULL;
+ PUCHAR DataBuffer = NULL;
+
+ if (NumBytesTransferred > 0)
+ {
+ //
+ // actaully got some data
+ //
+ Buffer = (PUCHAR)WdfMemoryGetBuffer(Memory, NULL);
+
+ //
+ // the header at the front is where we will put the MDL
+ //
+ Mdl = (PMDL)Buffer;
+
+ //
+ // the actual payload starts after the header/mdl
+ //
+ DataBuffer = Buffer + BusObject->BulkInHeaderSize;
+
+ ASSERT(((ULONG_PTR)DataBuffer & 0x7) == 0);
+
+ //
+ // bytes transfered does not include the header
+ //
+ MmInitializeMdl(Mdl, DataBuffer, NumBytesTransferred);
+
+ MmBuildMdlForNonPagedPool(Mdl);
+
+ ASSERT(BusObject->BulkInHeaderSize >= MmSizeOfMdl(Mdl, NumBytesTransferred));
+
+ WdfObjectReference(Memory);
+
+ (*BusObject->ReceiveDataCallback)(BusObject->ProtocolHandle, Memory, Mdl);
+ }
+
+ return;
+}
+
+BOOLEAN
+BulkInReadError(__in WDFUSBPIPE Pipe, __in NTSTATUS Status, __in USBD_STATUS UsbdStatus)
+
+{
+ return TRUE;
+}
+
+VOID MbbBusReturnReceiveBuffer(__in MBB_BUS_HANDLE BusHandle, __in MBB_RECEIVE_CONTEXT ReceiveContext, __in PMDL Mdl)
+
+{
+ WDFMEMORY Memory = (WDFMEMORY)ReceiveContext;
+
+ WdfObjectDereference(Memory);
+
+ return;
+}
+
+NTSTATUS
+CreateWriteRequest(WDFUSBDEVICE UsbDevice, WDFREQUEST* ReturnedWriteRequest)
+
+{
+
+ WDFREQUEST WriteRequest = NULL;
+ PUSB_WRITE_REQ_CONTEXT writeContext = NULL;
+ WDF_OBJECT_ATTRIBUTES objectAttribs;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ *ReturnedWriteRequest = NULL;
+
+ usbDeviceContext = GetUsbDeviceContext(UsbDevice);
+
+ if (usbDeviceContext->BulkOutputPipe == NULL)
+ {
+ goto Cleanup;
+ }
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttribs, USB_WRITE_REQ_CONTEXT);
+ objectAttribs.ParentObject = UsbDevice;
+
+ //
+ // create the request
+ //
+ Status = WdfRequestCreate(&objectAttribs, WdfUsbTargetPipeGetIoTarget(usbDeviceContext->BulkOutputPipe), &WriteRequest);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ writeContext = GetWriteRequestContext(WriteRequest);
+ RtlZeroMemory(writeContext, sizeof(*writeContext));
+
+ //
+ // Preallocate the request timer to prevent the request from failing while trying to send it.
+ //
+ Status = WdfRequestAllocateTimer(WriteRequest);
+
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ Status = WdfUsbTargetPipeFormatRequestForWrite(usbDeviceContext->BulkOutputPipe, WriteRequest, NULL, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+
+ goto Cleanup;
+ }
+
+ *ReturnedWriteRequest = WriteRequest;
+ WriteRequest = NULL;
+
+Cleanup:
+
+ if (WriteRequest != NULL)
+ {
+ WdfObjectDelete(WriteRequest);
+ WriteRequest = NULL;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+PreAllocateWriteRequests(WDFUSBDEVICE UsbDevice)
+
+{
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ WDFREQUEST WriteRequest = NULL;
+ NTSTATUS Status;
+ ULONG i = 0;
+
+ usbDeviceContext = GetUsbDeviceContext(UsbDevice);
+
+ for (i = 0; i < MAX_PREALLOCATED_WRITE_REQUESTS; i++)
+ {
+ Status = CreateWriteRequest(UsbDevice, &WriteRequest);
+
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+
+ Status = WdfCollectionAdd(usbDeviceContext->WriteRequestCollection, WriteRequest);
+
+ if (!NT_SUCCESS(Status))
+ {
+ WdfObjectDelete(WriteRequest);
+ WriteRequest = NULL;
+ break;
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS
+GetWriteRequests(WDFUSBDEVICE UsbDevice, WDFREQUEST* ReturnedWriteRequest)
+{
+
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ WDF_REQUEST_REUSE_PARAMS ReuseParams;
+ PUSB_WRITE_REQ_CONTEXT writeContext = NULL;
+
+ usbDeviceContext = GetUsbDeviceContext(UsbDevice);
+
+ *ReturnedWriteRequest = NULL;
+
+ if (usbDeviceContext->BulkOutputPipe == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ WdfSpinLockAcquire(usbDeviceContext->WriteCollectionLock);
+
+ *ReturnedWriteRequest = (WDFREQUEST)WdfCollectionGetLastItem(usbDeviceContext->WriteRequestCollection);
+
+ if (*ReturnedWriteRequest == NULL)
+ {
+ //
+ // the collection is empty, try creating a new one
+ //
+ WdfSpinLockRelease(usbDeviceContext->WriteCollectionLock);
+
+ Status = CreateWriteRequest(UsbDevice, ReturnedWriteRequest);
+ }
+ else
+ {
+
+ WdfCollectionRemove(usbDeviceContext->WriteRequestCollection, *ReturnedWriteRequest);
+
+ WdfSpinLockRelease(usbDeviceContext->WriteCollectionLock);
+
+ WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, 0, STATUS_SUCCESS);
+
+ WdfRequestReuse(*ReturnedWriteRequest, &ReuseParams);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ writeContext = GetWriteRequestContext(*ReturnedWriteRequest);
+ RtlZeroMemory(writeContext, sizeof(*writeContext));
+ }
+
+ return Status;
+}
+
+VOID FreeWriteRequest(WDFUSBDEVICE UsbDevice, WDFREQUEST WriteRequest)
+
+{
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG RequestCount = 0;
+
+ usbDeviceContext = GetUsbDeviceContext(UsbDevice);
+
+ WdfSpinLockAcquire(usbDeviceContext->WriteCollectionLock);
+
+ RequestCount = WdfCollectionGetCount(usbDeviceContext->WriteRequestCollection);
+
+ if (RequestCount < MAX_PREALLOCATED_WRITE_REQUESTS * 2)
+ {
+ //
+ // put it back in the collection
+ //
+ Status = WdfCollectionAdd(usbDeviceContext->WriteRequestCollection, WriteRequest);
+
+ if (NT_SUCCESS(Status))
+ {
+ WriteRequest = NULL;
+ }
+ }
+
+ WdfSpinLockRelease(usbDeviceContext->WriteCollectionLock);
+
+ if (WriteRequest != NULL)
+ {
+ WdfObjectDelete(WriteRequest);
+ WriteRequest = NULL;
+ }
+
+ return;
+}
+
+VOID MbbBusResetDataPipes(_In_ MBB_BUS_HANDLE BusHandle)
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ if (!InterlockedCompareExchange(&usbDeviceContext->BulkPipeResetFlag, TRUE, FALSE))
+ {
+ WdfWorkItemEnqueue(usbDeviceContext->BulkPipeResetWorkitem);
+ }
+ else
+ {
+ }
+}
+
+VOID MbbUsbDeviceCyclePort(_In_ PUSB_DEVICE_CONTEXT usbDeviceContext)
+{
+ NTSTATUS Status = WdfUsbTargetDeviceCyclePortSynchronously(usbDeviceContext->BusObject->WdfUsbDevice);
+ if (!NT_SUCCESS(Status))
+ {
+ }
+}
+
+void ResetDataPipeWorkItem(_In_ WDFWORKITEM WorkItem)
+{
+ PUSB_DEVICE_CONTEXT usbDeviceContext = GetUsbDeviceContext(WdfWorkItemGetParentObject(WorkItem));
+
+ ExWaitForRundownProtectionRelease(&usbDeviceContext->BulkPipeResetRundown);
+ ExRundownCompleted(&usbDeviceContext->BulkPipeResetRundown);
+
+ MbbUsbDeviceStopDataPipes(usbDeviceContext);
+
+ MbbUsbDeviceResetBulkPipe(usbDeviceContext, TRUE);
+
+ MbbUsbDeviceCyclePort(usbDeviceContext);
+
+ MbbUsbDeviceStartDataPipes(usbDeviceContext);
+
+ ExReInitializeRundownProtection(&usbDeviceContext->BulkPipeResetRundown);
+
+ InterlockedExchange(&usbDeviceContext->BulkPipeResetFlag, FALSE);
+}
diff --git a/network/wwan/cxwmbclass/device.cpp b/network/wwan/cxwmbclass/device.cpp
new file mode 100644
index 00000000..0aadfc35
--- /dev/null
+++ b/network/wwan/cxwmbclass/device.cpp
@@ -0,0 +1,381 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+#include "device.h"
+#include "rxqueue.h"
+
+const ULONG MBB_DEFAULT_IDLE_TIMEOUT_HINT_MS = 2u * 1000u; // 2 seconds
+
+_Use_decl_annotations_ VOID EvtMbbDeviceSendMbimFragment(WDFDEVICE Device, MBBREQUEST Fragment)
+{
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+
+ size_t bufferSize = 0;
+ PVOID buffer = MbbRequestGetBuffer(Fragment, &bufferSize);
+
+ auto completionRoutine = [](MBB_PROTOCOL_HANDLE, MBB_REQUEST_HANDLE RequestHandle, NTSTATUS NtStatus) {
+ MbbRequestComplete((MBBREQUEST)RequestHandle, NtStatus);
+ };
+
+ NTSTATUS sendStatus = MbbBusSendMessageFragment(
+ deviceContext->BusHandle, Fragment, buffer, (ULONG)bufferSize, (LPGUID)MbbRequestGetCorrelationId(Fragment), completionRoutine);
+
+ // Accoding to the documentation of MbbBusSendMessageFragment the completion routine
+ // will be called only when ntStatus is STATUS_PENDING, so we need to call it ourselves
+ // for the other cases
+ if (sendStatus != STATUS_PENDING)
+ {
+ completionRoutine(deviceContext, Fragment, sendStatus);
+ }
+}
+
+VOID MbbNdisResponseFragmentAvailable(__in MBB_PROTOCOL_HANDLE ProtocolHandle)
+{
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = (PWMBCLASS_DEVICE_CONTEXT)ProtocolHandle;
+ MbbDeviceResponseAvailable(deviceContext->WdfDevice);
+}
+
+_Use_decl_annotations_ VOID EvtMbbDeviceReceiveMbimFragment(WDFDEVICE Device, MBBREQUEST Fragment)
+{
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+
+ size_t bufferSize = 0;
+ PVOID buffer = MbbRequestGetBuffer(Fragment, &bufferSize);
+
+ auto completionRoutine = [](MBB_PROTOCOL_HANDLE, MBB_REQUEST_HANDLE RequestHandle, NTSTATUS Status, ULONG_PTR ReceivedLength) {
+ MbbRequestCompleteWithInformation((MBBREQUEST)RequestHandle, Status, ReceivedLength);
+ };
+
+ // Accoding to the documentation of MbbBusReceiveMessageFragment the completion routine
+ // will be called only when ntStatus is STATUS_PENDING, so we need to call it ourselves
+ // for the other cases
+ NTSTATUS receiveStatus = MbbBusReceiveMessageFragment(
+ deviceContext->BusHandle, Fragment, buffer, (ULONG)bufferSize, (LPGUID)MbbRequestGetCorrelationId(Fragment), completionRoutine);
+
+ if (receiveStatus != STATUS_PENDING)
+ {
+ completionRoutine(deviceContext, Fragment, receiveStatus, 0);
+ }
+}
+
+static NTSTATUS SetupAdapterSpecificPowerSettings(_In_ PWMBCLASS_DEVICE_CONTEXT DeviceContext)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (DeviceContext->BusParams.RemoteWakeCapable)
+ {
+ //
+ // Configure USB selective suspend with default timeout
+ //
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleUsbSelectiveSuspend);
+
+ idleSettings.IdleTimeout = MBB_DEFAULT_IDLE_TIMEOUT_HINT_MS;
+ idleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint;
+
+ status = WdfDeviceAssignS0IdleSettings(DeviceContext->WdfDevice, &idleSettings);
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+ }
+Exit:
+ return status;
+}
+
+NTSTATUS
+MbbInitializeHardware(_In_ PWMBCLASS_DEVICE_CONTEXT DeviceContext)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ WDF_OBJECT_ATTRIBUTES attributes;
+ UNICODE_STRING manufacturer;
+ UNICODE_STRING model;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = DeviceContext->WdfDevice;
+ status = WdfLookasideListCreate(
+ &attributes,
+ sizeof(MBB_NDIS_RECEIVE_CONTEXT),
+ NonPagedPoolNx,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ MbbPoolTagMdlReceive,
+ &DeviceContext->ReceiveLookasideList);
+ if (!NT_SUCCESS(status))
+ {
+ goto Cleanup;
+ }
+
+ for (int i = 0; i < MBB_MAX_NUMBER_OF_SESSIONS; i++)
+ {
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = DeviceContext->WdfDevice;
+
+ status = WdfSpinLockCreate(&attributes, &DeviceContext->Sessions[i].WdfRecvSpinLock);
+ if (!NT_SUCCESS(status))
+ {
+ goto Cleanup;
+ }
+ }
+
+ status = MbbBusInitializeByWdf(
+ DeviceContext->WdfDevice,
+ MbbNdisResponseFragmentAvailable,
+ MbbNdisReceiveCallback,
+ nullptr,
+ nullptr,
+ DeviceContext,
+ &DeviceContext->BusHandle,
+ nullptr);
+
+ if (status != STATUS_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ //
+ // Initialize the OID/CID handlers before the device is OPENED.
+ // Once the device is opened and the interrupt pipe is connected.
+ // This driver will start receiving unsolicited interrupt message
+ // from the device.
+ //
+ status = MbbBusQueryBusParameters(DeviceContext->BusHandle, &DeviceContext->BusParams);
+
+ if (status != STATUS_SUCCESS)
+ {
+ goto Cleanup;
+ }
+
+ WDFMEMORY sharedPaddingMemory;
+ ULONG sharedPaddingLength = max(DeviceContext->BusParams.NdpOutAlignment, DeviceContext->BusParams.NdpOutDivisor);
+ status = CreateNonPagedWdfMemory(
+ sharedPaddingLength, &sharedPaddingMemory, (PVOID*)&DeviceContext->sharedPaddingBuffer, DeviceContext->WdfDevice, MbbPoolTagNtbSend);
+ if (!NT_SUCCESS(status))
+ {
+ goto Cleanup;
+ }
+
+ RtlInitUnicodeString(&manufacturer, DeviceContext->BusParams.Manufacturer);
+ RtlInitUnicodeString(&model, DeviceContext->BusParams.Model);
+ MBB_DEVICE_MBIM_PARAMETERS mbimParams;
+
+ // 2.0 by default
+ MBB_MBIM_EXTENDED_VERSION mbimExVer = MbbMbimExtendedVersion2Dot0;
+ switch(DeviceContext->BusParams.MbimExtendedVersion)
+ {
+ case 0x0100:
+ mbimExVer = MbbMbimExtendedVersion1Dot0;
+ break;
+ case 0x0200:
+ mbimExVer = MbbMbimExtendedVersion2Dot0;
+ break;
+ case 0x0300:
+ mbimExVer = MbbMbimExtendedVersion3Dot0;
+ break;
+ case 0x0400:
+ mbimExVer = MbbMbimExtendedVersion4Dot0;
+ break;
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ MBB_DEVICE_MBIM_PARAMETERS_INIT(
+ &mbimParams,
+ DeviceContext->BusParams.IsErrataDevice ? MbbMbimVersion1Dot0Errata : MbbMbimVersion1Dot0,
+ DeviceContext->BusParams.FragmentSize,
+ mbimExVer);
+
+ MbbDeviceSetMbimParameters(DeviceContext->WdfDevice, &mbimParams);
+
+ MBB_DEVICE_WAKE_CAPABILITIES mbbWakeCapabilities;
+ MBB_DEVICE_WAKE_CAPABILITIES_INIT(&mbbWakeCapabilities);
+
+ mbbWakeCapabilities.PacketState = TRUE;
+ mbbWakeCapabilities.RegisterState = TRUE;
+ mbbWakeCapabilities.SmsReceive = TRUE;
+ mbbWakeCapabilities.UiccChange = TRUE;
+ mbbWakeCapabilities.UssdReceive = TRUE;
+
+ MbbDeviceSetWakeCapabilities(DeviceContext->WdfDevice, &mbbWakeCapabilities);
+
+ status = SetupAdapterSpecificPowerSettings(DeviceContext);
+ if (NT_ERROR(status))
+ {
+ goto Cleanup;
+ }
+
+Cleanup:
+
+ if (status != STATUS_SUCCESS)
+ {
+ if (DeviceContext != NULL)
+ {
+ if (DeviceContext->BusHandle != NULL)
+ {
+ MbbBusStop(DeviceContext->BusHandle);
+ MbbBusCleanup(DeviceContext->BusHandle);
+ DeviceContext->BusHandle = NULL;
+ }
+ }
+
+ }
+
+ return status;
+}
+
+void MbbReleaseHardware(_In_ PWMBCLASS_DEVICE_CONTEXT DeviceContext)
+{
+
+ if (DeviceContext->BusHandle != NULL)
+ {
+ MbbBusCleanup(DeviceContext->BusHandle);
+ DeviceContext->BusHandle = NULL;
+ }
+
+ return;
+}
+
+NTSTATUS
+EvtDevicePrepareHardware(_In_ WDFDEVICE device, _In_ WDFCMRESLIST resourcesRaw, _In_ WDFCMRESLIST resourcesTranslated)
+{
+ UNREFERENCED_PARAMETER(resourcesRaw);
+ UNREFERENCED_PARAMETER(resourcesTranslated);
+
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(device);
+
+ NTSTATUS status = MbbInitializeHardware(deviceContext);
+
+ return status;
+}
+
+NTSTATUS
+EvtDeviceReleaseHardware(_In_ WDFDEVICE device, _In_ WDFCMRESLIST resourcesTranslated)
+{
+ UNREFERENCED_PARAMETER(resourcesTranslated);
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(device);
+
+ MbbReleaseHardware(deviceContext);
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_ void EvtDeviceSurpriseRemoval(WDFDEVICE device)
+{
+ UNREFERENCED_PARAMETER(device);
+}
+
+NTSTATUS MbbInitAdapterContext(_In_ WDFDEVICE Device, _In_ NETADAPTER NetAdapter)
+{
+ WDF_OBJECT_ATTRIBUTES adapterAttributes;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = WmbClassGetNetAdapterContext(NetAdapter);
+
+ ULONG ntbSize;
+ ntbSize = FIELD_OFFSET(MBB_NTB_BUILD_CONTEXT, NdpDatagramEntries);
+ ntbSize += (deviceContext->BusParams.MaxOutDatagrams * sizeof(MBB_NDP_HEADER_ENTRY));
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&adapterAttributes);
+ adapterAttributes.ParentObject = NetAdapter;
+
+ NTSTATUS ntStatus = WdfLookasideListCreate(
+ &adapterAttributes, ntbSize, NonPagedPoolNx, WDF_NO_OBJECT_ATTRIBUTES, MbbPoolTagNtbSend, &netAdapterContext->NtbLookasideList);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&adapterAttributes);
+ adapterAttributes.ParentObject = NetAdapter;
+ ntStatus = WdfLookasideListCreate(
+ &adapterAttributes,
+ sizeof(MBB_RECEIVE_NDP_CONTEXT),
+ NonPagedPoolNx,
+ WDF_NO_OBJECT_ATTRIBUTES,
+ MbbPoolTagMdlReceive,
+ &netAdapterContext->ReceiveNdpLookasideList);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+ netAdapterContext->SessionId = MbbAdapterGetSessionId(NetAdapter);
+ WdfSpinLockAcquire(deviceContext->Sessions[netAdapterContext->SessionId].WdfRecvSpinLock);
+ deviceContext->Sessions[netAdapterContext->SessionId].NetAdapterContext = netAdapterContext;
+ // Allow to receive data from this point since connection may happen before RxQueueCreate, if it happens, we allow to cache the recieved NDP
+ netAdapterContext->AllowRxTraffic = TRUE;
+ InitializeListHead(&netAdapterContext->ReceiveNdpList);
+ netAdapterContext->WmbDeviceContext = deviceContext;
+ netAdapterContext->NetAdapter = NetAdapter;
+ WdfSpinLockRelease(deviceContext->Sessions[netAdapterContext->SessionId].WdfRecvSpinLock);
+ return ntStatus;
+}
+
+_Use_decl_annotations_ NTSTATUS EvtMbbDeviceCreateAdapter(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, WMBCLASS_NETADAPTER_CONTEXT);
+ adapterAttributes.EvtCleanupCallback = EvtAdapterCleanup;
+
+ NETADAPTER netAdapter;
+ NTSTATUS ntStatus = NetAdapterCreate(AdapterInit, &adapterAttributes, &netAdapter);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
+ ntStatus = MbbAdapterInitialize(netAdapter);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
+ ntStatus = MbbInitAdapterContext(Device, netAdapter);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
+ ntStatus = WmbClassAdapterStart(netAdapter);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
+ return ntStatus;
+}
+
+_Use_decl_annotations_ VOID EvtAdapterCleanup(_In_ WDFOBJECT NetAdapter)
+{
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = WmbClassGetNetAdapterContext(NetAdapter);
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = netAdapterContext->WmbDeviceContext;
+ if (deviceContext == NULL || deviceContext->Sessions[netAdapterContext->SessionId].NetAdapterContext == NULL)
+ {
+ return;
+ }
+
+ // Cancel these Ndps which are cached before RxQueueCreate but not cleaned in case RxQueueCreate failed.
+ // NetAdapter should be destoryed immediately if RxQueueCreate failed, or these cached Ndps will stay in memory until release device or delete additional PDP
+ MbbRecvCancelNdps(deviceContext, netAdapterContext->SessionId);
+
+ WdfSpinLockAcquire(deviceContext->Sessions[netAdapterContext->SessionId].WdfRecvSpinLock);
+ deviceContext->Sessions[netAdapterContext->SessionId].NetAdapterContext = NULL;
+ WdfSpinLockRelease(deviceContext->Sessions[netAdapterContext->SessionId].WdfRecvSpinLock);
+
+}
+
+_Use_decl_annotations_ VOID EvtMbbDeviceReset(WDFDEVICE WdfDevice)
+{
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(WdfDevice);
+ MbbBusResetDataPipes(deviceContext->BusHandle);
+}
diff --git a/network/wwan/cxwmbclass/driver.cpp b/network/wwan/cxwmbclass/driver.cpp
new file mode 100644
index 00000000..e1c8bc69
--- /dev/null
+++ b/network/wwan/cxwmbclass/driver.cpp
@@ -0,0 +1,120 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+#include "device.h"
+#include "power.h"
+
+MINIPORT_DRIVER_CONTEXT GlobalControl = {0};
+
+EXTERN_C __declspec(code_seg("INIT")) DRIVER_INITIALIZE DriverEntry;
+EVT_WDF_DRIVER_UNLOAD EvtDriverUnload;
+EVT_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd;
+
+#define MBB_DRIVER_DEFAULT_POOL_TAG 'DBMW'
+
+__declspec(code_seg("INIT")) NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT driverObject, _In_ PUNICODE_STRING registryPath)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WDF_DRIVER_CONFIG driverConfig;
+ WDF_DRIVER_CONFIG_INIT(&driverConfig, EvtDriverDeviceAdd);
+ driverConfig.DriverPoolTag = MBB_DRIVER_DEFAULT_POOL_TAG;
+
+ driverConfig.EvtDriverUnload = EvtDriverUnload;
+
+ WDFDRIVER driver;
+ status = WdfDriverCreate(driverObject, registryPath, WDF_NO_OBJECT_ATTRIBUTES, &driverConfig, &driver);
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+EvtDriverDeviceAdd(_In_ WDFDRIVER driver, _Inout_ PWDFDEVICE_INIT deviceInit)
+{
+ UNREFERENCED_PARAMETER((driver));
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = NetDeviceInitConfig(deviceInit);
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+
+ status = MbbDeviceInitConfig(deviceInit);
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+
+ // Register with the NetAdapter framework that we want to do the Device Reset
+ //NET_DEVICE_RESET_CONFIG resetConfig;
+ //NET_DEVICE_RESET_CONFIG_INIT(&resetConfig, EvtMbbDeviceReset);
+ //NetDeviceInitSetResetConfig(deviceInit, &resetConfig);
+
+ NET_DEVICE_POWER_POLICY_EVENT_CALLBACKS netPowerPolicyCallbacks;
+ NET_DEVICE_POWER_POLICY_EVENT_CALLBACKS_INIT(&netPowerPolicyCallbacks);
+ netPowerPolicyCallbacks.EvtDevicePreviewBitmapPattern = EvtDevicePreviewBitmapPattern;
+
+ NetDeviceInitSetPowerPolicyEventCallbacks(deviceInit, &netPowerPolicyCallbacks);
+
+ WDF_OBJECT_ATTRIBUTES deviceAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, WMBCLASS_DEVICE_CONTEXT);
+
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
+ pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
+ pnpPowerCallbacks.EvtDeviceReleaseHardware = EvtDeviceReleaseHardware;
+ pnpPowerCallbacks.EvtDeviceSurpriseRemoval = EvtDeviceSurpriseRemoval;
+ pnpPowerCallbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;
+ pnpPowerCallbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;
+ WdfDeviceInitSetPnpPowerEventCallbacks(deviceInit, &pnpPowerCallbacks);
+
+ WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks;
+ WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks);
+ powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = EvtDeviceArmWakeFromS0;
+ powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = EvtDeviceDisarmWakeFromS0;
+ WdfDeviceInitSetPowerPolicyEventCallbacks(deviceInit, &powerPolicyCallbacks);
+
+ WDFDEVICE wdfDevice;
+ status = WdfDeviceCreate(&deviceInit, &deviceAttributes, &wdfDevice);
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+
+ // Set the device to be not ejectable
+ WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities;
+ WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities);
+ pnpCapabilities.SurpriseRemovalOK = WdfTrue;
+ WdfDeviceSetPnpCapabilities(wdfDevice, &pnpCapabilities);
+
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(wdfDevice);
+ deviceContext->WdfDevice = wdfDevice;
+
+ MBB_DEVICE_CONFIG mbbDeviceConfig;
+ MBB_DEVICE_CONFIG_INIT(
+ &mbbDeviceConfig, EvtMbbDeviceSendMbimFragment, EvtMbbDeviceReceiveMbimFragment, EvtMbbDeviceSendDeviceServiceSessionData, EvtMbbDeviceCreateAdapter);
+
+ status = MbbDeviceInitialize(wdfDevice, &mbbDeviceConfig);
+ if (!NT_SUCCESS(status))
+ {
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+VOID EvtDriverUnload(_In_ WDFDRIVER driver)
+{
+ UNREFERENCED_PARAMETER(driver);
+}
diff --git a/network/wwan/cxwmbclass/inc/BusInterface.h b/network/wwan/cxwmbclass/inc/BusInterface.h
new file mode 100644
index 00000000..d72c663a
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/BusInterface.h
@@ -0,0 +1,573 @@
+/***************************************************************************
+
+Copyright (c) 2010 Microsoft Corporation
+
+Module Name:
+
+ BusInterface.h
+
+Abstract:
+
+ This module defines the interface between the upper NDIS layer and lower
+ bus layer of the MBB (Mobile BroadBand) Class driver.
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+ The upper ndis layer may only communicate with the lower bus layer through
+ these interfaces.
+
+Revision History:
+
+ 2/7/2010 : created
+
+Authors:
+
+ TriRoy
+
+****************************************************************************/
+
+#ifndef _BusInterface_H_
+#define _BusInterface_H_
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// INCLUDES
+//
+////////////////////////////////////////////////////////////////////////////////
+#if 0
+#include "MbbDebug.h"
+#endif
+////////////////////////////////////////////////////////////////////////////////
+//
+// DEFINES
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#define MAX_PARAMETER_STRING (128)
+
+#define ALT_DATA_SETTING_0 (0)
+#define ALT_DATA_SETTING_1 (1)
+
+#define MAX_PENDING_SENDS (3)
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// TYPEDEFS
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef PVOID MBB_BUS_HANDLE;
+typedef PVOID MBB_PROTOCOL_HANDLE;
+typedef PVOID MBB_REQUEST_HANDLE;
+typedef PVOID MBB_RECEIVE_CONTEXT;
+
+typedef struct _MBB_BUS_PARAMETERS
+{
+ ULONG FragmentSize;
+
+ ULONG MaxSegmentSize;
+
+ BOOLEAN ChainedMdlsSupported;
+ BOOLEAN Ntb32BitSupported;
+ BOOLEAN CurrentMode32Bit;
+ BOOLEAN SelectiveSuspendSupported;
+
+ ULONG MaxOutNtb;
+ USHORT MaxOutDatagrams;
+ USHORT NdpOutDivisor;
+ USHORT NdpOutRemainder;
+ USHORT NdpOutAlignment;
+
+ BYTE PowerFiltersSupported;
+ BYTE MaxPowerFilterSize;
+
+ WCHAR Manufacturer[MAX_PARAMETER_STRING];
+ WCHAR Model[MAX_PARAMETER_STRING];
+
+ BYTE MaxOutstandingCommandMessages;
+ USHORT MTU;
+ BOOLEAN IsErrataDevice;
+ USHORT MbimVersion;
+ BOOLEAN RemoteWakeCapable;
+ USHORT MbimExtendedVersion;
+
+} MBB_BUS_PARAMETERS, *PMBB_BUS_PARAMETERS;
+
+typedef struct _MBB_CONNECTION_STATE
+{
+
+ BOOLEAN ConnectionUp;
+ ULONGLONG UpStreamBitRate;
+ ULONGLONG DownStreamBitRate;
+
+} MBB_CONNECTION_STATE, *PMBB_CONNECTION_STATE;
+
+typedef __callback VOID (*MBB_BUS_SEND_COMPLETION_CALLBACK)(__in MBB_PROTOCOL_HANDLE ProtocolHandle, __in MBB_REQUEST_HANDLE RequestHandle, __in NTSTATUS Status);
+
+typedef __callback VOID (*MBB_BUS_RECEIVE_COMPLETION_CALLBACK)(
+ __in MBB_PROTOCOL_HANDLE ProtocolHandle, __in MBB_REQUEST_HANDLE RequestHandle, __in NTSTATUS Status, __in ULONG_PTR ReceivedLength);
+
+typedef __callback VOID (*MBB_BUS_RESPONSE_AVAILABLE_CALLBACK)(__in MBB_PROTOCOL_HANDLE ProtocolHandle);
+
+typedef __callback VOID (*MBB_BUS_SEND_DATA_COMPLETION_CALLBACK)(
+ __in MBB_PROTOCOL_HANDLE ProtocolHandle, __in MBB_REQUEST_HANDLE RequestHandle, __in NTSTATUS Status, __in PMDL Mdl);
+
+typedef __callback VOID (*MBB_BUS_DATA_RECEIVE_CALLBACK)(__in MBB_PROTOCOL_HANDLE ProtocolHandle, __in MBB_RECEIVE_CONTEXT ReceiveContext, __in PMDL Mdl);
+
+typedef __callback VOID (*MBB_BUS_SS_IDLE_CONFIRM_CALLBACK)(__in MBB_PROTOCOL_HANDLE ProtocolHandle, __in DEVICE_POWER_STATE PowerState);
+
+typedef __callback VOID (*MBB_BUS_SS_IDLE_NOTIFICATION_COMPLETE_CALLBACK)(__in MBB_PROTOCOL_HANDLE ProtocolHandle, __in NTSTATUS Status);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// INTERFACE
+//
+////////////////////////////////////////////////////////////////////////////////
+EXTERN_C
+NTSTATUS
+MbbBusInitialize(
+ _In_ PDEVICE_OBJECT Pdo,
+ _In_ PDEVICE_OBJECT Fdo,
+ _In_ PDEVICE_OBJECT NextDeviceObject,
+ _In_ MBB_BUS_RESPONSE_AVAILABLE_CALLBACK ResponseAvailableCallback,
+ _In_ MBB_BUS_DATA_RECEIVE_CALLBACK ReceiveDataCallback,
+ _In_ MBB_BUS_SS_IDLE_CONFIRM_CALLBACK IdleConfirmCallback,
+ _In_ MBB_BUS_SS_IDLE_NOTIFICATION_COMPLETE_CALLBACK IdleNotificationComplete,
+ _In_ MBB_PROTOCOL_HANDLE ProtocolHandle,
+ _Outptr_ MBB_BUS_HANDLE* BusHandle);
+/*
+ Description
+ This routine initializes the bus layer i.e. the lower layer in the
+ MBB Class Driver. All bus layer implementations need to have this
+ function. The Protocol Layer i.e. the upper layer in the MBB Class
+ Driver will call this function before calling any other function in
+ the Bus Layer.
+
+ Parameters
+ _In_ PDEVICE_OBJECT DeviceObject,
+ The WDM device representation of the device.
+
+ _In_ MBB_BUS_NOTIFICATION_CALLBACK NotificationCallback,
+ The routine the bus layer calls when it needs to notify
+ the upper protocol layer.
+
+ _In_ MBB_PROTOCOL_HANDLE ProtocolHandle,
+ The handle the bus layer passes back to the protocol layer
+ when it calls any callback. The protocol layer uses this handle
+ to identify the instance of the MBB device the callback is meant for.
+
+ _Outptr_ MBB_BUS_HANDLE BusHandle
+ The handle returned by the bus layer on successful initialization.
+ The protocol layer passes this handle to the bus layer on subsequent
+ calls to the bus layer. The bus layer uses this handle to indetify
+ the instance of the MBB device.
+
+ Return Value
+ NTSTATUS_SUCCESS
+ Initialization was successful.
+
+ Other failure code
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusInitializeByWdf(
+ _In_ WDFDEVICE WdfDevice,
+ _In_ MBB_BUS_RESPONSE_AVAILABLE_CALLBACK ResponseAvailableCallback,
+ _In_ MBB_BUS_DATA_RECEIVE_CALLBACK ReceiveDataCallback,
+ _In_ MBB_BUS_SS_IDLE_CONFIRM_CALLBACK IdleConfirmCallback,
+ _In_ MBB_BUS_SS_IDLE_NOTIFICATION_COMPLETE_CALLBACK IdleNotificationComplete,
+ _In_ MBB_PROTOCOL_HANDLE ProtocolHandle,
+ _Outptr_ MBB_BUS_HANDLE* BusHandle,
+ _Inout_opt_ MBB_BUS_HANDLE preAllocatedBusObject);
+
+EXTERN_C
+VOID MbbBusCleanup(__in MBB_BUS_HANDLE BusHandle);
+/*
+ Description
+ This will be last call from Protocol layer in to Bus Layer
+ to cleanup the bus layer. The bus layer should free all
+ resources. The BusHandle will not be used for subsequent calls.
+ If there are pending requests the Bus Layer should not return
+ from this call unless all operations are complete.
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle
+ BusHandle identifies the instance of the bus layer.
+
+ Return Value
+ None
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusQueryBusParameters(__in MBB_BUS_HANDLE BusHandle, __out PMBB_BUS_PARAMETERS BusParameters);
+/*
+ Description
+ This routine queries the bus specific parameters like transfer size,
+ DMA support etc... This is called when the bus is initialized to format
+ requests correctly before sending to the bus.
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ __out PMBB_BUS_PARAMETERS BusParameters
+ The buffer where the bus layer returns the information to the caller.
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+EXTERN_C
+NTSTATUS
+MbbBusSendMessageFragment(
+ __in MBB_BUS_HANDLE BusHandle,
+ __in MBB_REQUEST_HANDLE RequestHandle,
+ __in PVOID MessageFragment,
+ __in ULONG FragmentLength,
+ __in LPGUID ActivityId,
+ __in MBB_BUS_SEND_COMPLETION_CALLBACK SendCompletionCallback);
+/*
+ Description
+ The protocol layer call this routine to request the bus layer to
+ send a message fragment. Fragmentation / Reassembly is handled by
+ the protocol layer and it will only handle fragments that are within
+ the maximum transfer size of the bus.
+
+ This routine is asynchronous and returns immediately after queueing
+ the transfer. The caller is notified of the completion through the
+ callback.
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ __in MBB_REQUEST_HANDLE RequestHandle,
+ Identifies the request.
+
+ __in PVOID MessageFragment,
+ The data payload that needs to be sent.
+
+ __in ULONG FragmentLength,
+ Length of the data payload. This will not be greater than the
+ maximum transfer size supported by the bus.
+
+ __in MBB_BUS_SEND_COMPLETION_CALLBACK SendCompletionCallback
+ The completion callback routine that will be called by the bus
+ when the transfer is complete.
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ The transfer has completed successfully. SendCompletionCallback will NOT be called.
+
+ NTSTATUS_PENDING
+ The transfer was queued. SendCompletionCallback will be called on completion.
+
+ Other failure code
+ The transfer could not be queued. SendCompletionCallback will NOT be called.
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusReceiveMessageFragment(
+ _In_ MBB_BUS_HANDLE BusHandle,
+ _In_ MBB_REQUEST_HANDLE RequestHandle,
+ _In_ __drv_aliasesMem PVOID MessageFragment,
+ _In_ ULONG FragmentLength,
+ _In_ LPGUID ActivityId,
+ _In_ MBB_BUS_RECEIVE_COMPLETION_CALLBACK ReceiveCompletionCallback);
+/*
+ Description
+
+ Parameters
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Initialization was successful.
+
+ Other failure code
+*/
+/*
+ Description
+ The protocol layer call this routine to request the bus layer to
+ receive data from the device. Reassembly is handled by the protocol layer.
+
+ This routine is asynchronous and returns immediately after queueing
+ the transfer. The caller is notified of the completion through the
+ callback.
+
+ Parameters
+ _In_ MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ _In_ MBB_REQUEST_HANDLE RequestHandle,
+ Identifies the request.
+
+ _InOut_ PVOID MessageFragment,
+ The data buffer that would be filled with the received data.
+
+ _In_ ULONG FragmentLength,
+ Length of the data requested from the device. This will not be
+ greater than the maximum transfer size supported by the bus.
+
+ _In_ MBB_BUS_RECEIVE_COMPLETION_CALLBACK ReceiveCompletionCallback
+ The completion callback routine that will be called by the bus
+ when the transfer is complete.
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ The transfer has completed successfully. ReceiveCompletionCallback will NOT be called.
+
+ NTSTATUS_PENDING
+ The transfer was queued. ReceiveCompletionCallback will be called on completion.
+
+ Other failure code
+ The transfer could not be queued. ReceiveCompletionCallback will NOT be called.
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusSetPacketFilter(__in MBB_BUS_HANDLE BusHandle, __in ULONG PacketFilter);
+/*
+ Description
+ Sets the packet filter on the device.
+ For MBB only directed is supported
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ __in ULONG PacketFilter
+ the filter to apply
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusGetStat(__in MBB_BUS_HANDLE BusHandle, __in USHORT StatIndex, __out ULONGLONG* Value);
+/*
+ Description
+ Retrieves a status from the device
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ __in ULONG PacketFilter
+ the filter to apply
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusStart(_In_ MBB_BUS_HANDLE BusHandle);
+
+EXTERN_C
+NTSTATUS
+MbbBusStop(__in MBB_BUS_HANDLE BusHandle);
+
+EXTERN_C
+BOOLEAN
+MbbBusIsStoped(_In_ MBB_BUS_HANDLE BusHandle);
+
+EXTERN_C
+NTSTATUS
+MbbBusOpen(_In_ MBB_BUS_HANDLE BusHandle, _In_ ULONG TransactionId, _In_opt_ PVOID FastIOSendNetBufferListsComplete, _In_opt_ PVOID FastIOIndicateReceiveNetBufferLists);
+/*
+ Description
+
+ Opens the session with the device
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusClose(__in MBB_BUS_HANDLE BusHandle, __in ULONG TransactionId, __in BOOLEAN ForceClose);
+/*
+ Description
+
+ Opens the session with the device
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+
+EXTERN_C
+NTSTATUS
+MbbBusStartDataPipes(__in MBB_BUS_HANDLE BusHandle);
+/*
+ Description
+
+ Selects alt data interface 1 and starts the IoTargets
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+
+EXTERN_C
+VOID MbbBusStopDataPipes(__in MBB_BUS_HANDLE BusHandle);
+/*
+ Description
+
+ Resets the IoTargets canceling all and waiting for io to compelte
+ Selects alt data interface 0 disabling the pipes
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+
+EXTERN_C
+void MbbBusResetDataPipes(_In_ MBB_BUS_HANDLE BusHandle);
+
+EXTERN_C
+NTSTATUS
+MbbBusWriteData(__in MBB_BUS_HANDLE BusHandle, __in MBB_REQUEST_HANDLE RequestHandle, __in PMDL Mdl, __in MBB_BUS_SEND_DATA_COMPLETION_CALLBACK Callback);
+/*
+ Description
+
+ Writes data to device bulk out pipe
+
+ Parameters
+ __in MBB_BUS_HANDLE BusHandle,
+ BusHandle identifies the instance of the bus layer.
+
+ __in MBB_REQUEST_HANDLE RequestHandle,
+ Identifies the request.
+
+ __in PMDL Mdl
+ pointer to an MDL identifying the data to send. The bus layer will own this until the completion callback is called.
+
+ __in MBB_BUS_SEND_DATA_COMPLETION_CALLBACK Callback
+ Callback that will be called when write is complete.
+
+ Return Value
+
+ NTSTATUS_SUCCESS
+ Information was successfully returned in the BusParameters structure.
+
+ NTSTATUS_INVALID_PARAMETER
+ One of the required parameters is missing or bad.
+
+ Other failure code
+*/
+EXTERN_C
+VOID MbbBusReturnReceiveBuffer(__in MBB_BUS_HANDLE BusHandle, __in MBB_RECEIVE_CONTEXT ReceiveContext, __in PMDL Mdl);
+
+EXTERN_C
+NTSTATUS
+MbbBusSelectDataAltSetting(__in MBB_BUS_HANDLE BusHandle, __in UCHAR AltSetting);
+
+EXTERN_C
+NTSTATUS
+MbbBusIdleNotification(__in MBB_BUS_HANDLE BusHandle, __in BOOLEAN ForceIdle);
+
+EXTERN_C
+VOID MbbBusCancelIdleNotification(__in MBB_BUS_HANDLE BusHandle);
+
+EXTERN_C
+NTSTATUS
+MbbBusSetPowerFilterPattern(
+ __in MBB_BUS_HANDLE BusHandle,
+ __in ULONG PatternId,
+ __in_bcount_opt(MaskSize) PCUCHAR Mask,
+ __in ULONG MaskSize,
+ __in_bcount_opt(PatternSize) PCUCHAR Pattern,
+ __in ULONG PatternSize);
+
+EXTERN_C
+NTSTATUS
+MbbBusResetBulkPipe(__in MBB_BUS_HANDLE BusHandle, __in BOOLEAN Out);
+
+EXTERN_C
+VOID MbbBusSetNotificationState(__in MBB_BUS_HANDLE BusHandle, __in BOOLEAN Enabled);
+
+EXTERN_C
+BOOLEAN
+MbbBusIsUde(_In_ MBB_BUS_HANDLE BusHandle);
+
+#endif
diff --git a/network/wwan/cxwmbclass/inc/MbbLibrary.h b/network/wwan/cxwmbclass/inc/MbbLibrary.h
new file mode 100644
index 00000000..03f64d8a
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/MbbLibrary.h
@@ -0,0 +1,175 @@
+/***************************************************************************
+
+Copyright (c) 2010 Microsoft Corporation
+
+Module Name:
+
+ MbbLibrary.h
+
+Abstract:
+
+ This header files contains the interfaces to the pack / unpack and
+ fragment / reassembly functions provided by the Mbb library.
+ The class driver Protocol layer calls the libary to convert payloads
+ to messages as defined in the MBB Class Driver Hardware Interface
+ document before sending it to the Bus Layer.
+
+Environment:
+
+ User and kernel mode only
+
+Notes:
+
+ This library can be used both in user and kernel mode because it does not
+ to make any memory allocations.
+
+Revision History:
+
+ 2/7/2010 : created
+
+Authors:
+
+ TriRoy
+
+****************************************************************************/
+EXTERN_C
+NTSTATUS
+MbbLibForamtBufferAsOpenMessage(__out_bcount_opt(*BufferLength) PVOID MessageBuffer, __inout PULONG BufferLength, __in ULONG MaximumControlTransfer);
+/*
+ Description
+ Formats an input buffer as a MBB Open Message.
+
+ Parameters
+ __out_opt_bcount(*BufferLength) PVOID MessageBuffer
+ The input message buffer. This parameter may be NULL
+ if BufferLength is 0. This parameter should not be NULL
+ when BufferLength is non-zero.
+
+ __inout PULONG BufferLength
+ This provides the length of the memory location described by MessageBuffer.
+ If BufferLength is 0 then the function will return the required buffer length
+ in this parameter with STATUS_BUFFER_OVERFLOW. On success, the amount of
+ buffer space used by the routine is returned to the caller in BufferLength.
+
+ __in ULONG MaximumControlTransfer
+ MaximumControlTransfer field of the Open Message.
+
+ Return Value
+ STATUS_BUFFER_OVERFLOW
+ The buffer passed in is not sufficient for formatting the message.
+
+ STATUS_INVALID_PARAMETER
+ One of the required parameters is missing.
+
+ STATUS_SUCCESS
+ The input buffer was formatted successfully and the amount of buffer
+ used is returned in BufferLength.
+*/
+EXTERN_C
+NTSTATUS
+MbbLibForamtBufferAsCloseMessage(__out_bcount_opt(*BufferLength) PVOID MessageBuffer, __inout PULONG BufferLength);
+/*
+ Description
+ Formats an input buffer as a MBB Close Message.
+
+ Parameters
+ __out_opt_bcount(*BufferLength) PVOID MessageBuffer
+ The input message buffer. This parameter may be NULL
+ if BufferLength is 0. This parameter should not be NULL
+ when BufferLength is non-zero.
+
+ __inout PULONG BufferLength
+ This provides the length of the memory location described by MessageBuffer.
+ If BufferLength is 0 then the function will return the required buffer length
+ in this parameter with STATUS_BUFFER_OVERFLOW. On success, the amount of
+ buffer space used by the routine is returned to the caller in BufferLength.
+
+ Return Value
+ STATUS_BUFFER_OVERFLOW
+ The buffer passed in is not sufficient for formatting the message.
+
+ STATUS_INVALID_PARAMETER
+ One of the required parameters is missing.
+
+ STATUS_SUCCESS
+ The input buffer was formatted successfully and the amount of buffer
+ used is returned in BufferLength.
+*/
+EXTERN_C
+NTSTATUS
+MbbLibFragmentBufferToCommandMessages(
+ __in PMBB_COMMAND Command,
+ __in MBB_COMMAND_TYPE CommandType,
+ __in_bcount_opt(PayloadLength) PCHAR Payload,
+ __in ULONG PayloadLength,
+ __inout_opt PULONG TransactionId,
+ __in ULONG CurrentFragment,
+ __inout PULONG FragmentBufferCount,
+ __inout PULONG FragmentLength,
+ __out_ecount_opt(*FragmentBufferCount) PCHAR* FragmentBuffers);
+/*
+ Description
+ Given the Payload the routine fragments the payload
+ in to the FragmentBuffers.
+
+ Parameters
+ __in MBB_COMMAND Command
+ Command contains the GUID and Cid.
+ The GUID identifying the service for this message.
+ The command identifier for the given service.
+
+ __in MBB_COMMAND_TYPE CommandType
+ Identifies whether the command is a Set or Query.
+
+ __in_bcount(PayloadLength) PCHAR Payload
+ The Payload is a byte array that needs to be fragmented.
+ If Payload length is not 0 Payload should be provided.
+
+ __in ULONG PayloadLength
+ Length of the payload. If there is no Payload for this command
+ Payload is set to 0.
+
+ __inout PULONG TransactionId
+ If non-zero then this is the transaction id used for the fragments.
+ If zero then a new transcation id is generated and returned to the caller.
+
+ __in ULONG CurrentFragment
+ If non-zero then Fragments are constructed starting this Fragment.
+ If zero then Fragments are constructed from the beginning.
+
+ __inout ULONG FragmentBufferCount
+ Number of input fragments i.e. numberof buffers described by
+ FragmentBuffers array. If the caller is querying for the
+ number of fragments required then this should be set to 0.
+ The function will return the number of fragment required
+ with STATUS_BUFFER_OVERFLOW.
+
+ __in ULONG FragmentLength
+ Length of each output fragment buffers. All fragment
+ buffers needs to be of the same size.
+ The length of the last fragment is returned on STATUS_SUCCESS.
+ All but the last fragment are of FragmentLength size.
+ The last fragment can be lesser than the FragmentLength size.
+
+ __out_ecount_opt(*FragmentBufferCount) PCHAR* FragmentBuffers
+ Array of input fragment buffers. If FragmentCount is 0
+ FragmentBuffers can be NULL. If FragmentCount is non 0
+ FragmentBuffers should be provided.
+
+ Return Value
+ STATUS_INVALID_PARAMETER
+ One of the required parameters is missing.
+
+ STATUS_SUCCESS
+ The Payload was fragmented successfully in to
+ FragmentBuffers and the number of fragments used is
+ returned in FragmentCount.
+
+ STATUS_MORE_PROCESSING_REQUIRED
+ The complete Payload is not fragmented yet.
+ This is not a failure code but an indication to the caller that
+ more calls are needed with more fragment buffers.
+*/
+
+ULONG
+MbbLibraryGetNextTransactionId();
diff --git a/network/wwan/cxwmbclass/inc/adapter.h b/network/wwan/cxwmbclass/inc/adapter.h
new file mode 100644
index 00000000..236daad4
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/adapter.h
@@ -0,0 +1,53 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#pragma once
+
+// packet and header sizes
+#define MBB_MAX_PACKET_SIZE (1514)
+
+// maximum link speed for send and recv in bps
+#define MBB_MEDIA_MAX_SPEED 1'000'000'000
+
+// supported filters
+#define WMBCLASS_MAX_WOL_PATTERN (256)
+#define WMBCLASS_MAX_MBIM_WOL_PATTERN (192)
+
+//
+// Context for each NetAdapter instance.
+// Each NetAdapter instance corresponds to an IP interface
+//
+typedef struct _WMBCLASS_NETADAPTER_CONTEXT
+{
+ PWMBCLASS_DEVICE_CONTEXT WmbDeviceContext; // Wdf device context
+ NETADAPTER NetAdapter; // NetAdapter object
+
+ ULONG ConnectionId;
+ ULONG SessionId;
+ MBB_CONNECTION_STATE ConnectionState;
+
+ // RxQuere-related objects
+
+ WDFLOOKASIDE NtbLookasideList;
+ WDFLOOKASIDE ReceiveNdpLookasideList;
+
+ LIST_ENTRY ReceiveNdpList;
+ NETPACKETQUEUE TxQueue; // Tx Queue object
+ NETPACKETQUEUE RxQueue; // Rx Queue object
+ BOOLEAN AllowRxTraffic;
+} WMBCLASS_NETADAPTER_CONTEXT, *PWMBCLASS_NETADAPTER_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WMBCLASS_NETADAPTER_CONTEXT, WmbClassGetNetAdapterContext);
+
+//
+// NetAdapter functions
+//
+
+EVT_NET_ADAPTER_CREATE_TXQUEUE EvtAdapterCreateTxQueue;
+EVT_NET_ADAPTER_CREATE_RXQUEUE EvtAdapterCreateRxQueue;
+
+EVT_WDF_DEVICE_CONTEXT_DESTROY MbbDestroyAdapterContext;
+
+NTSTATUS
+WmbClassAdapterStart(_In_ NETADAPTER netAdapter);
diff --git a/network/wwan/cxwmbclass/inc/align.h b/network/wwan/cxwmbclass/inc/align.h
new file mode 100644
index 00000000..5c8117d3
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/align.h
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1988-1992 Microsoft Corporation
+
+Module Name:
+
+ Align.h
+
+Abstract:
+
+
+Author:
+
+ John Rogers (JohnRo) 15-May-1991
+
+Environment:
+
+ This code assumes that sizeof(DWORD) >= sizeof(PVOID).
+
+Revision History:
+
+ 15-May-1991 JohnRo
+ Created align.h for NT/LAN from OS/2 1.2 HPFS pbmacros.h.
+ 19-Jun-1991 JohnRo
+ Make sure pointer-to-wider-then-byte doesn't get messed up.
+ 10-Jul-1991 JohnRo
+ Added ALIGN_BYTE and ALIGN_CHAR for completeness.
+ 21-Aug-1991 CliffV
+ Fix ROUND_DOWN_* to include ~
+ 03-Dec-1991 JohnRo
+ Worst-case on MIPS is 8-byte alignment.
+ Added COUNT_IS_ALIGNED() and POINTER_IS_ALIGNED() macros.
+ 26-Jun-1992 JohnRo
+ RAID 9933: ALIGN_WORST should be 8 for x86 builds.
+
+--*/
+
+#ifndef _ALIGN_
+#define _ALIGN_
+
+
+// BOOL
+// COUNT_IS_ALIGNED(
+// IN DWORD Count,
+// IN DWORD Pow2 // undefined if this isn't a power of 2.
+// );
+//
+#define COUNT_IS_ALIGNED(Count,Pow2) \
+ ( ( ( (Count) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE )
+
+// BOOL
+// POINTER_IS_ALIGNED(
+// IN PVOID Ptr,
+// IN DWORD Pow2 // undefined if this isn't a power of 2.
+// );
+//
+#define POINTER_IS_ALIGNED(Ptr,Pow2) \
+ ( ( ( ((ULONG_PTR)(Ptr)) & (((Pow2)-1)) ) == 0) ? TRUE : FALSE )
+
+
+// Note .............
+// There is a subtle issue with all these alignment methods
+// The way the alignment is done depends on the lValue assignment of these MACRO
+// For example:
+// UINT64 fileSizeAlligned = ROUND_UP_COUNT(fileSize, pageSize)
+// will do a correct 64 bit aligned rounding up
+// UINT32 pagesInFileCount = ROUND_UP_COUNT(fileSize, pageSize) / pageSize;
+// this will truncate the pageSize to UINT32 when evaluating ~(Pow2-1) below
+// causing the result to truncate the most significant 32 bits in fileSize
+
+
+#define ROUND_DOWN_COUNT(Count,Pow2) \
+ ( (Count) & (~(((LONG)(Pow2))-1)) )
+
+#define ROUND_DOWN_POINTER(Ptr,Pow2) \
+ ( (PVOID) ROUND_DOWN_COUNT( ((ULONG_PTR)(Ptr)), (Pow2) ) )
+
+
+// If Count is not already aligned, then
+// round Count up to an even multiple of "Pow2". "Pow2" must be a power of 2.
+//
+// DWORD
+// ROUND_UP_COUNT(
+// IN DWORD Count,
+// IN DWORD Pow2
+// );
+#define ROUND_UP_COUNT(Count,Pow2) \
+ ( ((Count)+(Pow2)-1) & (~(((LONG)(Pow2))-1)) )
+
+// PVOID
+// ROUND_UP_POINTER(
+// IN PVOID Ptr,
+// IN DWORD Pow2
+// );
+
+// If Ptr is not already aligned, then round it up until it is.
+#define ROUND_UP_POINTER(Ptr,Pow2) \
+ ( (PVOID) ( (((ULONG_PTR)(Ptr))+(Pow2)-1) & (~(((LONG)(Pow2))-1)) ) )
+
+
+// Usage: myPtr = ROUND_UP_POINTER( unalignedPtr, ALIGN_LPVOID )
+
+#define ALIGN_BYTE sizeof(UCHAR)
+#define ALIGN_CHAR sizeof(CHAR)
+#define ALIGN_DESC_CHAR sizeof(DESC_CHAR)
+#define ALIGN_DWORD sizeof(DWORD)
+#define ALIGN_LONG sizeof(LONG)
+#define ALIGN_LPBYTE sizeof(LPBYTE)
+#define ALIGN_LPDWORD sizeof(LPDWORD)
+#define ALIGN_LPSTR sizeof(LPSTR)
+#define ALIGN_LPTSTR sizeof(LPTSTR)
+#define ALIGN_LPVOID sizeof(PVOID)
+#define ALIGN_LPWORD sizeof(LPWORD)
+#define ALIGN_TCHAR sizeof(TCHAR)
+#define ALIGN_WCHAR sizeof(WCHAR)
+#define ALIGN_WORD sizeof(WORD)
+
+//
+// For now, use a hardcoded constant. however, this should be visited again
+// and maybe changed to sizeof(QUAD).
+//
+
+#define ALIGN_QUAD 8
+
+#if defined(_X86_)
+
+#define ALIGN_WORST 8
+
+#elif defined(_AMD64_)
+
+#define ALIGN_WORST 8
+
+#elif defined(_ARM_)
+
+#define ALIGN_WORST 8
+
+#elif defined(_ARM64_)
+
+#define ALIGN_WORST 8
+
+#elif defined(_ALPHA_)
+
+//
+// Worst-case alignment on ALPHA is 8 bytes (for double). Specify this here,
+// in case our allocator is used for structures containing this. (That is,
+// even though NT/LAN doesn't need this for our data structures, let's be
+// permissive.) The alignment requirements apply to Alpha.
+//
+
+#define ALIGN_WORST 8
+
+#elif defined(_IA64_)
+
+//
+// IA64 note for QUAD: The NT QUAD type definition is NOT the EM 16byte quad type.
+// Because of some NT constraints, QUAD type size cannot be changed.
+//
+
+#define ALIGN_WORST 16
+
+#else // none of the above
+
+#error "Unknown alignment requirements for align.h"
+
+#endif // none of the above
+
+#endif // _ALIGN_
+
diff --git a/network/wwan/cxwmbclass/inc/data.h b/network/wwan/cxwmbclass/inc/data.h
new file mode 100644
index 00000000..4ac1a8ab
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/data.h
@@ -0,0 +1,185 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// DEFINES
+//
+////////////////////////////////////////////////////////////////////////////////
+#pragma once
+
+#define MBB_DEFAULT_SESSION_ID 0
+
+typedef struct _DSS_PACKET
+{
+ WDFMEMORY Data;
+ PMDL Mdl;
+} DSS_PACKET, *PDSS_PACKET;
+
+typedef struct _MBB_PORT MBB_PORT, *PMBB_PORT;
+
+typedef struct _MINIPORT_DRIVER_CONTEXT
+{
+ WDFDRIVER hDriver;
+} MINIPORT_DRIVER_CONTEXT, *PMINIPORT_DRIVER_CONTEXT;
+
+typedef struct _MBB_RECEIVE_QUEUE
+{
+ //
+ // Queue State
+ //
+ BOOLEAN LookasideList;
+ NDIS_SPIN_LOCK Lock;
+ KEVENT QueueEmptyEvent;
+ //
+ // Track Receives
+ //
+ LIST_ENTRY ReceivedQueue;
+ //
+ // Resources
+ //
+ NDIS_HANDLE NblPool;
+ NPAGED_LOOKASIDE_LIST ReceiveLookasideList;
+
+} MBB_RECEIVE_QUEUE, *PMBB_RECEIVE_QUEUE;
+
+typedef struct _MBB_NDIS_RECEIVE_CONTEXT
+{
+ //
+ // Resources
+ //
+
+ PMDL Mdl;
+ PUCHAR ReceiveNtbBuffer;
+ WDFLOOKASIDE ReceiveLookasideList;
+ PMBB_RECEIVE_QUEUE RecvQueue;
+ MBB_BUS_HANDLE BusHandle;
+ MBB_RECEIVE_CONTEXT BusContext;
+ PWMBCLASS_DEVICE_CONTEXT WmbDeviceContext;
+ //
+ // Parse state
+ //
+ ULONG NtbSequence;
+ WDFMEMORY ReceiveLookasideBufferMemory;
+
+ LONG TotalNdpCount;
+ LONG CompletedNdpCount;
+} MBB_NDIS_RECEIVE_CONTEXT, *PMBB_NDIS_RECEIVE_CONTEXT;
+
+typedef struct _MBB_RECEIVE_NDP_CONTEXT
+{
+ LIST_ENTRY ReceiveNdpNode;
+ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext;
+ WDFMEMORY ReceiveNdpLookasideBufferMemory;
+ PVOID Nth;
+ PVOID Ndp;
+ ULONG CurrentDatagramIndex;
+ ULONG IndicatedPackets;
+ PWMBCLASS_NETADAPTER_CONTEXT NetAdapterContext;
+} MBB_RECEIVE_NDP_CONTEXT, *PMBB_RECEIVE_NDP_CONTEXT;
+
+extern MINIPORT_DRIVER_CONTEXT GlobalControl;
+
+typedef enum
+{
+ MbbNdpTypeNoCrc = 0,
+ MbbNdpTypeCrc,
+ MbbNdpTypeIps,
+ MbbNdpTypeVendor_1, // Vendor with session id X (need not be 1)
+ MbbNdpTypeVendor_2, // Vendor with session id Y (need not be X + 1)
+ MbbNdpTypeVendor_3,
+ MbbNdpTypeVendor_Max, // Max 4 vendor sessions in one NTB
+ MbbNdpTypeMax
+
+} MBB_NDP_TYPE;
+
+typedef struct _MBB_PACKET_CONTEXT
+{
+ PMDL DataStartMdl;
+ PMDL DataEndMdl;
+ PMDL PaddingMdl;
+ PMDL ModifiedMdl;
+ MDL OriginalMdl;
+
+} MBB_PACKET_CONTEXT, *PMBB_PACKET_CONTEXT;
+
+typedef struct _MBB_NDP_HEADER_ENTRY
+{
+ MBB_NDP_TYPE NdpType;
+ ULONG SessionId;
+ ULONG DatagramOffset;
+ ULONG DatagramLength;
+ ULONG NextEntryIndex;
+ PNET_BUFFER NetBuffer;
+ PNET_BUFFER_LIST NetBufferList;
+
+ union
+ {
+ NET_PACKET* NetPacket;
+ PDSS_PACKET DssPacket;
+ };
+ MBB_PACKET_CONTEXT NetPacketContext;
+} MBB_NDP_HEADER_ENTRY, *PMBB_NDP_HEADER_ENTRY;
+
+typedef struct _MBB_NTB_BUILD_CONTEXT
+{
+ LIST_ENTRY NtbQLink;
+ //
+ // Read-only values
+ //
+ BOOLEAN IsNtb32Bit;
+ ULONG NtbHeaderSize;
+ ULONG NdpHeaderFixedSize;
+ ULONG NdpDatagramEntrySize;
+ ULONG NtbOutMaxSize;
+ USHORT NtbOutMaxDatagrams;
+ USHORT NdpOutDivisor;
+ USHORT NdpOutPayloadRemainder;
+ USHORT NdpOutAlignment;
+ PVOID PaddingBuffer;
+ WDFLOOKASIDE NtbLookasideList;
+ //
+ // Network Transfer Header(NTH)
+ //
+ union
+ {
+ NCM_NTH16 Nth16;
+ NCM_NTH32 Nth32;
+ };
+ PMDL NthMdl;
+ //
+ // NDP Header
+ //
+ PMDL NdpMdl;
+ ULONG NdpSize;
+ PVOID NdpBuffer;
+ //
+ // NDP Datagrams
+ //
+ ULONG DatagramCount;
+ ULONG DatagramLength;
+ PMDL DatagramLastMdl;
+
+ WDFMEMORY NtbLookasideBufferMemory;
+ WDFMEMORY NdpBufferMemory;
+ NETPACKETQUEUE NetTxQueue;
+ NETADAPTER NetAdapter;
+ NET_RING_COLLECTION const* NetDatapathDescriptor;
+
+#if DBG
+ //
+ // Testing
+ //
+ PCHAR ScratchBuffer;
+ ULONG ScratchLength;
+#endif
+
+ //
+ // NDP Headers. Varialble length array is limited
+ // to NdpMaxDatagrams. NdpFirstDatagramEntry of -1
+ // is invalid.
+ //
+ ULONG NdpFirstDatagramEntry[MbbNdpTypeMax];
+ MBB_NDP_HEADER_ENTRY NdpDatagramEntries[ANYSIZE_ARRAY];
+
+} MBB_NTB_BUILD_CONTEXT, *PMBB_NTB_BUILD_CONTEXT;
diff --git a/network/wwan/cxwmbclass/inc/device.h b/network/wwan/cxwmbclass/inc/device.h
new file mode 100644
index 00000000..a00ea7f4
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/device.h
@@ -0,0 +1,45 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#pragma once
+
+typedef struct _WMBCLASS_DEVICE_CONTEXT
+{
+ void* WdfTriageInfoPtr;
+
+ WDFDEVICE WdfDevice;
+ bool m_armedWake;
+ ULONG TraceInstance;
+
+ MBB_BUS_HANDLE BusHandle;
+ MBB_BUS_PARAMETERS BusParams;
+
+ ULONGLONG DSSPacketsReceivedCount;
+ ULONGLONG DSSPacketsSentCount;
+
+ LONG NtbSequenceNumber;
+
+ WDFLOOKASIDE ReceiveLookasideList;
+ PUCHAR sharedPaddingBuffer;
+
+ struct
+ {
+ WDFSPINLOCK WdfRecvSpinLock;
+ struct _WMBCLASS_NETADAPTER_CONTEXT* NetAdapterContext; // the context of the netAdapter instance if this session is in use
+ } Sessions[MBB_MAX_NUMBER_OF_SESSIONS];
+
+} WMBCLASS_DEVICE_CONTEXT, *PWMBCLASS_DEVICE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WMBCLASS_DEVICE_CONTEXT, WmbClassGetDeviceContext);
+
+EVT_WDF_DEVICE_PREPARE_HARDWARE EvtDevicePrepareHardware;
+EVT_WDF_DEVICE_RELEASE_HARDWARE EvtDeviceReleaseHardware;
+EVT_WDF_DEVICE_SURPRISE_REMOVAL EvtDeviceSurpriseRemoval;
+
+EVT_MBB_DEVICE_SEND_MBIM_FRAGMENT EvtMbbDeviceSendMbimFragment;
+EVT_MBB_DEVICE_RECEIVE_MBIM_FRAGMENT EvtMbbDeviceReceiveMbimFragment;
+EVT_MBB_DEVICE_CREATE_ADAPTER EvtMbbDeviceCreateAdapter;
+//EVT_NET_DEVICE_RESET EvtMbbDeviceReset;
+
+EVT_WDF_OBJECT_CONTEXT_CLEANUP EvtAdapterCleanup;
diff --git a/network/wwan/cxwmbclass/inc/mbbmessages.h b/network/wwan/cxwmbclass/inc/mbbmessages.h
new file mode 100644
index 00000000..61957009
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/mbbmessages.h
@@ -0,0 +1,3273 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 8.01.0625 */
+/* at Mon Jan 18 19:14:07 2038
+ */
+/* @@MIDL_FILE_HEADING( ) */
+
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 500
+#endif
+
+/* verify that the <rpcsal.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCSAL_H_VERSION__
+#define __REQUIRED_RPCSAL_H_VERSION__ 100
+#endif
+
+#if 0
+#include <rpc.h>
+#include <rpcndr.h>
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif /* __RPCNDR_H_VERSION__ */
+#endif
+
+#ifndef __MbbMessages_h__
+#define __MbbMessages_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#ifndef DECLSPEC_XFGVIRT
+#if _CONTROL_FLOW_GUARD_XFG
+#define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func))
+#else
+#define DECLSPEC_XFGVIRT(base, func)
+#endif
+#endif
+
+/* Forward Declarations */
+
+/* header files for imported files */
+// #include "wtypes.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+/* interface __MIDL_itf_MbbMessages_0000_0000 */
+/* [local] */
+
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#include <initguid.h>
+//
+// Service Ids
+//
+// Invald GUID
+// 00000000-0000-0000-0000-000000000000
+DEFINE_GUID( MBB_UUID_INVALID, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 );
+#define MBB_UUID_INVALID_CONSTANT { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+// Basic IP Connectivity
+// a289cc33-bcbb-8b4f-b6b0-133ec2aae6df
+DEFINE_GUID( MBB_UUID_BASIC_CONNECT, 0xa289cc33, 0xbcbb, 0x8b4f, 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf );
+#define MBB_UUID_BASIC_CONNECT_CONSTANT { 0xa289cc33, 0xbcbb, 0x8b4f, { 0xb6, 0xb0, 0x13, 0x3e, 0xc2, 0xaa, 0xe6, 0xdf } }
+// SMS
+// 533fbeeb-14fe-4467-9f90-33a223e56c3f
+DEFINE_GUID( MBB_UUID_SMS, 0x533fbeeb, 0x14fe, 0x4467, 0x9f, 0x90, 0x33, 0xa2, 0x23, 0xe5, 0x6c, 0x3f );
+#define MBB_UUID_SMS_CONSTANT { 0x533fbeeb, 0x14fe, 0x4467, { 0x9f, 0x90, 0x33, 0xa2, 0x23, 0xe5, 0x6c, 0x3f } }
+// USSD
+// e550a0c8-5e82-479e-82f7-10abf4c3351f
+DEFINE_GUID( MBB_UUID_USSD, 0xe550a0c8, 0x5e82, 0x479e, 0x82, 0xf7, 0x10, 0xab, 0xf4, 0xc3, 0x35, 0x1f );
+#define MBB_UUID_USSD_CONSTANT { 0xe550a0c8, 0x5e82, 0x479e, { 0x82, 0xf7, 0x10, 0xab, 0xf4, 0xc3, 0x35, 0x1f } }
+// Phonebook
+// 4bf38476-1e6a-41db-b1d8-bed289c25bdb
+DEFINE_GUID( MBB_UUID_PHONEBOOK, 0x4bf38476, 0x1e6a, 0x41db, 0xb1, 0xd8, 0xbe, 0xd2, 0x89, 0xc2, 0x5b, 0xdb );
+#define MBB_UUID_PHONEBOOK_CONSTANT { 0x4bf38476, 0x1e6a, 0x41db, { 0xb1, 0xd8, 0xbe, 0xd2, 0x89, 0xc2, 0x5b, 0xdb } }
+// SIM Application Toolkit
+// d8f20131-fcb5-4e17-8602-d6ed3816164c
+DEFINE_GUID( MBB_UUID_SAT, 0xd8f20131, 0xfcb5, 0x4e17, 0x86, 0x02, 0xd6, 0xed, 0x38, 0x16, 0x16, 0x4c );
+#define MBB_UUID_SAT_CONSTANT { 0xd8f20131, 0xfcb5, 0x4e17, { 0x86, 0x02, 0xd6, 0xed, 0x38, 0x16, 0x16, 0x4c } }
+// Windows 7 Vendor Extension
+// b492e7e2-adba-499d-8401-7794bb913c1c
+DEFINE_GUID( MBB_UUID_MS_VENDOR_EXTENSION, 0xb492e7e2, 0xadba, 0x499d, 0x84, 0x01, 0x77, 0x94, 0xbb, 0x91, 0x3c, 0x1c );
+#define MBB_UUID_MS_VENDOR_EXTENSION_CONSTANT { 0xb492e7e2, 0xadba, 0x499d, { 0x84, 0x01, 0x77, 0x94, 0xbb, 0x91, 0x3c, 0x1c } }
+// Authentication
+// 1d2b5ff7-0aa1-48b2-aa52-50f15767174e
+DEFINE_GUID( MBB_UUID_AUTH, 0x1d2b5ff7, 0x0aa1, 0x48b2, 0xaa, 0x52, 0x50, 0xf1, 0x57,0x67, 0x17, 0x4e );
+#define MBB_UUID_AUTH_CONSTANT { 0x1d2b5ff7, 0x0aa1, 0x48b2, { 0xaa, 0x52, 0x50, 0xf1, 0x57,0x67, 0x17, 0x4e } }
+// Device Service Stream
+// c08a26dd-7718-4382-8482-6e0d583c4d0e
+DEFINE_GUID( MBB_UUID_DSS, 0xc08a26dd, 0x7718, 0x4382, 0x84, 0x82, 0x6e, 0x0d, 0x58, 0x3c, 0x4d, 0x0e );
+#define MBB_UUID_DSS_CONSTANT { 0xc08a26dd, 0x7718, 0x4382, { 0x84, 0x82, 0x6e, 0x0d, 0x58, 0x3c, 0x4d, 0x0e } }
+// Multi-carrier device service
+// 8b569648-628d-4653-9b9f-1025404424e1
+DEFINE_GUID( MBB_UUID_MULTICARRIER, 0x8b569648, 0x628d, 0x4653, 0x9b, 0x9f, 0x10, 0x25, 0x40, 0x44, 0x24, 0xe1 );
+#define MBB_UUID_MULTICARRIER_CONSTANT { 0x8b569648, 0x628d, 0x4653, { 0x9b, 0x9f, 0x10, 0x25, 0x40, 0x44, 0x24, 0xe1 } }
+// Host Shutdown device service
+// 883b7c26-985f-43fa-9804-27d7fb80959c
+DEFINE_GUID( MBB_UUID_HOSTSHUTDOWN, 0x883b7c26, 0x985f, 0x43fa, 0x98, 0x04, 0x27, 0xd7, 0xfb, 0x80, 0x95, 0x9c );
+#define MBB_UUID_HOSTSHUTDOWN_CONSTANT { 0x883b7c26, 0x985f, 0x43fa, { 0x98, 0x04, 0x27, 0xd7, 0xfb, 0x80, 0x95, 0x9c } }
+// MBIM 2.0 voice extensions
+// 8d8b9eba-37be-449b-8f1e-61cb034a702e
+DEFINE_GUID( MBB_UUID_VOICEEXTENSIONS, 0x8d8b9eba, 0x37be, 0x449b, 0x8f, 0x1e, 0x61, 0xcb, 0x03, 0x4a, 0x70, 0x2e );
+#define MBB_UUID_VOICEEXTENSIONS_CONSTANT { 0x8d8b9eba, 0x37be, 0x449b, { 0x8f, 0x1e, 0x61, 0xcb, 0x03, 0x4a, 0x70, 0x2e } }
+// Low-Level UICC Access
+// c2f6588e-f037-4bc9-8665-f4d44bd09367
+DEFINE_GUID( MBB_UUID_UICC_LOW_LEVEL, 0xc2f6588e, 0xf037, 0x4bc9, 0x86, 0x65, 0xf4, 0xd4, 0x4b, 0xd0, 0x93, 0x67 );
+#define MBB_UUID_UICC_LOW_LEVEL_CONSTANT { 0xc2f6588e, 0xf037, 0x4bc9, { 0x86, 0x65, 0xf4, 0xd4, 0x4b, 0xd0, 0x93, 0x67 } }
+// Selective Absorption Rate (SAR) control
+// 68223d04-9f6c-4e0f-822d-28441fb72340
+DEFINE_GUID( MBB_UUID_SARCONTROL, 0x68223d04, 0x9f6c, 0x4e0f, 0x82, 0x2d, 0x28, 0x44, 0x1f, 0xb7, 0x23, 0x40 );
+#define MBB_UUID_SARCONTROL_CONSTANT { 0x68223d04, 0x9f6c, 0x4e0f, { 0x82, 0x2d, 0x28, 0x44, 0x1f, 0xb7, 0x23, 0x40 } }
+// Basic IP Connectivity Extensions (a private Microsoft service not approved by MBIM USB forum as of 2016/11/09)
+// 3d01dcc5-fef5-4d05-0d3a-bef7058e9aaf
+DEFINE_GUID( MBB_UUID_BASIC_CONNECT_EXTENSIONS, 0x3d01dcc5, 0xfef5, 0x4d05, 0x0d, 0x3a, 0xbe, 0xf7, 0x05, 0x8e, 0x9a, 0xaf );
+#define MBB_UUID_BASIC_CONNECT_EXT_CONSTANT { 0x3d01dcc5, 0xfef5, 0x4d05, { 0x0d, 0x3a, 0xbe, 0xf7, 0x05, 0x8e, 0x9a, 0xaf } }
+// DeviceService GUID for Modem Log Transfer (parameter for DSS connect/disconnect request to open/close DSS data channel)
+// 0ebb1ceb-af2d-484d-8df3-53bc51fd162c
+DEFINE_GUID( MBB_UUID_MODEM_LOG_TRANSFER, 0x0ebb1ceb, 0xaf2d, 0x484d, 0x8d, 0xf3, 0x53, 0xbc, 0x51, 0xfd, 0x16, 0x2c );
+#define MBB_UUID_MODEM_LOG_TRANSFER_CONSTANT { 0x0ebb1ceb, 0xaf2d, 0x484d, { 0x8d, 0xf3, 0x53, 0xbc, 0x51, 0xfd, 0x16, 0x2c } }
+//
+// Context Type GUIDs
+//
+// MBIMContextTypeNone
+// B43F758C-A560-4B46-B35E-C5869641FB54
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_NONE, 0xB43F758C, 0xA560, 0x4B46, 0xB3, 0x5E, 0xC5, 0x86, 0x96, 0x41, 0xFB, 0x54 );
+// MBIMContextTypeInternet
+// 7E5E2A7E-4E6F-7272-736B-656E7E5E2A7E
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_INTERNET, 0x7E5E2A7E, 0x4E6F, 0x7272, 0x73, 0x6B, 0x65, 0x6E, 0x7E, 0x5E, 0x2A, 0x7E );
+// MBIMContextTypeVpn
+// 9B9F7BBE-8952-44B7-83AC-CA41318DF7A0
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_VPN, 0x9B9F7BBE, 0x8952, 0x44B7, 0x83, 0xAC, 0xCA, 0x41, 0x31, 0x8D, 0xF7, 0xA0 );
+// MBIMContextTypeVoice
+// 88918294-0EF4-4396-8CCA-A8588FBC02B2
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_VOICE, 0x88918294, 0x0EF4, 0x4396, 0x8C, 0xCA, 0xA8, 0x58, 0x8F, 0xBC, 0x02, 0xB2 );
+// MBIMContextTypeVideoShare
+// 05A2A716-7C34-4B4D-9A91-C5EF0C7AAACC
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_VIDEO_SHARE, 0x05A2A716,0x7C34, 0x4B4D, 0x9A, 0x91, 0xC5, 0xEF, 0x0C, 0x7A, 0xAA, 0xCC );
+// MBIMContextTypePurchase
+// B3272496-AC6C-422B-A8C0-ACF687A27217
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_PURCHASE, 0xB3272496, 0xAC6C, 0x422B, 0xA8, 0xC0, 0xAC, 0xF6, 0x87, 0xA2, 0x72, 0x17 );
+// MBIMContextTypeIMS
+// 21610D01-3074-4BCE-9425-B53A07D697D6
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_IMS, 0x21610D01, 0x3074, 0x4BCE, 0x94, 0x25, 0xB5, 0x3A, 0x07, 0xD6, 0x97, 0xD6 );
+// MBIMContextTypeMMS
+// 46726664-7269-6BC6-9624-D1D35389ACA9
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_MMS, 0x46726664, 0x7269, 0x6BC6, 0x96, 0x24, 0xD1, 0xD3, 0x53, 0x89, 0xAC, 0xA9 );
+// MBIMContextTypeLocal
+// A57A9AFC-B09F-45D7-BB40-033C39F60DB9
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_LOCAL, 0xA57A9AFC, 0xB09F, 0x45D7, 0xBB, 0x40, 0x03, 0x3C, 0x39, 0xF6, 0x0D, 0xB9 );
+// MBIMMsContextTypeAdmin
+// 5f7e4c2e-e80b-40a9-a239-f0abcfd11f4b
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_MS_ADMIN, 0x5f7e4c2e, 0xe80b, 0x40a9, 0xa2, 0x39, 0xf0, 0xab, 0xcf, 0xd1, 0x1f, 0x4b );
+// MBIMMSContextTypeApp
+// 74d88a3d-dfbd-4799-9a8c-7310a37bb2ee
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_MS_APP, 0x74d88a3d, 0xdfbd, 0x4799, 0x9a, 0x8c, 0x73, 0x10, 0xa3, 0x7b, 0xb2, 0xee );
+// MBIMMsContextTypeXcap
+// 50d378a7-baa5-4a50-b872-3fe5bb463411
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_MS_XCAP, 0x50d378a7, 0xbaa5, 0x4a50, 0xb8, 0x72, 0x3f, 0xe5, 0xbb, 0x46, 0x34, 0x11 );
+// MBIMMsContextTypeTethering
+// 5e4e0601-48dc-4e2b-acb8-08b4016bbaac
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_MS_TETHERING, 0x5e4e0601, 0x48dc, 0x4e2b, 0xac, 0xb8, 0x08, 0xb4, 0x01, 0x6b, 0xba, 0xac );
+// MBIMMsContextTypeEmergencyCalling
+// 5f41adb8-204e-4d31-9da8-b3c970e360f2
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_MS_EMERGENCYCALL, 0x5f41adb8, 0x204e, 0x4d31, 0x9d, 0xa8, 0xb3, 0xc9, 0x70, 0xe3, 0x60, 0xf2 );
+// 9C494542-A43B-4EA5-B8B7-53310E71DF10
+DEFINE_GUID( MBB_UUID_CONTEXT_TYPE_CUSTOM, 0x9C494542, 0xA43B, 0x4EA5, 0xB8, 0xB7, 0x53, 0x31, 0x0E, 0x71, 0xDF, 0x10);
+// 146FED19-EB71-42A7-B3EB-3875DEA61D92
+DEFINE_GUID(GUID_USB_CAPABILITY_DEVICE_TYPE, 0x146FED19, 0xEB71, 0x42A7, 0xB3, 0xEB, 0x38, 0x75, 0xDE, 0xA6, 0x1D, 0x92);
+#define MBB_STATUS_SUCCESS( STATUS ) \
+ ( \
+ ((STATUS) == MBB_STATUS_SUCCESS) || \
+ ((STATUS) == MBB_STATUS_SMS_MORE_DATA) \
+ )
+#define MBB_STATUS_IS_BASIC(MBBSTATUS) (((MBBSTATUS) >= MBB_STATUS_BASIC_START) && ((MBBSTATUS) < MBB_STATUS_BASIC_END))
+#define MBB_STATUS_BASIC_INDEX(MBBSTATUS) ((MBBSTATUS)-MBB_STATUS_BASIC_START)
+#define MBB_STATUS_BASIC_COUNT() (MBB_STATUS_BASIC_END-MBB_STATUS_BASIC_START)
+#define MBB_STATUS_IS_SMS(MBBSTATUS) (((MBBSTATUS) >= MBB_STATUS_SMS_START) && ((MBBSTATUS) < MBB_STATUS_SMS_END))
+#define MBB_STATUS_SMS_INDEX(MBBSTATUS) ((MBBSTATUS)-MBB_STATUS_SMS_START)
+#define MBB_STATUS_SMS_COUNT() (MBB_STATUS_SMS_END-MBB_STATUS_SMS_START)
+#define MBB_STATUS_IS_UICC(MBBSTATUS) (((MBBSTATUS) >= MBB_STATUS_UICC_START) && ((MBBSTATUS) < MBB_STATUS_UICC_END))
+#define MBB_STATUS_UICC_INDEX(MBBSTATUS) ((MBBSTATUS)-MBB_STATUS_UICC_START)
+#define MBB_STATUS_UICC_COUNT() (MBB_STATUS_UICC_END-MBB_STATUS_UICC_START)
+#define MBB_UUID_TO_NET(_dest, _src) \
+{ \
+ (_dest)->Data1 = RtlUlongByteSwap((_src)->Data1); \
+ (_dest)->Data2 = RtlUshortByteSwap((_src)->Data2); \
+ (_dest)->Data3 = RtlUshortByteSwap((_src)->Data3); \
+ RtlCopyMemory((_dest)->Data4, (_src)->Data4, sizeof((_src)->Data4)); \
+ \
+}
+#define MBB_UUID_TO_HOST(_dest, _src) MBB_UUID_TO_NET(_dest, _src)
+#define MBB_IS_DEVICE_REGISTERED( _State_ ) \
+( \
+ ( (_State_) == MbbRegisterStateHome ) || \
+ ( (_State_) == MbbRegisterStateRoaming ) || \
+ ( (_State_) == MbbRegisterStatePartner ) \
+)
+#include <packon.h>
+#define MBB_MAXIMUM_DATA_CLASS_NAME_LENGTH ( 11 )
+
+#define MBB_MAXIMUM_DEVICE_ID_LENGTH ( 17 )
+
+#define MBB_MAXIMUM_FIRMWARE_INFO_LENGTH ( 31 )
+
+#define MBB_MAXIMUM_SUBSCRIBER_ID_LENGTH ( 15 )
+
+#define MBB_MAXIMUM_SIM_ICC_ID_LENGTH ( 20 )
+
+#define MBB_MAXIMUM_TELEPHONE_NUMBER_LENGTH ( 15 )
+
+#define MBB_MAXIMUM_TELEPHONE_NUMBER_ERRATA_LENGTH ( 22 )
+
+#define MBB_MAXIMUM_PIN_LENGTH ( 16 )
+
+#define MBB_MAXIMUM_PROVIDER_ID_LENGTH ( 6 )
+
+#define MBB_MAXIMUM_PROVIDER_NAME_LENGTH ( 20 )
+
+#define MBB_MAXIMUM_ROAMING_TEXT_LENGTH ( 63 )
+
+#define MBB_MAXIMUM_ACCESS_STRING_LENGTH ( 100 )
+
+#define MBB_MAXIMUM_USERNAME_LENGTH ( 255 )
+
+#define MBB_MAXIMUM_PASSWORD_LENGTH ( 255 )
+
+#define MBB_MAXIMUM_SMS_ADDRESS_LENGTH ( 20 )
+
+#define MBB_MAXIMUM_SMS_CDMA_ADDRESS_LENGTH ( 49 )
+
+#define MBB_MAXIMUM_SMS_CDMA_TIMESTAMP_LENGTH ( 21 )
+
+#define MBB_MAXIMUM_SMS_CDMA_BUFFER_LENGTH ( 160 )
+
+#define MBB_MAXIMUM_SMS_GSM_PDU_BUFFER_LENGTH ( 183 )
+
+#define MBB_MAXIMUM_SMS_CDMA_PDU_BUFFER_LENGTH ( 255 )
+
+#define MBB_USSD_STRING_LEN_MAX ( 160 )
+
+#define MBB_RSSI_DISABLE ( 0xffffffff )
+
+#define MBB_RSSI_DEFAULT ( 0 )
+
+#define MBB_SET_CONTEXT_STATE_EX3_MIN_TLV_CNT ( 3 )
+
+#define MBB_CONTEXT_STATE_EX3_MIN_TLV_CNT ( 1 )
+
+#define MBIM_VERSION_1_0 ( 0x100 )
+
+#define MBIM_MS_EXTENDED_VER_1_0 ( 0x100 )
+
+#define MBIM_MS_EXTENDED_VER_2_0 ( 0x200 )
+
+#define MBIM_MS_EXTENDED_VER_3_0 ( 0x300 )
+
+#define MBB_MS_DEVICE_CAPS_INFO_V3_MIN_TLV_CNT ( 6 )
+
+#define MBB_TLV_TYPE_RESERVED ( 0 )
+
+#define MBB_TLV_TYPE_UE_POLICIES ( 1 )
+
+#define MBB_TLV_TYPE_SINGLE_NSSAI ( 2 )
+
+#define MBB_TLV_TYPE_ALLOWED_NSSAI ( 3 )
+
+#define MBB_TLV_TYPE_CFG_NSSAI ( 4 )
+
+#define MBB_TLV_TYPE_DFLT_CFG_NSSAI ( 5 )
+
+#define MBB_TLV_TYPE_PRECFG_DFLT_CFG_NSSAI ( 6 )
+
+#define MBB_TLV_TYPE_REJ_NSSAI ( 7 )
+
+#define MBB_TLV_TYPE_LADN ( 8 )
+
+#define MBB_TLV_TYPE_TAI ( 9 )
+
+#define MBB_TLV_TYPE_WCHAR_STR ( 10 )
+
+#define MBB_TLV_TYPE_UINT16_TBL ( 11 )
+
+#define MBB_TLV_TYPE_EAP_PACKET ( 12 )
+
+#define MBB_TLV_TYPE_PCO ( 13 )
+
+#define MBB_TLV_TYPE_ROUTE_SELECTION_DESCRIPTORS ( 14 )
+
+#define MBB_TLV_TYPE_TRAFFIC_PARAMETERS ( 15 )
+
+#define MBB_TLV_TYPE_WAKE_COMMAND ( 16 )
+
+#define MBB_TLV_TYPE_WAKE_PACKET ( 17 )
+
+#define MBB_NW_PARAMS_INFO_CONFIG_TLV_CNT ( 6 )
+
+#define MBB_NW_PARAMS_INFO_UE_POLICIES_TLV_CNT ( 1 )
+
+typedef unsigned short MBB_TLV_TYPE;
+
+typedef
+enum _USB_CAP_DEVICE_TYPE
+ {
+ USB_CAP_DEVICE_TYPE_USB = 0,
+ USB_CAP_DEVICE_TYPE_UDE_MBIM = 1,
+ USB_CAP_DEVICE_TYPE_UDE_MBIM_FASTIO = 2,
+ USB_CAP_DEVICE_TYPE_MAXIMUM = ( USB_CAP_DEVICE_TYPE_UDE_MBIM_FASTIO + 1 )
+ } USB_CAP_DEVICE_TYPE;
+
+typedef struct _USB_CAP_DEVICE_INFO_HEADER
+ {
+ USB_CAP_DEVICE_TYPE DeviceType;
+ UCHAR DeviceMinorVersion;
+ UCHAR DeviceMajorVersion;
+ ULONG Reserved;
+ } USB_CAP_DEVICE_INFO_HEADER;
+
+typedef struct _USB_CAP_DEVICE_INFO_HEADER *PUSB_CAP_DEVICE_INFO_HEADER;
+
+typedef struct _USB_CAP_DEVICE_INFO
+ {
+ USB_CAP_DEVICE_INFO_HEADER DeviceInfoHeader;
+ } USB_CAP_DEVICE_INFO;
+
+typedef struct _USB_CAP_DEVICE_INFO *PUSB_CAP_DEVICE_INFO;
+
+typedef
+enum _MBB_NBL_TYPE
+ {
+ MBB_NBL_TYPE_IP = 0,
+ MBB_NBL_TYPE_DSS = 1,
+ MBB_NBL_TYPE_MAXIMUM = ( MBB_NBL_TYPE_DSS + 1 )
+ } MBB_NBL_TYPE;
+
+typedef
+enum _MBB_STATUS
+ {
+ MBB_STATUS_SUCCESS = 0,
+ MBB_STATUS_BASIC_START = 0,
+ MBB_STATUS_BUSY = 1,
+ MBB_STATUS_FAILURE = 2,
+ MBB_STATUS_SIM_NOT_INSERTED = 3,
+ MBB_STATUS_BAD_SIM = 4,
+ MBB_STATUS_PIN_REQUIRED = 5,
+ MBB_STATUS_PIN_DISABLED = 6,
+ MBB_STATUS_NOT_REGISTERED = 7,
+ MBB_STATUS_PROVIDERS_NOT_FOUND = 8,
+ MBB_STATUS_NO_DEVICE_SUPPORT = 9,
+ MBB_STATUS_PROVIDER_NOT_VISIBLE = 10,
+ MBB_STATUS_DATA_CLASS_NOT_AVAILABLE = 11,
+ MBB_STATUS_PACKET_SVC_DETACHED = 12,
+ MBB_STATUS_MAX_ACTIVATED_CONTEXTS = 13,
+ MBB_STATUS_NOT_INITIALIZED = 14,
+ MBB_STATUS_VOICE_CALL_IN_PROGRESS = 15,
+ MBB_STATUS_CONTEXT_NOT_ACTIVATED = 16,
+ MBB_STATUS_SERVICE_NOT_ACTIVATED = 17,
+ MBB_STATUS_INVALID_ACCESS_STRING = 18,
+ MBB_STATUS_INVALID_USER_NAME_PWD = 19,
+ MBB_STATUS_RADIO_POWER_OFF = 20,
+ MBB_STATUS_INVALID_PARAMETERS = 21,
+ MBB_STATUS_READ_FAILURE = 22,
+ MBB_STATUS_WRITE_FAILURE = 23,
+ MBB_STATUS_DENIED_POLICY = 24,
+ MBB_STATUS_NO_PHONEBOOK = 25,
+ MBB_STATUS_PARAMETER_TOO_LONG = 26,
+ MBB_STATUS_STK_BUSY = 27,
+ MBB_STATUS_OPERATION_NOT_ALLOWED = 28,
+ MBB_STATUS_MEMORY_FAILURE = 29,
+ MBB_STATUS_INVALID_MEMORY_INDEX = 30,
+ MBB_STATUS_MEMORY_FULL = 31,
+ MBB_STATUS_FILTER_NOT_SUPPORTED = 32,
+ MBB_STATUS_DSS_INSTANCE_LIMIT = 33,
+ MBB_STATUS_INVALID_DEVICE_SERVICE_OPERATION = 34,
+ MBB_STATUS_AUTH_INCORRECT_AUTN = 35,
+ MBB_STATUS_AUTH_SYNC_FAILURE = 36,
+ MBB_STATUS_AUTH_AMF_NOT_SET = 37,
+ MBB_STATUS_CONTEXT_NOT_SUPPORTED = 38,
+ MBB_STATUS_SHAREABILITY_CONDITION_ERROR = 39,
+ MBB_STATUS_PIN_FAILURE = 40,
+ MBB_STATUS_NO_LTE_ATTACH_CONFIG = 41,
+ MBB_STATUS_SESSION_ALREADY_EXISTS = 42,
+ MBB_STATUS_BASIC_END = ( MBB_STATUS_SESSION_ALREADY_EXISTS + 1 ) ,
+ MBB_STATUS_SMS_UNKNOWN_SMSC_ADDRESS = 100,
+ MBB_STATUS_SMS_START = 100,
+ MBB_STATUS_SMS_NETWORK_TIMEOUT = 101,
+ MBB_STATUS_SMS_LANG_NOT_SUPPORTED = 102,
+ MBB_STATUS_SMS_ENCODING_NOT_SUPPORTED = 103,
+ MBB_STATUS_SMS_FORMAT_NOT_SUPPORTED = 104,
+ MBB_STATUS_SMS_MORE_DATA = 105,
+ MBB_STATUS_SMS_END = ( MBB_STATUS_SMS_MORE_DATA + 1 ) ,
+ MBB_STATUS_UICC_NO_LOGICAL_CHANNELS = 0x87430001,
+ MBB_STATUS_UICC_START = 0x87430001,
+ MBB_STATUS_UICC_SELECT_FAILED = 0x87430002,
+ MBB_STATUS_UICC_INVALID_LOGICAL_CHANNEL = 0x87430003,
+ MBB_STATUS_UICC_END = ( MBB_STATUS_UICC_INVALID_LOGICAL_CHANNEL + 1 )
+ } MBB_STATUS;
+
+typedef
+enum _MBB_ERROR
+ {
+ MBB_ERROR_NONE = 0,
+ MBB_ERROR_TIMEOUT_FRAGMENT = 1,
+ MBB_ERROR_FRAGMENT_OUT_OF_SEQUENCE = 2,
+ MBB_ERROR_LENGTH_MISMATCH = 3,
+ MBB_ERROR_DUPLICATE_TID = 4,
+ MBB_ERROR_NOT_OPENED = 5,
+ MBB_ERROR_UNKNOWN = 6,
+ MBB_ERROR_CANCEL = 7,
+ MBB_ERROR_MAX_TRANSFER = 8
+ } MBB_ERROR;
+
+typedef
+enum _MBB_MESSAGE_TYPE
+ {
+ MBB_MESSAGE_TYPE_NONE = 0,
+ MBB_MESSAGE_TYPE_OPEN = 0x1,
+ MBB_MESSAGE_TYPE_CLOSE = 0x2,
+ MBB_MESSAGE_TYPE_COMMAND = 0x3,
+ MBB_MESSAGE_TYPE_HOST_ERROR = 0x4,
+ MBB_MESSAGE_TYPE_OPEN_DONE = 0x80000001,
+ MBB_MESSAGE_TYPE_CLOSE_DONE = 0x80000002,
+ MBB_MESSAGE_TYPE_COMMAND_DONE = 0x80000003,
+ MBB_MESSAGE_TYPE_FUNCTION_ERROR = 0x80000004,
+ MBB_MESSAGE_TYPE_INDICATE_STATUS = 0x80000007
+ } MBB_MESSAGE_TYPE;
+
+typedef
+enum _MBB_COMMAND_TYPE
+ {
+ MBB_COMMAND_TYPE_QUERY = 0,
+ MBB_COMMAND_TYPE_SET = 1
+ } MBB_COMMAND_TYPE;
+
+typedef struct _MBB_MESSAGE_HEADER
+ {
+ MBB_MESSAGE_TYPE MessageType;
+ ULONG MessageLength;
+ ULONG MessageTransactionId;
+ } MBB_MESSAGE_HEADER;
+
+typedef struct _MBB_MESSAGE_HEADER *PMBB_MESSAGE_HEADER;
+
+typedef struct _MBB_FRAGMENT_HEADER
+ {
+ ULONG TotalFragments;
+ ULONG CurrentFragment;
+ } MBB_FRAGMENT_HEADER;
+
+typedef struct _MBB_FRAGMENT_HEADER *PMBB_FRAGMENT_HEADER;
+
+typedef struct _MBB_COMMAND
+ {
+ GUID ServiceId;
+ ULONG CommandId;
+ } MBB_COMMAND;
+
+typedef struct _MBB_COMMAND *PMBB_COMMAND;
+
+typedef struct _MBB_COMMAND_HEADER
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_FRAGMENT_HEADER FragmentHeader;
+ MBB_COMMAND Command;
+ MBB_COMMAND_TYPE CommandType;
+ ULONG InformationBufferLength;
+ } MBB_COMMAND_HEADER;
+
+typedef struct _MBB_COMMAND_HEADER *PMBB_COMMAND_HEADER;
+
+typedef struct _MBB_COMMAND_FRAGMENT_HEADER
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_FRAGMENT_HEADER FragmentHeader;
+ } MBB_COMMAND_FRAGMENT_HEADER;
+
+typedef struct _MBB_COMMAND_FRAGMENT_HEADER *PMBB_COMMAND_FRAGMENT_HEADER;
+
+typedef struct _MBB_COMMAND_DONE_HEADER
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_FRAGMENT_HEADER FragmentHeader;
+ MBB_COMMAND Command;
+ MBB_STATUS MbbStatus;
+ ULONG InformationBufferLength;
+ } MBB_COMMAND_DONE_HEADER;
+
+typedef struct _MBB_COMMAND_DONE_HEADER *PMBB_COMMAND_DONE_HEADER;
+
+typedef struct _MBB_INDICATE_STATUS_HEADER
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_FRAGMENT_HEADER FragmentHeader;
+ MBB_COMMAND Command;
+ ULONG InformationBufferLength;
+ } MBB_INDICATE_STATUS_HEADER;
+
+typedef struct _MBB_INDICATE_STATUS_HEADER *PMBB_INDICATE_STATUS_HEADER;
+
+typedef struct _MBB_OPEN_MESSAGE
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ ULONG MaximumControlTransfer;
+ } MBB_OPEN_MESSAGE;
+
+typedef struct _MBB_OPEN_MESSAGE *PMBB_OPEN_MESSAGE;
+
+typedef struct _MBB_OPEN_MESSAGE_FASTIO
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ ULONG MaximumControlTransfer;
+ PVOID AdapterContext;
+ PVOID SendNetBufferListsCompleteHandler;
+ PVOID ReceiveNetBufferListsHandler;
+ } MBB_OPEN_MESSAGE_FASTIO;
+
+typedef struct _MBB_OPEN_MESSAGE_FASTIO *PMBB_OPEN_MESSAGE_FASTIO;
+
+typedef struct _MBB_CLOSE_MESSAGE
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ } MBB_CLOSE_MESSAGE;
+
+typedef struct _MBB_CLOSE_MESSAGE *PMBB_CLOSE_MESSAGE;
+
+typedef struct _MBB_OPEN_DONE
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_STATUS MbbStatus;
+ } MBB_OPEN_DONE;
+
+typedef struct _MBB_OPEN_DONE *PMBB_OPEN_DONE;
+
+typedef struct _MBB_OPEN_DONE_FASTIO
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_STATUS MbbStatus;
+ PVOID ModemContext;
+ PVOID SendNetBufferListsHandler;
+ PVOID ReturnNetBufferListsHandler;
+ PVOID CancelSendHandler;
+ PVOID HaltHandler;
+ PVOID PauseHandler;
+ PVOID ShutdownHandler;
+ PVOID ResetHandler;
+ PVOID RestartHandler;
+ } MBB_OPEN_DONE_FASTIO;
+
+typedef struct _MBB_OPEN_DONE_FASTIO *PMBB_OPEN_DONE_FASTIO;
+
+typedef struct _MBB_CLOSE_DONE
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_STATUS MbbStatus;
+ } MBB_CLOSE_DONE;
+
+typedef struct _MBB_CLOSE_DONE *PMBB_CLOSE_DONE;
+
+typedef struct _MBB_ERROR_MESSAGE
+ {
+ MBB_MESSAGE_HEADER MessageHeader;
+ MBB_ERROR ErrorCode;
+ } MBB_ERROR_MESSAGE;
+
+typedef struct _MBB_ERROR_MESSAGE *PMBB_ERROR_MESSAGE;
+
+typedef
+enum _MBB_BASIC_CID
+ {
+ MBB_BASIC_CID_DEVICE_CAPS = 1,
+ MBB_BASIC_CID_SUBSCRIBER_READY_INFO = 2,
+ MBB_BASIC_CID_RADIO_STATE = 3,
+ MBB_BASIC_CID_PIN_INFO = 4,
+ MBB_BASIC_CID_PIN_LIST = 5,
+ MBB_BASIC_CID_HOME_PROVIDER = 6,
+ MBB_BASIC_CID_PREFERRED_PROVIDERS = 7,
+ MBB_BASIC_CID_VISIBLE_PROVIDERS = 8,
+ MBB_BASIC_CID_REGISTER_STATE = 9,
+ MBB_BASIC_CID_PACKET_SERVICE = 10,
+ MBB_BASIC_CID_SIGNAL_STATE = 11,
+ MBB_BASIC_CID_CONNECT = 12,
+ MBB_BASIC_CID_PROVISIONED_CONTEXTS = 13,
+ MBB_BASIC_CID_SERVICE_ACTIVATION = 14,
+ MBB_BASIC_CID_IP_ADDRESS_INFO = 15,
+ MBB_BASIC_CID_DEVICE_SERVICES = 16,
+ MBB_BASIC_CID_NOTIFY_DEVICE_SERVICE_UPDATES = 19,
+ MBB_BASIC_CID_PACKET_STATISTICS = 20,
+ MBB_BASIC_CID_NETWORK_IDLE_HINT = 21,
+ MBB_BASIC_CID_EMERGENCY_MODE = 22,
+ MBB_BASIC_CID_PACKET_FILTERS = 23,
+ MBB_BASIC_CID_MULTICARRIER_PROVIDERS = 24,
+ MBB_BASIC_CID_MAXIMUM = ( MBB_BASIC_CID_MULTICARRIER_PROVIDERS + 1 )
+ } MBB_BASIC_CID;
+
+typedef
+enum _MBB_SMS_CID
+ {
+ MBB_SMS_CID_CONFIGURATION = 1,
+ MBB_SMS_CID_READ = 2,
+ MBB_SMS_CID_SEND = 3,
+ MBB_SMS_CID_DELETE = 4,
+ MBB_SMS_CID_STATUS = 5,
+ MBB_SMS_CID_MAXIMUM = ( MBB_SMS_CID_STATUS + 1 )
+ } MBB_SMS_CID;
+
+typedef
+enum _MBB_VENDOR_CID
+ {
+ MBB_VENDOR_CID_MS_VENDOR_SPECIFIC = 1,
+ MBB_VENDOR_CID_MAXIMUM = ( MBB_VENDOR_CID_MS_VENDOR_SPECIFIC + 1 )
+ } MBB_VENDOR_CID;
+
+typedef
+enum _MBB_USSD_CID
+ {
+ MBB_USSD_CID_USSD = 1,
+ MBB_USSD_CID_MAXIMUM = ( MBB_USSD_CID_USSD + 1 )
+ } MBB_USSD_CID;
+
+typedef
+enum _MBB_PHONEBOOK_CID
+ {
+ MBB_PHONEBOOK_CID_CONFIGURATION = 1,
+ MBB_PHONEBOOK_CID_READ = 2,
+ MBB_PHONEBOOK_CID_DELETE = 3,
+ MBB_PHONEBOOK_CID_SAVE = 4,
+ MBB_PHONEBOOK_CID_MAXIMUM = ( MBB_PHONEBOOK_CID_SAVE + 1 )
+ } MBB_PHONEBOOK_CID;
+
+typedef
+enum _MBB_SAT_CID
+ {
+ MBB_SAT_CID_PAC = 1,
+ MBB_SAT_CID_TERMINAL_RESPONSE = 2,
+ MBB_SAT_CID_ENVELOPE = 3,
+ MBB_SAT_CID_MAXIMUM = ( MBB_SAT_CID_ENVELOPE + 1 )
+ } MBB_SAT_CID;
+
+typedef
+enum _MBB_AUTH_CID
+ {
+ MBB_AUTH_CID_AKA = 1,
+ MBB_AUTH_CID_AKAP = 2,
+ MBB_AUTH_CID_SIM = 3,
+ MBB_AUTH_CID_MAXIUM = ( MBB_AUTH_CID_SIM + 1 )
+ } MBB_AUTH_CID;
+
+typedef
+enum _MBB_DSS_CID
+ {
+ MBB_DSS_CID_CONNECT = 1,
+ MBB_DSS_CID_MAXIUM = ( MBB_DSS_CID_CONNECT + 1 )
+ } MBB_DSS_CID;
+
+typedef
+enum _MBB_MULTICARRIER_CID
+ {
+ MBB_MULTICARRIER_CID_CAPABILITIES = 1,
+ MBB_MULTICARRIER_CID_LOCATION_INFO = 2,
+ MBB_MULTICARRIER_CID_CURRENT_CID_LIST = 3,
+ MBB_MULTICARRIER_CID_MAXIMUM = ( MBB_MULTICARRIER_CID_CURRENT_CID_LIST + 1 )
+ } MBB_MULTICARRIER_CID;
+
+typedef
+enum _MBB_HOSTSHUTDOWN_CID
+ {
+ MBB_HOSTSHUTDOWN_CID_ONE = 1,
+ MBB_HOSTSHUTDOWN_CID_PRESHUTDOWN = 2,
+ MBB_HOSTSHUTDOWN_CID_MAX = ( MBB_HOSTSHUTDOWN_CID_PRESHUTDOWN + 1 )
+ } MBB_HOSTSHUTDOWN_CID;
+
+typedef
+enum _MBB_VOICEEXTENSIONS_CID
+ {
+ MBB_VOICEEXTENSIONS_CID_SYS_CAPS = 1,
+ MBB_VOICEEXTENSIONS_CID_DEVICE_CAPS_V2 = 2,
+ MBB_VOICEEXTENSIONS_CID_SYS_SLOTMAPPINGS = 3,
+ MBB_VOICEEXTENSIONS_CID_SLOT_INFO_STATUS = 4,
+ MBB_VOICEEXTENSIONS_CID_DEVICE_BINDINGS = 5,
+ MBB_VOICEEXTENSIONS_CID_REGISTER_STATE_V2 = 6,
+ MBB_VOICEEXTENSIONS_CID_IMS_VOICE_STATE = 7,
+ MBB_VOICEEXTENSIONS_CID_SIGNAL_STATE_V2 = 8,
+ MBB_VOICEEXTENSIONS_CID_LOCATION_STATE = 9,
+ MBB_VOICEEXTENSIONS_CID_NITZ = 10,
+ MBB_VOICEEXTENSIONS_CID_MAX = ( MBB_VOICEEXTENSIONS_CID_NITZ + 1 )
+ } MBB_VOICEEXTENSIONS_CID;
+
+typedef
+enum _MBB_UICC_CID
+ {
+ MBB_UICC_CID_ATR = 1,
+ MBB_UICC_CID_OPEN_CHANNEL = 2,
+ MBB_UICC_CID_CLOSE_CHANNEL = 3,
+ MBB_UICC_CID_APDU = 4,
+ MBB_UICC_CID_TERMINAL_CAPABILITY = 5,
+ MBB_UICC_CID_RESET = 6,
+ MBB_UICC_CID_APP_LIST = 7,
+ MBB_UICC_CID_FILE_STATUS = 8,
+ MBB_UICC_CID_ACCESS_BINARY = 9,
+ MBB_UICC_CID_ACCESS_RECORD = 10,
+ MBB_UICC_CID_MAXIMUM = ( MBB_UICC_CID_ACCESS_RECORD + 1 )
+ } MBB_UICC_CID;
+
+typedef
+enum _MBB_SAR_CID
+ {
+ MBB_SAR_CID_CONFIG = 1,
+ MBB_SAR_CID_TRANSMISSION_STATUS = 2,
+ MBB_SAR_CID_MAXIMUM = ( MBB_SAR_CID_TRANSMISSION_STATUS + 1 )
+ } MBB_SAR_CID;
+
+typedef
+enum _MBB_BASICCONNECTEXT_CID
+ {
+ MBB_BASICCONNECTEXT_CID_PROVISIONED_CONTEXT_V2 = 1,
+ MBB_BASICCONNECTEXT_CID_NETWORK_BLACKLIST = 2,
+ MBB_BASICCONNECTEXT_CID_LTE_ATTACH_CONFIG = 3,
+ MBB_BASICCONNECTEXT_CID_LTE_ATTACH_STATUS = 4,
+ MBB_BASICCONNECTEXT_CID_SYS_CAPS = 5,
+ MBB_BASICCONNECTEXT_CID_DEVICE_CAPS_V2 = 6,
+ MBB_BASICCONNECTEXT_CID_DEVICE_SLOT_MAPPINGS = 7,
+ MBB_BASICCONNECTEXT_CID_SLOT_INFO_STATUS = 8,
+ MBB_BASICCONNECTEXT_CID_PCO = 9,
+ MBB_BASICCONNECTEXT_CID_DEVICE_RESET = 10,
+ MBB_BASICCONNECTEXT_CID_BASE_STATIONS_INFO = 11,
+ MBB_BASICCONNECTEXT_CID_LOCATION_INFO_STATUS = 12,
+ MBB_BASICCONNECTEXT_CID_MODEM_LOGGING_CONFIG = 13,
+ MBB_BASICCONNECTEXT_CID_PIN_INFO_EX2 = 14,
+ MBB_BASICCONNECTEXT_CID_VERSION = 15,
+ MBB_BASICCONNECTEXT_CID_MODEM_CONFIG = 16,
+ MBB_BASICCONNECTEXT_CID_REGISTRATION_PARAMS = 17,
+ MBB_BASICCONNECTEXT_CID_NETWORK_PARAMS = 18,
+ MBB_BASICCONNECTEXT_CID_WAKE_REASON = 19,
+ MBB_BASICCONNECTEXT_CID_MAXIMUM = ( MBB_BASICCONNECTEXT_CID_WAKE_REASON + 1 )
+ } MBB_BASICCONNECTEXT_CID;
+
+typedef
+enum _MBB_DEVICE_TYPE
+ {
+ MbbDeviceTypeUnknown = 0,
+ MbbDeviceTypeEmbedded = 1,
+ MbbDeviceTypeRemovable = 2,
+ MbbDeviceTypeRemote = 3,
+ MbbDeviceTypeMaximum = ( MbbDeviceTypeRemote + 1 )
+ } MBB_DEVICE_TYPE;
+
+typedef
+enum _MBB_CELLULAR_CLASS
+ {
+ MbbCellularClassInvalid = 0,
+ MbbCellularClassGsm = 1,
+ MbbCellularClassCdma = 2,
+ MbbCellularClassMaximum = ( MbbCellularClassCdma + 1 )
+ } MBB_CELLULAR_CLASS;
+
+typedef
+enum _MBB_VOICE_CLASS
+ {
+ MbbVoiceClassInvalid = 0,
+ MbbVoiceClassNoVoice = 1,
+ MbbVoiceClassSeparateVoiceData = 2,
+ MbbVoiceClassSimultaneousVoiceData = 3,
+ MbbVoiceClassMaximum = ( MbbVoiceClassSimultaneousVoiceData + 1 )
+ } MBB_VOICE_CLASS;
+
+typedef
+enum _MBB_SIM_CLASS
+ {
+ MbbSimClassInvalid = 0,
+ MbbSimClassSimLogical = 1,
+ MbbSimClassSimRemovable = 2,
+ MbbSimClassMaximum = ( MbbSimClassSimRemovable + 1 )
+ } MBB_SIM_CLASS;
+
+typedef
+enum _MBB_DATA_CLASS_VALUE
+ {
+ MbbDataClassNone = 0,
+ MbbDataClassGprs = 0x1,
+ MbbDataClassEdge = 0x2,
+ MbbDataClassUmts = 0x4,
+ MbbDataClassHsdpa = 0x8,
+ MbbDataClassHsupa = 0x10,
+ MbbDataClassLte = 0x20,
+ MbbDataClass5G = 0x40,
+ MbbDataClass_UNUSED = 0x80,
+ MbbDataClassTdScdma = 0x1000,
+ MbbDataClass1xRtt = 0x10000,
+ MbbDataClass1xEvdo = 0x20000,
+ MbbDataClass1xEvdoReva = 0x40000,
+ MbbDataClass1xEvdv = 0x80000,
+ MbbDataClass3xRtt = 0x100000,
+ MbbDataClass1xEvdoRevb = 0x200000,
+ MbbDataClassUmb = 0x400000,
+ MbbDataClassCustom = 0x80000000
+ } MBB_DATA_CLASS_VALUE;
+
+typedef
+enum _MBB_DATA_SUBCLASS_VALUE
+ {
+ MbbDataSubClassNone = 0,
+ MbbDataSubClass5GENDC = 0x1,
+ MbbDataSubClass5GNR = 0x2,
+ MbbDataSubClass5GNEDC = 0x4,
+ MbbDataSubClass5GELTE = 0x8,
+ MbbDataSubClassNGENDC = 0x10
+ } MBB_DATA_SUBCLASS_VALUE;
+
+typedef
+enum _MBB_FREQUENCY_RANGE
+ {
+ MbbFrequencyRangeUnknown = 0,
+ MbbFrequencyRange1 = 1,
+ MbbFrequencyRange2 = 2,
+ MbbFrequencyRange1AndRange2 = 3,
+ MbbFrequencyRangeMaximum = ( MbbFrequencyRange1AndRange2 + 1 )
+ } MBB_FREQUENCY_RANGE;
+
+typedef
+enum _MBB_BAND_CLASS_VALUE
+ {
+ MbbBandClassUnknown = 0,
+ MbbBandClass0 = 0x1,
+ MbbBandClassI = 0x2,
+ MbbBandClassII = 0x4,
+ MbbBandClassIII = 0x8,
+ MbbBandClassIV = 0x10,
+ MbbBandClassV = 0x20,
+ MbbBandClassVI = 0x40,
+ MbbBandClassVII = 0x80,
+ MbbBandClassVIII = 0x100,
+ MbbBandClassIX = 0x200,
+ MbbBandClassX = 0x400,
+ MbbBandClassXI = 0x800,
+ MbbBandClassXII = 0x1000,
+ MbbBandClassXIII = 0x2000,
+ MbbBandClassXIV = 0x4000,
+ MbbBandClassXV = 0x8000,
+ MbbBandClassXVI = 0x10000,
+ MbbBandClassXVII = 0x20000,
+ MbbBandClassCustom = 0x80000000
+ } MBB_BAND_CLASS_VALUE;
+
+typedef
+enum _MBB_SMS_CAPS_VALUE
+ {
+ MbbSmsCapsNone = 0,
+ MbbSmsCapsPduReceive = 0x1,
+ MbbSmsCapsPduSend = 0x2,
+ MbbSmsCapsTextReceive = 0x4,
+ MbbSmsCapsTextSend = 0x8
+ } MBB_SMS_CAPS_VALUE;
+
+typedef
+enum _MBB_CONTROL_CAPS_VALUE
+ {
+ MbbControlCapsNone = 0,
+ MbbControlCapsRegManual = 0x1,
+ MbbControlCapsHwRadioSwitch = 0x2,
+ MbbControlCapsCdmaMobileIp = 0x4,
+ MbbControlCapsCdmaSimpleIp = 0x8,
+ MbbControlCapsMultiCarrier = 0x10,
+ MbbControlCapsESIM = 0x20,
+ MbbControlCapsUEPolicyRouteSelection = 0x40,
+ MbbControlCapsSIMHotSwapCapable = 0x80
+ } MBB_CONTROL_CAPS_VALUE;
+
+typedef
+enum _MBB_READY_STATE
+ {
+ MbbReadyStateOff = 0,
+ MbbReadyStateInitialized = 1,
+ MbbReadyStateSimNotInserted = 2,
+ MbbReadyStateBadSim = 3,
+ MbbReadyStateFailure = 4,
+ MbbReadyStateNotActivated = 5,
+ MbbReadyStateDeviceLocked = 6,
+ MbbReadyStateNoEsimProfile = 7,
+ MbbReadyStateMaximum = ( MbbReadyStateNoEsimProfile + 1 )
+ } MBB_READY_STATE;
+
+typedef
+enum _MBB_READY_INFO_FLAGS
+ {
+ MbbReadyInfoFlagsNone = 0,
+ MbbReadyInfoFlagsUniqueId = 1
+ } MBB_READY_INFO_FLAGS;
+
+typedef
+enum _MBB_EMERGENCY_MODE
+ {
+ MbbEmergencyModeOff = 0,
+ MbbEmergencyModeOn = 1,
+ MbbEmergencyModeMaximum = ( MbbEmergencyModeOn + 1 )
+ } MBB_EMERGENCY_MODE;
+
+typedef
+enum _MBB_RADIO_STATE
+ {
+ MbbRadioStateOff = 0,
+ MbbRadioStateOn = 1,
+ MbbRadioStateMaximum = ( MbbRadioStateOn + 1 )
+ } MBB_RADIO_STATE;
+
+typedef
+enum _MBB_PIN_TYPE
+ {
+ MbbPinTypeNone = 0,
+ MbbPinTypeCustom = 1,
+ MbbPinTypePin1 = 2,
+ MbbPinTypePin2 = 3,
+ MbbPinTypeDeviceSimPin = 4,
+ MbbPinTypeDeviceFirstSimPin = 5,
+ MbbPinTypeNetworkPin = 6,
+ MbbPinTypeNetworkSubsetPin = 7,
+ MbbPinTypeSvcProviderPin = 8,
+ MbbPinTypeCorporatePin = 9,
+ MbbPinTypeSubsidyLock = 10,
+ MbbPinTypePuk1 = 11,
+ MbbPinTypePuk2 = 12,
+ MbbPinTypeDeviceFirstSimPuk = 13,
+ MbbPinTypeNetworkPuk = 14,
+ MbbPinTypeNetworkSubsetPuk = 15,
+ MbbPinTypeSvcProviderPuk = 16,
+ MbbPinTypeCorporatePuk = 17,
+ MbbPinTypeNev = 18,
+ MbbPinTypeAdm = 19,
+ MbbPinTypeMaximum = ( MbbPinTypeAdm + 1 )
+ } MBB_PIN_TYPE;
+
+typedef
+enum _MBB_PIN_STATE
+ {
+ MbbPinStateUnlocked = 0,
+ MbbPinStateLocked = 1,
+ MbbPinStateMaximum = ( MbbPinStateLocked + 1 )
+ } MBB_PIN_STATE;
+
+typedef
+enum _MBB_PIN_OPERATION
+ {
+ MbbPinOperationEnter = 0,
+ MbbPinOperationEnable = 1,
+ MbbPinOperationDisable = 2,
+ MbbPinOperationChange = 3,
+ MbbPinOperationMaximum = ( MbbPinOperationChange + 1 )
+ } MBB_PIN_OPERATION;
+
+typedef
+enum _MBB_PIN_MODE
+ {
+ MbbPinModeNotSupported = 0,
+ MbbPinModeEnabled = 1,
+ MbbPinModeDisabled = 2,
+ MbbPinModeMaximum = ( MbbPinModeDisabled + 1 )
+ } MBB_PIN_MODE;
+
+typedef
+enum _MBB_PIN_FORMAT
+ {
+ MbbPinFormatUnknown = 0,
+ MbbPinFormatNumeric = 1,
+ MbbPinFormatAlphaNumeric = 2,
+ MbbPinFormatMaximum = ( MbbPinFormatAlphaNumeric + 1 )
+ } MBB_PIN_FORMAT;
+
+typedef
+enum _MBB_PROVIDER_STATE_VALUE
+ {
+ MbbProviderStateHome = 0x1,
+ MbbProviderStateForbidden = 0x2,
+ MbbProviderStatePreferred = 0x4,
+ MbbProviderStateVisible = 0x8,
+ MbbProviderStateRegistered = 0x10,
+ MbbProviderStatePreferredMulticarrier = 0x20
+ } MBB_PROVIDER_STATE_VALUE;
+
+typedef
+enum _MBB_REGISTER_ACTION
+ {
+ MbbRegisterActionAutomatic = 0,
+ MbbRegisterActionManual = 1,
+ MbbRegisterActionMaximum = ( MbbRegisterActionManual + 1 )
+ } MBB_REGISTER_ACTION;
+
+typedef
+enum _MBB_REGISTER_STATE
+ {
+ MbbRegisterStateUnknown = 0,
+ MbbRegisterStateDeregistered = 1,
+ MbbRegisterStateSearching = 2,
+ MbbRegisterStateHome = 3,
+ MbbRegisterStateRoaming = 4,
+ MbbRegisterStatePartner = 5,
+ MbbRegisterStateDenied = 6,
+ MbbRegisterStateMaximum = ( MbbRegisterStateDenied + 1 )
+ } MBB_REGISTER_STATE;
+
+typedef
+enum _MBB_REGISTER_MODE
+ {
+ MbbRegisterModeUnknown = 0,
+ MbbRegisterModeAutomatic = 1,
+ MbbRegisterModeManual = 2,
+ MbbRegisterModeMaximum = ( MbbRegisterModeManual + 1 )
+ } MBB_REGISTER_MODE;
+
+typedef
+enum _MBB_PACKET_SERVICE_ACTION
+ {
+ MbbPacketServiceActionAttach = 0,
+ MbbPacketServiceActionDetach = 1,
+ MbbPacketServiceActionMaximum = ( MbbPacketServiceActionDetach + 1 )
+ } MBB_PACKET_SERVICE_ACTION;
+
+typedef
+enum _MBB_PACKET_SERVICE_STATE
+ {
+ MbbPacketServiceStateUnknown = 0,
+ MbbPacketServiceStateAttaching = 1,
+ MbbPacketServiceStateAttached = 2,
+ MbbPacketServiceStateDetaching = 3,
+ MbbPacketServiceStateDetached = 4,
+ MbbPacketServiceStateMaximum = ( MbbPacketServiceStateDetached + 1 )
+ } MBB_PACKET_SERVICE_STATE;
+
+typedef
+enum _MBB_CONTEXT_IP_TYPE
+ {
+ MbbContextIPTypeDefault = 0,
+ MbbContextIPTypeIPv4 = 1,
+ MbbContextIPTypeIPv6 = 2,
+ MbbContextIPTypeIPv4v6 = 3,
+ MbbContextIPTypeIPv4AndIPv6 = 4,
+ MbbContextIPTypeMaximum = ( MbbContextIPTypeIPv4AndIPv6 + 1 )
+ } MBB_CONTEXT_IP_TYPE;
+
+typedef
+enum _MBB_ACTIVATION_COMMAND
+ {
+ MbbActivationCommandDeactivate = 0,
+ MbbActivationCommandActivate = 1,
+ MbbActivationCommandCancel = 2,
+ MbbActivationCommandMaximum = ( MbbActivationCommandCancel + 1 )
+ } MBB_ACTIVATION_COMMAND;
+
+typedef
+enum _MBB_COMPRESSION
+ {
+ MbbCompressionNone = 0,
+ MbbCompressionEnable = 1,
+ MbbCompressionMaximum = ( MbbCompressionEnable + 1 )
+ } MBB_COMPRESSION;
+
+typedef
+enum _MBB_AUTH_PROTOCOL
+ {
+ MbbAuthProtocolNone = 0,
+ MbbAuthProtocolPap = 1,
+ MbbAuthProtocolChap = 2,
+ MbbAuthProtocolMsChapV2 = 3,
+ MbbAuthProtocolMaximum = ( MbbAuthProtocolMsChapV2 + 1 )
+ } MBB_AUTH_PROTOCOL;
+
+typedef
+enum _MBB_ACTIVATION_STATE
+ {
+ MbbActivationStateUnknown = 0,
+ MbbActivationStateActivated = 1,
+ MbbActivationStateActivating = 2,
+ MbbActivationStateDeactivated = 3,
+ MbbActivationStateDeactivating = 4,
+ MbbActivationStateMaximum = ( MbbActivationStateDeactivating + 1 )
+ } MBB_ACTIVATION_STATE;
+
+typedef
+enum _MBB_VOICE_CALL_STATE
+ {
+ MbbVoiceCallStateNone = 0,
+ MbbVoiceCallStateInProgress = 1,
+ MbbVoiceCallStateHangUp = 2,
+ MbbVoiceCallStateMaximum = ( MbbVoiceCallStateHangUp + 1 )
+ } MBB_VOICE_CALL_STATE;
+
+typedef
+enum _MBB_SMS_FORMAT
+ {
+ MbbSmsFormatPdu = 0,
+ MbbSmsFormatCdma = 1,
+ MbbSmsFormatMaximum = ( MbbSmsFormatCdma + 1 )
+ } MBB_SMS_FORMAT;
+
+typedef
+enum _MBB_SMS_FLAG
+ {
+ MbbSmsFlagAll = 0,
+ MbbSmsFlagIndex = 1,
+ MbbSmsFlagNew = 2,
+ MbbSmsFlagOld = 3,
+ MbbSmsFlagSent = 4,
+ MbbSmsFlagDraft = 5,
+ MbbSmsFlagMaximum = ( MbbSmsFlagDraft + 1 )
+ } MBB_SMS_FLAG;
+
+typedef
+enum _MBB_SMS_CDMA_LANGUAGE
+ {
+ MbbSmsCdmaLanguageUnknown = 0,
+ MbbSmsCdmaLanguageEnglish = 1,
+ MbbSmsCdmaLanguageFrench = 2,
+ MbbSmsCdmaLanguageSpanish = 3,
+ MbbSmsCdmaLanguageJapanese = 4,
+ MbbSmsCdmaLanguageKorean = 5,
+ MbbSmsCdmaLanguageChinese = 6,
+ MbbSmsCdmaLanguageHebrew = 7,
+ MbbSmsCdmaLanguageMaximum = ( MbbSmsCdmaLanguageHebrew + 1 )
+ } MBB_SMS_CDMA_LANGUAGE;
+
+typedef
+enum _MBB_SMS_CDMA_ENCODING
+ {
+ MbbSmsCdmaEncodingOctet = 0,
+ MbbSmsCdmaEncodingEpm = 1,
+ MbbSmsCdmaEncoding7BitAscii = 2,
+ MbbSmsCdmaEncodingIa5 = 3,
+ MbbSmsCdmaEncodingUnicode = 4,
+ MbbSmsCdmaEncodingShiftJis = 5,
+ MbbSmsCdmaEncodingKorean = 6,
+ MbbSmsCdmaEncodingLatinHebrew = 7,
+ MbbSmsCdmaEncodingLatin = 8,
+ MbbSmsCdmaEncodingGsm7Bit = 9,
+ MbbSmsCdmaEncodingMaximum = ( MbbSmsCdmaEncodingGsm7Bit + 1 )
+ } MBB_SMS_CDMA_ENCODING;
+
+typedef
+enum _MBB_SMS_MESSAGE_STATUS
+ {
+ MbbSmsMessageStatusNew = 0,
+ MbbSmsMessageStatusOld = 1,
+ MbbSmsMessageStatusDraft = 2,
+ MbbSmsMessageStatusSent = 3,
+ MbbSmsMessageStatusMaximum = ( MbbSmsMessageStatusSent + 1 )
+ } MBB_SMS_MESSAGE_STATUS;
+
+typedef
+enum _MBB_REG_FLAGS_VALUE
+ {
+ MbbRegFlagsNone = 0,
+ MbbRegFlagsNoManualReg = 0x1,
+ MbbRegFlagsPSAutoAttach = 0x2
+ } MBB_REG_FLAGS_VALUE;
+
+typedef
+enum _MBB_SMS_STATUS_FLAGS_VALUE
+ {
+ MbbSmsFlagNone = 0,
+ MbbSmsFlagMessageStoreFull = 1,
+ MbbSmsFlagNewMessage = 2
+ } MBB_SMS_STATUS_FLAGS_VALUE;
+
+typedef struct _MBB_STRING
+ {
+ ULONG Offset;
+ ULONG Size;
+ } MBB_STRING;
+
+typedef struct _MBB_STRING *PMBB_STRING;
+
+typedef struct _MBB_ARRAY_ELEMENT
+ {
+ ULONG Offset;
+ ULONG Size;
+ } MBB_ARRAY_ELEMENT;
+
+typedef struct _MBB_ARRAY_ELEMENT *PMBB_ARRAY_ELEMENT;
+
+typedef struct _MBB_ARRAY_ELEMENT2
+ {
+ ULONG Size;
+ ULONG Offset;
+ } MBB_ARRAY_ELEMENT2;
+
+typedef struct _MBB_ARRAY_ELEMENT2 *PMBB_ARRAY_ELEMENT2;
+
+typedef
+enum _MBB_DSS_PAYLOAD_SUPPORT
+ {
+ MbbDssPayloadNone = 0,
+ MbbDssPayloadHostToDevice = 0x1,
+ MbbDssPayloadDeviceToHost = 0x2
+ } MBB_DSS_PAYLOAD_SUPPORT;
+
+typedef
+enum _MBB_DSS_LINK_STATE
+ {
+ MbbDssLinkDeactivate = 0,
+ MbbDssLinkActivate = 0x1
+ } MBB_DSS_LINK_STATE;
+
+typedef
+enum _MBB_IP_CONFIGURATION_FLAGS_VALUE
+ {
+ MbbIpFlagsNone = 0,
+ MbbIpFlagsAddressAvailable = 0x1,
+ MbbIpFlagsGatewayAvailable = 0x2,
+ MbbIpFlagsDnsServerAvailable = 0x4,
+ MbbIpFlagsMTUAvailable = 0x8
+ } MBB_IP_CONFIGURATION_FLAGS_VALUE;
+
+typedef
+enum _MBB_NETWORK_IDLE_HINT_STATE
+ {
+ MbbNetworkIdleHintDisabled = 0,
+ MbbNetworkIdleHintEnabled = 1
+ } MBB_NETWORK_IDLE_HINT_STATE;
+
+typedef
+enum _MBB_SAR_BACKOFF_STATE
+ {
+ MbbSarBackoffStatusDisabled = 0,
+ MbbSarBackoffStatusEnabled = 1,
+ MbbSarBackoffStatusMaximum = ( MbbSarBackoffStatusEnabled + 1 )
+ } MBB_SAR_BACKOFF_STATE;
+
+typedef
+enum _MBB_SAR_CONTROL_MODE
+ {
+ MbbSarControlModeDevice = 0,
+ MbbSarControlModeOS = 1,
+ MbbSarControlModeMaximum = ( MbbSarControlModeOS + 1 )
+ } MBB_SAR_CONTROL_MODE;
+
+typedef
+enum _MBB_SAR_WIFI_HARDWARE_INTEGRATION
+ {
+ MbbSarWifiHardwareNotIntegrated = 0,
+ MbbSarWifiHardwareIntegrated = 1,
+ MbbSarWifiHardwareIntegrationMaximum = ( MbbSarWifiHardwareIntegrated + 1 )
+ } MBB_SAR_WIFI_HARDWARE_INTEGRATION;
+
+typedef
+enum _MBB_SAR_TRANSMISSION_STATUS_NOTIFICATION_STATE
+ {
+ MbbTransmissionNotificationDisabled = 0,
+ MbbTransmissionNotificationEnabled = 1,
+ MbbTransmissionNotificationMaximum = ( MbbTransmissionNotificationEnabled + 1 )
+ } MBB_SAR_TRANSMISSION_STATUS_NOTIFICATION_STATE;
+
+typedef
+enum _MBB_SAR_TRANSMISSION_STATUS
+ {
+ MbbTransmissionStateInactive = 0,
+ MbbTransmissionStateActive = 1,
+ MbbTransmissionStateMaximum = ( MbbTransmissionStateActive + 1 )
+ } MBB_SAR_TRANSMISSION_STATUS;
+
+typedef
+enum _MBB_BASICCONNECTEXT_CONTEXT_ROAMING_CONTROL
+ {
+ MbbMsContextRoamingControlHomeOnly = 0,
+ MbbMsContextRoamingControlPartnerOnly = 1,
+ MbbMsContextRoamingControlNonPartnerOnly = 2,
+ MbbMsContextRoamingControlHomeAndPartner = 3,
+ MbbMsContextRoamingControlHomeAndNonPartner = 4,
+ MbbMsContextRoamingControlPartnerAndNonPartner = 5,
+ MbbMsContextRoamingControlAllowAll = 6,
+ MbbMsContextRoamingControlMaximum = ( MbbMsContextRoamingControlAllowAll + 1 )
+ } MBB_BASICCONNECTEXT_CONTEXT_ROAMING_CONTROL;
+
+typedef
+enum _MBB_BASICCONNECTEXT_CONTEXT_MEDIA_TYPE
+ {
+ MbbMsContextMediaTypeCellularOnly = 0,
+ MbbMsContextMediaTypeWifiOnly = 1,
+ MbbMsContextMediaTypeAll = 2,
+ MbbMsContextMediaTypeMaximum = ( MbbMsContextMediaTypeAll + 1 )
+ } MBB_BASICCONNECTEXT_CONTEXT_MEDIA_TYPE;
+
+typedef
+enum _MBB_BASICCONNECTEXT_CONTEXT_ENABLE
+ {
+ MbbMsContextDisabled = 0,
+ MbbMsContextEnabled = 1,
+ MbbMsContextEnableMaximum = ( MbbMsContextEnabled + 1 )
+ } MBB_BASICCONNECTEXT_CONTEXT_ENABLE;
+
+typedef
+enum _MBB_BASICCONNECTEXT_CONTEXT_SOURCE
+ {
+ MbbMsContextSourceAdmin = 0,
+ MbbMsContextSourceUser = 1,
+ MbbMsContextSourceOperator = 2,
+ MbbMsContextSourceModem = 3,
+ MbbMsContextSourceDevice = 4,
+ MbbMsContextSourceMaximum = ( MbbMsContextSourceDevice + 1 )
+ } MBB_BASICCONNECTEXT_CONTEXT_SOURCE;
+
+typedef
+enum _MBB_BASICCONNECTEXT_CONTEXT_OPERATIONS
+ {
+ MbbMsContextOperationDefault = 0,
+ MbbMsContextOperationDelete = 1,
+ MbbMsContextOperationRestoreFactory = 2,
+ MbbMsContextOperationMaximum = ( MbbMsContextOperationRestoreFactory + 1 )
+ } MBB_BASICCONNECTEXT_CONTEXT_OPERATIONS;
+
+typedef
+enum _MBB_BASICCONNECTEXT_NETWORK_BLACKLIST_STATE
+ {
+ MbbMsNetworkBlacklistStateNotActuated = 0,
+ MbbMsNetworkBlacklistSIMProviderActuated = 1,
+ MbbMsNetworkBlacklistNetworkProviderActuated = 2,
+ MbbMsNetworkBlacklistStateMaximum = ( MbbMsNetworkBlacklistNetworkProviderActuated + 1 )
+ } MBB_BASICCONNECTEXT_NETWORK_BLACKLIST_STATE;
+
+typedef
+enum _MBB_BASICCONNECTEXT_NETWORK_BLACKLIST_TYPE
+ {
+ MbbMsNetworkBlacklistTypeSIM = 0,
+ MbbMsNetworkBlacklistTypeNetwork = 1,
+ MbbMsNetworkBlacklistTypeMaximum = ( MbbMsNetworkBlacklistTypeNetwork + 1 )
+ } MBB_BASICCONNECTEXT_NETWORK_BLACKLIST_TYPE;
+
+typedef
+enum _MBB_BASICCONNECTEXT_LTEATTACH_ROAMING_CONTROL
+ {
+ MbbMsLteAttachContextRoamingControlHome = 0,
+ MbbMsLteAttachContextRoamingControlPartner = 1,
+ MbbMsLteAttachContextRoamingControlNonPartner = 2,
+ MbbMsLteAttachContextRoamingControlMaximum = ( MbbMsLteAttachContextRoamingControlNonPartner + 1 )
+ } MBB_BASICCONNECTEXT_LTEATTACH_ROAMING_CONTROL;
+
+typedef
+enum _MBB_BASICCONNECTEXT_LTEATTACH_CONTEXT_OPERATIONS
+ {
+ MbbMsLteAttachContextOperationDefault = 0,
+ MbbMsLteAttachContextOperationRestoreFactory = 1,
+ MbbMsLteAttachContextOperationMaximum = ( MbbMsLteAttachContextOperationRestoreFactory + 1 )
+ } MBB_BASICCONNECTEXT_LTEATTACH_CONTEXT_OPERATIONS;
+
+typedef
+enum _MBB_BASICCONNECTEXT_LTEATTACH_STATE
+ {
+ MbbMsLteAttachStateDetached = 0,
+ MbbMsLteAttachStateAttached = 1,
+ MbbMsLteAttachStateMaximum = ( MbbMsLteAttachStateAttached + 1 )
+ } MBB_BASICCONNECTEXT_LTEATTACH_STATE;
+
+typedef
+enum _MBB_BASICCONNECTEXT_UICCSLOT_STATE
+ {
+ MbbMsUiccSlotStateUnknown = 0,
+ MbbMsUiccSlotStateOffEmpty = 1,
+ MbbMsUiccSlotStateOff = 2,
+ MbbMsUiccSlotStateEmpty = 3,
+ MbbMsUiccSlotStateNotReady = 4,
+ MbbMsUiccSlotStateActive = 5,
+ MbbMsUiccSlotStateError = 6,
+ MbbMsUiccSlotStateActiveEsim = 7,
+ MbbMsUiccSlotStateActiveEsimNoProfiles = 8
+ } MBB_BASICCONNECTEXT_UICCSLOT_STATE;
+
+typedef
+enum _MBB_BASICCONNECTEXT_MODEM_LOGGING_LEVEL_CONFIG
+ {
+ MbbMsModemLoggingLevelProd = 0,
+ MbbMsModemLoggingLevelLabVerbose = 1,
+ MbbMsModemLoggingLevelLabMedium = 2,
+ MbbMsModemLoggingLevelLabLow = 3,
+ MbbMsModemLoggingLevelOem = 4,
+ MbbMsModemLoggingLevelMaximum = ( MbbMsModemLoggingLevelOem + 1 )
+ } MBB_BASICCONNECTEXT_MODEM_LOGGING_LEVEL_CONFIG;
+
+typedef
+enum _MBB_PCO_TYPE
+ {
+ MbbPcoTypeComplete = 0,
+ MbbPcoTypePartial = 1,
+ MbbPcoTypeMaximum = ( MbbPcoTypePartial + 1 )
+ } MBB_PCO_TYPE;
+
+typedef struct _MBB_DEVICE_CAPS
+ {
+ MBB_DEVICE_TYPE DeviceType;
+ MBB_CELLULAR_CLASS CellularClass;
+ MBB_VOICE_CLASS VoiceClass;
+ MBB_SIM_CLASS SimClass;
+ ULONG DataClass;
+ ULONG SmsCaps;
+ ULONG ControlCaps;
+ ULONG dwMaxSessions;
+ MBB_STRING CustomDataClass;
+ MBB_STRING DeviceIdString;
+ MBB_STRING FirmwareInfo;
+ MBB_STRING HardwareInfo;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_DEVICE_CAPS;
+
+typedef struct _MBB_DEVICE_CAPS *PMBB_DEVICE_CAPS;
+
+typedef struct _MBB_SUBSCRIBER_READY_INFO
+ {
+ MBB_READY_STATE ReadyState;
+ MBB_STRING SubscriberId;
+ MBB_STRING SimIccId;
+ MBB_READY_INFO_FLAGS ReadyInfoFlags;
+ ULONG TelephoneNumberCount;
+ MBB_STRING TelephoneNumbers[ 1 ];
+ } MBB_SUBSCRIBER_READY_INFO;
+
+typedef struct _MBB_SUBSCRIBER_READY_INFO *PMBB_SUBSCRIBER_READY_INFO;
+
+typedef
+enum _MBB_SUBSCRIBER_READY_STATUS_FLAGS
+ {
+ MbbSubscriberReadyStatusFlagNone = 0,
+ MbbSubscriberReadyStatusFlagESim = 0x1,
+ MbbSubscriberReadyStatusFlagSIMRemovabilityKnown = 0x2,
+ MbbSubscriberReadyStatusFlagSIMRemovable = 0x4
+ } MBB_SUBSCRIBER_READY_STATUS_FLAGS;
+
+typedef struct _MBB_SUBSCRIBER_READY_INFO_EX3
+ {
+ MBB_READY_STATE ReadyState;
+ MBB_SUBSCRIBER_READY_STATUS_FLAGS StatusFlags;
+ MBB_STRING SubscriberId;
+ MBB_STRING SimIccId;
+ MBB_READY_INFO_FLAGS ReadyInfoFlags;
+ ULONG TelephoneNumberCount;
+ MBB_STRING TelephoneNumbers[ 1 ];
+ } MBB_SUBSCRIBER_READY_INFO_EX3;
+
+typedef struct _MBB_SUBSCRIBER_READY_INFO_EX3 *PMBB_SUBSCRIBER_READY_INFO_EX3;
+
+typedef struct _MBB_QUERY_RADIO_STATE
+ {
+ MBB_RADIO_STATE HwRadioState;
+ MBB_RADIO_STATE SwRadioState;
+ } MBB_QUERY_RADIO_STATE;
+
+typedef struct _MBB_QUERY_RADIO_STATE *PMBB_QUERY_RADIO_STATE;
+
+typedef struct _MBB_PIN_INFO
+ {
+ MBB_PIN_TYPE PinType;
+ MBB_PIN_STATE PinState;
+ ULONG AttemptsRemaining;
+ } MBB_PIN_INFO;
+
+typedef struct _MBB_PIN_INFO *PMBB_PIN_INFO;
+
+typedef struct _MBB_PIN_ACTION
+ {
+ MBB_PIN_TYPE PinType;
+ MBB_PIN_OPERATION PinOperation;
+ MBB_STRING Pin;
+ MBB_STRING NewPin;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_PIN_ACTION;
+
+typedef struct _MBB_PIN_ACTION *PMBB_PIN_ACTION;
+
+typedef struct _MBB_PIN_DESCRIPTION
+ {
+ MBB_PIN_MODE PinMode;
+ MBB_PIN_FORMAT PinFormat;
+ ULONG PinLengthMin;
+ ULONG PinLengthMax;
+ } MBB_PIN_DESCRIPTION;
+
+typedef struct _MBB_PIN_DESCRIPTION *PMBB_PIN_DESCRIPTION;
+
+typedef struct _MBB_PIN_LIST
+ {
+ MBB_PIN_DESCRIPTION PinDescPin1;
+ MBB_PIN_DESCRIPTION PinDescPin2;
+ MBB_PIN_DESCRIPTION PinDescDeviceSimPin;
+ MBB_PIN_DESCRIPTION PinDescDeviceFirstSimPin;
+ MBB_PIN_DESCRIPTION PinDescNetworkPin;
+ MBB_PIN_DESCRIPTION PinDescNetworkSubsetPin;
+ MBB_PIN_DESCRIPTION PinDescSvcProviderPin;
+ MBB_PIN_DESCRIPTION PinDescCorporatePin;
+ MBB_PIN_DESCRIPTION PinDescSubsidyLock;
+ MBB_PIN_DESCRIPTION PinDescCustom;
+ } MBB_PIN_LIST;
+
+typedef struct _MBB_PIN_LIST *PMBB_PIN_LIST;
+
+typedef struct _MBB_PROVIDER
+ {
+ MBB_STRING ProviderId;
+ ULONG ProviderState;
+ MBB_STRING ProviderName;
+ MBB_CELLULAR_CLASS CellularClass;
+ ULONG Rssi;
+ ULONG ErrorRate;
+ } MBB_PROVIDER;
+
+typedef struct _MBB_PROVIDER *PMBB_PROVIDER;
+
+typedef struct _MBB_PROVIDER_LIST
+ {
+ ULONG ProviderCount;
+ MBB_ARRAY_ELEMENT Providers[ 1 ];
+ } MBB_PROVIDER_LIST;
+
+typedef struct _MBB_PROVIDER_LIST *PMBB_PROVIDER_LIST;
+
+typedef struct _MBB_REGISTRATION_STATE
+ {
+ ULONG NetworkError;
+ MBB_REGISTER_STATE RegisterState;
+ MBB_REGISTER_MODE RegisterMode;
+ ULONG AvailableDataClasses;
+ MBB_CELLULAR_CLASS CurrentCellularClass;
+ MBB_STRING ProviderId;
+ MBB_STRING ProviderName;
+ MBB_STRING RoamingText;
+ ULONG RegFlags;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_REGISTRATION_STATE;
+
+typedef struct _MBB_REGISTRATION_STATE *PMBB_REGISTRATION_STATE;
+
+typedef struct _MBB_SET_REGISTER_STATE
+ {
+ MBB_STRING ProviderId;
+ MBB_REGISTER_ACTION RegisterAction;
+ ULONG DataClass;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SET_REGISTER_STATE;
+
+typedef struct _MBB_SET_REGISTER_STATE *PMBB_SET_REGISTER_STATE;
+
+typedef struct _MBB_SET_PACKET_SERVICE
+ {
+ MBB_PACKET_SERVICE_ACTION PacketServiceAction;
+ } MBB_SET_PACKET_SERVICE;
+
+typedef struct _MBB_SET_PACKET_SERVICE *PMBB_SET_PACKET_SERVICE;
+
+typedef struct _MBB_PACKET_SERVICE
+ {
+ ULONG NetworkError;
+ MBB_PACKET_SERVICE_STATE PacketServiceState;
+ ULONG HighestAvailableDataClass;
+ ULONGLONG UplinkSpeed;
+ ULONGLONG DownlinkSpeed;
+ } MBB_PACKET_SERVICE;
+
+typedef struct _MBB_PACKET_SERVICE *PMBB_PACKET_SERVICE;
+
+typedef struct _MBB_PACKET_SERVICE_INFO_V2
+ {
+ ULONG NetworkError;
+ MBB_PACKET_SERVICE_STATE PacketServiceState;
+ MBB_DATA_CLASS_VALUE CurrentDataClass;
+ ULONGLONG UplinkSpeed;
+ ULONGLONG DownlinkSpeed;
+ MBB_FREQUENCY_RANGE FrequencyRange;
+ } MBB_PACKET_SERVICE_INFO_V2;
+
+typedef struct _MBB_PACKET_SERVICE_INFO_V2 *PMBB_PACKET_SERVICE_INFO_V2;
+
+typedef struct _MBB_PLMN
+ {
+ USHORT Mcc;
+ USHORT Mnc;
+ } MBB_PLMN;
+
+typedef struct _MBB_PLMN *PMBB_PLMN;
+
+typedef struct _MBB_TAI
+ {
+ MBB_PLMN Plmn;
+ ULONG Tac;
+ } MBB_TAI;
+
+typedef struct _MBB_TAI *PMBB_TAI;
+
+typedef struct _MBB_PACKET_SERVICE_INFO_V3
+ {
+ ULONG NetworkError;
+ MBB_PACKET_SERVICE_STATE PacketServiceState;
+ MBB_DATA_CLASS_VALUE CurrentDataClass;
+ ULONGLONG UplinkSpeed;
+ ULONGLONG DownlinkSpeed;
+ MBB_FREQUENCY_RANGE FrequencyRange;
+ MBB_DATA_SUBCLASS_VALUE CurrentDataSubClass;
+ MBB_TAI TrackingAreaId;
+ } MBB_PACKET_SERVICE_INFO_V3;
+
+typedef struct _MBB_PACKET_SERVICE_INFO_V3 *PMBB_PACKET_SERVICE_INFO_V3;
+
+typedef struct _MBB_SET_SIGNAL_INDICATION
+ {
+ ULONG RssiInterval;
+ ULONG RssiThreshold;
+ ULONG ErrorRateThreshold;
+ } MBB_SET_SIGNAL_INDICATION;
+
+typedef struct _MBB_SET_SIGNAL_INDICATION *PMBB_SET_SIGNAL_INDICATION;
+
+typedef struct _MBB_SIGNAL_STATE
+ {
+ ULONG Rssi;
+ ULONG ErrorRate;
+ ULONG RssiInterval;
+ ULONG RssiThreshold;
+ ULONG ErrorRateThreshold;
+ } MBB_SIGNAL_STATE;
+
+typedef struct _MBB_SIGNAL_STATE *PMBB_SIGNAL_STATE;
+
+typedef struct _MBB_SET_CONTEXT_STATE
+ {
+ ULONG SessionId;
+ MBB_ACTIVATION_COMMAND ActivationCommand;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ MBB_CONTEXT_IP_TYPE IPType;
+ GUID ContextType;
+ CHAR DataBuffer[ 1 ];
+ } MBB_SET_CONTEXT_STATE;
+
+typedef struct _MBB_SET_CONTEXT_STATE *PMBB_SET_CONTEXT_STATE;
+
+typedef
+enum _MBB_ACCESS_MEDIA_PREF
+ {
+ MbbAccessMediaPrefNone = 0,
+ MbbAccessMediaPref3GPP = 1,
+ MbbAccessMediaPref3GPPPreferred = 2,
+ MbbAccessMediaPrefMaximum = ( MbbAccessMediaPref3GPPPreferred + 1 )
+ } MBB_ACCESS_MEDIA_PREF;
+
+typedef struct _MBB_SET_CONTEXT_STATE_EX3
+ {
+ ULONG SessionId;
+ MBB_ACTIVATION_COMMAND ActivationCommand;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ MBB_CONTEXT_IP_TYPE IPType;
+ GUID ContextType;
+ MBB_ACCESS_MEDIA_PREF MediaPreference;
+ } MBB_SET_CONTEXT_STATE_EX3;
+
+typedef struct _MBB_SET_CONTEXT_STATE_EX3 *PMBB_SET_CONTEXT_STATE_EX3;
+
+typedef struct _MBB_QUERY_CONTEXT_EX3
+ {
+ ULONG SessionId;
+ } MBB_QUERY_CONTEXT_EX3;
+
+typedef struct _MBB_QUERY_CONTEXT_EX3 *PMBB_QUERY_CONTEXT_EX3;
+
+typedef struct _MBB_CONTEXT_STATE
+ {
+ ULONG SessionId;
+ MBB_ACTIVATION_STATE ActivationState;
+ MBB_VOICE_CALL_STATE VoiceCallState;
+ MBB_CONTEXT_IP_TYPE IPType;
+ GUID ContextType;
+ ULONG NetworkError;
+ } MBB_CONTEXT_STATE;
+
+typedef struct _MBB_CONTEXT_STATE *PMBB_CONTEXT_STATE;
+
+typedef struct _MBB_CONTEXT_STATE_EX3
+ {
+ ULONG SessionId;
+ MBB_ACTIVATION_STATE ActivationState;
+ MBB_VOICE_CALL_STATE VoiceCallState;
+ MBB_CONTEXT_IP_TYPE IPType;
+ GUID ContextType;
+ ULONG NetworkError;
+ MBB_ACCESS_MEDIA_PREF MediaPreference;
+ } MBB_CONTEXT_STATE_EX3;
+
+typedef struct _MBB_CONTEXT_STATE_EX3 *PMBB_CONTEXT_STATE_EX3;
+
+typedef struct _MBB_SET_CONTEXT
+ {
+ ULONG ContextId;
+ GUID ContextType;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ MBB_STRING ProviderId;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SET_CONTEXT;
+
+typedef struct _MBB_SET_CONTEXT *PMBB_SET_CONTEXT;
+
+typedef struct _MBB_CONTEXT
+ {
+ ULONG ContextId;
+ GUID ContextType;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_CONTEXT;
+
+typedef struct _MBB_CONTEXT *PMBB_CONTEXT;
+
+typedef struct _MBB_CONTEXT_LIST
+ {
+ ULONG ContextCount;
+ MBB_ARRAY_ELEMENT Contexts[ 1 ];
+ } MBB_CONTEXT_LIST;
+
+typedef struct _MBB_CONTEXT_LIST *PMBB_CONTEXT_LIST;
+
+typedef struct _MBB_SERVICE_ACTIVATION
+ {
+ CHAR VendorSpecificBuffer[ 1 ];
+ } MBB_SERVICE_ACTIVATION;
+
+typedef struct _MBB_SERVICE_ACTIVATION *PMBB_SERVICE_ACTIVATION;
+
+typedef struct _MBB_SERVICE_ACTIVATION_STATUS
+ {
+ ULONG NetworkError;
+ CHAR VendorSpecificBuffer[ 1 ];
+ } MBB_SERVICE_ACTIVATION_STATUS;
+
+typedef struct _MBB_SERVICE_ACTIVATION_STATUS *PMBB_SERVICE_ACTIVATION_STATUS;
+
+typedef struct _MBB_IPV4_ADDRESS
+ {
+ ULONG OnLinkPrefixLength;
+ UCHAR IPV4Address[ 4 ];
+ } MBB_IPV4_ADDRESS;
+
+typedef struct _MBB_IPV4_ADDRESS *PMBB_IPV4_ADDRESS;
+
+typedef struct _MBB_IPV6_ADDRESS
+ {
+ ULONG OnLinkPrefixLength;
+ UCHAR IPV6Address[ 16 ];
+ } MBB_IPV6_ADDRESS;
+
+typedef struct _MBB_IPV6_ADDRESS *PMBB_IPV6_ADDRESS;
+
+typedef struct _MBB_IP_ADDRESS_INFO
+ {
+ ULONG SessionId;
+ ULONG IPv4Flags;
+ ULONG IPv6Flags;
+ ULONG IPv4AddressCount;
+ ULONG IPv4AddressOffset;
+ ULONG IPv6AddressCount;
+ ULONG IPv6AddressOffset;
+ ULONG IPv4GatewayOffset;
+ ULONG IPv6GatewayOffset;
+ ULONG IPv4DnsServerCount;
+ ULONG IPv4DnsServerOffset;
+ ULONG IPv6DnsServerCount;
+ ULONG IPv6DnsServerOffset;
+ ULONG IPv4MTU;
+ ULONG IPv6MTU;
+ } MBB_IP_ADDRESS_INFO;
+
+typedef struct _MBB_IP_ADDRESS_INFO *PMBB_IP_ADDRESS_INFO;
+
+typedef struct _MBB_PACKET_STATISTICS
+ {
+ ULONG InDiscards;
+ ULONG InErrors;
+ ULONGLONG InOctets;
+ ULONGLONG InPackets;
+ ULONGLONG OutOctets;
+ ULONGLONG OutPackets;
+ ULONG OutErrors;
+ ULONG OutDiscards;
+ } MBB_PACKET_STATISTICS;
+
+typedef struct _MBB_PACKET_STATISTICS *PMBB_PACKET_STATISTICS;
+
+typedef
+enum _MBB_VISIBLE_PROVIDERS_ACTION_VALUE
+ {
+ MbbVisibleProvidersActionFull = 0,
+ MbbVisibleProvidersActionMulticarrier = 0x1,
+ MbbVisibleProvidersActionMax = ( MbbVisibleProvidersActionMulticarrier + 1 )
+ } MBB_VISIBLE_PROVIDERS_ACTION_VALUE;
+
+typedef struct _MBB_GET_VISIBLE_PROVIDERS
+ {
+ ULONG Action;
+ } MBB_GET_VISIBLE_PROVIDERS;
+
+typedef struct _MBB_GET_VISIBLE_PROVIDERS *PMBB_GET_VISIBLE_PROVIDERS;
+
+typedef
+enum _MBB_SMS_STORAGE_STATE
+ {
+ MbbSmsStorageNotInitialized = 0,
+ MbbSmsStorageInitialized = 1
+ } MBB_SMS_STORAGE_STATE;
+
+typedef struct _MBB_SET_SMS_CONFIGURATION
+ {
+ MBB_SMS_FORMAT SmsFormat;
+ MBB_STRING ScAddress;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SET_SMS_CONFIGURATION;
+
+typedef struct _MBB_SET_SMS_CONFIGURATION *PMBB_SET_SMS_CONFIGURATION;
+
+typedef struct _MBB_SMS_CONFIGURATION
+ {
+ MBB_SMS_STORAGE_STATE SmsStorageState;
+ MBB_SMS_FORMAT SmsFormat;
+ ULONG MaxMessages;
+ ULONG CdmaShortMessageSize;
+ MBB_STRING ScAddress;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SMS_CONFIGURATION;
+
+typedef struct _MBB_SMS_CONFIGURATION *PMBB_SMS_CONFIGURATION;
+
+typedef struct _MBB_SMS_READ
+ {
+ MBB_SMS_FORMAT SmsFormat;
+ MBB_SMS_FLAG SmsFlag;
+ ULONG MessageIndex;
+ } MBB_SMS_READ;
+
+typedef struct _MBB_SMS_READ *PMBB_SMS_READ;
+
+typedef struct _MBB_SMS_CDMA_RECORD
+ {
+ ULONG MessageIndex;
+ MBB_SMS_MESSAGE_STATUS MessageStatus;
+ MBB_STRING Address;
+ MBB_STRING TimeStamp;
+ MBB_SMS_CDMA_ENCODING EncodingId;
+ MBB_SMS_CDMA_LANGUAGE LanguageId;
+ MBB_ARRAY_ELEMENT EncodedMessage;
+ ULONG SizeInCharacters;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SMS_CDMA_RECORD;
+
+typedef struct _MBB_SMS_CDMA_RECORD *PMBB_SMS_CDMA_RECORD;
+
+typedef struct _MBB_SMS_PDU_RECORD
+ {
+ ULONG MessageIndex;
+ MBB_SMS_MESSAGE_STATUS MessageStatus;
+ MBB_ARRAY_ELEMENT PduData;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SMS_PDU_RECORD;
+
+typedef struct _MBB_SMS_PDU_RECORD *PMBB_SMS_PDU_RECORD;
+
+typedef struct _MBB_SMS_RECEIVE
+ {
+ MBB_SMS_FORMAT SmsFormat;
+ ULONG MessageCount;
+ MBB_ARRAY_ELEMENT MessageElement[ 1 ];
+ } MBB_SMS_RECEIVE;
+
+typedef struct _MBB_SMS_RECEIVE *PMBB_SMS_RECEIVE;
+
+typedef struct _MBB_SMS_SEND_PDU
+ {
+ MBB_ARRAY_ELEMENT PduData;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SMS_SEND_PDU;
+
+typedef struct _MBB_SMS_SEND_PDU *PMBB_SMS_SEND_PDU;
+
+typedef struct _MBB_SMS_SEND_CDMA
+ {
+ MBB_SMS_CDMA_ENCODING EncodingId;
+ MBB_SMS_CDMA_LANGUAGE LanguageId;
+ MBB_STRING Address;
+ MBB_ARRAY_ELEMENT EncodedMessage;
+ ULONG SizeInCharacters;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SMS_SEND_CDMA;
+
+typedef struct _MBB_SMS_SEND_CDMA *PMBB_SMS_SEND_CDMA;
+
+typedef struct _MBB_SMS_SEND
+ {
+ MBB_SMS_FORMAT SmsFormat;
+ /* [switch_is] */ /* [switch_type] */ union __MIDL___MIDL_itf_MbbMessages_0000_0000_0001
+ {
+ /* [case()] */ MBB_SMS_SEND_PDU Pdu;
+ /* [case()] */ MBB_SMS_SEND_CDMA Cdma;
+ } u;
+ } MBB_SMS_SEND;
+
+typedef struct _MBB_SMS_SEND *PMBB_SMS_SEND;
+
+typedef struct _MBB_SMS_SEND_STATUS
+ {
+ ULONG MessageReference;
+ } MBB_SMS_SEND_STATUS;
+
+typedef struct _MBB_SMS_SEND_STATUS *PMBB_SMS_SEND_STATUS;
+
+typedef struct _MBB_SMS_DELETE
+ {
+ MBB_SMS_FLAG SmsFlags;
+ ULONG MessageIndex;
+ } MBB_SMS_DELETE;
+
+typedef struct _MBB_SMS_DELETE *PMBB_SMS_DELETE;
+
+typedef struct _MBB_SMS_STATUS
+ {
+ ULONG StatusFlags;
+ ULONG MessageIndex;
+ } MBB_SMS_STATUS;
+
+typedef struct _MBB_SMS_STATUS *PMBB_SMS_STATUS;
+
+typedef
+enum _MBB_USSD_ACTION
+ {
+ MbbUSSDInitiate = 0,
+ MbbUSSDContinue = 1,
+ MbbUSSDCancel = 2
+ } MBB_USSD_ACTION;
+
+typedef
+enum _MBB_USSD_RESPONSE
+ {
+ MbbUSSDNoActionRequired = 0,
+ MbbUSSDActionRequired = 1,
+ MbbUSSDTerminated = 2,
+ MbbUSSDOtherLocalClient = 3,
+ MbbUSSDOperationNotSupported = 4,
+ MbbUSSDNetworkTimeOut = 5
+ } MBB_USSD_RESPONSE;
+
+typedef
+enum _MBB_USSD_SESSION_STATE
+ {
+ MbbUSSDNewSession = 0,
+ MbbUSSDExistingSession = 1
+ } MBB_USSD_SESSION_STATE;
+
+typedef struct _MBB_SET_USSD
+ {
+ MBB_USSD_ACTION USSDAction;
+ ULONG USSDDataCodingScheme;
+ MBB_ARRAY_ELEMENT USSDPayload;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SET_USSD;
+
+typedef struct _MBB_SET_USSD *PMBB_SET_USSD;
+
+typedef struct _MBB_USSD
+ {
+ MBB_USSD_RESPONSE USSDResponse;
+ MBB_USSD_SESSION_STATE USSDSessionState;
+ ULONG USSDDataCodingScheme;
+ MBB_ARRAY_ELEMENT USSDPayload;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_USSD;
+
+typedef struct _MBB_USSD *PMBB_USSD;
+
+typedef struct _MBB_AKA_AUTH_CHALLENGE
+ {
+ UCHAR Rand[ 16 ];
+ UCHAR Autn[ 16 ];
+ } MBB_AKA_AUTH_CHALLENGE;
+
+typedef struct _MBB_AKA_AUTH_CHALLENGE *PMBB_AKA_AUTH_CHALLENGE;
+
+typedef struct _MBB_AKA_AUTH_RESPONSE
+ {
+ UCHAR Res[ 16 ];
+ ULONG ResLength;
+ UCHAR IK[ 16 ];
+ UCHAR CK[ 16 ];
+ UCHAR Auts[ 14 ];
+ } MBB_AKA_AUTH_RESPONSE;
+
+typedef struct _MBB_AKA_AUTH_RESPONSE *PMBB_AKA_AUTH_RESPONSE;
+
+typedef struct _MBB_AKAP_AUTH_CHALLENGE
+ {
+ UCHAR Rand[ 16 ];
+ UCHAR Autn[ 16 ];
+ MBB_STRING NetworkName;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_AKAP_AUTH_CHALLENGE;
+
+typedef struct _MBB_AKAP_AUTH_CHALLENGE *PMBB_AKAP_AUTH_CHALLENGE;
+
+typedef struct _MBB_AKAP_AUTH_RESPONSE
+ {
+ UCHAR Res[ 16 ];
+ ULONG ResLength;
+ UCHAR IK[ 16 ];
+ UCHAR CK[ 16 ];
+ UCHAR Auts[ 14 ];
+ } MBB_AKAP_AUTH_RESPONSE;
+
+typedef struct _MBB_AKAP_AUTH_RESPONSE *PMBB_AKAP_AUTH_RESPONSE;
+
+typedef struct _MBB_SIM_AUTH_CHALLENGE
+ {
+ UCHAR Rand1[ 16 ];
+ UCHAR Rand2[ 16 ];
+ UCHAR Rand3[ 16 ];
+ ULONG n;
+ } MBB_SIM_AUTH_CHALLENGE;
+
+typedef struct _MBB_SIM_AUTH_CHALLENGE *PMBB_SIM_AUTH_CHALLENGE;
+
+typedef struct _MBB_SIM_AUTH_RESPONSE
+ {
+ UCHAR Sres1[ 4 ];
+ UCHAR Kc1[ 8 ];
+ UCHAR Sres2[ 4 ];
+ UCHAR Kc2[ 8 ];
+ UCHAR Sres3[ 4 ];
+ UCHAR Kc3[ 8 ];
+ ULONG n;
+ } MBB_SIM_AUTH_RESPONSE;
+
+typedef struct _MBB_SIM_AUTH_RESPONSE *PMBB_SIM_AUTH_RESPONSE;
+
+typedef struct _MBB_PACKET_FILTERS
+ {
+ ULONG SessionId;
+ ULONG PacketFiltersCount;
+ MBB_ARRAY_ELEMENT ArrayElement[ 1 ];
+ } MBB_PACKET_FILTERS;
+
+typedef struct _MBB_PACKET_FILTERS *PMBB_PACKET_FILTERS;
+
+typedef struct _MBB_SINGLE_PACKET_FILTER
+ {
+ ULONG FilterSize;
+ ULONG PacketFilterOffset;
+ ULONG PacketMaskOffset;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SINGLE_PACKET_FILTER;
+
+typedef struct _MBB_SINGLE_PACKET_FILTER *PMBB_SINGLE_PACKET_FILTER;
+
+typedef struct _MBB_SINGLE_PACKET_FILTER_V2
+ {
+ ULONG FilterSize;
+ ULONG PacketFilterOffset;
+ ULONG PacketMaskOffset;
+ ULONG FilterId;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SINGLE_PACKET_FILTER_V2;
+
+typedef struct _MBB_SINGLE_PACKET_FILTER_V2 *PMBB_SINGLE_PACKET_FILTER_V2;
+
+typedef struct _MBB_NETWORK_IDLE_HINT
+ {
+ MBB_NETWORK_IDLE_HINT_STATE NetworkIdleHintState;
+ } MBB_NETWORK_IDLE_HINT;
+
+typedef struct _MBB_NETWORK_IDLE_HINT *PMBB_NETWORK_IDLE_HINT;
+
+typedef struct _MBB_DEVICE_SERVICE_ELEMENT
+ {
+ GUID DeviceServiceId;
+ MBB_DSS_PAYLOAD_SUPPORT DSSPayload;
+ ULONG MaxDSSInstances;
+ ULONG CIDCount;
+ ULONG CIDList[ 1 ];
+ } MBB_DEVICE_SERVICE_ELEMENT;
+
+typedef struct _MBB_DEVICE_SERVICE_ELEMENT *PMBB_DEVICE_SERVICE_ELEMENT;
+
+typedef struct _MBB_DEVICE_SERVICES_HEADER
+ {
+ ULONG DeviceServicesCount;
+ ULONG MaxDSSSessions;
+ MBB_ARRAY_ELEMENT ArrayElement[ 1 ];
+ } MBB_DEVICE_SERVICES_HEADER;
+
+typedef struct _MBB_DEVICE_SERVICES_HEADER *PMBB_DEVICE_SERVICES_HEADER;
+
+typedef struct _MBB_SUBSCRIBE_EVENT_ENTRY
+ {
+ GUID DeviceServiceId;
+ ULONG CIDCount;
+ ULONG CIDList[ 1 ];
+ } MBB_SUBSCRIBE_EVENT_ENTRY;
+
+typedef struct _MBB_SUBSCRIBE_EVENT_ENTRY *PMBB_SUBSCRIBE_EVENT_ENTRY;
+
+typedef struct _MBB_SUBSCRIBE_EVENT_LIST
+ {
+ ULONG Count;
+ MBB_ARRAY_ELEMENT ArrayElement[ 1 ];
+ } MBB_SUBSCRIBE_EVENT_LIST;
+
+typedef struct _MBB_SUBSCRIBE_EVENT_LIST *PMBB_SUBSCRIBE_EVENT_LIST;
+
+typedef struct _MBB_SET_DSS_CONNECT
+ {
+ GUID DeviceServiceId;
+ ULONG DssSessionId;
+ MBB_DSS_LINK_STATE DssLinkState;
+ } MBB_SET_DSS_CONNECT;
+
+typedef struct _MBB_SET_DSS_CONNECT *PMBB_SET_DSS_CONNECT;
+
+typedef struct _MBB_SET_DSS_CLOSE
+ {
+ ULONG DssSessionId;
+ } MBB_SET_DSS_CLOSE;
+
+typedef struct _MBB_SET_DSS_CLOSE *PMBB_SET_DSS_CLOSE;
+
+typedef struct _MBB_MULTICARRIER_CURRENT_CID_LIST
+ {
+ ULONG CIDCount;
+ ULONG CIDList[ 1 ];
+ } MBB_MULTICARRIER_CURRENT_CID_LIST;
+
+typedef struct _MBB_MULTICARRIER_CURRENT_CID_LIST *PMBB_MULTICARRIER_CURRENT_CID_LIST;
+
+typedef
+enum _MBB_UICC_APP_TYPE
+ {
+ MbbUiccAppTypeUnknown = 0,
+ MbbUiccAppTypeMf = 1,
+ MbbUiccAppTypeMfSIM = 2,
+ MbbUiccAppTypeMfRUIM = 3,
+ MbbUiccAppTypeUSIM = 4,
+ MbbUiccAppTypeCSIM = 5,
+ MbbUiccAppTypeISIM = 6,
+ MbbUiccAppTypeMax = ( MbbUiccAppTypeISIM + 1 )
+ } MBB_UICC_APP_TYPE;
+
+typedef struct _MBB_UICC_APP_INFO
+ {
+ MBB_UICC_APP_TYPE AppType;
+ MBB_ARRAY_ELEMENT AppId;
+ MBB_ARRAY_ELEMENT AppName;
+ ULONG NumPins;
+ MBB_ARRAY_ELEMENT PinRef;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_UICC_APP_INFO;
+
+typedef struct _MBB_UICC_APP_INFO *PMBB_UICC_APP_INFO;
+
+typedef struct _MBB_UICC_APP_LIST
+ {
+ ULONG Version;
+ ULONG AppCount;
+ ULONG ActiveAppIndex;
+ ULONG AppListSize;
+ MBB_ARRAY_ELEMENT DataBuffer[ 1 ];
+ } MBB_UICC_APP_LIST;
+
+typedef struct _MBB_UICC_APP_LIST *PMBB_UICC_APP_LIST;
+
+typedef
+enum _MBB_UICC_FILE_ACCESSIBILITY
+ {
+ MbbUiccFileAccessibilityUnknown = 0,
+ MbbUiccFileAccessibilityNotShareable = 1,
+ MbbUiccFileAccessibilityShareable = 2,
+ MbbUiccFileAccessibilityMax = ( MbbUiccFileAccessibilityShareable + 1 )
+ } MBB_UICC_FILE_ACCESSIBILITY;
+
+typedef
+enum _MBB_UICC_FILE_TYPE
+ {
+ MbbUiccFileTypeUnknown = 0,
+ MbbUiccFileTypeWorkingEf = 1,
+ MbbUiccFileTypeInternalEf = 2,
+ MbbUiccFileTypeDfOrAdf = 3,
+ MbbUiccFileTypeMax = ( MbbUiccFileTypeDfOrAdf + 1 )
+ } MBB_UICC_FILE_TYPE;
+
+typedef
+enum _MBB_UICC_FILE_STRUCTURE
+ {
+ MbbUiccFileStructureUnknown = 0,
+ MbbUiccFileStructureTransparent = 1,
+ MbbUiccFileStructureCyclic = 2,
+ MbbUiccFileStructureLinear = 3,
+ MbbUiccFileStructureBertlv = 4,
+ MbbUiccFileStructureMax = ( MbbUiccFileStructureBertlv + 1 )
+ } MBB_UICC_FILE_STRUCTURE;
+
+typedef struct _MBB_UICC_FILE_PATH
+ {
+ ULONG Version;
+ MBB_ARRAY_ELEMENT AppId;
+ MBB_ARRAY_ELEMENT FilePath;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_UICC_FILE_PATH;
+
+typedef struct _MBB_UICC_FILE_PATH *PMBB_UICC_FILE_PATH;
+
+typedef struct _MBB_UICC_FILE_STATUS
+ {
+ ULONG Version;
+ ULONG StatusWord1;
+ ULONG StatusWord2;
+ MBB_UICC_FILE_ACCESSIBILITY FileAccessibility;
+ MBB_UICC_FILE_TYPE FileType;
+ MBB_UICC_FILE_STRUCTURE FileStructure;
+ ULONG ItemCount;
+ ULONG ItemSize;
+ MBB_PIN_TYPE FileLockStatus[ 4 ];
+ } MBB_UICC_FILE_STATUS;
+
+typedef struct _MBB_UICC_FILE_STATUS *PMBB_UICC_FILE_STATUS;
+
+typedef struct _MBB_UICC_ACCESS_BINARY
+ {
+ ULONG Version;
+ MBB_ARRAY_ELEMENT AppId;
+ MBB_ARRAY_ELEMENT UiccFilePath;
+ ULONG FileOffset;
+ ULONG NumberOfBytes;
+ MBB_ARRAY_ELEMENT LocalPin;
+ MBB_ARRAY_ELEMENT BinaryData;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_UICC_ACCESS_BINARY;
+
+typedef struct _MBB_UICC_ACCESS_BINARY *PMBB_UICC_ACCESS_BINARY;
+
+typedef struct _MBB_UICC_ACCESS_RECORD
+ {
+ ULONG Version;
+ MBB_ARRAY_ELEMENT AppId;
+ MBB_ARRAY_ELEMENT UiccFilePath;
+ ULONG RecordNumber;
+ MBB_ARRAY_ELEMENT LocalPin;
+ MBB_ARRAY_ELEMENT RecordData;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_UICC_ACCESS_RECORD;
+
+typedef struct _MBB_UICC_ACCESS_RECORD *PMBB_UICC_ACCESS_RECORD;
+
+typedef struct _MBB_UICC_RESPONSE
+ {
+ ULONG Version;
+ ULONG StatusWord1;
+ ULONG StatusWord2;
+ MBB_ARRAY_ELEMENT ResponseData;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_UICC_RESPONSE;
+
+typedef struct _MBB_UICC_RESPONSE *PMBB_UICC_RESPONSE;
+
+typedef struct _MBB_PIN_APP
+ {
+ ULONG Version;
+ MBB_ARRAY_ELEMENT AppId;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_PIN_APP;
+
+typedef struct _MBB_PIN_APP *PMBB_PIN_APP;
+
+typedef struct _MBB_PIN_ACTION_EX2
+ {
+ MBB_PIN_TYPE PinType;
+ MBB_PIN_OPERATION PinOperation;
+ MBB_STRING Pin;
+ MBB_STRING NewPin;
+ MBB_ARRAY_ELEMENT AppId;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_PIN_ACTION_EX2;
+
+typedef struct _MBB_PIN_ACTION_EX2 *PMBB_PIN_ACTION_EX2;
+
+typedef struct _MBB_SYS_CAPS_INFO
+ {
+ ULONG NumberOfExecutors;
+ ULONG NumberOfSlots;
+ ULONG Concurrency;
+ } MBB_SYS_CAPS_INFO;
+
+typedef struct _MBB_SYS_CAPS_INFO *PMBB_SYS_CAPS_INFO;
+
+typedef struct _MBB_DEVICE_CAPS_V2
+ {
+ MBB_DEVICE_TYPE DeviceType;
+ MBB_CELLULAR_CLASS CellularClass;
+ MBB_VOICE_CLASS VoiceClass;
+ MBB_SIM_CLASS SimClass;
+ ULONG DataClass;
+ ULONG SmsCaps;
+ ULONG ControlCaps;
+ ULONG dwMaxSessions;
+ MBB_STRING CustomDataClass;
+ MBB_STRING DeviceIdString;
+ MBB_STRING FirmwareInfo;
+ MBB_STRING HardwareInfo;
+ ULONG DeviceIndex;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_DEVICE_CAPS_V2;
+
+typedef struct _MBB_DEVICE_CAPS_V2 *PMBB_DEVICE_CAPS_V2;
+
+typedef struct _MBB_DEVICE_SLOT_MAPPING_INFO
+ {
+ ULONG MapCount;
+ MBB_ARRAY_ELEMENT SlotMapList[ 1 ];
+ } MBB_DEVICE_SLOT_MAPPING_INFO;
+
+typedef struct _MBB_DEVICE_SLOT_MAPPING_INFO *PMBB_DEVICE_SLOT_MAPPING_INFO;
+
+typedef
+enum _MBB_UICCSLOT_STATE
+ {
+ MbbUiccSlotStateOffEmpty = 0,
+ MbbUiccSlotStateOff = 1,
+ MbbUiccSlotStateEmpty = 2,
+ MbbUiccSlotStateNotReady = 3,
+ MbbUiccSlotStateActive = 4,
+ MbbUiccSlotStateError = 5
+ } MBB_UICCSLOT_STATE;
+
+typedef struct _MBB_SLOT_INFO_REQ
+ {
+ ULONG SlotIndex;
+ } MBB_SLOT_INFO_REQ;
+
+typedef struct _MBB_SLOT_INFO_REQ *PMBB_SLOT_INFO_REQ;
+
+typedef struct _MBB_SLOT_INFO
+ {
+ ULONG SlotIndex;
+ MBB_UICCSLOT_STATE State;
+ } MBB_SLOT_INFO;
+
+typedef struct _MBB_SLOT_INFO *PMBB_SLOT_INFO;
+
+typedef struct _MBB_DEVICE_BINDINGS_INFO
+ {
+ ULONG ApplicationCount;
+ MBB_ARRAY_ELEMENT ApplicationList[ 1 ];
+ } MBB_DEVICE_BINDINGS_INFO;
+
+typedef struct _MBB_DEVICE_BINDINGS_INFO *PMBB_DEVICE_BINDINGS_INFO;
+
+typedef
+enum _MBB_REGISTRATION_VOICE_CLASS
+ {
+ MbbRegistrationVoiceClassVoiceCentric = 0,
+ MbbRegistrationVoiceClassDataCentric = 1
+ } MBB_REGISTRATION_VOICE_CLASS;
+
+typedef
+enum _MBB_REGISTRATION_VOICE_DOMAIN_PREFERENCE
+ {
+ MbbRegistrationVoiceDomainPreferenceCsOnly = 0,
+ MbbRegistrationVoiceDomainPreferenceCsPreferred = 1,
+ MbbRegistrationVoiceDomainPreferenceImsPreferred = 2,
+ MbbRegistrationVoiceDomainPreferenceImsOnly = 3
+ } MBB_REGISTRATION_VOICE_DOMAIN_PREFERENCE;
+
+typedef
+enum _MBB_REGISTRATION_VOICE_SUPPORT
+ {
+ MbbRegistrationVoiceSupportNone = 0,
+ MbbRegistrationVoiceSupportIms = 0x1,
+ MbbRegistrationVoiceSupportEmergencyAttach = 0x2,
+ MbbRegistrationVoiceSupportCs = 0x4,
+ MbbRegistrationVoiceSupportCsfb = 0x8,
+ MbbRegistrationVoiceSupport1xCsfb = 0x10,
+ MbbRegistrationVoiceSupportCsEmergency = 0x20
+ } MBB_REGISTRATION_VOICE_SUPPORT;
+
+typedef
+enum _MBB_REGISTRATION_CDMA_ROAM_MODE
+ {
+ MbbRegistrationCdmaRoamModeAutomatic = 0,
+ MbbRegistrationCdmaRoamModeHomeOnly = 1
+ } MBB_REGISTRATION_CDMA_ROAM_MODE;
+
+typedef struct _MBB_SET_REGISTER_STATE_V2
+ {
+ MBB_STRING ProviderId;
+ MBB_REGISTER_ACTION RegisterAction;
+ ULONG DataClass;
+ MBB_REGISTRATION_VOICE_CLASS VoiceClass;
+ MBB_REGISTRATION_VOICE_DOMAIN_PREFERENCE VoiceDomain;
+ MBB_REGISTRATION_CDMA_ROAM_MODE CdmaRoamMode;
+ MBB_ARRAY_ELEMENT AcquisitionOrder[ 1 ];
+ } MBB_SET_REGISTER_STATE_V2;
+
+typedef struct _MBB_SET_REGISTER_STATE_V2 *PMBB_SET_REGISTER_STATE_V2;
+
+typedef struct _MBB_REGISTRATION_STATE_V2
+ {
+ ULONG NetworkError;
+ MBB_REGISTER_STATE RegisterState;
+ MBB_REGISTER_MODE RegisterMode;
+ ULONG AvailableDataClasses;
+ MBB_CELLULAR_CLASS CurrentCellularClass;
+ MBB_STRING ProviderId;
+ MBB_STRING ProviderName;
+ MBB_STRING RoamingText;
+ ULONG RegFlags;
+ MBB_REGISTRATION_VOICE_SUPPORT VoiceSupport;
+ ULONG CurrentRATClass;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_REGISTRATION_STATE_V2;
+
+typedef struct _MBB_REGISTRATION_STATE_V2 *PMBB_REGISTRATION_STATE_V2;
+
+typedef struct _MBB_REGISTRATION_STATE_INFOS_V2
+ {
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT RegistrationStateList[ 1 ];
+ } MBB_REGISTRATION_STATE_INFOS_V2;
+
+typedef struct _MBB_REGISTRATION_STATE_INFOS_V2 *PMBB_REGISTRATION_STATE_INFOS_V2;
+
+typedef struct _MBB_REGISTRATION_STATE_INFO_V2
+ {
+ ULONG NetworkError;
+ MBB_REGISTER_STATE RegisterState;
+ MBB_REGISTER_MODE RegisterMode;
+ ULONG AvailableDataClasses;
+ MBB_CELLULAR_CLASS CurrentCellularClass;
+ MBB_STRING ProviderId;
+ MBB_STRING ProviderName;
+ MBB_STRING RoamingText;
+ ULONG RegistrationFlag;
+ ULONG PreferredDataClasses;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_REGISTRATION_STATE_INFO_V2;
+
+typedef struct _MBB_REGISTRATION_STATE_INFO_V2 *PMBB_REGISTRATION_STATE_INFO_V2;
+
+typedef
+enum _MBB_IMS_VOICE_STATUS
+ {
+ MbbImsVoiceStatusUnknown = 0,
+ MbbImsVoiceStatusUnregistered = 1,
+ MbbImsVoiceStatusRegistered = 2
+ } MBB_IMS_VOICE_STATUS;
+
+typedef struct _MBB_SET_IMS_VOICE_STATE
+ {
+ MBB_IMS_VOICE_STATUS ImsVoiceStatus;
+ } MBB_SET_IMS_VOICE_STATE;
+
+typedef struct _MBB_SET_IMS_VOICE_STATE *PMBB_SET_IMS_VOICE_STATE;
+
+typedef struct _MBB_IMS_VOICE_STATE
+ {
+ MBB_IMS_VOICE_STATUS ImsVoiceStatus;
+ } MBB_IMS_VOICE_STATE;
+
+typedef struct _MBB_IMS_VOICE_STATE *PMBB_IMS_VOICE_STATE;
+
+typedef struct _MBB_SET_SIGNAL_INDICATION_V2
+ {
+ ULONG RssiInterval;
+ ULONG RssiThreshold;
+ ULONG ErrorRateThreshold;
+ ULONG SnrThreshold;
+ } MBB_SET_SIGNAL_INDICATION_V2;
+
+typedef struct _MBB_SET_SIGNAL_INDICATION_V2 *PMBB_SET_SIGNAL_INDICATION_V2;
+
+typedef struct _MBB_SIGNAL_STATE_V2
+ {
+ ULONG Rssi;
+ ULONG ErrorRate;
+ ULONG RssiInterval;
+ ULONG RssiThreshold;
+ ULONG ErrorRateThreshold;
+ ULONG Snr;
+ ULONG SnrThreshold;
+ ULONG DataClass;
+ } MBB_SIGNAL_STATE_V2;
+
+typedef struct _MBB_SIGNAL_STATE_V2 *PMBB_SIGNAL_STATE_V2;
+
+typedef struct _MBB_RSRP_SNR_INFO
+ {
+ ULONG RSRP;
+ ULONG SNR;
+ ULONG RSRPThreshold;
+ ULONG SNRThreshold;
+ MBB_DATA_CLASS_VALUE SystemType;
+ } MBB_RSRP_SNR_INFO;
+
+typedef struct _MBB_RSRP_SNR_INFO *PMBB_RSRP_SNR_INFO;
+
+typedef struct _MBB_RSRP_SNR
+ {
+ ULONG ElementCount;
+ MBB_RSRP_SNR_INFO DataBuffer[ 1 ];
+ } MBB_RSRP_SNR;
+
+typedef struct _MBB_RSRP_SNR *PMBB_RSRP_SNR;
+
+typedef struct _MBB_SIGNAL_STATE_INFO_V2
+ {
+ ULONG Rssi;
+ ULONG ErrorRate;
+ ULONG SignalStrengthInterval;
+ ULONG RssiThreshold;
+ ULONG ErrorRateThreshold;
+ ULONG RsrpSnrOffset;
+ ULONG RsrpSnrSize;
+ MBB_RSRP_SNR DataBuffer;
+ } MBB_SIGNAL_STATE_INFO_V2;
+
+typedef struct _MBB_SIGNAL_STATE_INFO_V2 *PMBB_SIGNAL_STATE_INFO_V2;
+
+typedef struct _MBB_SIGNAL_STATE_INFOS_V2
+ {
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT SignalStateList[ 1 ];
+ } MBB_SIGNAL_STATE_INFOS_V2;
+
+typedef struct _MBB_SIGNAL_STATE_INFOS_V2 *PMBB_SIGNAL_STATE_INFOS_V2;
+
+typedef
+enum _MBB_LOCATION_TRIGGER_MODE
+ {
+ MbbLocationTriggerNone = 0,
+ MbbLocationTriggerAreaCode = 1,
+ MbbLocationTriggerAreaCellId = 2
+ } MBB_LOCATION_TRIGGER_MODE;
+
+typedef struct _MBB_SET_LOCATION_STATE
+ {
+ MBB_LOCATION_TRIGGER_MODE Trigger;
+ } MBB_SET_LOCATION_STATE;
+
+typedef struct _MBB_SET_LOCATION_STATE *PMBB_SET_LOCATION_STATE;
+
+typedef struct _MBB_LOCATION_STATE_INFO
+ {
+ MBB_LOCATION_TRIGGER_MODE Trigger;
+ ULONG DataClass;
+ ULONG AreaCode;
+ ULONG CellId;
+ } MBB_LOCATION_STATE_INFO;
+
+typedef struct _MBB_LOCATION_STATE_INFO *PMBB_LOCATION_STATE_INFO;
+
+typedef struct _MBB_NITZ_INFO
+ {
+ ULONG Year;
+ ULONG Month;
+ ULONG Day;
+ ULONG Hour;
+ ULONG Minute;
+ ULONG Second;
+ ULONG TimeZoneOffsetMinutes;
+ ULONG DaylightSavingTimeOffsetMinutes;
+ ULONG DataClasses;
+ } MBB_NITZ_INFO;
+
+typedef struct _MBB_NITZ_INFO *PMBB_NITZ_INFO;
+
+typedef struct _MBB_ATR_INFO
+ {
+ MBB_ARRAY_ELEMENT2 Atr;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_ATR_INFO;
+
+typedef struct _MBB_ATR_INFO *PMBB_ATR_INFO;
+
+typedef struct _MBB_SET_UICC_OPEN_CHANNEL
+ {
+ MBB_ARRAY_ELEMENT2 AppId;
+ ULONG SelectP2Arg;
+ ULONG ChannelGroup;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SET_UICC_OPEN_CHANNEL;
+
+typedef struct _MBB_SET_UICC_OPEN_CHANNEL *PMBB_SET_UICC_OPEN_CHANNEL;
+
+typedef struct _MBB_UICC_OPEN_CHANNEL_INFO
+ {
+ UCHAR Status[ 4 ];
+ ULONG Channel;
+ MBB_ARRAY_ELEMENT2 Response;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_UICC_OPEN_CHANNEL_INFO;
+
+typedef struct _MBB_UICC_OPEN_CHANNEL_INFO *PMBB_UICC_OPEN_CHANNEL_INFO;
+
+typedef struct _MBB_SET_UICC_CLOSE_CHANNEL
+ {
+ ULONG Channel;
+ ULONG ChannelGroup;
+ ULONG SelectP2Arg;
+ } MBB_SET_UICC_CLOSE_CHANNEL;
+
+typedef struct _MBB_SET_UICC_CLOSE_CHANNEL *PMBB_SET_UICC_CLOSE_CHANNEL;
+
+typedef struct _MBB_UICC_CLOSE_CHANNEL_INFO
+ {
+ UCHAR Status[ 4 ];
+ } MBB_UICC_CLOSE_CHANNEL_INFO;
+
+typedef struct _MBB_UICC_CLOSE_CHANNEL_INFO *PMBB_UICC_CLOSE_CHANNEL_INFO;
+
+typedef
+enum _MBB_UICC_SECURE_MESSAGING
+ {
+ MbbUiccSecureMessagingNone = 0,
+ MbbUiccSecureMessagingNoHdrAuth = 1
+ } MBB_UICC_SECURE_MESSAGING;
+
+typedef
+enum _MBB_UICC_CLASS_BYTE_TYPE
+ {
+ MbbUiccClassByteTypeInterindustry = 0,
+ MbbUiccClassByteTypeExtended = 1
+ } MBB_UICC_CLASS_BYTE_TYPE;
+
+typedef struct _MBB_SET_UICC_APDU
+ {
+ ULONG Channel;
+ MBB_UICC_SECURE_MESSAGING SecureMessaging;
+ MBB_UICC_CLASS_BYTE_TYPE Type;
+ MBB_ARRAY_ELEMENT2 Command;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SET_UICC_APDU;
+
+typedef struct _MBB_SET_UICC_APDU *PMBB_SET_UICC_APDU;
+
+typedef struct _MBB_UICC_APDU_INFO
+ {
+ UCHAR Status[ 4 ];
+ MBB_ARRAY_ELEMENT2 Response;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_UICC_APDU_INFO;
+
+typedef struct _MBB_UICC_APDU_INFO *PMBB_UICC_APDU_INFO;
+
+typedef struct _MBB_UICC_TERMINAL_CAPABILITY_TLV
+ {
+ UCHAR Data[ 3 ];
+ } MBB_UICC_TERMINAL_CAPABILITY_TLV;
+
+typedef struct _MBB_UICC_TERMINAL_CAPABILITY_TLV *PMBB_UICC_TERMINAL_CAPABILITY_TLV;
+
+typedef struct _MBB_SET_UICC_TERMINAL_CAPABILITY
+ {
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT CapabilityList[ 1 ];
+ } MBB_SET_UICC_TERMINAL_CAPABILITY;
+
+typedef struct _MBB_SET_UICC_TERMINAL_CAPABILITY *PMBB_SET_UICC_TERMINAL_CAPABILITY;
+
+typedef struct _MBB_UICC_TERMINAL_CAPABILITY_INFO
+ {
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT CapabilityList[ 1 ];
+ } MBB_UICC_TERMINAL_CAPABILITY_INFO;
+
+typedef struct _MBB_UICC_TERMINAL_CAPABILITY_INFO *PMBB_UICC_TERMINAL_CAPABILITY_INFO;
+
+typedef
+enum _MBB_UICC_PASSTHROUGH_ACTION
+ {
+ MbbUiccPassThroughDisable = 0,
+ MbbUiccPassThroughEnable = 1
+ } MBB_UICC_PASSTHROUGH_ACTION;
+
+typedef
+enum _MBB_UICC_PASSTHROUGH_STATUS
+ {
+ MbbUiccPassThroughDisabled = 0,
+ MbbUiccPassThroughEnabled = 1
+ } MBB_UICC_PASSTHROUGH_STATUS;
+
+typedef struct _MBB_SET_UICC_RESET
+ {
+ MBB_UICC_PASSTHROUGH_ACTION PassThroughAction;
+ } MBB_SET_UICC_RESET;
+
+typedef struct _MBB_SET_UICC_RESET *PMBB_SET_UICC_RESET;
+
+typedef struct _MBB_UICC_RESET_INFO
+ {
+ MBB_UICC_PASSTHROUGH_STATUS PassThroughStatus;
+ } MBB_UICC_RESET_INFO;
+
+typedef struct _MBB_UICC_RESET_INFO *PMBB_UICC_RESET_INFO;
+
+typedef struct _MBB_SAR_CONFIG_INDICES
+ {
+ ULONG SarAntennaIndex;
+ ULONG SarBackoffIndex;
+ } MBB_SAR_CONFIG_INDICES;
+
+typedef struct _MBB_SAR_CONFIG_INDICES *PMBB_SAR_CONFIG_INDICES;
+
+typedef struct _MBB_SAR_CONFIG_INFO
+ {
+ MBB_SAR_CONTROL_MODE SarMode;
+ MBB_SAR_BACKOFF_STATE SarBackoffStatus;
+ MBB_SAR_WIFI_HARDWARE_INTEGRATION SarWifiIntegration;
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT Configurations[ 1 ];
+ } MBB_SAR_CONFIG_INFO;
+
+typedef struct _MBB_SAR_CONFIG_INFO *PMBB_SAR_CONFIG_INFO;
+
+typedef struct _MBB_SET_SAR_CONFIG
+ {
+ MBB_SAR_CONTROL_MODE SarMode;
+ MBB_SAR_BACKOFF_STATE SarBackoffStatus;
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT Configurations[ 1 ];
+ } MBB_SET_SAR_CONFIG;
+
+typedef struct _MBB_SET_SAR_CONFIG *PMBB_SET_SAR_CONFIG;
+
+typedef struct _MBB_SAR_TRANSMISSION_STATUS_INFO
+ {
+ MBB_SAR_TRANSMISSION_STATUS_NOTIFICATION_STATE ChannelNotification;
+ MBB_SAR_TRANSMISSION_STATUS TransmissionStatus;
+ ULONG HysteresisTimer;
+ } MBB_SAR_TRANSMISSION_STATUS_INFO;
+
+typedef struct _MBB_SAR_TRANSMISSION_STATUS_INFO *PMBB_SAR_TRANSMISSION_STATUS_INFO;
+
+typedef struct _MBB_SET_SAR_TRANSMISSION_STATUS
+ {
+ MBB_SAR_TRANSMISSION_STATUS_NOTIFICATION_STATE ChannelNotification;
+ ULONG HysteresisTimer;
+ } MBB_SET_SAR_TRANSMISSION_STATUS;
+
+typedef struct _MBB_SET_SAR_TRANSMISSION_STATUS *PMBB_SET_SAR_TRANSMISSION_STATUS;
+
+typedef struct _MBB_SET_MS_CONTEXT_PROVISIONED_CONTEXT_V2
+ {
+ MBB_BASICCONNECTEXT_CONTEXT_OPERATIONS Operation;
+ GUID ContextType;
+ MBB_CONTEXT_IP_TYPE IPType;
+ MBB_BASICCONNECTEXT_CONTEXT_ENABLE Enable;
+ MBB_BASICCONNECTEXT_CONTEXT_ROAMING_CONTROL Roaming;
+ MBB_BASICCONNECTEXT_CONTEXT_MEDIA_TYPE MediaType;
+ MBB_BASICCONNECTEXT_CONTEXT_SOURCE Source;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_SET_MS_CONTEXT_PROVISIONED_CONTEXT_V2;
+
+typedef struct _MBB_SET_MS_CONTEXT_PROVISIONED_CONTEXT_V2 *PMBB_SET_MS_CONTEXT_PROVISIONED_CONTEXT_V2;
+
+typedef struct _MBB_MS_CONTEXT_V2
+ {
+ ULONG ContextId;
+ GUID ContextType;
+ MBB_CONTEXT_IP_TYPE IPType;
+ MBB_BASICCONNECTEXT_CONTEXT_ENABLE Enable;
+ MBB_BASICCONNECTEXT_CONTEXT_ROAMING_CONTROL Roaming;
+ MBB_BASICCONNECTEXT_CONTEXT_MEDIA_TYPE MediaType;
+ MBB_BASICCONNECTEXT_CONTEXT_SOURCE Source;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_MS_CONTEXT_V2;
+
+typedef struct _MBB_MS_CONTEXT_V2 *PMBB_MS_CONTEXT_V2;
+
+typedef struct _MBB_MS_NETWORK_BLACKLIST_PROVIDER
+ {
+ ULONG MCC;
+ ULONG MNC;
+ MBB_BASICCONNECTEXT_NETWORK_BLACKLIST_TYPE NetworkBlacklistType;
+ } MBB_MS_NETWORK_BLACKLIST_PROVIDER;
+
+typedef struct _MBB_MS_NETWORK_BLACKLIST_PROVIDER *PMBB_MS_NETWORK_BLACKLIST_PROVIDER;
+
+typedef struct _MBB_MS_NETWORK_BLACKLIST_INFO
+ {
+ MBB_BASICCONNECTEXT_NETWORK_BLACKLIST_STATE BlacklistState;
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT Contexts[ 1 ];
+ } MBB_MS_NETWORK_BLACKLIST_INFO;
+
+typedef struct _MBB_MS_NETWORK_BLACKLIST_INFO *PMBB_MS_NETWORK_BLACKLIST_INFO;
+
+typedef struct _MBB_MS_VERSION_INFO
+ {
+ USHORT bcdMBIMVersion;
+ USHORT bcdMBIMExtendedVersion;
+ } MBB_MS_VERSION_INFO;
+
+typedef struct _MBB_MS_VERSION_INFO *PMBB_MS_VERSION_INFO;
+
+typedef struct _MBB_MS_LTE_ATTACH_CONTEXT
+ {
+ MBB_CONTEXT_IP_TYPE IPType;
+ MBB_BASICCONNECTEXT_LTEATTACH_ROAMING_CONTROL Roaming;
+ MBB_BASICCONNECTEXT_CONTEXT_SOURCE Source;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_MS_LTE_ATTACH_CONTEXT;
+
+typedef struct _MBB_MS_LTE_ATTACH_CONTEXT *PMBB_MS_LTE_ATTACH_CONTEXT;
+
+typedef struct _MBB_SET_MS_CONTEXT_LTE_ATTACH_CONFIG
+ {
+ MBB_BASICCONNECTEXT_LTEATTACH_CONTEXT_OPERATIONS Operation;
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT Contexts[ 1 ];
+ } MBB_SET_MS_CONTEXT_LTE_ATTACH_CONFIG;
+
+typedef struct _MBB_SET_MS_CONTEXT_LTE_ATTACH_CONFIG *PMBB_SET_MS_CONTEXT_LTE_ATTACH_CONFIG;
+
+typedef struct _MBB_MS_LTE_ATTACH_CONFIG_INFO
+ {
+ ULONG ElementCount;
+ MBB_ARRAY_ELEMENT Contexts[ 1 ];
+ } MBB_MS_LTE_ATTACH_CONFIG_INFO;
+
+typedef struct _MBB_MS_LTE_ATTACH_CONFIG_INFO *PMBB_MS_LTE_ATTACH_CONFIG_INFO;
+
+typedef struct _MBB_MS_LTE_ATTACH_STATUS
+ {
+ MBB_BASICCONNECTEXT_LTEATTACH_STATE LteAttachState;
+ MBB_CONTEXT_IP_TYPE IPType;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_MS_LTE_ATTACH_STATUS;
+
+typedef struct _MBB_MS_LTE_ATTACH_STATUS *PMBB_MS_LTE_ATTACH_STATUS;
+
+typedef struct _MBB_MS_LTE_ATTACH_STATUS_V2
+ {
+ MBB_BASICCONNECTEXT_LTEATTACH_STATE LteAttachState;
+ ULONG NetworkError;
+ MBB_CONTEXT_IP_TYPE IPType;
+ MBB_STRING AccessString;
+ MBB_STRING UserName;
+ MBB_STRING Password;
+ MBB_COMPRESSION Compression;
+ MBB_AUTH_PROTOCOL AuthProtocol;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_MS_LTE_ATTACH_STATUS_V2;
+
+typedef struct _MBB_MS_LTE_ATTACH_STATUS_V2 *PMBB_MS_LTE_ATTACH_STATUS_V2;
+
+typedef struct _MBB_MS_SYS_CAPS_INFO
+ {
+ ULONG NumberOfExecutors;
+ ULONG NumberOfSlots;
+ ULONG Concurrency;
+ ULONG64 ModemId;
+ } MBB_MS_SYS_CAPS_INFO;
+
+typedef struct _MBB_MS_SYS_CAPS_INFO *PMBB_MS_SYS_CAPS_INFO;
+
+typedef struct _MBB_MS_DEVICE_CAPS_INFO_V2
+ {
+ MBB_DEVICE_TYPE DeviceType;
+ MBB_CELLULAR_CLASS CellularClass;
+ MBB_VOICE_CLASS VoiceClass;
+ MBB_SIM_CLASS SimClass;
+ ULONG DataClass;
+ ULONG SmsCaps;
+ ULONG ControlCaps;
+ ULONG dwMaxSessions;
+ MBB_STRING CustomDataClass;
+ MBB_STRING DeviceIdString;
+ MBB_STRING FirmwareInfo;
+ MBB_STRING HardwareInfo;
+ ULONG ExecutorIndex;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_MS_DEVICE_CAPS_INFO_V2;
+
+typedef struct _MBB_MS_DEVICE_CAPS_INFO_V2 *PMBB_MS_DEVICE_CAPS_INFO_V2;
+
+typedef struct _MBB_MS_DEVICE_CAPS_INFO_V3_OBS
+ {
+ MBB_DEVICE_TYPE DeviceType;
+ MBB_CELLULAR_CLASS CellularClass;
+ MBB_VOICE_CLASS VoiceClass;
+ ULONG SimClassBitMasks;
+ ULONG DataClass;
+ ULONG SmsCaps;
+ ULONG ControlCaps;
+ ULONGLONG MiscCaps;
+ ULONG dwMaxSessions;
+ ULONG ExecutorIndex;
+ ULONG WcdmaBandClass;
+ } MBB_MS_DEVICE_CAPS_INFO_V3_OBS;
+
+typedef struct _MBB_MS_DEVICE_CAPS_INFO_V3_OBS *PMBB_MS_DEVICE_CAPS_INFO_V3_OBS;
+
+typedef struct _MBB_MS_DEVICE_CAPS_INFO_V3
+ {
+ MBB_DEVICE_TYPE DeviceType;
+ MBB_CELLULAR_CLASS CellularClass;
+ MBB_VOICE_CLASS VoiceClass;
+ ULONG SimClassBitMasks;
+ ULONG DataClass;
+ ULONG SmsCaps;
+ ULONG ControlCaps;
+ ULONGLONG DataSubClass;
+ ULONG dwMaxSessions;
+ ULONG ExecutorIndex;
+ ULONG WcdmaBandClass;
+ } MBB_MS_DEVICE_CAPS_INFO_V3;
+
+typedef struct _MBB_MS_DEVICE_CAPS_INFO_V3 *PMBB_MS_DEVICE_CAPS_INFO_V3;
+
+typedef struct _MBB_MS_DEVICE_SLOT_MAPPING_INFO
+ {
+ ULONG MapCount;
+ MBB_ARRAY_ELEMENT SlotMapList[ 1 ];
+ } MBB_MS_DEVICE_SLOT_MAPPING_INFO;
+
+typedef struct _MBB_MS_DEVICE_SLOT_MAPPING_INFO *PMBB_MS_DEVICE_SLOT_MAPPING_INFO;
+
+typedef struct _MBB_MS_SLOT_INFO_REQ
+ {
+ ULONG SlotIndex;
+ } MBB_MS_SLOT_INFO_REQ;
+
+typedef struct _MBB_MS_SLOT_INFO_REQ *PMBB_MS_SLOT_INFO_REQ;
+
+typedef struct _MBB_MS_SLOT_INFO
+ {
+ ULONG SlotIndex;
+ MBB_BASICCONNECTEXT_UICCSLOT_STATE State;
+ } MBB_MS_SLOT_INFO;
+
+typedef struct _MBB_MS_SLOT_INFO *PMBB_MS_SLOT_INFO;
+
+typedef struct _MBB_MS_PCO_VALUE
+ {
+ ULONG SessionId;
+ ULONG PcoDataSize;
+ MBB_PCO_TYPE PcoDataType;
+ UCHAR PcoDataBuffer[ 1 ];
+ } MBB_MS_PCO_VALUE;
+
+typedef struct _MBB_MS_PCO_VALUE *PMBB_MS_PCO_VALUE;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO_REQ
+ {
+ ULONG MaxGSMCount;
+ ULONG MaxUMTSCount;
+ ULONG MaxTDSCDMACount;
+ ULONG MaxLTECount;
+ ULONG MaxCDMACount;
+ } MBB_MS_BASE_STATIONS_INFO_REQ;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO_REQ *PMBB_MS_BASE_STATIONS_INFO_REQ;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO_REQ_V2
+ {
+ ULONG MaxGSMCount;
+ ULONG MaxUMTSCount;
+ ULONG MaxTDSCDMACount;
+ ULONG MaxLTECount;
+ ULONG MaxCDMACount;
+ ULONG MaxNRCount;
+ } MBB_MS_BASE_STATIONS_INFO_REQ_V2;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO_REQ_V2 *PMBB_MS_BASE_STATIONS_INFO_REQ_V2;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO
+ {
+ MBB_DATA_CLASS_VALUE SystemType;
+ MBB_ARRAY_ELEMENT GSMServingCell;
+ MBB_ARRAY_ELEMENT UMTSServingCell;
+ MBB_ARRAY_ELEMENT TDSCDMAServingCell;
+ MBB_ARRAY_ELEMENT LTEServingCell;
+ MBB_ARRAY_ELEMENT GSMNmr;
+ MBB_ARRAY_ELEMENT UMTSMrl;
+ MBB_ARRAY_ELEMENT TDSCDMAMrl;
+ MBB_ARRAY_ELEMENT LTEMrl;
+ MBB_ARRAY_ELEMENT CDMAMrl;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_MS_BASE_STATIONS_INFO;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO *PMBB_MS_BASE_STATIONS_INFO;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO_V2
+ {
+ MBB_DATA_CLASS_VALUE SystemType;
+ MBB_DATA_SUBCLASS_VALUE SystemSubType;
+ MBB_ARRAY_ELEMENT GSMServingCell;
+ MBB_ARRAY_ELEMENT UMTSServingCell;
+ MBB_ARRAY_ELEMENT TDSCDMAServingCell;
+ MBB_ARRAY_ELEMENT LTEServingCell;
+ MBB_ARRAY_ELEMENT GSMNmr;
+ MBB_ARRAY_ELEMENT UMTSMrl;
+ MBB_ARRAY_ELEMENT TDSCDMAMrl;
+ MBB_ARRAY_ELEMENT LTEMrl;
+ MBB_ARRAY_ELEMENT CDMAMrl;
+ MBB_ARRAY_ELEMENT NRServingCells;
+ MBB_ARRAY_ELEMENT NRNeighborCells;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_MS_BASE_STATIONS_INFO_V2;
+
+typedef struct _MBB_MS_BASE_STATIONS_INFO_V2 *PMBB_MS_BASE_STATIONS_INFO_V2;
+
+typedef struct _MBB_MODEM_LOGGING_CONFIG
+ {
+ ULONG Version;
+ ULONG MaxSegmentSize;
+ ULONG MaxFlushTime;
+ MBB_BASICCONNECTEXT_MODEM_LOGGING_LEVEL_CONFIG LevelConfig;
+ } MBB_MODEM_LOGGING_CONFIG;
+
+typedef struct _MBB_MODEM_LOGGING_CONFIG *PMBB_MODEM_LOGGING_CONFIG;
+
+typedef struct _MBB_TLV_IE
+ {
+ MBB_TLV_TYPE Type;
+ UCHAR Reserved;
+ UCHAR PaddingLength;
+ ULONG DataLength;
+ } MBB_TLV_IE;
+
+typedef struct _MBB_TLV_IE *PMBB_TLV_IE;
+
+typedef
+enum _MBB_ACCESS_TYPE
+ {
+ MbbAccessUnknown = 0,
+ MbbAccess3GPP = 1,
+ MbbAccessNon3GPP = 2,
+ MbbAccessMaximum = ( MbbAccessNon3GPP + 1 )
+ } MBB_ACCESS_TYPE;
+
+typedef struct _MBB_PRE_DFLT_NSSAI_INFO
+ {
+ MBB_ACCESS_TYPE AccessType;
+ MBB_TLV_IE PreferredNSSAI;
+ } MBB_PRE_DFLT_NSSAI_INFO;
+
+typedef struct _MBB_PRE_DFLT_NSSAI_INFO *PMBB_PRE_DFLT_NSSAI_INFO;
+
+typedef struct _MBB_SNSSAI_INFO
+ {
+ UCHAR SnssaiLength;
+ UCHAR Sst;
+ } MBB_SNSSAI_INFO;
+
+typedef struct _MBB_SNSSAI_INFO *PMBB_SNSSAI_INFO;
+
+typedef struct _MBB_TAI_LIST_SINGLE_PLMN
+ {
+ MBB_PLMN Plmn;
+ UCHAR ElementCount;
+ ULONG TacList[ 1 ];
+ } MBB_TAI_LIST_SINGLE_PLMN;
+
+typedef struct _MBB_TAI_LIST_SINGLE_PLMN *PMBB_TAI_LIST_SINGLE_PLMN;
+
+typedef struct _MBB_TAI_LIST_MULTI_PLMNS
+ {
+ UCHAR ElementCount;
+ MBB_TAI TaiList[ 1 ];
+ } MBB_TAI_LIST_MULTI_PLMNS;
+
+typedef struct _MBB_TAI_LIST_MULTI_PLMNS *PMBB_TAI_LIST_MULTI_PLMNS;
+
+typedef struct _MBB_TAI_LIST_INFO
+ {
+ UCHAR ListType;
+ /* [switch_is] */ /* [switch_type] */ union __MIDL___MIDL_itf_MbbMessages_0000_0000_0002
+ {
+ /* [case()] */ MBB_TAI_LIST_SINGLE_PLMN SinglePlmnTaiList;
+ /* [case()] */ MBB_TAI_LIST_MULTI_PLMNS MultiPlmnsTaiList;
+ } u;
+ } MBB_TAI_LIST_INFO;
+
+typedef struct _MBB_TAI_LIST_INFO *PMBB_TAI_LIST_INFO;
+
+typedef struct _MBB_DNN
+ {
+ UCHAR DnnLength;
+ } MBB_DNN;
+
+typedef struct _MBB_DNN *PMBB_DNN;
+
+typedef struct _MBB_LADN
+ {
+ MBB_DNN Dnn;
+ } MBB_LADN;
+
+typedef struct _MBB_LADN *PMBB_LADN;
+
+typedef
+enum _MBB_MODEM_CONFIG_STATUS
+ {
+ ModemConfigStatusUnknown = 0,
+ ModemConfigStatusStarted = 1,
+ ModemConfigStatusCompleted = 2,
+ ModemConfigStatusMaximum = ( ModemConfigStatusCompleted + 1 )
+ } MBB_MODEM_CONFIG_STATUS;
+
+typedef struct _MBB_MODEM_CONFIG_INFO
+ {
+ MBB_MODEM_CONFIG_STATUS ConfigStatus;
+ MBB_TLV_IE ConfigName;
+ } MBB_MODEM_CONFIG_INFO;
+
+typedef struct _MBB_MODEM_CONFIG_INFO *PMBB_MODEM_CONFIG_INFO;
+
+typedef
+enum _MBB_MICO_MODE
+ {
+ MicoModeDisabled = 0,
+ MicoModeEnabled = 1,
+ MicoModeUnsupported = 2,
+ MBIMMicoModeDefault = 3,
+ MicoModeMaximum = ( MBIMMicoModeDefault + 1 )
+ } MBB_MICO_MODE;
+
+typedef
+enum _MBB_DRX_PARAMS
+ {
+ DRXNotSpecified = 0,
+ MBIMDRXNotSupported = 1,
+ DRXCycle32 = 2,
+ DRXCycle64 = 3,
+ DRXCycle128 = 4,
+ DRXCycle256 = 5,
+ DRXCycleMaximum = ( DRXCycle256 + 1 )
+ } MBB_DRX_PARAMS;
+
+typedef
+enum _MBB_DEFAULT_PDU_HINT
+ {
+ MBIMDefaultPDUSessionActivationUnlikely = 0,
+ MBIMDefaultPDUSessionActivationLikely = 1,
+ DefaultPDUMaximum = ( MBIMDefaultPDUSessionActivationLikely + 1 )
+ } MBB_DEFAULT_PDU_HINT;
+
+typedef
+enum _MBB_MS_LADN_IND
+ {
+ LADNInfoNotNeeded = 0,
+ LADNInfoRequested = 1,
+ LADNInfoMaximum = ( LADNInfoRequested + 1 )
+ } MBB_MS_LADN_IND;
+
+typedef struct _MBB_REGISTRATION_PARAMS_INFO
+ {
+ MBB_MICO_MODE MicoMode;
+ MBB_DRX_PARAMS DRXParams;
+ MBB_MS_LADN_IND LADNInfo;
+ MBB_DEFAULT_PDU_HINT DefaultPDUHint;
+ ULONG ReRegisterIfNeeded;
+ } MBB_REGISTRATION_PARAMS_INFO;
+
+typedef struct _MBB_REGISTRATION_PARAMS_INFO *PMBB_REGISTRATION_PARAMS_INFO;
+
+typedef
+enum _MBB_MICO_IND
+ {
+ RaaiTypeRaNotAllocated = 0,
+ RaaiTypeRaAllocated = 1,
+ RaaiTypeNotAvailable = 0xffffffff
+ } MBB_MICO_IND;
+
+typedef struct _MBB_NW_PARAMS_QUERY_INFO
+ {
+ USHORT AreConfigurationsNeeded;
+ USHORT AreUEPoliciesNeeded;
+ } MBB_NW_PARAMS_QUERY_INFO;
+
+typedef struct _MBB_NW_PARAMS_QUERY_INFO *PMBB_NW_PARAMS_QUERY_INFO;
+
+typedef struct _MBB_NW_PARAMS_INFO
+ {
+ MBB_MICO_IND MicoInd;
+ MBB_DRX_PARAMS DRXParams;
+ } MBB_NW_PARAMS_INFO;
+
+typedef struct _MBB_NW_PARAMS_INFO *PMBB_NW_PARAMS_INFO;
+
+typedef
+enum _MBB_WAKE_TYPE
+ {
+ WakeTypeCIDResponse = 0,
+ WakeTypeCIDIndication = 1,
+ WakeTypePacket = 2
+ } MBB_WAKE_TYPE;
+
+typedef struct _MBB_WAKE_REASON
+ {
+ MBB_WAKE_TYPE WakeType;
+ ULONG SessionId;
+ } MBB_WAKE_REASON;
+
+typedef struct _MBB_WAKE_REASON *PMBB_WAKE_REASON;
+
+typedef struct _MBB_WAKE_COMMAND
+ {
+ MBB_COMMAND Command;
+ ULONG PayloadOffset;
+ ULONG PayloadSize;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_WAKE_COMMAND;
+
+typedef struct _MBB_WAKE_COMMAND *PMBB_WAKE_COMMAND;
+
+typedef struct _MBB_WAKE_PACKET
+ {
+ ULONG FilterId;
+ ULONG OriginalPacketSize;
+ ULONG SavedPacketOffset;
+ ULONG SavedPacketSize;
+ UCHAR DataBuffer[ 1 ];
+ } MBB_WAKE_PACKET;
+
+typedef struct _MBB_WAKE_PACKET *PMBB_WAKE_PACKET;
+
+#include <packoff.h>
+
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/network/wwan/cxwmbclass/inc/mbbncm.h b/network/wwan/cxwmbclass/inc/mbbncm.h
new file mode 100644
index 00000000..9731dedf
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/mbbncm.h
@@ -0,0 +1,431 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#pragma once
+
+#define NCM10_CC_INTERFACE_CLASS (0x02)
+#define NCM10_CC_INTERFACE_SUBCLASS (0x0d)
+#define NCM10_CC_INTERFACE_PROTOCOL (0x00)
+
+#define MBIM_CC_INTERFACE_CLASS (0x02)
+#define MBIM_CC_INTERFACE_SUBCLASS (0x0e)
+#define MBIM_CC_INTERFACE_PROTOCOL (0x00)
+#define MBIM_CC_INTERFACE_NBL_PROTOCOL (0x01)
+#define MBIM_CC_INTERFACE_NETPACKET_PROTOCOL (0x02)
+
+
+#define MBIM_DC_INTERFACE_CLASS (0x0A)
+#define MBIM_DC_INTERFACE_SUBCLASS (0x00)
+#define MBIM_DC_INTERFACE_PROTOCOL (0x02)
+
+#define MBIM_MBB_FUNCDESC_MIN_VERSION (0x0100)
+#define MBIM_MBB_FUNCDESC_EXTENDED_MIN_VERSION (0x0100)
+
+#define SEND_ENCAPSULATE_COMMAND (0x00)
+#define GET_ENCAPSULATE_RESPONSE (0x01)
+#define RESET_FUNCTION (0x05)
+#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER (0x41)
+#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER (0x42)
+#define SET_PACKET_FILTER (0x43)
+#define GET_STATISTIC (0x44)
+
+#define GET_NTB_PARAMETERS (0x80)
+#define GET_NBT_FORMAT (0x83)
+#define SET_NBT_FORMAT (0x84)
+#define GET_NTB_INPUT_SIZE (0x85)
+#define SET_NTB_INPUT_SIZE (0x86)
+#define GET_MAX_DATAGRAM_SIZE (0x87)
+
+
+#define MBIM_MIN_SEGMENT_SIZE (1280)
+#define MBIM_MAX_PACKET_FILTER_SIZE (192)
+#define MBIM_MIN_NUMBER_OF_PACKET_FILTERS (16)
+#define MBIM_MIN_MTU_SIZE (1280)
+#define MBIM_MAX_MTU_SIZE (1500)
+
+#define USB_CDC_CS_DESCRIPTOR_TYPE (0x24)
+
+#define USB_CDC_CS_DESCRIPTOR_SUBTYPE (0x0)
+#define USB_CDC_UNION_DESCRIPTOR_SUBTYPE (0x6)
+#define USB_CDC_CS_ECM_DESCRIPTOR_SUBTYPE (0xf)
+#define USB_CDC_CS_NCM_DESCRIPTOR_SUBTYPE (0x1a)
+#define USB_CDC_CS_MBB_DESCRIPTOR_SUBTYPE (0x1b)
+#define USB_CDC_CS_MBB_DESCRIPTOR_EXTENDED_SUBTYPE (0x1c)
+
+
+#define USB_CDC_NOTIFICATION_NETWORK_CONNECTION (0x00)
+#define USB_CDC_NOTIFICATION_RESPONSE_AVAILABLE (0x01)
+#define USB_CDC_NOTIFICATION_CONNECTION_SPEED_CHANGE (0x2a)
+
+#define NCM_NETWORK_CAPS_SET_FILTER_SUPPORTED (1 << 0)
+#define NCM_NETWORK_CAPS_GET_SET_ADDRESS_SUPPORTED (1 << 1)
+#define NCM_NETWORK_CAPS_ENCAPSULATED_COMMAND_SUPPORTED (1 << 2)
+#define NCM_NETWORK_CAPS_MAX_DATAGRAM_SUPPORTED (1 << 3)
+#define NCM_NETWORK_CAPS_GET_SET_CRC_SUPPORTED (1 << 4)
+#define NCM_NETWORK_CAPS_GET_8_BYTE_INPUT_SIZE_SUPPORTED (1 << 5)
+
+#define NCM_NTB_FORMAT_16_BIT (1 << 0)
+#define NCM_NTB_FORMAT_32_BIT (1 << 1)
+
+#define NCM_PACKET_FILTER_DIRECTED (1 << 2)
+
+#define NCM_SET_NTB_FORMAT_16_BIT (0x0)
+#define NCM_SET_NTB_FORMAT_32_BIT (0x1)
+
+
+
+#define NCM_STAT_RESERVED 0x00
+#define NCM_XMIT_OK 0x01
+#define NCM_RCV_OK 0x02
+#define NCM_XMIT_ERROR 0x03
+#define NCM_RCV_ERROR 0x04
+#define NCM_RCV_NO_BUFFER 0x05
+#define NCM_DIRECTED_BYTES_XMIT 0x06
+#define NCM_DIRECTED_FRAMES_XMIT 0x07
+#define NCM_MULTICAST_BYTES_XMIT 0x08
+#define NCM_MULTICAST_FRAMES_XMIT 0x09
+#define NCM_BROADCAST_BYTES_XMIT 0x0A
+#define NCM_BROADCAST_FRAMES_XMIT 0x0B
+#define NCM_DIRECTED_BYTES_RCV 0x0C
+#define NCM_DIRECTED_FRAMES_RCV 0x0D
+#define NCM_MULTICAST_BYTES_RCV 0x0E
+#define NCM_MULTICAST_FRAMES_RCV 0x0F
+#define NCM_BROADCAST_BYTES_RCV 0x10
+#define NCM_BROADCAST_FRAMES_RCV 0x11
+#define NCM_RCV_CRC_ERROR 0x12
+#define NCM_TRANSMIT_QUEUE_LENGTH 0x13
+#define NCM_RCV_ERROR_ALIGNMENT 0x14
+#define NCM_XMIT_ONE_COLLISION 0x15
+#define NCM_XMIT_MORE_COLLISIONS 0x16
+#define NCM_XMIT_DEFERRED 0x17
+#define NCM_XMIT_MAX_COLLISIONS 0x18
+#define NCM_RCV_OVERRUN 0x19
+#define NCM_XMIT_UNDERRUN 0x1A
+#define NCM_XMIT_HEARTBEAT_FAILURE 0x1B
+#define NCM_XMIT_TIMES_CRS_LOST 0x1C
+#define NCM_XMIT_LATE_COLLISIONS 0x1D
+
+#define NCM_NDP_SESSION_SHIFT 24
+#define NCM_NDP_SIGNATURE_MASK 0x00FFFFFF
+
+#define NCM_NTH16_SIG 'HMCN'
+#define NCM_NTH32_SIG 'hmcn'
+
+#define NCM_NDP16_IPS 'SPI'
+#define NCM_NDP16_VENDOR 'SSD'
+
+#define NCM_NDP32_IPS 'spi'
+#define NCM_NDP32_VENDOR 'ssd'
+
+#define NCM_CID_SIG 'dcbm'
+
+#pragma pack( push,1)
+
+typedef struct _NCM_NTB_PARAMETER {
+
+ USHORT wLength;
+ USHORT bmNtbFormatSupported;
+ ULONG dwNtbInMaxSize;
+ USHORT wNdpInDivisor;
+ USHORT wNdpInPayloadRemainder;
+ USHORT wNdpInAlignment;
+ USHORT wReserved1;
+ ULONG dwNtbOutMaxSize;
+ USHORT wNdpOutDivisor;
+ USHORT wNdpOutPayloadRemainder;
+ USHORT wNdpOutAlignment;
+ USHORT wNtbOutMaxDatagrams;
+
+} NCM_NTB_PARAMETER, *PNCM_NTB_PARAMETER;
+
+typedef struct _USB_CS_DESCRIPTOR {
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+ BYTE bSubType;
+
+} USB_CS_DESCRIPTOR, *PUSB_CS_DESCRIPTOR;
+
+typedef struct _USB_CS_UNION_DESCRIPTOR {
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+ BYTE bSubType;
+ BYTE bControlInterface;
+ BYTE bSubordinateInterface[1];
+
+} USB_CS_UNION_DESCRIPTOR, *PUSB_CS_UNION_DESCRIPTOR;
+
+
+typedef struct _USB_CS_CDC_DESCRIPTOR {
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+ BYTE bSubType;
+ USHORT wCDCVersion;
+
+} USB_CS_CDC_DESCRIPTOR, *PUSB_CS_CDC_DESCRIPTOR;
+
+typedef struct _USB_CS_ECM_DESCRIPTOR {
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+ BYTE bSubType;
+ BYTE iMacAddress;
+ ULONG bmEthernetStatistics;
+ USHORT wMaxSegmentSize;
+ USHORT wNumberMCFilters;
+ BYTE bNumberPowerFilters;
+
+} USB_CS_ECM_DESCRIPTOR, *PUSB_CS_ECM_DESCRIPTOR;
+
+typedef struct _USB_CS_NCM_DESCRIPTOR {
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+ BYTE bSubType;
+ USHORT wNcmVersion;
+ BYTE bmNetworkCapabilities;
+
+} USB_CS_NCM_DESCRIPTOR, *PUSB_CS_NCM_DESCRIPTOR;
+
+
+typedef struct _USB_CS_MBB_DESCRIPTOR {
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+ BYTE bSubType;
+ USHORT wMbbVersion;
+ USHORT wMaxControlMessage;
+ BYTE bNumberPowerFilters;
+ BYTE bMaxFilterSize;
+ USHORT wMaxSegmentSize;
+ BYTE bmNetworkCapabilities;
+
+} USB_CS_MBB_DESCRIPTOR, *PUSB_CS_MBB_DESCRIPTOR;
+
+typedef struct _USB_CS_MBB_DESCRIPTOR_EXTENDED {
+
+ BYTE bLength;
+ BYTE bDescriptorType;
+ BYTE bSubType;
+ USHORT wMbbVersion;
+ BYTE bMaxOutstandingCommandMessages;
+ USHORT wMTU;
+
+} USB_CS_MBB_DESCRIPTOR_EXTENDED, *PUSB_CS_MBB_DESCRIPTOR_EXTENDED;
+
+typedef struct _USB_CDC_NOTIFICATION {
+
+ BYTE bmRequestType;
+ BYTE bNotificationCode;
+ USHORT wValue;
+ USHORT wIndex;
+ USHORT wLength;
+
+} USB_CDC_NOTIFICATION, *PUSB_CDC_NOTIFICATION;
+
+typedef struct _USB_CDC_NOTIFICATION_SPEED_CHANGE {
+
+ USB_CDC_NOTIFICATION NotificationHeader;
+ ULONG DownLinkBitRate;
+ ULONG UpLinkBitRate;
+
+} USB_CDC_NOTIFICATION_SPEED_CHANGE, *PUSB_CDC_NOTIFICATION_SPEED_CHANGE;
+
+
+typedef struct _NCM_NTH16 {
+
+ ULONG dwSignature;
+ USHORT wHeaderLength;
+ USHORT wSequence;
+ USHORT wBlockLength;
+ USHORT wFpIndex;
+
+} NCM_NTH16, *PNCM_NTH16;
+
+typedef struct _NCM_NTH32 {
+
+ ULONG dwSignature;
+ USHORT wHeaderLength;
+ USHORT wSequence;
+ ULONG dwBlockLength;
+ ULONG dwFpIndex;
+
+} NCM_NTH32, *PNCM_NTH32;
+
+typedef struct _NCM_NDP16_DATAGRAM {
+
+ USHORT wDatagramIndex;
+ USHORT wDatagramLength;
+
+} NCM_NDP16_DATAGRAM, *PNCM_NDP16_DATAGRAM;
+
+
+typedef struct _NCM_NDP16 {
+
+ ULONG dwSignature;
+ USHORT wLength;
+ USHORT wNextFpIndex;
+
+ NCM_NDP16_DATAGRAM Datagram[1];
+
+} NCM_NDP16, *PNCM_NDP16;
+
+
+typedef struct _NCM_NDP32_DATAGRAM {
+
+ ULONG dwDatagramIndex;
+ ULONG dwDatagramLength;
+
+} NCM_NDP32_DATAGRAM, *PNCM_NDP32_DATAGRAM;
+
+
+typedef struct _NCM_NDP32 {
+
+ ULONG dwSignature;
+ USHORT wLength;
+ USHORT wReserved6;
+ ULONG dwNextFpIndex;
+ ULONG dwReserved12;
+
+ NCM_NDP32_DATAGRAM Datagram[1];
+
+} NCM_NDP32, *PNCM_NDP32;
+
+
+#pragma pack( pop)
+
+//
+// NTB
+//
+
+#define MBB_NTB_GET_OFFSET(NTH,_X_) ((ULONG)(((SIZE_T)(_X_))-((SIZE_T)(NTH))))
+#define MBB_NTB_GET_SEQUENCE(NTH) (((PNCM_NTH32)(NTH))->wSequence)
+#define MBB_NTB_GET_SIGNATURE(NTH) (((PNCM_NTH32)(NTH))->dwSignature)
+#define MBB_NTB_GET_HEADER_LENGTH(NTH) (((PNCM_NTH32)(NTH))->wHeaderLength)
+#define MBB_NTB_IS_32BIT(NTH) (MBB_NTB_GET_SIGNATURE(NTH) == NCM_NTH32_SIG)
+#define MBB_NTB_IS_16BIT(NTH) (MBB_NTB_GET_SIGNATURE(NTH) == NCM_NTH16_SIG)
+
+//
+// NTB32
+
+#define MBB_NTH32_GET_SEQUENCE(NTH) MBB_NTB_GET_SEQUENCE(NTH)
+#define MBB_NTH32_GET_SIGNATURE(NTH) MBB_NTB_GET_SIGNATURE(NTH)
+#define MBB_NTH32_GET_HEADER_LENGTH(NTH) MBB_NTB_GET_HEADER_LENGTH(NTH)
+#define MBB_NTH32_GET_BLOCK_LENGTH(NTH) ((NTH)->dwBlockLength)
+#define MBB_NTH32_GET_FIRST_NDP_OFFSET(NTH) ((NTH)->dwFpIndex)
+#define MBB_NTH32_GET_FIRST_NDP(NTH) ((MBB_NTH32_GET_FIRST_NDP_OFFSET(NTH) != 0)? ((PNCM_NDP32)(((PCHAR)(NTH)) + MBB_NTH32_GET_FIRST_NDP_OFFSET(NTH))): NULL)
+#define MBB_NTH32_IS_VALID_BLOCK_LENGTH(NTH,MAXLEN) (MBB_NTH32_GET_BLOCK_LENGTH(NTH) <= (MAXLEN))
+#define MBB_NTH32_IS_VALID_HEADER_LENGTH(NTH) (MBB_NTB_GET_HEADER_LENGTH(NTH) == sizeof(NCM_NTH32))
+#define MBB_NTH32_IS_VALID_SIGNATURE(NTH) (MBB_NTB_GET_SIGNATURE(NTH) == NCM_NTH32_SIG)
+#define MBB_NTH32_IS_VALID_FIRST_NDP(NTH) \
+ ( \
+ MBB_NTH32_GET_FIRST_NDP_OFFSET(NTH)<= (ULONG_MAX - sizeof(NCM_NDP32)) && \
+ (MBB_NTH32_GET_FIRST_NDP_OFFSET(NTH) + sizeof(NCM_NDP32)) <= MBB_NTH32_GET_BLOCK_LENGTH(NTH) \
+ )
+
+#define MBB_NDP32_GET_SIGNATURE(NDP) ((NDP)->dwSignature)
+#define MBB_NDP32_GET_SESSIONID(NDP) (MBB_NDP32_GET_SIGNATURE(NDP) >> NCM_NDP_SESSION_SHIFT)
+#define MBB_NDP32_GET_SIGNATURE_TYPE(NDP) (MBB_NDP32_GET_SIGNATURE(NDP) & NCM_NDP_SIGNATURE_MASK)
+#define MBB_NDP32_GET_LENGTH(NDP) ((NDP)->wLength)
+#define MBB_NDP32_GET_NEXT_NDP_OFFSET(NDP) ((NDP)->dwNextFpIndex)
+#define MBB_NDP32_GET_NEXT_NDP(NTH,NDP) ((MBB_NDP32_GET_NEXT_NDP_OFFSET(NDP) != 0)? ((PNCM_NDP32)(((PCHAR)(NTH)) + MBB_NDP32_GET_NEXT_NDP_OFFSET(NDP))): NULL)
+#define MBB_NDP32_GET_DATAGRAM_COUNT(NDP) ((MBB_NDP32_GET_LENGTH(NDP)-FIELD_OFFSET(NCM_NDP32,Datagram)) / sizeof(NCM_NDP32_DATAGRAM))
+#define MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX) ((NDP)->Datagram[(IDX)].dwDatagramIndex)
+#define MBB_NDP32_GET_DATAGRAM_LENGTH(NDP,IDX) ((NDP)->Datagram[(IDX)].dwDatagramLength)
+#define MBB_NDP32_GET_DATAGRAM(NTH,NDP,IDX) ((MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX) != 0)? (((PCHAR)(NTH)) + MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX)): NULL)
+#define MBB_NDP32_IS_DATAGRAM_PRESENT(NDP,IDX) ((FIELD_OFFSET(NCM_NDP32,Datagram)+((IDX)*sizeof(NCM_NDP32_DATAGRAM))) <= MBB_NDP32_GET_LENGTH(NDP))
+
+#define MBB_NTB32_IS_END_DATAGRAM(NTH,NDP,IDX) \
+ ( \
+ MBB_NDP32_IS_DATAGRAM_PRESENT(NDP,IDX) && \
+ ( \
+ MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX) == 0 || \
+ MBB_NDP32_GET_DATAGRAM_LENGTH(NDP,IDX) == 0 \
+ ) \
+ )
+#define MBB_NTB32_IS_VALID_DATAGRAM(NTH,NDP,IDX) \
+ ( \
+ MBB_NDP32_IS_DATAGRAM_PRESENT(NDP,IDX) && \
+ MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX) != 0 && \
+ MBB_NDP32_GET_DATAGRAM_LENGTH(NDP,IDX) != 0 && \
+ MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX) < MBB_NTH32_GET_BLOCK_LENGTH(NTH) && \
+ MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX) <= (ULONG_MAX - MBB_NDP32_GET_DATAGRAM_LENGTH(NDP,IDX)) && \
+ (MBB_NDP32_GET_DATAGRAM_OFFSET(NDP,IDX) + MBB_NDP32_GET_DATAGRAM_LENGTH(NDP,IDX)) <= MBB_NTH32_GET_BLOCK_LENGTH(NTH) \
+ )
+#define MBB_NTB32_IS_VALID_NDP_LENGTH(NTH,NDP) \
+ ( \
+ (MBB_NTB_GET_OFFSET(NTH,NDP) < MBB_NTH32_GET_BLOCK_LENGTH(NTH)) && \
+ (MBB_NDP32_GET_LENGTH(NDP) >= FIELD_OFFSET(NCM_NDP32,Datagram)) && \
+ (MBB_NTB_GET_OFFSET(NTH,NDP) <= ULONG_MAX - MBB_NDP32_GET_LENGTH(NDP)) && \
+ ((MBB_NTB_GET_OFFSET(NTH,NDP)+MBB_NDP32_GET_LENGTH(NDP)) <= MBB_NTH32_GET_BLOCK_LENGTH(NTH)) \
+ )
+#define MBB_NTB32_IS_VALID_NDP_SIGNATURE(NDP) \
+ ( \
+ ((MBB_NDP32_GET_SIGNATURE(NDP) & NCM_NDP_SIGNATURE_MASK) == NCM_NDP32_IPS) || \
+ ((MBB_NDP32_GET_SIGNATURE(NDP) & NCM_NDP_SIGNATURE_MASK) == NCM_NDP32_VENDOR) \
+ )
+
+//
+// NTB16
+//
+
+#define MBB_NTH16_GET_SEQUENCE(NTH) MBB_NTB_GET_SEQUENCE(NTH)
+#define MBB_NTH16_GET_SIGNATURE(NTH) MBB_NTB_GET_SIGNATURE(NTH)
+#define MBB_NTH16_GET_HEADER_LENGTH(NTH) MBB_NTB_GET_HEADER_LENGTH(NTH)
+#define MBB_NTH16_GET_BLOCK_LENGTH(NTH) ((NTH)->wBlockLength)
+#define MBB_NTH16_GET_FIRST_NDP_OFFSET(NTH) ((NTH)->wFpIndex)
+#define MBB_NTH16_GET_FIRST_NDP(NTH) ((MBB_NTH16_GET_FIRST_NDP_OFFSET(NTH) != 0)? ((PNCM_NDP16)(((PCHAR)(NTH)) + MBB_NTH16_GET_FIRST_NDP_OFFSET(NTH))): NULL)
+#define MBB_NTH16_IS_VALID_BLOCK_LENGTH(NTH,MAXLEN) (MBB_NTH16_GET_BLOCK_LENGTH(NTH) <= (MAXLEN))
+#define MBB_NTH16_IS_VALID_HEADER_LENGTH(NTH) (MBB_NTB_GET_HEADER_LENGTH(NTH) == sizeof(NCM_NTH16))
+#define MBB_NTH16_IS_VALID_SIGNATURE(NTH) (MBB_NTB_GET_SIGNATURE(NTH) == NCM_NTH16_SIG)
+#define MBB_NTH16_IS_VALID_FIRST_NDP(NTH) \
+ ( \
+ MBB_NTH16_GET_FIRST_NDP_OFFSET(NTH) <= (USHRT_MAX - sizeof(NCM_NDP16)) &&\
+ (MBB_NTH16_GET_FIRST_NDP_OFFSET(NTH) + sizeof(NCM_NDP16)) <= MBB_NTH16_GET_BLOCK_LENGTH(NTH) \
+ )
+
+#define MBB_NDP16_GET_SIGNATURE(NDP) ((NDP)->dwSignature)
+#define MBB_NDP16_GET_SESSIONID(NDP) (MBB_NDP16_GET_SIGNATURE(NDP) >> NCM_NDP_SESSION_SHIFT)
+#define MBB_NDP16_GET_SIGNATURE_TYPE(NDP) (MBB_NDP16_GET_SIGNATURE(NDP) & NCM_NDP_SIGNATURE_MASK)
+#define MBB_NDP16_GET_LENGTH(NDP) ((NDP)->wLength)
+#define MBB_NDP16_GET_NEXT_NDP_OFFSET(NDP) ((NDP)->wNextFpIndex)
+#define MBB_NDP16_GET_NEXT_NDP(NTH,NDP) ((MBB_NDP16_GET_NEXT_NDP_OFFSET(NDP) != 0)? ((PNCM_NDP16)(((PCHAR)(NTH)) + MBB_NDP16_GET_NEXT_NDP_OFFSET(NDP))): NULL)
+#define MBB_NDP16_GET_DATAGRAM_COUNT(NDP) ((MBB_NDP16_GET_LENGTH(NDP)-FIELD_OFFSET(NCM_NDP16,Datagram)) / sizeof(NCM_NDP16_DATAGRAM))
+#define MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX) ((NDP)->Datagram[(IDX)].wDatagramIndex)
+#define MBB_NDP16_GET_DATAGRAM_LENGTH(NDP,IDX) ((NDP)->Datagram[(IDX)].wDatagramLength)
+#define MBB_NDP16_GET_DATAGRAM(NTH,NDP,IDX) ((MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX) != 0)? (((PCHAR)(NTH)) + MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX)): NULL)
+#define MBB_NDP16_IS_DATAGRAM_PRESENT(NDP,IDX) ((FIELD_OFFSET(NCM_NDP16,Datagram)+((IDX)*sizeof(NCM_NDP16_DATAGRAM))) <= MBB_NDP16_GET_LENGTH(NDP))
+
+#define MBB_NTB16_IS_END_DATAGRAM(NTH,NDP,IDX) \
+ ( \
+ MBB_NDP16_IS_DATAGRAM_PRESENT(NDP,IDX) && \
+ ( \
+ MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX) == 0 || \
+ MBB_NDP16_GET_DATAGRAM_LENGTH(NDP,IDX) == 0 \
+ ) \
+ )
+#define MBB_NTB16_IS_VALID_DATAGRAM(NTH,NDP,IDX) \
+ ( \
+ MBB_NDP16_IS_DATAGRAM_PRESENT(NDP,IDX) && \
+ MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX) != 0 && \
+ MBB_NDP16_GET_DATAGRAM_LENGTH(NDP,IDX) != 0 && \
+ MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX) < MBB_NTH16_GET_BLOCK_LENGTH(NTH) && \
+ MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX) <= (USHRT_MAX - MBB_NDP16_GET_DATAGRAM_LENGTH(NDP,IDX)) &&\
+ (MBB_NDP16_GET_DATAGRAM_OFFSET(NDP,IDX) + MBB_NDP16_GET_DATAGRAM_LENGTH(NDP,IDX)) <= MBB_NTH16_GET_BLOCK_LENGTH(NTH) \
+ )
+#define MBB_NTB16_IS_VALID_NDP_LENGTH(NTH,NDP) \
+ ( \
+ (MBB_NTB_GET_OFFSET(NTH,NDP) < MBB_NTH16_GET_BLOCK_LENGTH(NTH)) && \
+ (MBB_NDP16_GET_LENGTH(NDP) >= FIELD_OFFSET(NCM_NDP16,Datagram)) && \
+ (MBB_NTB_GET_OFFSET(NTH,NDP) <= (ULONG)(USHRT_MAX - MBB_NDP16_GET_LENGTH(NDP))) &&\
+ ((MBB_NTB_GET_OFFSET(NTH,NDP)+MBB_NDP16_GET_LENGTH(NDP)) <= MBB_NTH16_GET_BLOCK_LENGTH(NTH)) \
+ )
+#define MBB_NTB16_IS_VALID_NDP_SIGNATURE(NDP) \
+ ( \
+ ((MBB_NDP16_GET_SIGNATURE(NDP) & NCM_NDP_SIGNATURE_MASK) == NCM_NDP16_IPS) || \
+ ((MBB_NDP16_GET_SIGNATURE(NDP) & NCM_NDP_SIGNATURE_MASK) == NCM_NDP16_VENDOR) \
+ )
+
diff --git a/network/wwan/cxwmbclass/inc/power.h b/network/wwan/cxwmbclass/inc/power.h
new file mode 100644
index 00000000..0205fb8e
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/power.h
@@ -0,0 +1,11 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#pragma once
+
+EVT_WDF_DEVICE_D0_ENTRY EvtDeviceD0Entry;
+EVT_WDF_DEVICE_D0_EXIT EvtDeviceD0Exit;
+EVT_WDF_DEVICE_ARM_WAKE_FROM_S0 EvtDeviceArmWakeFromS0;
+EVT_WDF_DEVICE_DISARM_WAKE_FROM_S0 EvtDeviceDisarmWakeFromS0;
+EVT_NET_DEVICE_PREVIEW_WAKE_SOURCE EvtDevicePreviewBitmapPattern;
diff --git a/network/wwan/cxwmbclass/inc/precomp.h b/network/wwan/cxwmbclass/inc/precomp.h
new file mode 100644
index 00000000..706407ba
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/precomp.h
@@ -0,0 +1,53 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#pragma once
+
+#include <ntddk.h>
+#include <ntstrsafe.h>
+
+#include <wdm.h>
+#include <wdf.h>
+#include <wdfminiport.h>
+#include <usbspec.h>
+#include <usb.h>
+#include <usbdlib.h>
+#include <usbiodef.h>
+#include <usbioctl.h>
+#include <wdfusb.h>
+#include <netadaptercx.h>
+#include <netdevice.h>
+#include <mbbcx.h>
+#include <net/returncontext.h>
+#include <net/virtualaddress.h>
+#include <net/mdl.h>
+#include <ndis.h>
+
+#include <netiodef.h>
+
+#define INITGUID
+#include <devpkey.h>
+
+#include <limits.h>
+
+#include "mbbncm.h"
+
+#include "mbbmessages.h"
+#define MBB_MAX_NUMBER_OF_SESSIONS 17 // including the default session for the physical/primary interface
+#define MBB_DEFAULT_SESSION_ID 0 // for physical/primay interface. Must be 0. Do NOT change it.
+#define MBB_INVALID_SESSION_ID MBB_MAX_NUMBER_OF_SESSIONS
+
+#define WMBCLASS_RADIO_STATE_OFF 0
+#define WMBCLASS_RADIO_STATE_ON 1
+
+#include "BusInterface.h"
+
+#include "align.h"
+#include "device.h"
+#include "adapter.h"
+#include "data.h"
+#include "txqueue.h"
+#include "util.h"
+#include "usbbus.h"
+#include "utils.h"
diff --git a/network/wwan/cxwmbclass/inc/rxqueue.h b/network/wwan/cxwmbclass/inc/rxqueue.h
new file mode 100644
index 00000000..fa57e6e0
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/rxqueue.h
@@ -0,0 +1,26 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#pragma once
+
+typedef struct _MBB_RXQUEUE_CONTEXT
+{
+ PWMBCLASS_NETADAPTER_CONTEXT NetAdapterContext;
+ LONG NotificationEnabled;
+ NET_RING_COLLECTION const* DatapathDescriptor;
+ NET_EXTENSION ReturnContextExtension;
+ NET_EXTENSION VirtualAddressExtension;
+} MBB_RXQUEUE_CONTEXT, *PMBB_RXQUEUE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MBB_RXQUEUE_CONTEXT, MbbGetRxQueueContext);
+
+EVT_WDF_OBJECT_CONTEXT_DESTROY EvtRxQueueDestroy;
+
+EVT_PACKET_QUEUE_SET_NOTIFICATION_ENABLED EvtRxQueueSetNotificationEnabled;
+EVT_PACKET_QUEUE_ADVANCE EvtRxQueueAdvance;
+EVT_PACKET_QUEUE_CANCEL EvtRxQueueCancel;
+
+VOID MbbNdisReceiveCallback(_In_ MBB_PROTOCOL_HANDLE ProtocolHandle, _In_ MBB_RECEIVE_CONTEXT ReceiveContext, _In_ PMDL Mdl);
+
+VOID EvtAdapterReturnRxBuffer(_In_ NETADAPTER Adapter, _In_ NET_FRAGMENT_RETURN_CONTEXT_HANDLE RxBufferReturnContext);
diff --git a/network/wwan/cxwmbclass/inc/txqueue.h b/network/wwan/cxwmbclass/inc/txqueue.h
new file mode 100644
index 00000000..7bab9c07
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/txqueue.h
@@ -0,0 +1,22 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#pragma once
+
+typedef struct _MBB_TXQUEUE_CONTEXT
+{
+ PWMBCLASS_NETADAPTER_CONTEXT NetAdapterContext;
+ LONG NotificationEnabled;
+ UINT32 CompletionBatchSize;
+ NET_RING_COLLECTION const* DatapathDescriptor;
+ NET_EXTENSION MdlExtension;
+} MBB_TXQUEUE_CONTEXT, *PMBB_TXQUEUE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MBB_TXQUEUE_CONTEXT, MbbGetTxQueueContext);
+
+EVT_WDF_OBJECT_CONTEXT_DESTROY EvtTxQueueDestroy;
+EVT_PACKET_QUEUE_SET_NOTIFICATION_ENABLED EvtTxQueueSetNotificationEnabled;
+EVT_PACKET_QUEUE_CANCEL EvtTxQueueCancel;
+EVT_PACKET_QUEUE_ADVANCE EvtTxQueueAdvance;
+
+EVT_MBB_DEVICE_SEND_DEVICE_SERVICE_SESSION_DATA EvtMbbDeviceSendDeviceServiceSessionData;
diff --git a/network/wwan/cxwmbclass/inc/usbbus.h b/network/wwan/cxwmbclass/inc/usbbus.h
new file mode 100644
index 00000000..cca02f60
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/usbbus.h
@@ -0,0 +1,235 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#pragma once
+
+#define INITIALIZE_PASSIVE_LOCK(__lock) KeInitializeGuardedMutex(__lock)
+
+#define ACQUIRE_PASSIVE_LOCK(__lock) KeAcquireGuardedMutex(__lock)
+
+#define RELEASE_PASSIVE_LOCK(__lock) KeReleaseGuardedMutex(__lock)
+
+#define WMB_PUSH_LOCK EX_PUSH_LOCK
+
+#define INIT_PUSHLOCK(PushLock) ExInitializePushLock(PushLock)
+
+#define ACQUIRE_PUSHLOCK_EXCLUSIVE(PushLock) \
+ do \
+ { \
+ KeEnterCriticalRegion(); \
+ ExAcquirePushLockExclusive((PushLock)); \
+ } while (0)
+
+#define RELEASE_PUSHLOCK_EXCLUSIVE(PushLock) \
+ do \
+ { \
+ ExReleasePushLockExclusive((PushLock)); \
+ KeLeaveCriticalRegion(); \
+ } while (0)
+
+#define ACQUIRE_PUSHLOCK_SHARED(PushLock) \
+ do \
+ { \
+ KeEnterCriticalRegion(); \
+ ExAcquirePushLockShared((PushLock)); \
+ } while (0)
+
+#define RELEASE_PUSHLOCK_SHARED(PushLock) \
+ do \
+ { \
+ ExReleasePushLockShared((PushLock)); \
+ KeLeaveCriticalRegion(); \
+ } while (0)
+
+#define MAX_PREALLOCATED_WRITE_REQUESTS (20)
+
+//#define DEFAULT_INTERRUPT_PIPE_READ_SIZE (8)
+#define DEFAULT_IO_TIMEOUT (10)
+
+#define MAX_HOST_NTB_SIZE (0x10000)
+#define MAX_HOST_NTB_SIZE_FOR_UDE_MBIM (0x20000)
+#define MAX_OUT_DATAGRAMS (64)
+
+#define INTERRUPT_REASSEMBLY_BUFFER_SIZE (64)
+
+#define MIN_CONTROL_MESSAGE_SIZE (64)
+#define MAX_CONTROL_MESSAGE_SIZE (4096)
+
+#define ALT_DATA_SETTING_0_PIPES (0)
+#define ALT_DATA_SETTING_1_PIPES (2)
+
+#define INITIAL_OPEN_TIMEOUT (5)
+#define MAX_OPEN_RETRY_ATTEMPTS (4)
+
+#define PENDING_BULK_IN_READS (3)
+#define PENDING_BULK_IN_READS_FOR_UDE_MBIM (10)
+
+typedef enum _BUS_STATE
+{
+
+ BUS_STATE_CLOSED = 0,
+ BUS_STATE_CLOSING,
+
+ BUS_STATE_OPENING,
+ BUS_STATE_OPENED
+
+} BUS_STATE,
+ *PBUS_STATE;
+
+typedef struct _POWER_FILTER_LOOKUP
+{
+
+ ULONG PatternId;
+ BOOLEAN InUse;
+
+} POWER_FILTER_LOOKUP, *PPOWER_FILTER_LOOKUP;
+
+typedef struct _BUS_OBJECT
+{
+
+ KGUARDED_MUTEX Lock;
+ BUS_STATE State;
+
+ PDEVICE_OBJECT Pdo;
+ PDEVICE_OBJECT Fdo;
+ PDEVICE_OBJECT NextDeviceObject;
+
+ MBB_PROTOCOL_HANDLE ProtocolHandle;
+ MBB_BUS_RESPONSE_AVAILABLE_CALLBACK ResponseAvailableCallback;
+
+ MBB_BUS_DATA_RECEIVE_CALLBACK ReceiveDataCallback;
+
+ MBB_BUS_SS_IDLE_CONFIRM_CALLBACK IdleConfirmCallback;
+ MBB_BUS_SS_IDLE_NOTIFICATION_COMPLETE_CALLBACK IdleNotificationComplete;
+
+ WDFDEVICE WdfDevice;
+ WDFUSBDEVICE WdfUsbDevice;
+
+ USHORT MaxControlChannelSize;
+
+ USHORT MaxSegmentSize;
+ BYTE NcmParams;
+ BOOLEAN NtbFormat32Bit;
+ BYTE PowerFiltersSupported;
+ BYTE MaxPowerFilterSize;
+
+ BYTE MaxOutstandingCommandMessages;
+ USHORT MTU;
+
+ NCM_NTB_PARAMETER NtbParam;
+
+ PWSTR Manufacturer;
+ PWSTR Model;
+
+ ULONG MaxBulkInTransfer;
+ ULONG BulkInHeaderSize;
+
+ BOOLEAN ChainedMdlsSupported;
+
+ PIRP UsbSsIrp;
+ USB_IDLE_CALLBACK_INFO UsbSsCallback;
+
+ KEVENT UsbSsIrpComplete;
+
+ PPOWER_FILTER_LOOKUP PowerFilterTable;
+
+ PUCHAR SyncInterruptReadBuffer;
+
+ UCHAR InterruptReassemnblyBuffer[INTERRUPT_REASSEMBLY_BUFFER_SIZE];
+ ULONG CurrentOffset;
+ ULONG ExpectLength;
+
+ USHORT MbimVersion;
+ USHORT MbimExtendedVersion;
+ BOOLEAN RemoteWakeCapable;
+
+ USB_CAP_DEVICE_INFO UsbCapDeviceInfo;
+ PVOID ModemContext;
+
+} BUS_OBJECT, *PBUS_OBJECT;
+
+typedef struct _WDF_DEVICE_INFO
+{
+
+ PBUS_OBJECT BusObject;
+
+} WDF_DEVICE_INFO, *PWDF_DEVICE_INFO;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WDF_DEVICE_INFO, GetWdfDeviceInfo)
+
+//
+// put this in the NIC data structure
+//
+typedef struct _USB_DEVICE_CONTEXT
+{
+ size_t NumberOfPipes;
+
+ WDFWAITLOCK PipeStateLock;
+
+ UCHAR UsbCommunicationInterfaceIndex;
+ UCHAR UsbDataInterfaceIndex;
+
+ UCHAR UsbCommunicationInterfaceSetting;
+ UCHAR UsbDataInterfaceSetting;
+
+ UCHAR WdfCommunicationInterfaceIndex;
+ UCHAR WdfDataInterfaceIndex;
+
+ BOOLEAN BulkInputPipeConfigured;
+ BOOLEAN BulkInputPipeStarted;
+ ULONG BulkInputPipeMaxPacket;
+ WDFUSBPIPE BulkInputPipe;
+
+ BOOLEAN BulkOutputPipeConfigured;
+ BOOLEAN BulkOutputPipeStarted;
+ ULONG BulkOutputPipeMaxPacket;
+ WDFUSBPIPE BulkOutputPipe;
+
+ WDFUSBPIPE InterruptPipe;
+
+ WDFIOTARGET InterruptPipeIoTarget;
+ ULONG InterruptPipeMaxPacket;
+
+ WDFLOOKASIDE LookasideList;
+
+ WDFSPINLOCK WriteCollectionLock;
+ WDFCOLLECTION WriteRequestCollection;
+
+ WDFWORKITEM BulkPipeResetWorkitem;
+ LONG BulkPipeResetFlag;
+ EX_RUNDOWN_REF BulkPipeResetRundown;
+ PBUS_OBJECT BusObject;
+} USB_DEVICE_CONTEXT, *PUSB_DEVICE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(USB_DEVICE_CONTEXT, GetUsbDeviceContext)
+
+typedef struct _REQUEST_CONTEXT
+{
+
+ PVOID CallbackContext;
+ union
+ {
+
+ MBB_BUS_SEND_COMPLETION_CALLBACK Send;
+ MBB_BUS_RECEIVE_COMPLETION_CALLBACK Receive;
+
+ } Callback;
+
+ MBB_PROTOCOL_HANDLE ProtocolHandle;
+
+ PUSB_DEVICE_CONTEXT UsbDeviceContext;
+
+ PVOID Buffer;
+ ULONG BufferLength;
+
+} REQUEST_CONTEXT, *PREQUEST_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, GetRequestContext)
+
+VOID MbbBusMiniportUsbIdle(PVOID Context);
+
+NTSTATUS
+PreAllocateWriteRequests(WDFUSBDEVICE UsbDevice);
+
+#define IS_USB_DEVICE_REMOTE_WAKE_CAPABLE(deviceInformation) \
+ ((deviceInformation.Traits & WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE) > 0 ? TRUE : FALSE);
diff --git a/network/wwan/cxwmbclass/inc/util.h b/network/wwan/cxwmbclass/inc/util.h
new file mode 100644
index 00000000..12d166b4
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/util.h
@@ -0,0 +1,42 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#pragma once
+typedef enum
+{
+ MbbPoolTagDefault = '0CBM',
+ MbbPoolTagNtbSend = '1CBM',
+ MbbPoolTagNblSend = '2CBM',
+ MbbPoolTagNbSend = '3CBM',
+ MbbPoolTagMdlReceive = '6CBM'
+} MBB_POOL_TAG;
+
+#define ALLOCATE_PAGED_POOL(_y) ExAllocatePool2(POOL_FLAG_PAGED, _y, MbbPoolTagDefault)
+#define ALLOCATE_NONPAGED_POOL(_y) ExAllocatePool2(POOL_FLAG_NON_PAGED, _y, MbbPoolTagDefault)
+#define ALLOCATE_NONPAGED_POOL_WITH_TAG(_x, _y) ExAllocatePool2(POOL_FLAG_NON_PAGED, _x, _y)
+
+#define FREE_POOL(_x) \
+ { \
+ ExFreePool(_x); \
+ _x = NULL; \
+ };
+
+#define MIN(_X_, _Y_) (((_X_) < (_Y_)) ? (_X_) : (_Y_))
+#define MAX(_X_, _Y_) (((_X_) > (_Y_)) ? (_X_) : (_Y_))
+
+#define ALIGN_FLOOR(_VALUE_, _ALIGN_) ALIGN_DOWN_BY(_VALUE_, _ALIGN_)
+#define ALIGN_CIELING(_VALUE_, _ALIGN_) ALIGN_UP_BY(_VALUE_, _ALIGN_)
+#define ALIGN(_VALUE_, _ALIGN_) ALIGN_CIELING(_VALUE_, _ALIGN_)
+#define ALIGN_AT_OFFSET(_VALUE_, _ALIGN_, _OFFSET_) \
+ (((SIZE_T)(_VALUE_) <= (ALIGN_FLOOR(_VALUE_, _ALIGN_) + (_OFFSET_))) ? (ALIGN_FLOOR(_VALUE_, _ALIGN_) + (_OFFSET_)) \
+ : (ALIGN(_VALUE_, _ALIGN_) + (_OFFSET_)))
+
+NTSTATUS
+MbbNtbValidate(_In_ PVOID Nth, _In_ ULONG BufferLength, _In_ BOOLEAN Is32Bit, _Out_opt_ ULONG* NdpCount);
+
+NTSTATUS
+CreateNonPagedWdfMemory(_In_ ULONG ObjectSize, _Out_ WDFMEMORY* WdfMemory, _Out_opt_ PVOID* ObjectMemory, _In_ WDFOBJECT Parent, _In_ ULONG PoolTag);
+
+PMDL AllocateNonPagedMdl(_In_reads_bytes_(Length) PVOID VirtualAddress, _In_ ULONG Length);
+
+VOID MbbRecvCancelNdps(_In_ PWMBCLASS_DEVICE_CONTEXT DeviceContext, _In_ ULONG SessionId);
diff --git a/network/wwan/cxwmbclass/inc/utils.h b/network/wwan/cxwmbclass/inc/utils.h
new file mode 100644
index 00000000..e7d06637
--- /dev/null
+++ b/network/wwan/cxwmbclass/inc/utils.h
@@ -0,0 +1,61 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#pragma once
+NTSTATUS
+SendSyncControlCommand(
+ __in WDFUSBDEVICE WdfUsbDevice,
+ __in WDF_USB_BMREQUEST_DIRECTION Direction,
+ __in WDF_USB_BMREQUEST_RECIPIENT Recipient,
+ __in BYTE Request,
+ __in USHORT Value,
+ __inout_bcount_opt(BufferLength) PUCHAR Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG BytesTransfered);
+
+NTSTATUS
+TransactControlChannel(
+ __in PBUS_OBJECT BusObject,
+ __in ULONG TimeOut,
+ __in_bcount_opt(InBufferLength) PUCHAR InBuffer,
+ __in ULONG InBufferLength,
+ __out_bcount_opt(OutBufferLength) PUCHAR OutBuffer,
+ __in ULONG OutBufferLength,
+ __out PULONG BytesRead);
+
+NTSTATUS
+ReadInterrupt(_In_ PBUS_OBJECT BusObject, _Inout_updates_bytes_(BufferLength) PUCHAR Buffer, _In_ ULONG BufferLength, _In_ ULONG Timeout, _Out_ PULONG BytesRead);
+
+NTSTATUS
+GetDeviceString(__in WDFUSBDEVICE UsbDevice, __in UCHAR Index, __out PWSTR* String);
+
+NTSTATUS
+MbbBusSetPacketFilter(__in MBB_BUS_HANDLE BusHandle, __in ULONG PacketFilter);
+
+NTSTATUS
+MbbBusSetNtbInSize(__in MBB_BUS_HANDLE BusHandle, __in ULONG InSize);
+
+NTSTATUS
+MbbBusGetStat(__in MBB_BUS_HANDLE BusHandle, __in USHORT StatIndex, __out ULONGLONG* Value);
+
+NTSTATUS
+MbbBusSetNtbFormat(__in MBB_BUS_HANDLE BusHandle, __in USHORT Format);
+
+NTSTATUS
+MbbBusResetFunction(__in MBB_BUS_HANDLE BusHandle);
+
+ULONG
+ProcessInterruptPipeRead(
+ PBUS_OBJECT BusObject,
+ __in_ecount(NewFragmentLength) PCUCHAR NewFragment,
+ ULONG NewFragmentLength,
+ __out_ecount(MessageBufferSize) PUCHAR CompleteMessageBuffer,
+ ULONG MessageBufferSize);
+
+NTSTATUS
+WaitForResponseAvailible(PBUS_OBJECT BusObject, ULONG TimeOut);
+
+NTSTATUS
+MbbBusResetDeviceAndSetParms(__in PBUS_OBJECT BusObject);
+
+BOOLEAN IsUsbCapDeviceInfoValid(_In_ USB_CAP_DEVICE_INFO UsbCapDeviceInfo, _In_ ULONG CapResultLength);
diff --git a/network/wwan/cxwmbclass/power.cpp b/network/wwan/cxwmbclass/power.cpp
new file mode 100644
index 00000000..e0726975
--- /dev/null
+++ b/network/wwan/cxwmbclass/power.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+#include "power.h"
+#include "device.h"
+#include "adapter.h"
+
+_Use_decl_annotations_ NTSTATUS EvtDeviceD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE previousPowerState)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+ UNREFERENCED_PARAMETER(previousPowerState);
+ do
+ {
+ if (MbbBusIsStoped(deviceContext->BusHandle))
+ {
+ //
+ // device was in d3, open it again
+ //
+ status = MbbBusStart(deviceContext->BusHandle);
+
+ if (!NT_SUCCESS(status))
+ {
+ WdfDeviceSetFailed(deviceContext->WdfDevice, WdfDeviceFailedAttemptRestart);
+ break;
+ }
+ }
+ else
+ {
+ MbbBusSetNotificationState(deviceContext->BusHandle, TRUE);
+ }
+ // Allow sessions to receive data from this point since RxQueueCreate happens later after D0Entry. We need cache NDPs receive before RxQueueCreate
+ for (int i = 0; i < MBB_MAX_NUMBER_OF_SESSIONS; i++)
+ {
+ if (deviceContext->Sessions[i].NetAdapterContext == NULL)
+ {
+ continue;
+ }
+ deviceContext->Sessions[i].NetAdapterContext->AllowRxTraffic = TRUE;
+ }
+ MbbBusStartDataPipes(deviceContext->BusHandle);
+ } while (FALSE);
+
+ return status;
+}
+
+_Use_decl_annotations_ NTSTATUS EvtDeviceD0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetPowerState)
+{
+ UNREFERENCED_PARAMETER(TargetPowerState);
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+
+ MbbBusStopDataPipes(deviceContext->BusHandle);
+ //
+ // If the device is not armed for wake, close has been sent by MbbCx. All response available notifications from close in MbbCx to EvtDeviceD0Exit will be ignored.
+ //
+ // If the device is armed for wake, No response available notification after EvtDeviceArmWakeFromS0 where we stop the notification.
+ if (!deviceContext->m_armedWake)
+ {
+ MbbBusStop(deviceContext->BusHandle);
+ }
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_ NTSTATUS EvtDevicePreviewBitmapPattern(WDFDEVICE Device, NETWAKESOURCE BitmapPattern)
+{
+ // We don't need to look at the pattern itself, only how many we currently have
+ UNREFERENCED_PARAMETER(BitmapPattern);
+
+ NET_WAKE_SOURCE_LIST wakeSourceList;
+ NET_WAKE_SOURCE_LIST_INIT(&wakeSourceList);
+ NetDeviceGetWakeSourceList(Device, &wakeSourceList);
+
+ auto const wakeSourceCount = NetWakeSourceListGetCount(&wakeSourceList);
+ size_t numberOfPowerFilters = 0;
+
+ // Count how many power filters are currently stored for this device
+ for (size_t i = 0; i < wakeSourceCount; i++)
+ {
+ auto wakeSource = NetWakeSourceListGetElement(&wakeSourceList, i);
+ auto const wakeSourceType = NetWakeSourceGetType(wakeSource);
+
+ if (wakeSourceType == NetWakeSourceTypeBitmapPattern)
+ {
+ numberOfPowerFilters++;
+ }
+ }
+
+ auto const deviceContext = WmbClassGetDeviceContext(Device);
+ auto const maxPowerFilters = deviceContext->BusParams.PowerFiltersSupported;
+
+ NT_ASSERT(numberOfPowerFilters <= maxPowerFilters);
+
+ if (numberOfPowerFilters == maxPowerFilters)
+ {
+ return STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_ NTSTATUS EvtDeviceArmWakeFromS0(WDFDEVICE Device)
+{
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+ deviceContext->m_armedWake = true;
+ MbbBusSetNotificationState(deviceContext->BusHandle, FALSE);
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_ VOID EvtDeviceDisarmWakeFromS0(WDFDEVICE Device)
+{
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+ deviceContext->m_armedWake = false;
+}
diff --git a/network/wwan/cxwmbclass/rxqueue.cpp b/network/wwan/cxwmbclass/rxqueue.cpp
new file mode 100644
index 00000000..836201a5
--- /dev/null
+++ b/network/wwan/cxwmbclass/rxqueue.cpp
@@ -0,0 +1,602 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+#include "device.h"
+#include "rxqueue.h"
+
+#define MBB_NTH_GET_FIRST_NDP_OFFSET(IS32BIT, NTH) \
+ ((IS32BIT) ? MBB_NTH32_GET_FIRST_NDP_OFFSET((PNCM_NTH32)NTH) : MBB_NTH16_GET_FIRST_NDP_OFFSET((PNCM_NTH16)NTH))
+
+void MbbNotifyRxReady(_In_ NETPACKETQUEUE RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ if (InterlockedExchange(&rxQueueContext->NotificationEnabled, FALSE) == TRUE)
+ {
+ NetRxQueueNotifyMoreReceivedPacketsAvailable(RxQueue);
+ }
+}
+
+VOID MbbRecvCleanup(_In_ PMBB_NDIS_RECEIVE_CONTEXT Receive)
+{
+ MbbBusReturnReceiveBuffer(Receive->BusHandle, Receive->BusContext, Receive->Mdl);
+
+ WdfObjectDelete(Receive->ReceiveLookasideBufferMemory);
+}
+
+VOID MbbRecvReturnNdp(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_opt_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext)
+{
+ LONG newCompletedCount = InterlockedIncrement(&ReceiveContext->CompletedNdpCount);
+ if (newCompletedCount == ReceiveContext->TotalNdpCount)
+ {
+ MbbRecvCleanup(ReceiveContext);
+ }
+ if (ReceiveNdpContext != NULL)
+ {
+ WdfObjectDelete(ReceiveNdpContext->ReceiveNdpLookasideBufferMemory);
+ }
+}
+
+_Use_decl_annotations_ VOID MbbRecvCancelNdps(PWMBCLASS_DEVICE_CONTEXT DeviceContext, ULONG SessionId)
+{
+ LIST_ENTRY tempList;
+ PLIST_ENTRY listEntry;
+ PLIST_ENTRY nextEntry;
+ PMBB_RECEIVE_NDP_CONTEXT receiveNdpContext = NULL;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = DeviceContext->Sessions[SessionId].NetAdapterContext;
+
+ InitializeListHead(&tempList);
+
+ WdfSpinLockAcquire(DeviceContext->Sessions[SessionId].WdfRecvSpinLock);
+ InsertHeadList(&netAdapterContext->ReceiveNdpList, &tempList);
+ RemoveEntryList(&netAdapterContext->ReceiveNdpList);
+ InitializeListHead(&netAdapterContext->ReceiveNdpList);
+ // Cannot cache the received Ndps anymore
+ netAdapterContext->AllowRxTraffic = FALSE;
+ WdfSpinLockRelease(DeviceContext->Sessions[SessionId].WdfRecvSpinLock);
+
+ for (listEntry = tempList.Flink; listEntry != &tempList; listEntry = nextEntry)
+ {
+ nextEntry = listEntry->Flink;
+ receiveNdpContext = CONTAINING_RECORD(listEntry, MBB_RECEIVE_NDP_CONTEXT, ReceiveNdpNode);
+ MbbRecvReturnNdp(receiveNdpContext->ReceiveContext, receiveNdpContext);
+ }
+}
+
+void MbbReceiveDssData(__in PWMBCLASS_DEVICE_CONTEXT DeviceContext, __in ULONG SessionId, __in_bcount_opt(InBufferSize) PUCHAR InBuffer, __in ULONG InBufferSize)
+{
+ NTSTATUS status;
+ WDFMEMORY data;
+
+ status = WdfMemoryCreatePreallocated(WDF_NO_OBJECT_ATTRIBUTES, InBuffer, InBufferSize, &data);
+
+ if (NT_SUCCESS(status))
+ {
+ DeviceContext->DSSPacketsReceivedCount++;
+
+ MbbDeviceReceiveDeviceServiceSessionData(DeviceContext->WdfDevice, SessionId, data);
+ WdfObjectDelete(data);
+ }
+}
+
+NTSTATUS
+MbbRecvNdpUnpackDss32(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_ PNCM_NTH32 Nth, _In_ PNCM_NDP32 Ndp)
+{
+ UNREFERENCED_PARAMETER(Nth);
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP32_GET_DATAGRAM_COUNT(Ndp);
+ ULONG sessionId = MBB_NDP32_GET_SESSIONID(Ndp);
+ for (ULONG index = 0; index < datagramCount; index++)
+ {
+ if (MBB_NTB32_IS_END_DATAGRAM(Nth, Ndp, index))
+ break;
+
+ // Forward to the dss receive handler
+ MbbReceiveDssData(
+ ReceiveContext->WmbDeviceContext, sessionId, (PUCHAR)MBB_NDP32_GET_DATAGRAM(Nth, Ndp, index), MBB_NDP32_GET_DATAGRAM_LENGTH(Ndp, index));
+ }
+
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ return status;
+}
+
+NTSTATUS
+MbbRecvNdpUnpackDss16(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_ PNCM_NTH16 Nth, _In_ PNCM_NDP16 Ndp)
+{
+ UNREFERENCED_PARAMETER(Nth);
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP16_GET_DATAGRAM_COUNT(Ndp);
+ ULONG sessionId = MBB_NDP16_GET_SESSIONID(Ndp);
+ for (ULONG index = 0; index < datagramCount; index++)
+ {
+ if (MBB_NTB16_IS_END_DATAGRAM(Nth, Ndp, index))
+ break;
+
+ // Forward to the dss receive handler
+ MbbReceiveDssData(
+ ReceiveContext->WmbDeviceContext, sessionId, (PUCHAR)MBB_NDP16_GET_DATAGRAM(Nth, Ndp, index), MBB_NDP16_GET_DATAGRAM_LENGTH(Ndp, index));
+ }
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ return status;
+}
+
+NTSTATUS
+MbbRecvAddNdp(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext, _In_ PVOID Nth, _In_ PVOID Ndp, _In_ ULONG SessionId)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = ReceiveContext->WmbDeviceContext;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = NULL;
+ WDFMEMORY ndpContextMemory;
+ PMBB_RECEIVE_NDP_CONTEXT ndpContext = NULL;
+ size_t ndpContextSize;
+ BOOLEAN returnNdp = FALSE;
+
+ WdfSpinLockAcquire(deviceContext->Sessions[SessionId].WdfRecvSpinLock);
+ do
+ {
+ netAdapterContext = deviceContext->Sessions[SessionId].NetAdapterContext;
+ if (netAdapterContext == NULL)
+ {
+ returnNdp = TRUE;
+ break;
+ }
+
+ if (!NT_SUCCESS(status = WdfMemoryCreateFromLookaside(netAdapterContext->ReceiveNdpLookasideList, &ndpContextMemory)))
+ {
+ returnNdp = TRUE;
+ break;
+ }
+
+ ndpContext = (PMBB_RECEIVE_NDP_CONTEXT)WdfMemoryGetBuffer(ndpContextMemory, &ndpContextSize);
+ RtlZeroMemory(ndpContext, ndpContextSize);
+ ndpContext->Nth = Nth;
+ ndpContext->Ndp = Ndp;
+ ndpContext->ReceiveContext = ReceiveContext;
+ ndpContext->ReceiveNdpLookasideBufferMemory = ndpContextMemory;
+ ndpContext->NetAdapterContext = netAdapterContext;
+ if (netAdapterContext->AllowRxTraffic)
+ {
+ InsertTailList(&netAdapterContext->ReceiveNdpList, &ndpContext->ReceiveNdpNode);
+ }
+ else
+ {
+ returnNdp = TRUE;
+ break;
+ }
+
+ // If RxQueueCreate hasn't completed yet, we only queue the received Ndp and don't need notify RxReady
+ if (netAdapterContext->RxQueue)
+ {
+ MbbNotifyRxReady(netAdapterContext->RxQueue);
+ }
+ } while (FALSE);
+ WdfSpinLockRelease(deviceContext->Sessions[SessionId].WdfRecvSpinLock);
+
+ if (returnNdp)
+ {
+ MbbRecvReturnNdp(ReceiveContext, ndpContext);
+ }
+ return status;
+}
+
+VOID MbbRecvNtbParse(_In_ PMBB_NDIS_RECEIVE_CONTEXT ReceiveContext)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PNCM_NTH32 nth32;
+ PNCM_NTH16 nth16;
+ PNCM_NDP32 ndp32;
+ PNCM_NDP16 ndp16;
+ PVOID nth = ReceiveContext->ReceiveNtbBuffer;
+
+ if (MBB_NTB_IS_32BIT(nth))
+ {
+ nth32 = (PNCM_NTH32)nth;
+ for (ndp32 = MBB_NTH32_GET_FIRST_NDP(nth32); ndp32 != NULL; ndp32 = MBB_NDP32_GET_NEXT_NDP(nth32, ndp32))
+ {
+ if (MBB_NDP32_GET_SIGNATURE_TYPE(ndp32) == NCM_NDP32_VENDOR)
+ {
+ status = MbbRecvNdpUnpackDss32(ReceiveContext, nth32, ndp32);
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else if (MBB_NDP32_GET_SIGNATURE_TYPE(ndp32) == NCM_NDP32_IPS)
+ {
+ status = MbbRecvAddNdp(ReceiveContext, nth32, ndp32, MBB_NDP32_GET_SESSIONID(ndp32));
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else
+ {
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ }
+ }
+ }
+ else if (MBB_NTB_IS_16BIT(nth))
+ {
+ nth16 = (PNCM_NTH16)nth;
+ for (ndp16 = MBB_NTH16_GET_FIRST_NDP(nth16); ndp16 != NULL; ndp16 = MBB_NDP16_GET_NEXT_NDP(nth16, ndp16))
+ {
+ if (MBB_NDP16_GET_SIGNATURE_TYPE(ndp16) == NCM_NDP16_VENDOR)
+ {
+ status = MbbRecvNdpUnpackDss16(ReceiveContext, nth16, ndp16);
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else if (MBB_NDP16_GET_SIGNATURE_TYPE(ndp16) == NCM_NDP16_IPS)
+ {
+ status = MbbRecvAddNdp(ReceiveContext, nth16, ndp16, MBB_NDP32_GET_SESSIONID(ndp16));
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ else
+ {
+ MbbRecvReturnNdp(ReceiveContext, NULL);
+ }
+ }
+ }
+}
+
+NTSTATUS
+MbbRecvNtbUnpackIpNdp32(_In_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext, _In_ PNCM_NTH32 Nth32, _In_ PNCM_NDP32 Ndp32, _Inout_ ULONG* IncompletedDatagramIndex, _In_ PMBB_RXQUEUE_CONTEXT RxQueueContext)
+{
+ PCHAR incompletedDatagram;
+ ULONG incompletedDatagramLength;
+ NET_PACKET* packet;
+ NET_FRAGMENT* fragment;
+ NET_FRAGMENT_RETURN_CONTEXT* returnContext;
+ NET_FRAGMENT_VIRTUAL_ADDRESS* virtualAddress;
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP32_GET_DATAGRAM_COUNT(Ndp32);
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(RxQueueContext->DatapathDescriptor);
+ NET_RING * fr = NetRingCollectionGetFragmentRing(RxQueueContext->DatapathDescriptor);
+
+ while ((incompletedDatagram = MBB_NDP32_GET_DATAGRAM(Nth32, Ndp32, *IncompletedDatagramIndex)) != NULL)
+ {
+ if (*IncompletedDatagramIndex >= datagramCount)
+ {
+ break;
+ }
+
+ if (fr->BeginIndex == fr->EndIndex)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+
+ incompletedDatagramLength = MBB_NDP32_GET_DATAGRAM_LENGTH(Ndp32, *IncompletedDatagramIndex);
+
+ UINT32 const fragmentIndex = fr->BeginIndex;
+ fragment = NetRingGetFragmentAtIndex(fr, fragmentIndex);
+ fragment->Capacity = incompletedDatagramLength;
+ fragment->ValidLength = incompletedDatagramLength;
+ fragment->Offset = 0;
+
+ returnContext = NetExtensionGetFragmentReturnContext(&RxQueueContext->ReturnContextExtension, fragmentIndex);
+ virtualAddress =
+ NetExtensionGetFragmentVirtualAddress(&RxQueueContext->VirtualAddressExtension, fragmentIndex);
+
+
+ returnContext->Handle = (NET_FRAGMENT_RETURN_CONTEXT_HANDLE)ReceiveNdpContext;
+ virtualAddress->VirtualAddress = incompletedDatagram;
+
+ (ReceiveNdpContext->IndicatedPackets)++;
+ (*IncompletedDatagramIndex)++;
+
+ UINT32 const packetIndex = pr->BeginIndex;
+ packet = NetRingGetPacketAtIndex(pr, packetIndex);
+ packet->FragmentIndex = fragmentIndex;
+ packet->FragmentCount = 1;
+ packet->Layout = {};
+
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ fr->BeginIndex = NetRingIncrementIndex(fr, fr->BeginIndex);
+ }
+ return status;
+}
+
+NTSTATUS
+MbbRecvNtbUnpackIpNdp16(_In_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext, _In_ PNCM_NTH16 Nth16, _In_ PNCM_NDP16 Ndp16, _Inout_ ULONG* IncompletedDatagramIndex, _In_ PMBB_RXQUEUE_CONTEXT RxQueueContext)
+{
+ PCHAR incompletedDatagram;
+ ULONG incompletedDatagramLength;
+ NET_PACKET* packet;
+ NET_FRAGMENT* fragment;
+ NET_FRAGMENT_RETURN_CONTEXT* returnContext;
+ NET_FRAGMENT_VIRTUAL_ADDRESS* virtualAddress;
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG datagramCount = MBB_NDP16_GET_DATAGRAM_COUNT(Ndp16);
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(RxQueueContext->DatapathDescriptor);
+ NET_RING * fr = NetRingCollectionGetFragmentRing(RxQueueContext->DatapathDescriptor);
+
+ while ((incompletedDatagram = MBB_NDP16_GET_DATAGRAM(Nth16, Ndp16, *IncompletedDatagramIndex)) != NULL)
+ {
+ if (*IncompletedDatagramIndex >= datagramCount)
+ {
+ break;
+ }
+
+ if (fr->BeginIndex == fr->EndIndex)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+
+ incompletedDatagramLength = MBB_NDP16_GET_DATAGRAM_LENGTH(Ndp16, *IncompletedDatagramIndex);
+
+ UINT32 const fragmentIndex = fr->BeginIndex;
+ fragment = NetRingGetFragmentAtIndex(fr, fragmentIndex);
+ fragment->Capacity = incompletedDatagramLength;
+ fragment->ValidLength = incompletedDatagramLength;
+ fragment->Offset = 0;
+
+ returnContext = NetExtensionGetFragmentReturnContext(&RxQueueContext->ReturnContextExtension, fragmentIndex);
+ virtualAddress =
+ NetExtensionGetFragmentVirtualAddress(&RxQueueContext->VirtualAddressExtension, fragmentIndex);
+
+ returnContext->Handle = (NET_FRAGMENT_RETURN_CONTEXT_HANDLE)ReceiveNdpContext;
+ virtualAddress->VirtualAddress = incompletedDatagram;
+
+ (ReceiveNdpContext->IndicatedPackets)++;
+ (*IncompletedDatagramIndex)++;
+
+ UINT32 const packetIndex = pr->BeginIndex;
+ packet = NetRingGetPacketAtIndex(pr, packetIndex);
+ packet->FragmentIndex = fragmentIndex;
+ packet->FragmentCount = 1;
+ packet->Layout = {};
+
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ fr->BeginIndex = NetRingIncrementIndex(fr, fr->BeginIndex);
+ }
+
+ return status;
+}
+
+NTSTATUS
+MbbRecvNdpUnpackIps(_In_ PMBB_RECEIVE_NDP_CONTEXT ReceiveNdpContext, _In_ PMBB_RXQUEUE_CONTEXT RxQueueContext)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PNCM_NTH32 nth32;
+ PNCM_NTH16 nth16;
+ PNCM_NDP32 ndp32;
+ PNCM_NDP16 ndp16;
+ PMBB_NDIS_RECEIVE_CONTEXT receiveContext = ReceiveNdpContext->ReceiveContext;
+ PVOID nth = receiveContext->ReceiveNtbBuffer;
+
+ if (MBB_NTB_IS_32BIT(nth))
+ {
+ nth32 = (PNCM_NTH32)nth;
+ ndp32 = (PNCM_NDP32)ReceiveNdpContext->Ndp;
+ status = MbbRecvNtbUnpackIpNdp32(ReceiveNdpContext, nth32, ndp32, &ReceiveNdpContext->CurrentDatagramIndex, RxQueueContext);
+ }
+ else if (MBB_NTB_IS_16BIT(nth))
+ {
+ nth16 = (PNCM_NTH16)nth;
+ ndp16 = (PNCM_NDP16)ReceiveNdpContext->Ndp;
+ status = MbbRecvNtbUnpackIpNdp16(ReceiveNdpContext, nth16, ndp16, &ReceiveNdpContext->CurrentDatagramIndex, RxQueueContext);
+ }
+
+ return status;
+}
+
+PMBB_NDIS_RECEIVE_CONTEXT
+MbbRecvQQueueReceive(_In_ PWMBCLASS_DEVICE_CONTEXT DeviceContext, _In_ MBB_RECEIVE_CONTEXT BusContext, _In_ PMDL Mdl, _In_reads_(sizeof(NCM_NTH32)) PUCHAR ReceiveNtbBuffer)
+{
+ PMBB_NDIS_RECEIVE_CONTEXT receiveContext = NULL;
+ WDFMEMORY receiveContextMemory;
+ size_t receiveContextSize;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ do
+ {
+ if (!NT_SUCCESS(status = WdfMemoryCreateFromLookaside(DeviceContext->ReceiveLookasideList, &receiveContextMemory)))
+ {
+ break;
+ }
+
+ receiveContext = (PMBB_NDIS_RECEIVE_CONTEXT)WdfMemoryGetBuffer(receiveContextMemory, &receiveContextSize);
+ RtlZeroMemory(receiveContext, receiveContextSize);
+
+ receiveContext->Mdl = Mdl;
+ receiveContext->WmbDeviceContext = DeviceContext;
+ receiveContext->BusHandle = DeviceContext->BusHandle;
+ receiveContext->BusContext = BusContext;
+ receiveContext->ReceiveLookasideList = DeviceContext->ReceiveLookasideList;
+ receiveContext->ReceiveLookasideBufferMemory = receiveContextMemory;
+ receiveContext->ReceiveNtbBuffer = ReceiveNtbBuffer;
+ receiveContext->NtbSequence = MBB_NTB_GET_SEQUENCE(ReceiveNtbBuffer);
+ } while (FALSE);
+
+ return receiveContext;
+}
+
+VOID MbbNdisReceiveCallback(_In_ MBB_PROTOCOL_HANDLE ProtocolHandle, _In_ MBB_RECEIVE_CONTEXT ReceiveContext, _In_ PMDL Mdl)
+{
+ PUCHAR dataBuffer;
+ ULONG dataLength;
+ PVOID nth;
+ BOOLEAN returnBuffer = TRUE;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = (PWMBCLASS_DEVICE_CONTEXT)ProtocolHandle;
+ PMBB_NDIS_RECEIVE_CONTEXT receive = NULL;
+ ULONG ndpCount = 1;
+ NTSTATUS status = STATUS_SUCCESS;
+ do
+ {
+ if ((dataBuffer = (PUCHAR)MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority | MdlMappingNoExecute)) == NULL)
+ {
+ status = STATUS_RESOURCE_DATA_NOT_FOUND;
+ break;
+ }
+ dataLength = MmGetMdlByteCount(Mdl);
+
+ nth = dataBuffer;
+
+ if (!NT_SUCCESS(status = MbbNtbValidate(nth, dataLength, deviceContext->BusParams.CurrentMode32Bit, &ndpCount)))
+ {
+ {
+ ULONG i;
+ ULONG j;
+
+ PUCHAR buffer = (PUCHAR)nth;
+
+ for (i = 0; i < dataLength; i += 16)
+ {
+ UCHAR numString[16 * 3 + 1];
+ UCHAR asciiBuffer[40];
+ UCHAR value = 0;
+ const char translateTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+ RtlZeroMemory(numString, sizeof(numString));
+ RtlZeroMemory(asciiBuffer, sizeof(asciiBuffer));
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i + j >= dataLength)
+ {
+ //
+ // past the end, just put spaces
+ //
+ numString[j * 3] = ' ';
+ numString[j * 3 + 1] = ' ';
+ numString[j * 3 + 2] = ' ';
+ }
+ else
+ {
+ value = buffer[i + j];
+
+ numString[j * 3] = translateTable[value >> 4];
+ numString[j * 3 + 1] = translateTable[value & 0xf];
+ numString[j * 3 + 2] = ' ';
+
+ if ((buffer[i + j] >= 32) && (buffer[i + j] < 128))
+ {
+ asciiBuffer[j] = value;
+ }
+ else
+ {
+ asciiBuffer[j] = '.';
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ if ((receive = MbbRecvQQueueReceive(deviceContext, ReceiveContext, Mdl, (PUCHAR)nth)) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ returnBuffer = FALSE;
+ receive->TotalNdpCount = ndpCount;
+
+ // Receive DSS, IPs will be received in EvtRxQueueAdvance
+ MbbRecvNtbParse(receive);
+ } while (FALSE);
+
+ if (returnBuffer)
+ {
+ if (receive != NULL)
+ {
+ MbbRecvCleanup(receive);
+ }
+ else
+ {
+ MbbBusReturnReceiveBuffer(deviceContext->BusHandle, ReceiveContext, Mdl);
+ }
+ }
+}
+
+void EvtRxQueueDestroy(_In_ WDFOBJECT RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = rxQueueContext->NetAdapterContext;
+ netAdapterContext->RxQueue = NULL;
+}
+
+VOID EvtRxQueueSetNotificationEnabled(_In_ NETPACKETQUEUE RxQueue, _In_ BOOLEAN NotificationEnabled)
+{
+ PMBB_RXQUEUE_CONTEXT txQueueContext = MbbGetRxQueueContext(RxQueue);
+ InterlockedExchange(&txQueueContext->NotificationEnabled, NotificationEnabled);
+}
+
+void EvtRxQueueAdvance(_In_ NETPACKETQUEUE RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = rxQueueContext->NetAdapterContext;
+ WDFSPINLOCK wdfRecvSpinLock = netAdapterContext->WmbDeviceContext->Sessions[netAdapterContext->SessionId].WdfRecvSpinLock;
+ PMBB_RECEIVE_NDP_CONTEXT receiveNdpContext;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WdfSpinLockAcquire(wdfRecvSpinLock);
+ while (!IsListEmpty(&netAdapterContext->ReceiveNdpList))
+ {
+ receiveNdpContext = CONTAINING_RECORD(RemoveHeadList(&netAdapterContext->ReceiveNdpList), MBB_RECEIVE_NDP_CONTEXT, ReceiveNdpNode);
+ receiveNdpContext->ReceiveNdpNode.Flink = receiveNdpContext->ReceiveNdpNode.Blink = NULL;
+ WdfSpinLockRelease(wdfRecvSpinLock);
+
+ status = MbbRecvNdpUnpackIps(receiveNdpContext, rxQueueContext);
+ if (status == STATUS_BUFFER_OVERFLOW)
+ {
+ WdfSpinLockAcquire(wdfRecvSpinLock);
+ InsertHeadList(&netAdapterContext->ReceiveNdpList, &receiveNdpContext->ReceiveNdpNode);
+ break;
+ }
+ else
+ {
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+
+ WdfSpinLockAcquire(wdfRecvSpinLock);
+ }
+ WdfSpinLockRelease(wdfRecvSpinLock);
+}
+
+void EvtRxQueueCancel(_In_ NETPACKETQUEUE RxQueue)
+{
+ PMBB_RXQUEUE_CONTEXT rxQueueContext = MbbGetRxQueueContext(RxQueue);
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = rxQueueContext->NetAdapterContext;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = netAdapterContext->WmbDeviceContext;
+ NET_RING_COLLECTION const* rings = rxQueueContext->DatapathDescriptor;
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(rings);
+
+ while (pr->BeginIndex != pr->EndIndex)
+ {
+ NET_PACKET * packet = NetRingGetPacketAtIndex(pr, pr->BeginIndex);
+ packet->Ignore = 1;
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ }
+
+ NET_RING * fr = NetRingCollectionGetFragmentRing(rings);
+ fr->BeginIndex = fr->EndIndex;
+
+ // Cancel received Ndps which may be received after EvtRxQueueCancel started, these Ndps may never be processed by EvtRxQueueAdvance
+ MbbRecvCancelNdps(deviceContext, netAdapterContext->SessionId);
+}
+
+VOID EvtAdapterReturnRxBuffer(_In_ NETADAPTER Adapter, _In_ NET_FRAGMENT_RETURN_CONTEXT_HANDLE RxBufferReturnContext)
+{
+ PMBB_RECEIVE_NDP_CONTEXT receiveNdpContext = (PMBB_RECEIVE_NDP_CONTEXT)RxBufferReturnContext;
+ UNREFERENCED_PARAMETER(Adapter);
+ NT_ASSERT(receiveNdpContext->IndicatedPackets);
+
+ receiveNdpContext->IndicatedPackets--;
+ if ((receiveNdpContext->IndicatedPackets == 0) && (receiveNdpContext->ReceiveNdpNode.Blink == NULL) &&
+ (receiveNdpContext->ReceiveNdpNode.Flink == NULL))
+ {
+ MbbRecvReturnNdp(receiveNdpContext->ReceiveContext, receiveNdpContext);
+ }
+}
diff --git a/network/wwan/cxwmbclass/sources.inc b/network/wwan/cxwmbclass/sources.inc
new file mode 100644
index 00000000..7b1e526c
--- /dev/null
+++ b/network/wwan/cxwmbclass/sources.inc
@@ -0,0 +1,12 @@
+MBBCX_MAJOR_VERSION=1
+MBBCX_MINOR_VERSION=0
+
+MBBCX_VERSION=$(MBBCX_MAJOR_VERSION).$(MBBCX_MINOR_VERSION)
+
+MBBCX_DDK_INC_PATH=$(ONECORE_EXTERNAL_DDK_INC_PATH)\mbbcx\$(MBBCX_VERSION)
+MBBCX_DDK_LIB_PATH=$(ONECORE_EXTERNAL_DDK_LIB_PATH)\mbbcx\$(MBBCX_VERSION)
+
+KMDF_VERSION_MAJOR=1
+KMDF_VERSION_MINOR=31
+KMDF_VERSION=$(KMDF_VERSION_MAJOR).$(KMDF_VERSION_MINOR)
+KMDF_DDK_INC_PATH=$(ONECORE_INTERNAL_DDK_INC_PATH)\wdf\kmdf\$(KMDF_VERSION);
diff --git a/network/wwan/cxwmbclass/txqueue.cpp b/network/wwan/cxwmbclass/txqueue.cpp
new file mode 100644
index 00000000..9708b8b2
--- /dev/null
+++ b/network/wwan/cxwmbclass/txqueue.cpp
@@ -0,0 +1,988 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+
+#include "precomp.h"
+
+#include "device.h"
+#include "txqueue.h"
+
+void MbbNotifyTxReady(_In_ NETPACKETQUEUE TxQueue)
+{
+ PMBB_TXQUEUE_CONTEXT txQueueContext = MbbGetTxQueueContext(TxQueue);
+
+ if (InterlockedExchange(&txQueueContext->NotificationEnabled, FALSE) == TRUE)
+ {
+ NetTxQueueNotifyMoreCompletedPacketsAvailable(TxQueue);
+ }
+}
+
+ULONG
+MbbGetNetPacketDataLength(_In_ NET_PACKET* NetPacket, _In_ NET_RING_COLLECTION const* Rings)
+{
+ ULONG length = 0;
+ auto fr = NetRingCollectionGetFragmentRing(Rings);
+ for (UINT32 i = 0; i < NetPacket->FragmentCount; i++)
+ {
+ auto fragment = NetRingGetFragmentAtIndex(fr, (NetPacket->FragmentIndex + i) & fr->ElementIndexMask);
+ length += static_cast<ULONG>(fragment->ValidLength);
+ }
+
+ return length;
+}
+
+VOID MbbPacketRestoreMdl(_In_ PMBB_PACKET_CONTEXT PacketContext)
+{
+ if (PacketContext->ModifiedMdl != NULL)
+ {
+ *PacketContext->ModifiedMdl = PacketContext->OriginalMdl;
+ PacketContext->ModifiedMdl = NULL;
+ }
+}
+
+VOID MbbPacketCleanupContext(_In_ PMBB_PACKET_CONTEXT PacketContext)
+{
+ MbbPacketRestoreMdl(PacketContext);
+ if (PacketContext->PaddingMdl != NULL)
+ {
+ IoFreeMdl(PacketContext->PaddingMdl);
+ PacketContext->PaddingMdl = NULL;
+ }
+ if (PacketContext->DataEndMdl != NULL)
+ {
+ IoFreeMdl(PacketContext->DataEndMdl);
+ PacketContext->DataEndMdl = NULL;
+ }
+ if (PacketContext->DataStartMdl != NULL)
+ {
+ IoFreeMdl(PacketContext->DataStartMdl);
+ PacketContext->DataStartMdl = NULL;
+ }
+}
+
+FORCEINLINE
+PMDL MbbPacketGetFirstMdl(_In_ PMBB_PACKET_CONTEXT PacketContext)
+{
+ if (PacketContext->PaddingMdl != NULL)
+ return PacketContext->PaddingMdl;
+ else
+ return PacketContext->DataStartMdl;
+}
+
+FORCEINLINE
+PMDL MbbPacketGetLastMdl(_In_ PMBB_PACKET_CONTEXT PacketContext)
+{
+ if (PacketContext->DataEndMdl != NULL)
+ return PacketContext->DataEndMdl;
+ else
+ return PacketContext->DataStartMdl;
+}
+
+VOID MbbPacketSaveAndSetMdl(_In_ PMBB_PACKET_CONTEXT PacketContext, _In_ PMDL MdlToSave, _In_ PMDL MdlToSet)
+{
+ if (PacketContext->ModifiedMdl == NULL)
+ {
+ PacketContext->ModifiedMdl = MdlToSave;
+ PacketContext->OriginalMdl = *MdlToSave;
+ }
+ *MdlToSave = *MdlToSet;
+}
+
+VOID MbbCleanupDssPacket(_In_ PDSS_PACKET Packet)
+{
+ if (Packet->Mdl != NULL)
+ {
+ IoFreeMdl(Packet->Mdl);
+ }
+ if (Packet != NULL)
+ {
+ FREE_POOL(Packet);
+ }
+}
+
+VOID MbbNtbCleanupContext(_In_ PMBB_NTB_BUILD_CONTEXT NtbContext, _In_ NTSTATUS NtStatus)
+{
+ ULONG DatagramIndex;
+ BOOLEAN NeedReturnCompletedPackets = FALSE;
+
+ for (DatagramIndex = 0; DatagramIndex < NtbContext->DatagramCount; DatagramIndex++)
+ {
+ MbbPacketCleanupContext(&NtbContext->NdpDatagramEntries[DatagramIndex].NetPacketContext);
+ if (NtbContext->NdpDatagramEntries[DatagramIndex].NdpType == MbbNdpTypeIps)
+ {
+ NtbContext->NdpDatagramEntries[DatagramIndex].NetPacket->Scratch = 1;
+ NeedReturnCompletedPackets = TRUE;
+ }
+ else if (NtbContext->NdpDatagramEntries[DatagramIndex].NdpType == MbbNdpTypeVendor_1)
+ {
+ MbbDeviceSendDeviceServiceSessionDataComplete(NtbContext->NdpDatagramEntries[DatagramIndex].DssPacket->Data, NtStatus);
+
+ MbbCleanupDssPacket(NtbContext->NdpDatagramEntries[DatagramIndex].DssPacket);
+ }
+ }
+ if (NtbContext->NdpMdl != NULL)
+ {
+ IoFreeMdl(NtbContext->NdpMdl);
+ }
+ if (NtbContext->NthMdl != NULL)
+ {
+ IoFreeMdl(NtbContext->NthMdl);
+ }
+ if (NtbContext->NdpBufferMemory != NULL)
+ {
+ WdfObjectDelete(NtbContext->NdpBufferMemory);
+ }
+#if DBG
+ if (NtbContext->ScratchBuffer != NULL)
+ {
+ FREE_POOL(NtbContext->ScratchBuffer);
+ }
+#endif
+ if (NeedReturnCompletedPackets)
+ {
+ MbbNotifyTxReady(NtbContext->NetTxQueue);
+ }
+ WdfObjectDelete(NtbContext->NtbLookasideBufferMemory);
+}
+
+FORCEINLINE
+ULONG
+MbbSendQGetNtbSequence(_In_ PWMBCLASS_DEVICE_CONTEXT DeviceContext)
+{
+ return InterlockedIncrement(&DeviceContext->NtbSequenceNumber);
+}
+
+PMBB_NTB_BUILD_CONTEXT
+MbbNtbAllocateContext(_In_ WDFLOOKASIDE NtbLookasideList, _In_ PMBB_BUS_PARAMETERS BusParams, _In_ PVOID PaddingBuffer, _In_ ULONG NtbSequence)
+{
+ NTSTATUS status = NDIS_STATUS_SUCCESS;
+ size_t ntbSize;
+ PMBB_NTB_BUILD_CONTEXT ntbContext = NULL;
+ WDFMEMORY ntbContextMemory;
+
+ do
+ {
+#pragma prefast(suppress \
+ : __WARNING_MEMORY_LEAK, "By Design: Allocate ntb context from lookaside pool, released when send completes.")
+ if (!NT_SUCCESS(status = WdfMemoryCreateFromLookaside(NtbLookasideList, &ntbContextMemory)))
+ {
+ break;
+ }
+
+ ntbContext = (PMBB_NTB_BUILD_CONTEXT)WdfMemoryGetBuffer(ntbContextMemory, &ntbSize);
+ RtlZeroMemory(ntbContext, ntbSize);
+ ntbContext->PaddingBuffer = PaddingBuffer;
+ ntbContext->NtbLookasideList = NtbLookasideList;
+ ntbContext->NtbLookasideBufferMemory = ntbContextMemory;
+
+#if DBG
+ ntbContext->ScratchLength = BusParams->MaxOutNtb;
+ if ((ntbContext->ScratchBuffer = (PCHAR)ALLOCATE_NONPAGED_POOL(ntbContext->ScratchLength)) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+#endif
+ //
+ // Initialize the NTH and the NTH MDL.
+ //
+ if ((ntbContext->IsNtb32Bit = BusParams->CurrentMode32Bit) == TRUE)
+ {
+ if ((ntbContext->NthMdl = AllocateNonPagedMdl(&ntbContext->Nth32, sizeof(ntbContext->Nth32))) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ ntbContext->Nth32.dwSignature = NCM_NTH32_SIG;
+ ntbContext->Nth32.wHeaderLength = sizeof(NCM_NTH32);
+ ntbContext->Nth32.wSequence = (USHORT)NtbSequence;
+
+ ntbContext->NtbHeaderSize = sizeof(NCM_NTH32);
+ ntbContext->NdpHeaderFixedSize = sizeof(NCM_NDP32);
+ ntbContext->NdpDatagramEntrySize = sizeof(NCM_NDP32_DATAGRAM);
+ }
+ else
+ {
+ if ((ntbContext->NthMdl = AllocateNonPagedMdl(&ntbContext->Nth16, sizeof(ntbContext->Nth16))) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ ntbContext->Nth16.dwSignature = NCM_NTH16_SIG;
+ ntbContext->Nth16.wHeaderLength = sizeof(NCM_NTH16);
+ ntbContext->Nth16.wSequence = (USHORT)NtbSequence;
+
+ ntbContext->NtbHeaderSize = sizeof(NCM_NTH16);
+ ntbContext->NdpHeaderFixedSize = sizeof(NCM_NDP16);
+ ntbContext->NdpDatagramEntrySize = sizeof(NCM_NDP16_DATAGRAM);
+ }
+
+ ntbContext->NtbOutMaxSize = BusParams->MaxOutNtb;
+ ntbContext->NtbOutMaxDatagrams = BusParams->MaxOutDatagrams;
+ ntbContext->NdpOutDivisor = BusParams->NdpOutDivisor;
+ ntbContext->NdpOutPayloadRemainder = BusParams->NdpOutRemainder;
+ ntbContext->NdpOutAlignment = BusParams->NdpOutAlignment;
+ } while (FALSE);
+
+ if (!NT_SUCCESS(status))
+ {
+ if (ntbContext != NULL)
+ {
+ MbbNtbCleanupContext(ntbContext, status);
+ }
+ ntbContext = NULL;
+ }
+ return ntbContext;
+}
+
+NTSTATUS
+MbbFillPacketContext(
+ _In_ PMBB_PACKET_CONTEXT PacketContext,
+ _In_ PMDL PacketDataStartMdl,
+ _In_ ULONG PacketDataStartMdlDataOffset,
+ _In_ ULONG DatagramLength,
+ _In_ PVOID PaddingBuffer,
+ _In_ ULONG PaddingLength)
+{
+ ULONG packetDataStartMdlDataLength;
+ PCHAR packetDataStartBuffer;
+ PMDL packetDataEndMdl;
+ ULONG packetDataEndMdlDataLength;
+ PCHAR packetDataEndBuffer;
+ PMDL packetMdl;
+ ULONG packetMdlOffset;
+ ULONG packetMdlLength;
+ PMDL packetPenultimateMdl;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ do
+ {
+ if ((packetDataStartBuffer = (PCHAR)MmGetSystemAddressForMdlSafe(PacketDataStartMdl, NormalPagePriority | MdlMappingNoExecute)) == NULL)
+ {
+ status = STATUS_RESOURCE_DATA_NOT_FOUND;
+ break;
+ }
+ packetDataStartBuffer += PacketDataStartMdlDataOffset;
+ //
+ // Create new DataStart and DataEnd Mdls
+ // to remove the unused data space.
+ //
+ packetDataStartMdlDataLength = MmGetMdlByteCount(PacketDataStartMdl);
+ packetDataStartMdlDataLength -= PacketDataStartMdlDataOffset;
+
+ if ((PacketContext->DataStartMdl =
+ AllocateNonPagedMdl(packetDataStartBuffer, (ULONG)(MIN(DatagramLength, packetDataStartMdlDataLength)))) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ PacketContext->DataStartMdl->Next = PacketDataStartMdl->Next;
+ //
+ // Find the end MDL and the amount of data in the end MDL
+ //
+ packetMdl = PacketDataStartMdl;
+ packetMdlOffset = PacketDataStartMdlDataOffset;
+ packetPenultimateMdl = NULL;
+
+ for (packetDataEndMdlDataLength = (ULONG)DatagramLength; packetDataEndMdlDataLength > (MmGetMdlByteCount(packetMdl) - packetMdlOffset);
+ packetDataEndMdlDataLength -= packetMdlLength)
+ {
+ packetPenultimateMdl = packetMdl;
+ packetMdlLength = MmGetMdlByteCount(packetMdl) - packetMdlOffset;
+ packetMdlOffset = 0;
+ packetMdl = packetMdl->Next;
+ }
+ packetDataEndMdl = packetMdl;
+ //
+ // If the starting and ending MDLs are not the same
+ // then build another partial MDL removing any unused
+ // data space.
+ //
+ if (packetDataEndMdl != PacketDataStartMdl)
+ {
+ if ((packetDataEndBuffer = (PCHAR)MmGetSystemAddressForMdlSafe(packetDataEndMdl, NormalPagePriority | MdlMappingNoExecute)) == NULL)
+ {
+ status = STATUS_RESOURCE_DATA_NOT_FOUND;
+ break;
+ }
+
+ if ((PacketContext->DataEndMdl = AllocateNonPagedMdl(packetDataEndBuffer, packetDataEndMdlDataLength)) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ PacketContext->DataEndMdl->Next = NULL;
+
+ if (packetPenultimateMdl != PacketDataStartMdl)
+ {
+ MDL TempMdl = *packetPenultimateMdl;
+ TempMdl.Next = PacketContext->DataEndMdl;
+
+ MbbPacketSaveAndSetMdl(PacketContext, packetPenultimateMdl, &TempMdl);
+ }
+
+ if (PacketContext->DataStartMdl->Next == packetDataEndMdl)
+ {
+ PacketContext->DataStartMdl->Next = PacketContext->DataEndMdl;
+ }
+ }
+ //
+ // Allocate padding, if needed. The padding buffer is a share buffer.
+ // Every padding MDL points to this same buffer. The buffer contains
+ // all 0s.
+ //
+ if (PaddingLength != 0)
+ {
+ if ((PacketContext->PaddingMdl = AllocateNonPagedMdl(PaddingBuffer, PaddingLength)) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ PacketContext->PaddingMdl->Next = PacketContext->DataStartMdl;
+ }
+ } while (FALSE);
+
+ return status;
+}
+
+VOID MbbNtbChainNb(_In_ PMBB_NTB_BUILD_CONTEXT NtbContext, _In_ PMBB_PACKET_CONTEXT PacketContext)
+{
+ if (NtbContext->DatagramLastMdl != NULL)
+ {
+ NtbContext->DatagramLastMdl->Next = MbbPacketGetFirstMdl(PacketContext);
+ }
+ else
+ {
+ NtbContext->NthMdl->Next = MbbPacketGetFirstMdl(PacketContext);
+ }
+
+ NtbContext->DatagramLastMdl = MbbPacketGetLastMdl(PacketContext);
+}
+
+NTSTATUS
+MbbNtbAddPacket(
+ _In_ PMBB_NTB_BUILD_CONTEXT NtbContext,
+ _In_ PVOID PacketContext,
+ _In_ ULONG DatagramLength,
+ _In_ PMDL PacketDataStartMdl,
+ _In_ ULONG PacketDataStartMdlDataOffset,
+ _In_ MBB_NDP_TYPE CurrentNdpType,
+ _In_ ULONG SessionId)
+{
+ ULONG datagramOffset;
+ ULONG paddingLength;
+ ULONG ndpSize;
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG totalLength;
+ PMBB_PACKET_CONTEXT packetContext = NULL;
+
+ do
+ {
+ if ((NtbContext->DatagramCount + 1) > NtbContext->NtbOutMaxDatagrams)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+
+ //
+ // Size of passed in NET_BUFFER, to be updated later in the NDP Context.
+ //
+ totalLength = NtbContext->NtbHeaderSize + NtbContext->DatagramLength;
+ paddingLength = ALIGN_AT_OFFSET(totalLength, NtbContext->NdpOutDivisor, NtbContext->NdpOutPayloadRemainder) - totalLength;
+ //
+ // Calculate the new NTB size based on the passed in MBB_PACKET
+ //
+
+ //
+ // Fixed size NTH & DatagramSize along with Padding for all NDPs
+ //
+ datagramOffset = totalLength + paddingLength;
+ totalLength += DatagramLength + paddingLength;
+
+ //
+ // Calculate NDP HeaderSize for all NDPs
+ //
+ ndpSize = totalLength;
+ totalLength = ALIGN(totalLength, NtbContext->NdpOutAlignment);
+ totalLength += NtbContext->NdpHeaderFixedSize;
+ totalLength += ((NtbContext->DatagramCount + 1) * NtbContext->NdpDatagramEntrySize);
+ ndpSize = totalLength - ndpSize;
+ //
+ // Can everything fit?
+ //
+ if (totalLength > NtbContext->NtbOutMaxSize)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+ packetContext = &NtbContext->NdpDatagramEntries[NtbContext->DatagramCount].NetPacketContext;
+ if (!NT_SUCCESS(
+ status = MbbFillPacketContext(
+ packetContext, PacketDataStartMdl, PacketDataStartMdlDataOffset, DatagramLength, NtbContext->PaddingBuffer, paddingLength)))
+ {
+ break;
+ }
+ //
+ // Update the NTB Context for the new NET_BUFFER.
+ //
+ NtbContext->NdpDatagramEntries[NtbContext->DatagramCount].DatagramOffset = datagramOffset;
+ NtbContext->NdpDatagramEntries[NtbContext->DatagramCount].DatagramLength = DatagramLength;
+ NtbContext->NdpDatagramEntries[NtbContext->DatagramCount].NdpType = CurrentNdpType;
+ NtbContext->NdpDatagramEntries[NtbContext->DatagramCount].SessionId = SessionId;
+ if (CurrentNdpType == MbbNdpTypeIps)
+ {
+ NtbContext->NdpDatagramEntries[NtbContext->DatagramCount].NetPacket = (NET_PACKET*)PacketContext;
+ }
+ else if (CurrentNdpType == MbbNdpTypeVendor_1)
+ {
+ NtbContext->NdpDatagramEntries[NtbContext->DatagramCount].DssPacket = (PDSS_PACKET)PacketContext;
+ }
+
+ NtbContext->NdpSize = ndpSize;
+ NtbContext->DatagramCount += 1;
+ NtbContext->DatagramLength += (DatagramLength + paddingLength);
+
+ MbbNtbChainNb(NtbContext, packetContext);
+ } while (FALSE);
+
+ if (!NT_SUCCESS(status))
+ {
+ if (packetContext != NULL)
+ {
+ MbbPacketCleanupContext(packetContext);
+ }
+ }
+ return status;
+}
+
+FORCEINLINE
+PMDL MbbNtbGetMdlChainHead(_In_ PMBB_NTB_BUILD_CONTEXT NtbContext)
+{
+ return NtbContext->NthMdl;
+}
+
+VOID MbbSendQCompleteNtb(_In_ MBB_PROTOCOL_HANDLE ProtocolHandle, _In_ MBB_REQUEST_HANDLE RequestHandle, _In_ NTSTATUS NtStatus, _In_ PMDL Mdl)
+{
+ UNREFERENCED_PARAMETER(ProtocolHandle);
+ PMBB_NTB_BUILD_CONTEXT ntbContext = (PMBB_NTB_BUILD_CONTEXT)RequestHandle;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetNetAdapterContext(ntbContext->NetAdapter)->WmbDeviceContext;
+ UNREFERENCED_PARAMETER(Mdl);
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ if (NtStatus == STATUS_NDIS_ADAPTER_NOT_READY)
+ {
+ }
+ else if (NtStatus == STATUS_CANCELLED)
+ {
+ }
+ else if (NtStatus == STATUS_NO_SUCH_DEVICE)
+ {
+ }
+ else
+ {
+ MbbBusResetDataPipes(deviceContext->BusHandle);
+ }
+ }
+
+ MbbNtbCleanupContext(ntbContext, NtStatus);
+}
+
+ULONG
+MbbNtbMapNdpTypeToSignature(_In_ MBB_NDP_TYPE MbbNdpType, _In_ BOOLEAN Is32Bit, _In_ ULONG SessionId)
+{
+ ULONG SessionMask = (SessionId << NCM_NDP_SESSION_SHIFT);
+
+ switch (MbbNdpType)
+ {
+ case MbbNdpTypeIps: return ((Is32Bit == TRUE) ? NCM_NDP32_IPS | SessionMask : NCM_NDP16_IPS | SessionMask);
+ default:
+ if ((MbbNdpType >= MbbNdpTypeVendor_1) && (MbbNdpType <= MbbNdpTypeVendor_Max))
+ {
+ return ((Is32Bit == TRUE) ? NCM_NDP32_VENDOR | SessionMask : NCM_NDP16_VENDOR | SessionMask);
+ }
+ }
+ return 0;
+}
+
+VOID MbbNtbFillNdp32Header(_In_ PNCM_NDP32 Ndp, _In_ MBB_NDP_TYPE NdpType, _In_ PMBB_NTB_BUILD_CONTEXT NtbContext)
+{
+ ULONG datagramIndex = 0;
+ ULONG ndpDatagramIndex = 0;
+ PNCM_NDP32_DATAGRAM ndpDatagramEntries;
+
+ Ndp->dwSignature = MbbNtbMapNdpTypeToSignature(NdpType, TRUE, NtbContext->NdpDatagramEntries[datagramIndex].SessionId);
+ Ndp->dwNextFpIndex = 0;
+ ndpDatagramEntries = Ndp->Datagram;
+ //
+ // Add datagram entries to the NDP Table
+ //
+
+ for (datagramIndex = 0; datagramIndex < NtbContext->DatagramCount; datagramIndex++)
+ {
+ ndpDatagramEntries[ndpDatagramIndex].dwDatagramIndex = NtbContext->NdpDatagramEntries[datagramIndex].DatagramOffset;
+ ndpDatagramEntries[ndpDatagramIndex].dwDatagramLength = NtbContext->NdpDatagramEntries[datagramIndex].DatagramLength;
+ ndpDatagramIndex++;
+ }
+ //
+ // Terminating entry is taken in to account
+ // in the fixed size NDP Header.
+ //
+ ndpDatagramEntries[ndpDatagramIndex].dwDatagramIndex = 0;
+ ndpDatagramEntries[ndpDatagramIndex].dwDatagramLength = 0;
+
+ Ndp->wLength = (USHORT)(NtbContext->NdpHeaderFixedSize + (ndpDatagramIndex * NtbContext->NdpDatagramEntrySize));
+}
+
+VOID MbbNtbFillNdp16Header(__in PNCM_NDP16 Ndp, __in MBB_NDP_TYPE NdpType, __in PMBB_NTB_BUILD_CONTEXT NtbContext)
+{
+ ULONG datagramIndex = 0;
+ ULONG ndpDatagramIndex = 0;
+ PNCM_NDP16_DATAGRAM ndpDatagramEntries;
+
+ Ndp->dwSignature = MbbNtbMapNdpTypeToSignature(NdpType, FALSE, NtbContext->NdpDatagramEntries[datagramIndex].SessionId);
+
+ Ndp->wNextFpIndex = 0;
+ ndpDatagramEntries = Ndp->Datagram;
+ //
+ // Add datagram entries to the NDP Table
+ //
+ for (datagramIndex = 0; datagramIndex < NtbContext->DatagramCount; datagramIndex++)
+ {
+ ndpDatagramEntries[ndpDatagramIndex].wDatagramIndex = (USHORT)NtbContext->NdpDatagramEntries[datagramIndex].DatagramOffset;
+ ndpDatagramEntries[ndpDatagramIndex].wDatagramLength = (USHORT)NtbContext->NdpDatagramEntries[datagramIndex].DatagramLength;
+ ndpDatagramIndex++;
+ }
+ //
+ // Terminating entry is taken in to account
+ // in the fixed size NDP Header.
+ //
+ ndpDatagramEntries[ndpDatagramIndex].wDatagramIndex = 0;
+ ndpDatagramEntries[ndpDatagramIndex].wDatagramLength = 0;
+
+ Ndp->wLength = (USHORT)(NtbContext->NdpHeaderFixedSize + (ndpDatagramIndex * NtbContext->NdpDatagramEntrySize));
+}
+
+NTSTATUS
+MbbNtbAddNdpHeaders(_In_ PMBB_NTB_BUILD_CONTEXT NtbContext)
+{
+ // Offset from the start of the NTB buffer to the start of NDP headers
+ ULONG ndpStartOffset;
+ // Offset from the start of the NTB Buffer to the current position.
+ ULONG ntbOffset;
+ PCHAR ndpBuffer;
+ MBB_NDP_TYPE ndpType;
+ PNCM_NDP16 ndp16;
+ PNCM_NDP32 ndp32;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ do
+ {
+ //
+ // Allocate buffer for all NDP headers.
+ // This includes padding for NDP Header alignment.
+ //
+ status = CreateNonPagedWdfMemory(
+ NtbContext->NdpSize,
+ &NtbContext->NdpBufferMemory,
+ &NtbContext->NdpBuffer,
+ NtbContext->NetTxQueue == NULL ? (WDFOBJECT)NtbContext->NetAdapter : NtbContext->NetTxQueue,
+ MbbPoolTagNtbSend);
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+ RtlZeroMemory(NtbContext->NdpBuffer, NtbContext->NdpSize);
+ ndpBuffer = (PCHAR)(NtbContext->NdpBuffer);
+ //
+ // Chain the NDP Header through its MDL to datagram MDL
+ //
+ if ((NtbContext->NdpMdl = AllocateNonPagedMdl(NtbContext->NdpBuffer, NtbContext->NdpSize)) == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ NtbContext->DatagramLastMdl->Next = NtbContext->NdpMdl;
+ ndpStartOffset = NtbContext->NtbHeaderSize + NtbContext->DatagramLength;
+
+ if (NtbContext->IsNtb32Bit)
+ NtbContext->Nth32.dwFpIndex = ALIGN(ndpStartOffset, NtbContext->NdpOutAlignment);
+ else
+ NtbContext->Nth16.wFpIndex = (USHORT)ALIGN(ndpStartOffset, NtbContext->NdpOutAlignment);
+
+ ntbOffset = ALIGN(ndpStartOffset, NtbContext->NdpOutAlignment);
+ ndpType = NtbContext->NdpDatagramEntries[0].NdpType;
+
+ if (NtbContext->IsNtb32Bit == TRUE)
+ {
+ ndp32 = (PNCM_NDP32)(ndpBuffer + (ntbOffset - ndpStartOffset));
+
+ MbbNtbFillNdp32Header(ndp32, ndpType, NtbContext);
+ }
+ else
+ {
+ ndp16 = (PNCM_NDP16)(ndpBuffer + (ntbOffset - ndpStartOffset));
+
+ MbbNtbFillNdp16Header(ndp16, ndpType, NtbContext);
+ }
+
+ if (NtbContext->IsNtb32Bit == TRUE)
+ {
+ NtbContext->Nth32.dwBlockLength = NtbContext->NtbHeaderSize;
+ NtbContext->Nth32.dwBlockLength += NtbContext->DatagramLength;
+ NtbContext->Nth32.dwBlockLength += NtbContext->NdpSize;
+ }
+ else
+ {
+ NtbContext->Nth16.wBlockLength = (USHORT)(NtbContext->NtbHeaderSize);
+ NtbContext->Nth16.wBlockLength += (USHORT)(NtbContext->DatagramLength);
+ NtbContext->Nth16.wBlockLength += (USHORT)(NtbContext->NdpSize);
+ }
+ } while (FALSE);
+ //
+ // No cleanup. Cleanup done by caller.
+ //
+ return status;
+}
+
+NTSTATUS
+MbbTestValidateNtb(_In_ PMBB_NTB_BUILD_CONTEXT NtbContext, _In_reads_bytes_(ScratchLength) PCHAR ScratchBuffer, _In_ ULONG ScratchLength)
+{
+ PMDL currentMdl;
+ ULONGLONG ntbLength;
+ ULONG mdlLength;
+ PVOID mdlVa;
+ PVOID nth;
+
+ nth = ScratchBuffer;
+ ntbLength = 0;
+
+ for (currentMdl = MbbNtbGetMdlChainHead(NtbContext); currentMdl != NULL; currentMdl = currentMdl->Next)
+ {
+ mdlLength = MmGetMdlByteCount(currentMdl);
+
+ if ((mdlVa = MmGetSystemAddressForMdlSafe(currentMdl, NormalPagePriority | MdlMappingNoExecute)) == NULL)
+ {
+ return STATUS_RESOURCE_DATA_NOT_FOUND;
+ }
+
+ if ((ntbLength + mdlLength) > ScratchLength)
+ {
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ RtlCopyMemory(ScratchBuffer, mdlVa, mdlLength);
+
+ ScratchBuffer += mdlLength;
+ ntbLength += mdlLength;
+ }
+
+ return MbbNtbValidate(nth, (ULONG)ntbLength, NtbContext->IsNtb32Bit, NULL);
+}
+
+void EvtTxQueueDestroy(_In_ WDFOBJECT TxQueue)
+{
+ PMBB_TXQUEUE_CONTEXT txQueueContext = MbbGetTxQueueContext(TxQueue);
+
+ txQueueContext->NetAdapterContext->TxQueue = NULL;
+}
+
+VOID EvtTxQueueSetNotificationEnabled(_In_ NETPACKETQUEUE TxQueue, _In_ BOOLEAN NotificationEnabled)
+{
+ PMBB_TXQUEUE_CONTEXT txQueueContext = MbbGetTxQueueContext(TxQueue);
+
+ InterlockedExchange(&txQueueContext->NotificationEnabled, NotificationEnabled);
+}
+
+void EvtTxQueueCancel(_In_ NETPACKETQUEUE TxQueue)
+{
+ NET_RING_COLLECTION const* rings = MbbGetTxQueueContext(TxQueue)->DatapathDescriptor;
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(rings);
+ while (pr->BeginIndex != pr->EndIndex)
+ {
+ UINT32 const packetIndex = pr->BeginIndex;
+ NetRingGetPacketAtIndex(pr, packetIndex)->Scratch = 1;
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ }
+}
+
+bool MbbEnableTxBatching(_In_ NET_RING_COLLECTION const* Rings)
+{
+ NET_RING * ring = Rings->Rings[NetRingTypeFragment];
+ return ((ring->EndIndex - ring->BeginIndex) & ring->ElementIndexMask) > (NetRingCollectionGetPacketRing(Rings)->NumberOfElements / 2);
+}
+
+inline
+VOID
+CompleteTxPacketsBatch(
+ _In_ NET_RING_COLLECTION const * Rings,
+ _In_ UINT32 BatchSize
+)
+{
+ UINT32 packetCount = 0;
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(Rings);
+
+ while (pr->BeginIndex != pr->EndIndex)
+ {
+ UINT32 const packetIndex = pr->BeginIndex;
+ auto packet = NetRingGetPacketAtIndex(pr, packetIndex);
+
+ // this function uses Scratch field as the bit for testing completion
+ if (!packet->Scratch)
+ {
+ break;
+ }
+
+ packetCount++;
+
+ NET_RING * fr = NetRingCollectionGetFragmentRing(Rings);
+ fr->BeginIndex = fr->EndIndex;
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+
+ if (packetCount >= BatchSize)
+ {
+ Rings->Rings[NetRingTypeFragment]->BeginIndex = fr->BeginIndex;
+ }
+ }
+}
+
+void EvtTxQueueAdvance(_In_ NETPACKETQUEUE TxQueue)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PMBB_TXQUEUE_CONTEXT txQueueContext = MbbGetTxQueueContext(TxQueue);
+ NET_RING_COLLECTION const* rings = txQueueContext->DatapathDescriptor;
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = txQueueContext->NetAdapterContext;
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = netAdapterContext->WmbDeviceContext;
+ PMBB_NTB_BUILD_CONTEXT ntbContext = NULL;
+ ULONG sessionId = netAdapterContext->SessionId;
+ ULONG batchSize = MbbEnableTxBatching(rings) ? txQueueContext->CompletionBatchSize : 1;
+
+ NET_RING * pr = NetRingCollectionGetPacketRing(rings);
+ while (pr->BeginIndex != pr->EndIndex)
+ {
+ UINT32 packetIndex = pr->BeginIndex;
+ auto packet = NetRingGetPacketAtIndex(pr, packetIndex);
+ if (packet->Ignore)
+ {
+ packet->Scratch = 1;
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ continue;
+ }
+
+ ntbContext = MbbNtbAllocateContext(
+ netAdapterContext->NtbLookasideList, &deviceContext->BusParams, deviceContext->sharedPaddingBuffer, MbbSendQGetNtbSequence(deviceContext));
+
+ if (ntbContext == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ ntbContext->NetTxQueue = TxQueue;
+ ntbContext->NetAdapter = netAdapterContext->NetAdapter;
+ ntbContext->NetDatapathDescriptor = rings;
+
+ auto fr = NetRingCollectionGetFragmentRing(rings);
+ while (NT_SUCCESS(
+ status = MbbNtbAddPacket(
+ ntbContext,
+ packet,
+ MbbGetNetPacketDataLength(packet, rings),
+ NetExtensionGetFragmentMdl(&txQueueContext->MdlExtension, packet->FragmentIndex)->Mdl,
+ NetRingGetFragmentAtIndex(fr, packet->FragmentIndex)->Offset,
+ MbbNdpTypeIps,
+ sessionId)))
+ {
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+
+ // the ring buffer has no more net packets to send,
+ // so packing is done. break now to make USB request
+ if (pr->BeginIndex == pr->EndIndex)
+ {
+ break;
+ }
+
+ packetIndex = pr->BeginIndex;
+ packet = NetRingGetPacketAtIndex(pr, packetIndex);
+ }
+
+ if (status == STATUS_BUFFER_OVERFLOW)
+ {
+ //
+ // If the NTB was empty and this packet couldnt be added
+ // then ignore this packet to prevent retrying forever.
+ // Or send this NTB to bus then start a new NTB
+ //
+ if (ntbContext->DatagramCount == 0)
+ {
+ packet->Scratch = 1;
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ }
+ }
+ else if (status != STATUS_SUCCESS)
+ {
+ //
+ // MbbNtbAddPacket failed, we should ignore this packet, or the loop may never complete
+ //
+ packet->Scratch = 1;
+ pr->BeginIndex = NetRingIncrementIndex(pr, pr->BeginIndex);
+ }
+
+ if (ntbContext->DatagramCount > 0)
+ {
+ status = MbbNtbAddNdpHeaders(ntbContext);
+ if (!NT_SUCCESS(status))
+ {
+ }
+ else
+ {
+#if DBG
+ if (!NT_SUCCESS(MbbTestValidateNtb(ntbContext, ntbContext->ScratchBuffer, ntbContext->ScratchLength)))
+ {
+ ASSERT(FALSE);
+ }
+#endif
+ //
+ // Send the data. On failure, cleanup.
+ //
+ status = MbbBusWriteData(deviceContext->BusHandle, ntbContext, MbbNtbGetMdlChainHead(ntbContext), MbbSendQCompleteNtb);
+ if (!NT_SUCCESS(status))
+ {
+ }
+ }
+ }
+ else
+ {
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ if (!NT_SUCCESS(status))
+ {
+ MbbSendQCompleteNtb(netAdapterContext, ntbContext, status, MbbNtbGetMdlChainHead(ntbContext));
+ }
+ }
+
+ CompleteTxPacketsBatch(rings, batchSize);
+}
+
+PDSS_PACKET MbbAllocateDssPacket(_In_ WDFMEMORY Data, _In_ PVOID DataBuffer, _In_ size_t DataSize)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PDSS_PACKET packet = NULL;
+ do
+ {
+// By Design: Allocate packet from NtbSend Pool, released in function MbbNtbCleanupContext called from MbbSendQCompleteNtb.
+#pragma prefast(suppress : __WARNING_MEMORY_LEAK, "Released in function MbbNtbCleanupContext")
+ packet = (PDSS_PACKET)ALLOCATE_NONPAGED_POOL_WITH_TAG(sizeof(DSS_PACKET), MbbPoolTagNtbSend);
+ if (packet == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ RtlZeroMemory(packet, sizeof(DSS_PACKET));
+
+ packet->Data = Data;
+ packet->Mdl = AllocateNonPagedMdl(DataBuffer, (ULONG)DataSize);
+
+ if (packet->Mdl == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ } while (FALSE);
+
+ if (!NT_SUCCESS(status))
+ {
+ if (packet != NULL)
+ {
+ MbbCleanupDssPacket(packet);
+ packet = NULL;
+ }
+ }
+
+ return packet;
+}
+
+_Use_decl_annotations_ VOID EvtMbbDeviceSendDeviceServiceSessionData(WDFDEVICE Device, DSS_SESSION_ID SessionId, WDFMEMORY Data)
+{
+ PWMBCLASS_DEVICE_CONTEXT deviceContext = WmbClassGetDeviceContext(Device);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PWMBCLASS_NETADAPTER_CONTEXT netAdapterContext = deviceContext->Sessions[MBB_DEFAULT_SESSION_ID].NetAdapterContext;
+
+ PMBB_NTB_BUILD_CONTEXT ntbContext = NULL;
+ PDSS_PACKET packet = NULL;
+ BOOLEAN completeNow = TRUE;
+
+ do
+ {
+ ntbContext = MbbNtbAllocateContext(
+ netAdapterContext->NtbLookasideList, &deviceContext->BusParams, deviceContext->sharedPaddingBuffer, MbbSendQGetNtbSequence(deviceContext));
+
+ if (ntbContext == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ ntbContext->NetTxQueue = NULL;
+ ntbContext->NetAdapter = netAdapterContext->NetAdapter;
+ size_t bufferSize = 0;
+ PVOID buffer = WdfMemoryGetBuffer(Data, &bufferSize);
+
+ packet = MbbAllocateDssPacket(Data, buffer, bufferSize);
+ if (packet == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ status = MbbNtbAddPacket(ntbContext, packet, (ULONG)bufferSize, packet->Mdl, 0, MbbNdpTypeVendor_1, SessionId);
+ if (!NT_SUCCESS(status))
+ {
+ MbbCleanupDssPacket(packet);
+ break;
+ }
+
+ completeNow = FALSE;
+
+ status = MbbNtbAddNdpHeaders(ntbContext);
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+
+#if DBG
+ if (!NT_SUCCESS(MbbTestValidateNtb(ntbContext, ntbContext->ScratchBuffer, ntbContext->ScratchLength)))
+ {
+ ASSERT(FALSE);
+ }
+#endif
+
+ //
+ // Send the data. On failure, cleanup. It will return STATUS_PENDING when success
+ //
+ status = MbbBusWriteData(deviceContext->BusHandle, ntbContext, MbbNtbGetMdlChainHead(ntbContext), MbbSendQCompleteNtb);
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+
+ deviceContext->DSSPacketsSentCount++;
+ } while (FALSE);
+
+ if (!NT_SUCCESS(status))
+ {
+ if (ntbContext != NULL)
+ {
+ MbbSendQCompleteNtb(deviceContext, ntbContext, status, MbbNtbGetMdlChainHead(ntbContext));
+ }
+ if (completeNow)
+ {
+ MbbDeviceSendDeviceServiceSessionDataComplete(Data, status);
+ }
+ }
+}
diff --git a/network/wwan/cxwmbclass/util.cpp b/network/wwan/cxwmbclass/util.cpp
new file mode 100644
index 00000000..2e2e5f34
--- /dev/null
+++ b/network/wwan/cxwmbclass/util.cpp
@@ -0,0 +1,326 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// INCLUDES
+//
+////////////////////////////////////////////////////////////////////////////////
+#include "precomp.h"
+
+NTSTATUS
+MbbNtbDetectNdp32Loop(_In_ PNCM_NTH32 Nth)
+{
+ PNCM_NDP32 FirstNdp;
+ PNCM_NDP32 Ndp;
+ PNCM_NDP32 LoopNdp;
+
+ if ((FirstNdp = MBB_NTH32_GET_FIRST_NDP(Nth)) == NULL)
+ return STATUS_SUCCESS;
+
+ if (!MBB_NTB32_IS_VALID_NDP_LENGTH(Nth, FirstNdp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ LoopNdp = MBB_NDP32_GET_NEXT_NDP(Nth, FirstNdp);
+
+ for (Ndp = FirstNdp; Ndp != NULL && LoopNdp != NULL; Ndp = MBB_NDP32_GET_NEXT_NDP(Nth, Ndp))
+ {
+ if (!MBB_NTB32_IS_VALID_NDP_LENGTH(Nth, LoopNdp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTB32_IS_VALID_NDP_LENGTH(Nth, Ndp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (LoopNdp == Ndp)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if ((LoopNdp = MBB_NDP32_GET_NEXT_NDP(Nth, LoopNdp)) != NULL)
+ {
+ if (!MBB_NTB32_IS_VALID_NDP_LENGTH(Nth, LoopNdp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ LoopNdp = MBB_NDP32_GET_NEXT_NDP(Nth, LoopNdp);
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbbNtbValidateNdp32(_In_ PNCM_NTH32 Nth, _In_ PNCM_NDP32 Ndp)
+{
+ ULONG Index;
+ ULONG DatagramCount = MBB_NDP32_GET_DATAGRAM_COUNT(Ndp);
+
+ if (!MBB_NTB32_IS_VALID_NDP_SIGNATURE(Ndp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (MBB_NDP32_GET_SIGNATURE_TYPE(Ndp) == NCM_NDP32_IPS)
+ {
+ //
+ // Check if the session id is valid, else discard
+ //
+
+ // Check if session Id is greater than maximum supported. Here
+ // we can also check against MaxActivatedContexts, but this would
+ // mean we need to take a lock for getting the value of maxactivatedcontexts
+ // The lock can be avoided by checking against the maximum number of ports
+ // supported by the class driver. SESSION_PORT_TABLE.InUse can be used
+ // to check whether the session id is in use.
+
+ if (MBB_NDP32_GET_SESSIONID(Ndp) >= MBB_MAX_NUMBER_OF_SESSIONS)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if (!MBB_NTB32_IS_VALID_NDP_LENGTH(Nth, Ndp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ for (Index = 0; Index < DatagramCount; Index++)
+ {
+ if (MBB_NTB32_IS_END_DATAGRAM(Nth, Ndp, Index))
+ return STATUS_SUCCESS;
+
+ if (!MBB_NTB32_IS_VALID_DATAGRAM(Nth, Ndp, Index))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbbNtbValidateNth32(_In_ PNCM_NTH32 Nth, _In_ ULONG BufferLength, _Out_opt_ ULONG* NdpCount)
+{
+ PNCM_NDP32 Ndp;
+ ULONG ndpCount = 0;
+ if (BufferLength < sizeof(NCM_NTH32))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH32_IS_VALID_SIGNATURE(Nth))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH32_IS_VALID_HEADER_LENGTH(Nth))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH32_IS_VALID_BLOCK_LENGTH(Nth, BufferLength))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH32_IS_VALID_FIRST_NDP(Nth))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (MbbNtbDetectNdp32Loop(Nth) != STATUS_SUCCESS)
+ return STATUS_UNSUCCESSFUL;
+
+ for (Ndp = MBB_NTH32_GET_FIRST_NDP(Nth); Ndp != NULL; Ndp = MBB_NDP32_GET_NEXT_NDP(Nth, Ndp))
+ {
+ if (MbbNtbValidateNdp32(Nth, Ndp) != STATUS_SUCCESS)
+ return STATUS_UNSUCCESSFUL;
+ ndpCount++;
+ }
+ if (NdpCount != NULL)
+ {
+ *NdpCount = ndpCount;
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbbNtbDetectNdp16Loop(_In_ PNCM_NTH16 Nth)
+{
+ PNCM_NDP16 FirstNdp;
+ PNCM_NDP16 Ndp;
+ PNCM_NDP16 LoopNdp;
+
+ if ((FirstNdp = MBB_NTH16_GET_FIRST_NDP(Nth)) == NULL)
+ return STATUS_SUCCESS;
+
+ if (!MBB_NTB16_IS_VALID_NDP_LENGTH(Nth, FirstNdp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ LoopNdp = MBB_NDP16_GET_NEXT_NDP(Nth, FirstNdp);
+
+ for (Ndp = FirstNdp; Ndp != NULL && LoopNdp != NULL; Ndp = MBB_NDP16_GET_NEXT_NDP(Nth, Ndp))
+ {
+ if (!MBB_NTB16_IS_VALID_NDP_LENGTH(Nth, LoopNdp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTB16_IS_VALID_NDP_LENGTH(Nth, Ndp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (LoopNdp == Ndp)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if ((LoopNdp = MBB_NDP16_GET_NEXT_NDP(Nth, LoopNdp)) != NULL)
+ {
+ if (!MBB_NTB16_IS_VALID_NDP_LENGTH(Nth, LoopNdp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ LoopNdp = MBB_NDP16_GET_NEXT_NDP(Nth, LoopNdp);
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbbNtbValidateNdp16(_In_ PNCM_NTH16 Nth, _In_ PNCM_NDP16 Ndp)
+{
+ ULONG Index;
+ ULONG DatagramCount = MBB_NDP16_GET_DATAGRAM_COUNT(Ndp);
+
+ if (!MBB_NTB16_IS_VALID_NDP_SIGNATURE(Ndp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (MBB_NDP16_GET_SIGNATURE_TYPE(Ndp) == NCM_NDP16_IPS)
+ {
+ //
+ // Check if the session id is valid, else discard
+ //
+
+ // Check if session Id is greater than maximum supported. Here
+ // we can also check against MaxActivatedContexts, but this would
+ // mean we need to take a lock for getting the value of maxactivatedcontexts
+ // The lock can be avoided by checking against the maximum number of ports
+ // supported by the class driver. SESSION_PORT_TABLE.InUse can be used
+ // to check whether the session id is in use.
+
+ if (MBB_NDP16_GET_SESSIONID(Ndp) >= MBB_MAX_NUMBER_OF_SESSIONS)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ if (!MBB_NTB16_IS_VALID_NDP_LENGTH(Nth, Ndp))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ for (Index = 0; Index < DatagramCount; Index++)
+ {
+ if (MBB_NTB16_IS_END_DATAGRAM(Nth, Ndp, Index))
+ return STATUS_SUCCESS;
+
+ if (!MBB_NTB16_IS_VALID_DATAGRAM(Nth, Ndp, Index))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbbNtbValidateNth16(_In_ PNCM_NTH16 Nth, _In_ ULONG BufferLength, _Out_opt_ ULONG* NdpCount)
+{
+ PNCM_NDP16 Ndp;
+ ULONG ndpCount = 0;
+ if (BufferLength < sizeof(NCM_NTH16))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH16_IS_VALID_SIGNATURE(Nth))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH16_IS_VALID_HEADER_LENGTH(Nth))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH16_IS_VALID_BLOCK_LENGTH(Nth, BufferLength))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (!MBB_NTH16_IS_VALID_FIRST_NDP(Nth))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (MbbNtbDetectNdp16Loop(Nth) != STATUS_SUCCESS)
+ return STATUS_UNSUCCESSFUL;
+
+ for (Ndp = MBB_NTH16_GET_FIRST_NDP(Nth); Ndp != NULL; Ndp = MBB_NDP16_GET_NEXT_NDP(Nth, Ndp))
+ {
+ if (MbbNtbValidateNdp16(Nth, Ndp) != STATUS_SUCCESS)
+ return STATUS_UNSUCCESSFUL;
+ ndpCount++;
+ }
+
+ if (NdpCount != NULL)
+ {
+ *NdpCount = ndpCount;
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+MbbNtbValidate(_In_ PVOID Nth, _In_ ULONG BufferLength, _In_ BOOLEAN Is32Bit, _Out_opt_ ULONG* NdpCount)
+{
+ if (Is32Bit == TRUE)
+ return MbbNtbValidateNth32((PNCM_NTH32)Nth, BufferLength, NdpCount);
+ else
+ return MbbNtbValidateNth16((PNCM_NTH16)Nth, BufferLength, NdpCount);
+}
+
+NTSTATUS
+CreateNonPagedWdfMemory(_In_ ULONG ObjectSize, _Out_ WDFMEMORY* WdfMemory, _Out_opt_ PVOID* ObjectMemory, _In_ WDFOBJECT Parent, _In_ ULONG PoolTag = 0)
+{
+ NTSTATUS status;
+ WDF_OBJECT_ATTRIBUTES objectAttribs;
+
+ WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
+ objectAttribs.ParentObject = Parent;
+
+ status = WdfMemoryCreate(&objectAttribs, NonPagedPoolNx, PoolTag, ObjectSize, WdfMemory, ObjectMemory);
+
+ return status;
+}
+
+PMDL AllocateNonPagedMdl(_In_reads_bytes_(Length) PVOID VirtualAddress, _In_ ULONG Length)
+{
+ PMDL Mdl;
+
+ Mdl = IoAllocateMdl(VirtualAddress, Length, FALSE, FALSE, NULL);
+
+ if (Mdl)
+ {
+ MmBuildMdlForNonPagedPool(Mdl);
+ Mdl->Next = NULL;
+ }
+
+ return Mdl;
+}
diff --git a/network/wwan/cxwmbclass/utils.cpp b/network/wwan/cxwmbclass/utils.cpp
new file mode 100644
index 00000000..ec791ab4
--- /dev/null
+++ b/network/wwan/cxwmbclass/utils.cpp
@@ -0,0 +1,588 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#include <precomp.h>
+#include "util.h"
+NTSTATUS
+SendSyncControlCommand(
+ __in WDFUSBDEVICE WdfUsbDevice,
+ __in WDF_USB_BMREQUEST_DIRECTION Direction,
+ __in WDF_USB_BMREQUEST_RECIPIENT Recipient,
+ __in BYTE Request,
+ __in USHORT Value,
+ __inout_bcount_opt(BufferLength) PUCHAR Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG BytesTransfered)
+
+{
+
+ NTSTATUS Status;
+ WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket;
+ WDF_MEMORY_DESCRIPTOR memoryDescriptor;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+
+ usbDeviceContext = GetUsbDeviceContext(WdfUsbDevice);
+
+ if (Buffer != NULL)
+ {
+
+ WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&memoryDescriptor, (PVOID)Buffer, BufferLength);
+ }
+
+ WDF_USB_CONTROL_SETUP_PACKET_INIT_CLASS(&controlSetupPacket, Direction, Recipient, Request, Value, usbDeviceContext->UsbCommunicationInterfaceIndex);
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, 0);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(10));
+
+ Status = WdfUsbTargetDeviceSendControlTransferSynchronously(
+ WdfUsbDevice, WDF_NO_HANDLE, &SendOptions, &controlSetupPacket, (Buffer != NULL) ? &memoryDescriptor : NULL, BytesTransfered);
+
+ if (!NT_SUCCESS(Status))
+ {
+ BOOLEAN ToHost = Direction == BmRequestDeviceToHost;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+TransactControlChannel(
+ __in PBUS_OBJECT BusObject,
+ __in ULONG TimeOut,
+ __in_bcount_opt(InBufferLength) PUCHAR InBuffer,
+ __in ULONG InBufferLength,
+ __out_bcount_opt(OutBufferLength) PUCHAR OutBuffer,
+ __in ULONG OutBufferLength,
+ __out PULONG BytesRead)
+
+{
+ ULONG BytesTransfered = 0;
+ NTSTATUS Status;
+
+ *BytesRead = 0;
+
+ Status = SendSyncControlCommand(
+ BusObject->WdfUsbDevice, BmRequestHostToDevice, BmRequestToInterface, SEND_ENCAPSULATE_COMMAND, 0, InBuffer, InBufferLength, &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (BytesTransfered < InBufferLength)
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = WaitForResponseAvailible(BusObject, TimeOut);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = SendSyncControlCommand(
+ BusObject->WdfUsbDevice, BmRequestDeviceToHost, BmRequestToInterface, GET_ENCAPSULATE_RESPONSE, 0, OutBuffer, OutBufferLength, &BytesTransfered);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ *BytesRead = BytesTransfered;
+
+Cleanup:
+
+ return Status;
+}
+
+NTSTATUS
+ReadInterrupt(_In_ PBUS_OBJECT BusObject, _Inout_updates_bytes_(BufferLength) PUCHAR Buffer, _In_ ULONG BufferLength, _In_ ULONG Timeout, _Out_ PULONG BytesRead)
+
+{
+
+ NTSTATUS status;
+ WDFMEMORY memHandle = NULL;
+
+ WDFREQUEST request = NULL;
+ BOOLEAN SentToDevice = FALSE;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ WDF_MEMORY_DESCRIPTOR MemoryDescriptor;
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&MemoryDescriptor, (PVOID)Buffer, BufferLength);
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(Timeout));
+
+ status = WdfUsbTargetPipeReadSynchronously(usbDeviceContext->InterruptPipe, NULL, &SendOptions, &MemoryDescriptor, BytesRead);
+
+ return status;
+}
+
+NTSTATUS
+GetDeviceString(__in WDFUSBDEVICE UsbDevice, __in UCHAR Index, __out PWSTR* String)
+
+{
+ NTSTATUS Status;
+ WDF_REQUEST_SEND_OPTIONS SendOptions;
+ USHORT CharacterCount = 0;
+ ULONG AllocationSize = 0;
+ PWSTR AllocatedString = NULL;
+
+ WDF_REQUEST_SEND_OPTIONS_INIT(&SendOptions, 0);
+
+ WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&SendOptions, WDF_REL_TIMEOUT_IN_SEC(DEFAULT_IO_TIMEOUT));
+
+ *String = NULL;
+
+ Status = WdfUsbTargetDeviceQueryString(UsbDevice, NULL, &SendOptions, NULL, &CharacterCount, Index, 0);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ //
+ // allocate one more char to make sure sting is null terminated
+ //
+ AllocationSize = (CharacterCount + 1) * sizeof(WCHAR);
+
+ AllocatedString = (PWSTR)ALLOCATE_PAGED_POOL(AllocationSize);
+
+ if (AllocatedString == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Cleanup;
+ }
+
+ RtlZeroMemory(AllocatedString, AllocationSize);
+
+ Status = WdfUsbTargetDeviceQueryString(UsbDevice, NULL, &SendOptions, AllocatedString, &CharacterCount, Index, 0);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ *String = AllocatedString;
+ AllocatedString = NULL;
+
+Cleanup:
+
+ if (AllocatedString != NULL)
+ {
+ FREE_POOL(AllocatedString);
+ AllocatedString = NULL;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusSetPacketFilter(__in MBB_BUS_HANDLE BusHandle, __in ULONG PacketFilter)
+
+{
+
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ ULONG BytesTransfered = 0;
+ UCHAR ReadBuffer[256];
+
+ Status = SendSyncControlCommand(
+ BusObject->WdfUsbDevice, BmRequestHostToDevice, BmRequestToInterface, SET_PACKET_FILTER, 0, (PUCHAR)&PacketFilter, sizeof(PacketFilter), &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (BytesTransfered < sizeof(PacketFilter))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusSetNtbInSize(__in MBB_BUS_HANDLE BusHandle, __in ULONG InSize)
+
+{
+
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ ULONG BytesTransfered = 0;
+
+ Status = SendSyncControlCommand(
+ BusObject->WdfUsbDevice, BmRequestHostToDevice, BmRequestToInterface, SET_NTB_INPUT_SIZE, 0, (PUCHAR)&InSize, sizeof(InSize), &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (BytesTransfered < sizeof(InSize))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusGetStat(__in MBB_BUS_HANDLE BusHandle, __in USHORT StatIndex, __out ULONGLONG* Value)
+
+{
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ ULONG BytesTransfered = 0;
+
+#pragma warning(suppress : 6001)
+ Status = SendSyncControlCommand(
+ BusObject->WdfUsbDevice, BmRequestDeviceToHost, BmRequestToInterface, GET_STATISTIC, StatIndex, (PUCHAR)Value, sizeof(*Value), &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (BytesTransfered < sizeof(Value))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusSetNtbFormat(__in MBB_BUS_HANDLE BusHandle, __in USHORT Format)
+
+{
+
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ ULONG BytesTransfered = 0;
+
+ Status = SendSyncControlCommand(
+ BusObject->WdfUsbDevice, BmRequestHostToDevice, BmRequestToInterface, SET_NBT_FORMAT, Format, (PUCHAR)NULL, 0, &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusResetFunction(__in MBB_BUS_HANDLE BusHandle)
+
+{
+
+ PBUS_OBJECT BusObject = (PBUS_OBJECT)BusHandle;
+ NTSTATUS Status;
+ ULONG BytesTransfered = 0;
+
+ Status = SendSyncControlCommand(
+ BusObject->WdfUsbDevice, BmRequestHostToDevice, BmRequestToInterface, RESET_FUNCTION, 0, (PUCHAR)NULL, 0, &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+ }
+
+ return Status;
+}
+
+NTSTATUS
+MbbBusResetDeviceAndSetParms(__in PBUS_OBJECT BusObject)
+
+{
+ NTSTATUS Status;
+ USHORT NtbFormat = NCM_SET_NTB_FORMAT_16_BIT;
+
+ //
+ // put the device back into a known state
+ //
+ Status = MbbBusResetFunction(BusObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ Status = MbbBusSetNtbInSize(BusObject, BusObject->MaxBulkInTransfer);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+
+ if ((BusObject->NtbParam.bmNtbFormatSupported & NCM_NTB_FORMAT_32_BIT) == NCM_NTB_FORMAT_32_BIT)
+ {
+ //
+ // device supports 32 bit mode
+ //
+ if (BusObject->NtbFormat32Bit)
+ {
+ //
+ // the device can actually handle a transfer larger than 16bit, change to 32 bit
+ //
+ NtbFormat = NCM_SET_NTB_FORMAT_32_BIT;
+ }
+
+ //
+ // set the format
+ //
+ Status = MbbBusSetNtbFormat(BusObject, NtbFormat);
+
+ if (!NT_SUCCESS(Status))
+ {
+ goto Cleanup;
+ }
+ }
+
+Cleanup:
+
+ return Status;
+}
+
+ULONG
+ProcessInterruptPipeRead(
+ PBUS_OBJECT BusObject,
+ __in_ecount(NewFragmentLength) PCUCHAR NewFragment,
+ ULONG NewFragmentLength,
+ __out_ecount(MessageBufferSize) PUCHAR CompleteMessageBuffer,
+ ULONG MessageBufferSize)
+
+{
+
+ ULONG CompleteMessageLength = 0;
+ PUSB_CDC_NOTIFICATION CdcNotification = NULL;
+
+ ASSERT(MessageBufferSize == sizeof(BusObject->InterruptReassemnblyBuffer));
+
+ if (BusObject->CurrentOffset == 0)
+ {
+ //
+ // beggining of interrupt transfer
+ //
+ if ((NewFragmentLength >= sizeof(*CdcNotification)) && (NewFragmentLength <= sizeof(BusObject->InterruptReassemnblyBuffer)))
+ {
+ //
+ // big enough for a notification
+ //
+ CdcNotification = (PUSB_CDC_NOTIFICATION)NewFragment;
+
+ if ((CdcNotification->bmRequestType == 0xa1))
+ {
+ BusObject->ExpectLength = sizeof(*CdcNotification) + CdcNotification->wLength;
+
+ RtlCopyMemory(&BusObject->InterruptReassemnblyBuffer[BusObject->CurrentOffset], NewFragment, NewFragmentLength);
+
+ BusObject->CurrentOffset += NewFragmentLength;
+ }
+ else
+ {
+ //
+ // wrong request type, drop
+ //
+ }
+ }
+ else
+ {
+ //
+ // not big enough to be a cdc notification, drop
+ //
+ }
+ }
+ else
+ {
+ //
+ // we already have some of the data
+ //
+ if ((NewFragmentLength + BusObject->CurrentOffset) <= sizeof(BusObject->InterruptReassemnblyBuffer))
+ {
+ //
+ // still room in the NewFragment
+ //
+ RtlCopyMemory(&BusObject->InterruptReassemnblyBuffer[BusObject->CurrentOffset], NewFragment, NewFragmentLength);
+ }
+ else
+ {
+ //
+ // over flow, Keep procssing until we get the whole thing so we don't get out of sync
+ //
+ }
+ BusObject->CurrentOffset += NewFragmentLength;
+ }
+
+ if (BusObject->CurrentOffset < BusObject->ExpectLength)
+ {
+ //
+ // we don't have the whole thing yet, keep going
+ //
+ if (NewFragmentLength == 0)
+ {
+ //
+ // got a zero length transfer, reset the re-assembly state
+ BusObject->ExpectLength = 0;
+ BusObject->CurrentOffset = 0;
+ }
+ }
+ else
+ {
+ if (BusObject->CurrentOffset == BusObject->ExpectLength)
+ {
+ //
+ // got it all
+ //
+ if ((BusObject->CurrentOffset <= sizeof(BusObject->InterruptReassemnblyBuffer)) && (BusObject->CurrentOffset <= MessageBufferSize))
+ {
+ //
+ // the whole thing fit in the NewFragment
+ //
+ RtlCopyMemory(CompleteMessageBuffer, BusObject->InterruptReassemnblyBuffer, BusObject->CurrentOffset);
+
+ CompleteMessageLength = BusObject->CurrentOffset;
+ BusObject->CurrentOffset = 0;
+ }
+ else
+ {
+ //
+ // it is bigger than the re-assembly NewFragment,
+ // drop it
+ //
+ }
+
+ //
+ // done with the current re-assembled NewFragment
+ //
+ BusObject->ExpectLength = 0;
+ BusObject->CurrentOffset = 0;
+ }
+ else
+ {
+ //
+ // current offset is beyond the what we expected
+ //
+ ASSERT(0);
+ }
+ }
+
+ return CompleteMessageLength;
+}
+
+NTSTATUS
+WaitForResponseAvailible(PBUS_OBJECT BusObject, ULONG TimeOut)
+
+{
+ NTSTATUS Status;
+ UCHAR IndicateBuffer[INTERRUPT_REASSEMBLY_BUFFER_SIZE];
+ ULONG BufferLength = 0;
+ ULONG BytesTransfered = 0;
+ BOOLEAN ExitLoop = FALSE;
+ PUSB_DEVICE_CONTEXT usbDeviceContext = NULL;
+ PUSB_CDC_NOTIFICATION Notification = NULL;
+
+ usbDeviceContext = GetUsbDeviceContext(BusObject->WdfUsbDevice);
+
+ BusObject->ExpectLength = 0;
+ BusObject->CurrentOffset = 0;
+
+ while (!ExitLoop)
+ {
+
+ Status = ReadInterrupt(BusObject, BusObject->SyncInterruptReadBuffer, usbDeviceContext->InterruptPipeMaxPacket, TimeOut, &BytesTransfered);
+
+ if (NT_SUCCESS(Status))
+ {
+
+ BufferLength = ProcessInterruptPipeRead(
+ BusObject, BusObject->SyncInterruptReadBuffer, BytesTransfered, IndicateBuffer, sizeof(IndicateBuffer));
+
+ if (BufferLength == 0)
+ {
+ //
+ //
+ // don't have a complete message yet
+ //
+ continue;
+ }
+ else
+ {
+ if (BufferLength < sizeof(*Notification))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ goto Cleanup;
+ }
+
+ Notification = (PUSB_CDC_NOTIFICATION)IndicateBuffer;
+
+ if (Notification->bNotificationCode != USB_CDC_NOTIFICATION_RESPONSE_AVAILABLE)
+ {
+ continue;
+ }
+ }
+ }
+ else
+ {
+ goto Cleanup;
+ }
+
+ ExitLoop = TRUE;
+ }
+
+ Status = STATUS_SUCCESS;
+
+Cleanup:
+
+ return Status;
+}
+
+BOOLEAN IsUsbCapDeviceInfoValid(_In_ USB_CAP_DEVICE_INFO UsbCapDeviceInfo, _In_ ULONG CapResultLength)
+{
+ if (CapResultLength < sizeof(USB_CAP_DEVICE_INFO_HEADER))
+ {
+ return FALSE;
+ }
+ switch (UsbCapDeviceInfo.DeviceInfoHeader.DeviceType)
+ {
+ case USB_CAP_DEVICE_TYPE_UDE_MBIM: __fallthrough;
+ case USB_CAP_DEVICE_TYPE_UDE_MBIM_FASTIO:
+ // Only support version 1.0 now
+ if (UsbCapDeviceInfo.DeviceInfoHeader.DeviceMajorVersion == 0x1 && UsbCapDeviceInfo.DeviceInfoHeader.DeviceMinorVersion == 0x0)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ default: return FALSE;
+ }
+}
+
+/*++
+
+Routine Description:
+
+ Check if the bus type is Ude
+
+Arguments:
+
+ BusHandle - identifies the instance of the bus layer.
+
+Return Value:
+
+ TRUE - The bus type is Ude
+ FALSE - The bus type isn't Ude
+
+--*/
+BOOLEAN
+MbbBusIsUde(_In_ MBB_BUS_HANDLE BusHandle)
+{
+ USB_CAP_DEVICE_TYPE DeviceType = ((PBUS_OBJECT)BusHandle)->UsbCapDeviceInfo.DeviceInfoHeader.DeviceType;
+ return (DeviceType == USB_CAP_DEVICE_TYPE_UDE_MBIM || DeviceType == USB_CAP_DEVICE_TYPE_UDE_MBIM_FASTIO);
+}