summaryrefslogtreecommitdiff
path: root/gnss
diff options
context:
space:
mode:
authorSanjeev Reddy <[email protected]>2019-02-06 13:12:11 -0800
committerGitHub <[email protected]>2019-02-06 13:12:11 -0800
commit27302e1d522bc16e1cc18232602f7eca1b79db0f (patch)
tree1035100a803e4e52abbda93288091bb50f4f5073 /gnss
parent46da8a0d4f0de180dd15b6ca088e095b5e2c0b96 (diff)
parent39d39e7485faddf601d51c897863ff2f876e391e (diff)
Merge pull request #1 from Microsoft/master
Updating to latest
Diffstat (limited to 'gnss')
-rw-r--r--gnss/GnssUmdfSampleDriver.wprp32
-rw-r--r--gnss/ReadMe.md97
-rw-r--r--gnss/gnss.yaml10
-rw-r--r--gnss/gnssUmdf.sln59
-rw-r--r--gnss/gnssUmdf/Defaults.h59
-rw-r--r--gnss/gnssUmdf/Device.cpp163
-rw-r--r--gnss/gnssUmdf/Device.h44
-rw-r--r--gnss/gnssUmdf/Driver.cpp107
-rw-r--r--gnss/gnssUmdf/Driver.h22
-rw-r--r--gnss/gnssUmdf/FixHandler.cpp228
-rw-r--r--gnss/gnssUmdf/FixHandler.h39
-rw-r--r--gnss/gnssUmdf/FixSession.cpp512
-rw-r--r--gnss/gnssUmdf/FixSession.h60
-rw-r--r--gnss/gnssUmdf/Queue.cpp482
-rw-r--r--gnss/gnssUmdf/Queue.h78
-rw-r--r--gnss/gnssUmdf/Trace.h64
-rw-r--r--gnss/gnssUmdf/gnssUmdf.infbin0 -> 3592 bytes
-rw-r--r--gnss/gnssUmdf/gnssUmdf.vcxproj301
-rw-r--r--gnss/gnssUmdf/gnssUmdf.vcxproj.filters69
-rw-r--r--gnss/gnssUmdf/precomp.h29
20 files changed, 2455 insertions, 0 deletions
diff --git a/gnss/GnssUmdfSampleDriver.wprp b/gnss/GnssUmdfSampleDriver.wprp
new file mode 100644
index 00000000..7bb78452
--- /dev/null
+++ b/gnss/GnssUmdfSampleDriver.wprp
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone='yes'?>
+
+<WindowsPerformanceRecorder Version="1.0" Author="Location Dev" Team="Location Dev" Comments="ETW profiles" Company="Microsoft Corporation" Copyright="Microsoft Corporation">
+ <Profiles>
+ <!-- Event Collectors -->
+ <EventCollector Id="EventCollector_SampleGNSS" Name="SampleGNSS Category Event Collector" Private="false" ProcessPrivate="false" Secure="false" Realtime="false">
+ <BufferSize Value="128"/>
+ <Buffers Value="40"/>
+ <MaximumFileSize Value="5" FileMode="Circular"/>
+ <FileMax Value="3"/>
+ </EventCollector>
+
+ <!-- Umdf Gnss Sample Driver providers -->
+ <EventProvider Id="GnssUmdfTraceGuid" Name="CEB3BF01-80E4-4DC7-B3BF-F6B5279EB8C4" Level="5">
+ <Keywords>
+ <Keyword Value="0xFFFFFFFF"/> <!-- Provider is enabled with these keywords throughout the tracing session. -->
+ </Keywords>
+ </EventProvider>
+
+ <!-- Profiles -->
+ <Profile Id="SampleGNSSCategory.Verbose.File" LoggingMode="File" Name="SampleGNSSCategory" DetailLevel="Verbose" Description="Sample GNSS category profile">
+ <Collectors>
+ <EventCollectorId Value="EventCollector_SampleGNSS">
+ <EventProviders>
+ <EventProviderId Value="GnssUmdfTraceGuid"/>
+ </EventProviders>
+ </EventCollectorId>
+ </Collectors>
+ </Profile>
+ </Profiles>
+
+</WindowsPerformanceRecorder>
diff --git a/gnss/ReadMe.md b/gnss/ReadMe.md
new file mode 100644
index 00000000..deaca7a6
--- /dev/null
+++ b/gnss/ReadMe.md
@@ -0,0 +1,97 @@
+<!---
+ name: GPS/GNSS UMDF Sample Driver (UMDF Version 2)
+ platform: UMDF2
+ language: cpp
+ category: GPS/GNSS
+ description: Provides base sample driver that IHVs and partners can use to extend to build their custom Windows GPS/GNSS drivers
+ samplefwlink: https://go.microsoft.com/fwlink/?linkid=2045369
+--->
+
+
+GNSS UMDF Sample Driver (UMDF Version 2)
+==============================================================================
+
+# Overview
+
+## What is covered?
+
+* This is a sample that adheres to GNSS driver design for Windows 10 with this MSDN link: https://docs.microsoft.com/en-us/windows-hardware/drivers/gnss/gnss-driver-design-guide-for-windows-10
+* Serves as base sample driver that IHVs and partners can use as a template and guidance to extend to build their custom Windows GNSS drivers.
+* Follows the WDF guidelines and best practices around PnP device arrival/removal, power management and driver installation/uninstallation.
+* Supports the GNSS DDI mandatory requirements.
+* This driver successfully passes HLK tests and WDF tests provided by Visual studio.
+
+## What is not covered?
+
+* This sample currently doesn't support Geofence, SUPL, and AGNSS, as this is not mandatory GNSS DDI functionality.
+* SUPL and AGNSS are mandatory only if required by mobile operator, and the sample does not support them currently.
+* Not a production driver.
+
+## What Partner needs to do?
+
+* Customer can install WDK and run Location HLK tests to validate their driver. All test cases should be either pass or skip without failure.
+* Partner owns the following:
+ - Installing the driver.
+ - Adding certificate and driver signing.
+ - Updating manufacturer name driver version etc. (the code has comments to update).
+* The GNSS sample code has "FIX ME" comments. Partner should update them accordingly.
+
+
+# Design
+
+* The sample demonstrates a very basic software only driver that meets the minimum requirements from the GNSS DDI.
+* The sample currently always returns a fake hardcoded location. Driver developers can extend this to fetch fake positions from a file or inject through a custom IOCTL or instead implement getting real positions from GNSS hardware.
+* Driver developer can extend this to pull the fake positions from a file or through custom IOCTLs if needed.
+
+
+# Trace Logging
+
+* The sample code provides Trace logging WPRP file.
+* To capture trace log, copy GnssUmdfSampleDriver.wprp in the solution folder into the device under test. On command line (MyLog.etl is an example file name below):
+ ```sh
+ wpr -start GnssUmdfSampleDriver.wprp -filemode
+ <Reproduce the issue>
+ wpr -stop MyLog.etl
+ ```
+* Inspect MyLog.etl with trace file analyzer. Note that corresponding PDB file is needed to decode the logging information.
+
+
+# Test Plan
+
+Customer should validate their driver after customizing it.
+
+#### Test method 1
+
+* This tests WDF fundamental functionality (PnP etc.), rather than Location-specific features.
+* Run Visual studio built-in run-time test for WDF.
+* General information: https://docs.microsoft.com/en-us/windows-hardware/drivers/develop/testing-a-driver-at-runtime
+* Expected result / Pass criteria: Pass rate 100%
+
+#### Test method 2
+
+* This tests Location-specific functionality (Getting fix etc.).
+* Run HLK tests with existing and standard GNSS driver tests.
+* General information: https://docs.microsoft.com/en-us/windows-hardware/test/hlk/windows-hardware-lab-kit
+* Run "TE.exe GNSSDriverTest.dll".
+* Expected result / Pass criteria: Pass rate 100%
+* Note that this sample does not support AGNSS, SUPL and Geofencing currently. Based on the capability of driver, HLK skips them automatically.
+
+#### Test method 3
+
+* This tests from Windows Geolocation API (https://docs.microsoft.com/en-us/windows/desktop/locationapi/windows-location-api-portal) layer on real apps.
+* Get current location by clicking on "Show my location" from the In-box Windows Maps app.
+* Run tracking scenario from Geolocation Sample app (Download from https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/Geolocation).
+* Get current location by clicking on "Start" from GPS Satellite app in Windows Store.
+
+
+# Resources
+
+* GNSS DDI reference
+ - https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/gnssdriver/index
+* Getting started with Windows drivers
+ - https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/
+* Windows Driver Kit documentation
+ - https://docs.microsoft.com/en-us/windows-hardware/drivers/
+* NMEA format documentation
+ - http://navspark.mybigcommerce.com/content/NMEA_Format_v0.1.pdf
+ \ No newline at end of file
diff --git a/gnss/gnss.yaml b/gnss/gnss.yaml
new file mode 100644
index 00000000..e53b2045
--- /dev/null
+++ b/gnss/gnss.yaml
@@ -0,0 +1,10 @@
+### YamlMime:Sample
+sample:
+- name: GPS/GNSS UMDF V2 Device Driver Sample
+ description: Demonstrates how to write a device driver that IHVs and partners can use to extend to build their custom drivers
+ generateZip: true
+ author: windows-driver-samples
+ languages:
+ - cpp
+ technologies:
+ - windows
diff --git a/gnss/gnssUmdf.sln b/gnss/gnssUmdf.sln
new file mode 100644
index 00000000..46b81091
--- /dev/null
+++ b/gnss/gnssUmdf.sln
@@ -0,0 +1,59 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2042
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gnssUmdf", "gnssUmdf\gnssUmdf.vcxproj", "{AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{79D3FD2A-EEAE-4C86-90AF-39B7FFD6D27D}"
+ ProjectSection(SolutionItems) = preProject
+ gnss.yaml = gnss.yaml
+ GnssUmdfSampleDriver.wprp = GnssUmdfSampleDriver.wprp
+ ReadMe.md = ReadMe.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|ARM = Debug|ARM
+ Debug|ARM64 = Debug|ARM64
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|ARM = Release|ARM
+ Release|ARM64 = Release|ARM64
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|ARM.ActiveCfg = Debug|ARM
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|ARM.Build.0 = Debug|ARM
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|ARM.Deploy.0 = Debug|ARM
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|ARM64.Build.0 = Debug|ARM64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|ARM64.Deploy.0 = Debug|ARM64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|x64.ActiveCfg = Debug|x64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|x64.Build.0 = Debug|x64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|x64.Deploy.0 = Debug|x64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|x86.ActiveCfg = Debug|Win32
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|x86.Build.0 = Debug|Win32
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Debug|x86.Deploy.0 = Debug|Win32
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|ARM.ActiveCfg = Release|ARM
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|ARM.Build.0 = Release|ARM
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|ARM.Deploy.0 = Release|ARM
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|ARM64.ActiveCfg = Release|ARM64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|ARM64.Build.0 = Release|ARM64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|ARM64.Deploy.0 = Release|ARM64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|x64.ActiveCfg = Release|x64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|x64.Build.0 = Release|x64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|x64.Deploy.0 = Release|x64
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|x86.ActiveCfg = Release|Win32
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|x86.Build.0 = Release|Win32
+ {AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}.Release|x86.Deploy.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C0D84930-F293-4CFC-ACFB-2A71C4CADDFD}
+ SolutionGuid = {E7531486-DB0B-43B1-AC4A-AFDE26BDED47}
+ EndGlobalSection
+EndGlobal
diff --git a/gnss/gnssUmdf/Defaults.h b/gnss/gnssUmdf/Defaults.h
new file mode 100644
index 00000000..bf78238e
--- /dev/null
+++ b/gnss/gnssUmdf/Defaults.h
@@ -0,0 +1,59 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ defaults.h
+
+Abstract:
+
+ This module contains the defaults used within the Umdf Gnss Driver.
+
+Environment:
+
+ driver and application
+
+--*/
+
+#pragma once
+
+#define GNSS_DRIVER_DDK_VERSION GNSS_DRIVER_VERSION_4
+#define INVALID_SESSION_ID (0xFFFFFFFF)
+#define DEFAULT_FIX_INTERVAL_SECONDS 1
+
+static const double c_MaximumLatitude = 90.0;
+static const double c_MinimumLatitude = -90.0;
+static const double c_MaximumLongitude = 180.0;
+static const double c_MinimumLongitude = -180.0;
+
+#define INIT_POD_GNSS_STRUCT(pName) \
+ memset((pName), 0, sizeof(*(pName))); \
+ (pName)->Size = sizeof(*(pName)); \
+ (pName)->Version = GNSS_DRIVER_DDK_VERSION
+
+const GNSS_FIXDATA g_DefaultGnssFixData =
+{
+ sizeof(GNSS_FIXDATA),
+ GNSS_DRIVER_DDK_VERSION,
+ INVALID_SESSION_ID,
+ { 0xCD700000, 0x1D48908 }, // an example date/time, Dec/01/2018
+ TRUE,
+ STATUS_SUCCESS,
+ GNSS_FIXDETAIL_BASIC | GNSS_FIXDETAIL_ACCURACY,
+ {
+ sizeof(GNSS_FIXDATA_BASIC),
+ GNSS_DRIVER_DDK_VERSION,
+ // Location: Mount Rainier National Park
+ 46.852273,
+ -121.757468,
+ 0.0,
+ 0.0,
+ 0.0
+ },
+ {
+ sizeof(GNSS_FIXDATA_ACCURACY),
+ GNSS_DRIVER_DDK_VERSION,
+ 10 // Meters accuracy
+ }
+};
diff --git a/gnss/gnssUmdf/Device.cpp b/gnss/gnssUmdf/Device.cpp
new file mode 100644
index 00000000..905b3e94
--- /dev/null
+++ b/gnss/gnssUmdf/Device.cpp
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ device.c
+
+Abstract:
+
+ This file contains the device entry points and callbacks.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#include "precomp.h"
+#include "Trace.h"
+#include "Defaults.h"
+#include "Device.h"
+#include "FixSession.h"
+#include "FixHandler.h"
+#include "Queue.h"
+
+#include "Device.tmh"
+
+
+CDevice::CDevice(
+ _In_ WDFDEVICE Device
+) :
+ _Device(Device),
+ _Queue(nullptr)
+{
+}
+
+CDevice::~CDevice()
+{
+ if (_Queue != nullptr)
+ {
+ _Queue = nullptr;
+ }
+}
+
+CQueue*
+CDevice::GetQueue()
+{
+ return _Queue;
+}
+
+NTSTATUS
+CDevice::OnDeviceAdd(
+ _In_ WDFDRIVER /*Driver*/,
+ _Inout_ PWDFDEVICE_INIT DeviceInit
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WDF_PNPPOWER_EVENT_CALLBACKS powerCallbacks;
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&powerCallbacks);
+
+ powerCallbacks.EvtDeviceD0Entry = CDevice::OnD0Entry;
+ powerCallbacks.EvtDeviceD0Exit = CDevice::OnD0Exit;
+
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &powerCallbacks);
+
+ WDF_OBJECT_ATTRIBUTES deviceAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes,
+ CDevice);
+
+ deviceAttributes.EvtCleanupCallback = CDevice::OnCleanup;
+ deviceAttributes.SynchronizationScope = WdfSynchronizationScopeNone;
+ deviceAttributes.ExecutionLevel = WdfExecutionLevelPassive;
+
+ WDFDEVICE device;
+ status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
+
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "WdfDeviceCreate failed with Status %!STATUS!", status);
+ goto Exit;
+ }
+
+ // Construct device object on the preallocated buffer using placement 'new'
+ CDevice* pDevice = new (GetDeviceObject(device)) CDevice(device);
+
+ status = pDevice->Initialize();
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CDevice::Initialize()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = CQueue::AddQueueToDevice(_Device, &_Queue);
+
+ // Register GNSS Device interface. Note that this sample is not publishing a symbolic link.
+ status = WdfDeviceCreateDeviceInterface(_Device,
+ (LPGUID)&GUID_DEVINTERFACE_GNSS,
+ nullptr);
+
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "WdfDeviceCreateDeviceInterface failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+void
+CDevice::OnCleanup(
+ _In_ WDFOBJECT Object
+)
+{
+ CDevice *pDevice = GetDeviceObject(Object);
+
+ // Device object constructed using placement 'new' so explicitly invoke destructor
+ pDevice->~CDevice();
+}
+
+NTSTATUS
+CDevice::OnD0Entry(
+ _In_ WDFDEVICE /*Device*/,
+ _In_ WDF_POWER_DEVICE_STATE /*PreviousState*/
+)
+{
+ NTSTATUS status;
+
+ //
+ // FIX ME:
+ // Add further functionality.
+ // Refer to power consideration from MSDN document: https://docs.microsoft.com/en-us/windows-hardware/drivers/gnss/gnss-driver-requirements
+ //
+
+ status = STATUS_SUCCESS;
+
+ return status;
+}
+
+NTSTATUS
+CDevice::OnD0Exit(
+ _In_ WDFDEVICE /*Device*/,
+ _In_ WDF_POWER_DEVICE_STATE /*TargetState*/
+)
+{
+ NTSTATUS status;
+
+ //
+ // FIX ME:
+ // Add further functionality.
+ // Refer to power consideration from MSDN document: https://docs.microsoft.com/en-us/windows-hardware/drivers/gnss/gnss-driver-requirements
+ //
+
+ status = STATUS_SUCCESS;
+
+ return status;
+}
diff --git a/gnss/gnssUmdf/Device.h b/gnss/gnssUmdf/Device.h
new file mode 100644
index 00000000..35072bfc
--- /dev/null
+++ b/gnss/gnssUmdf/Device.h
@@ -0,0 +1,44 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ device.h
+
+Abstract:
+
+ This file contains the device definitions.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#pragma once
+
+class CQueue;
+
+class CDevice
+{
+public:
+ // This is called from PnP manager in response to AddDevice call
+ static EVT_WDF_DRIVER_DEVICE_ADD OnDeviceAdd;
+
+private:
+ CDevice(_In_ WDFDEVICE Device);
+ ~CDevice();
+
+ static EVT_WDF_OBJECT_CONTEXT_CLEANUP OnCleanup;
+ static EVT_WDF_DEVICE_D0_ENTRY OnD0Entry;
+ static EVT_WDF_DEVICE_D0_EXIT OnD0Exit;
+
+ NTSTATUS Initialize();
+ CQueue* GetQueue();
+
+ WDFDEVICE _Device = nullptr;
+ CQueue* _Queue = nullptr;
+};
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CDevice, GetDeviceObject);
diff --git a/gnss/gnssUmdf/Driver.cpp b/gnss/gnssUmdf/Driver.cpp
new file mode 100644
index 00000000..af443b12
--- /dev/null
+++ b/gnss/gnssUmdf/Driver.cpp
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ driver.cpp
+
+Abstract:
+
+ This file contains the driver entry points and callbacks.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#include "precomp.h"
+#include "Trace.h"
+#include "Defaults.h"
+#include "Driver.h"
+#include "Device.h"
+
+#include "Driver.tmh"
+
+
+extern "C"
+NTSTATUS
+DriverEntry(
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PUNICODE_STRING RegistryPath
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ // Initialize WPP Tracing
+ WPP_INIT_TRACING(DriverObject, RegistryPath);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
+
+ // Register a cleanup callback so that we can call WPP_CLEANUP when
+ // the framework driver object is deleted during driver unload.
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.EvtCleanupCallback = GnssUmdfEvtDriverContextCleanup;
+
+ WDF_DRIVER_CONFIG config;
+ WDF_DRIVER_CONFIG_INIT(&config,
+ CDevice::OnDeviceAdd);
+
+ config.EvtDriverUnload = OnDriverUnload;
+
+ status = WdfDriverCreate(DriverObject,
+ RegistryPath,
+ &attributes,
+ &config,
+ WDF_NO_HANDLE);
+
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
+
+ WPP_CLEANUP(DriverObject);
+
+ return status;
+ }
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
+
+ return status;
+}
+
+void
+GnssUmdfEvtDriverContextCleanup(
+ _In_ WDFOBJECT DriverObject
+)
+/*++
+Routine Description:
+
+ Free all the resources allocated in DriverEntry.
+
+Arguments:
+
+ DriverObject - handle to a WDF Driver object.
+
+Return Value:
+
+ void.
+
+--*/
+{
+ UNREFERENCED_PARAMETER(DriverObject);
+
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
+
+ // Stop WPP Tracing
+ WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
+}
+
+void
+OnDriverUnload(
+ _In_ WDFDRIVER /* Driver */
+)
+{
+ WPP_CLEANUP(Driver);
+}
diff --git a/gnss/gnssUmdf/Driver.h b/gnss/gnssUmdf/Driver.h
new file mode 100644
index 00000000..5de6d35e
--- /dev/null
+++ b/gnss/gnssUmdf/Driver.h
@@ -0,0 +1,22 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ driver.h
+
+Abstract:
+
+ This file contains the driver definitions.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#pragma once
+
+EVT_WDF_DRIVER_UNLOAD OnDriverUnload;
+EVT_WDF_OBJECT_CONTEXT_CLEANUP GnssUmdfEvtDriverContextCleanup;
diff --git a/gnss/gnssUmdf/FixHandler.cpp b/gnss/gnssUmdf/FixHandler.cpp
new file mode 100644
index 00000000..52b09a82
--- /dev/null
+++ b/gnss/gnssUmdf/FixHandler.cpp
@@ -0,0 +1,228 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ fixhandler.cpp
+
+Abstract:
+
+ This file contains the Fix handler and contains logic to provide position.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#include "precomp.h"
+#include "Trace.h"
+#include "Defaults.h"
+#include "FixSession.h"
+#include "FixHandler.h"
+
+#include "FixHandler.tmh"
+
+
+NTSTATUS
+CFixHandler::Initialize(
+ _In_ WDFQUEUE Queue
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = _SingleShotSession.Initialize(Queue);
+
+ return status;
+}
+
+NTSTATUS
+CFixHandler::StartFix(
+ _In_ WDFREQUEST Request,
+ _In_ BOOL LocationServiceEnabled
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PGNSS_FIXSESSION_PARAM fixSessionParameters = nullptr;
+
+ // For privacy reasons, the location stack notifies the driver when user toggles the location device controls.
+ // When set to off, the driver must not entertain any new location sessions.
+ if (!LocationServiceEnabled)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "Location master switch is off, we do not start a fix session");
+ goto Exit;
+ }
+
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(GNSS_FIXSESSION_PARAM), (void**)&fixSessionParameters, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "WdfRequestRetrieveInputBuffer failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+ //
+ // FIX ME:
+ // This sample currently supports only single shot session fix.
+ // If you support another session type, e.g., distance tracking, update the logic below accordingly.
+ //
+ if (fixSessionParameters->SessionType != GNSS_FixSession_SingleShot)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "Session type is not GNSS_FixSession_SingleShot");
+ goto Exit;
+ }
+
+ _CurrentSinglsShotSessionId = fixSessionParameters->FixSessionID;
+
+ status = _SingleShotSession.StartAcquiringFix(fixSessionParameters);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "StartFix failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CFixHandler::StopFix(
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PGNSS_STOPFIXSESSION_PARAM stopFixSessionParam = nullptr;
+
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(GNSS_STOPFIXSESSION_PARAM), (void**)&stopFixSessionParam, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "WdfRequestRetrieveInputBuffer failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+ // Send the session parameters to the right session based on the ID
+ if (stopFixSessionParam->FixSessionID != _CurrentSinglsShotSessionId)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "Session type is not GNSS_FixSession_SingleShot");
+ goto Exit;
+ }
+
+ _CurrentSinglsShotSessionId = INVALID_SESSION_ID;
+
+ status = _SingleShotSession.StopAcquiringFix(stopFixSessionParam);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "StopFix failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CFixHandler::StopExistingSinglsShotFix()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PGNSS_STOPFIXSESSION_PARAM stopFixSessionParam = nullptr;
+
+ if (_CurrentSinglsShotSessionId == INVALID_SESSION_ID)
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FIX, "There is no single shot session to stop");
+ goto Exit;
+ }
+
+ _CurrentSinglsShotSessionId = INVALID_SESSION_ID;
+
+ INIT_POD_GNSS_STRUCT(stopFixSessionParam);
+ status = _SingleShotSession.StopAcquiringFix(stopFixSessionParam);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "StopFix failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CFixHandler::ModifyFix(
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PGNSS_FIXSESSION_PARAM fixSessionParameters = nullptr;
+
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(GNSS_FIXSESSION_PARAM), (void**)&fixSessionParameters, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "WdfRequestRetrieveInputBuffer failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+ //
+ // FIX ME:
+ // We currently support only single shot session fix.
+ // If you support another session type, e.g., distance tracking, update the logic below accordingly.
+ //
+ if (fixSessionParameters->SessionType != GNSS_FixSession_SingleShot)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "Session type is not GNSS_FixSession_SingleShot");
+ goto Exit;
+ }
+
+ //
+ // FIX ME:
+ // Since only single session is supported, use _SingleShotSession instance.
+ // If multiple sessions, get the right session pointer searched by the session ID.
+ //
+ _SingleShotSession.ModifyAcquiringFix(fixSessionParameters);
+
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "ModifyFix failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CFixHandler::GetFixRequest(
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG sessionId = INVALID_SESSION_ID;
+ ULONG *pSessionId = nullptr;
+
+ // Get the session ID this get fix is for
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(sessionId), (void**)&pSessionId, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "Could not retrieve input sessionID for request");
+ goto Exit;
+ }
+
+ //
+ // FIX ME:
+ // Single session is only option now, but if multiple sessions, this sample should do this check at the FixHandler Level.
+ //
+ sessionId = *pSessionId;
+
+ status = _SingleShotSession.GetFix(Request);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "SinglShotSession.GetFix failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
diff --git a/gnss/gnssUmdf/FixHandler.h b/gnss/gnssUmdf/FixHandler.h
new file mode 100644
index 00000000..6ade10a7
--- /dev/null
+++ b/gnss/gnssUmdf/FixHandler.h
@@ -0,0 +1,39 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ Fixhandler.h
+
+Abstract:
+
+ This module contains the type definitions of the fix logic of the Umdf Gnss Driver.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#pragma once
+
+class CFixSession;
+
+class CFixHandler
+{
+public:
+ NTSTATUS Initialize(_In_ WDFQUEUE Queue);
+
+ NTSTATUS StartFix(_In_ WDFREQUEST Request, _In_ BOOL LocationServiceEnabled);
+ NTSTATUS StopFix(_In_ WDFREQUEST Request);
+ NTSTATUS GetFixRequest(_In_ WDFREQUEST Request);
+ NTSTATUS ModifyFix(_In_ WDFREQUEST Request);
+ NTSTATUS StopExistingSinglsShotFix();
+
+private:
+ // Session objects (single shot, distance tracking etc.)
+ CFixSession _SingleShotSession;
+
+ ULONG _CurrentSinglsShotSessionId = INVALID_SESSION_ID;
+};
diff --git a/gnss/gnssUmdf/FixSession.cpp b/gnss/gnssUmdf/FixSession.cpp
new file mode 100644
index 00000000..14418a8f
--- /dev/null
+++ b/gnss/gnssUmdf/FixSession.cpp
@@ -0,0 +1,512 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ fixsession.cpp
+
+Abstract:
+
+ This file contains the Fix sessions and contains logic to provide position.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#include "precomp.h"
+#include "Trace.h"
+#include "Defaults.h"
+#include "FixSession.h"
+#include "FixHandler.h"
+
+#include "FixSession.tmh"
+
+
+static void CALLBACK
+s_FixThreadStub(
+ _Inout_ PTP_CALLBACK_INSTANCE Instance,
+ _Inout_opt_ PVOID Context,
+ _Inout_ PTP_WORK Work
+);
+
+CFixSession::CFixSession() :
+ _Id(INVALID_SESSION_ID),
+ _State(STOPPED),
+ _HasCachedFix(false),
+ _StopFixEvent(nullptr),
+ _ThreadpoolWork(nullptr)
+{
+ InitializeCriticalSection(&_Lock);
+ _GnssPosition = g_DefaultGnssFixData;
+}
+
+CFixSession::~CFixSession()
+{
+ if (_StopFixEvent != nullptr && _ThreadpoolWork != nullptr)
+ {
+ SetEvent(_StopFixEvent);
+ WaitForThreadpoolWorkCallbacks(_ThreadpoolWork, TRUE);
+ }
+
+ if (_StopFixEvent != nullptr)
+ {
+ CloseHandle(_StopFixEvent);
+ _StopFixEvent = nullptr;
+ }
+
+ if (_ThreadpoolWork != nullptr)
+ {
+ CloseThreadpoolWork(_ThreadpoolWork);
+ _ThreadpoolWork = nullptr;
+ }
+
+ DeleteCriticalSection(&_Lock);
+}
+
+NTSTATUS
+CFixSession::Initialize(
+ _In_ WDFQUEUE Queue
+)
+{
+ EnterCriticalSection(&_Lock);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ // set the state
+ _State = STOPPED;
+
+ // Create the TP work
+ _ThreadpoolWork = CreateThreadpoolWork(
+ (PTP_WORK_CALLBACK)s_FixThreadStub,
+ (PVOID)this,
+ nullptr
+ );
+
+ if (_ThreadpoolWork == nullptr)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto Exit;
+ }
+
+ // Create the stop fix Event
+ _StopFixEvent = CreateEvent(/* lpEventAttributes */ nullptr, /* bManualReset */ FALSE, /* bInitialState */ FALSE, /* lpName */ nullptr);
+ if (_StopFixEvent == nullptr)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto Exit;
+ }
+
+ // Create the manual dispatch queue
+ WDF_IO_QUEUE_CONFIG queueConfiguration;
+ WDF_IO_QUEUE_CONFIG_INIT(&queueConfiguration, WdfIoQueueDispatchManual);
+
+ // Initialize the attributes of the queue. Set the execution level to
+ // passive to force all IRPs to be sent to the driver at passive IRQL.
+ WDF_OBJECT_ATTRIBUTES ioQueueAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&ioQueueAttributes);
+ ioQueueAttributes.SynchronizationScope = WdfSynchronizationScopeQueue;
+ ioQueueAttributes.ExecutionLevel = WdfExecutionLevelPassive;
+ status = WdfIoQueueCreate(WdfIoQueueGetDevice(Queue),
+ &queueConfiguration,
+ &ioQueueAttributes,
+ &_FixAcquisitionRequestQueue);
+
+Exit:
+ LeaveCriticalSection(&_Lock);
+ return status;
+}
+
+NTSTATUS
+CFixSession::StartAcquiringFix(
+ _In_ PGNSS_FIXSESSION_PARAM FixSessionParameters
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&_Lock);
+
+ // Check the state of the thread.
+ // If already running we should not get this request
+ // as multiplexing is not supported for Singleshot
+ if (_State == ACQUIRING)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto Exit;
+ }
+
+ // Create PTP_WORK only when first start fix is called.
+ if (_ThreadpoolWork == nullptr)
+ {
+ // Not initialized. Error out
+ status = STATUS_UNSUCCESSFUL;
+ goto Exit;
+ }
+
+ _Id = FixSessionParameters->FixSessionID;
+ _State = ACQUIRING;
+ _FixParameter = *FixSessionParameters;
+
+ ResetEvent(_StopFixEvent);
+
+ // Post a work object to the thread
+ SubmitThreadpoolWork(_ThreadpoolWork);
+
+ // Initialize the GetFix Queue
+ WdfIoQueueStart(_FixAcquisitionRequestQueue);
+
+Exit:
+ LeaveCriticalSection(&_Lock);
+
+ return status;
+}
+
+NTSTATUS
+CFixSession::StopAcquiringFix(
+ _In_ PGNSS_STOPFIXSESSION_PARAM StopFixSessionParam
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ {
+ EnterCriticalSection(&_Lock);
+
+ // If Ids don't Match return Error
+ if (StopFixSessionParam->FixSessionID != _Id)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FIX, "Id mismatch in Stop Fix Session call");
+ goto Exit;
+ }
+
+ // Check the state of the session
+ if (_State != ACQUIRING)
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FIX, "Can't stop an inactive session.");
+ goto Exit;
+ }
+
+ // Stop the current processing of the fix session
+ if (_StopFixEvent != nullptr)
+ {
+ SetEvent(_StopFixEvent);
+ }
+
+ LeaveCriticalSection(&_Lock);
+ }
+
+ // Wait for any threadpool work to finish.
+ if (_ThreadpoolWork != nullptr)
+ {
+ WaitForThreadpoolWorkCallbacks(_ThreadpoolWork, TRUE);
+ }
+
+ EnterCriticalSection(&_Lock);
+ _State = STOPPED;
+
+ // Drain the GetFix Queue
+ WdfIoQueuePurgeSynchronously(_FixAcquisitionRequestQueue);
+
+Exit:
+ LeaveCriticalSection(&_Lock);
+
+ return status;
+}
+
+NTSTATUS
+CFixSession::ModifyAcquiringFix(
+ _In_ PGNSS_FIXSESSION_PARAM ModifyFixSessionParam
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&_Lock);
+
+ memcpy_s(&_FixParameter, sizeof(GNSS_FIXSESSION_PARAM), ModifyFixSessionParam, sizeof(*ModifyFixSessionParam));
+
+ LeaveCriticalSection(&_Lock);
+
+ return status;
+}
+
+NTSTATUS
+CFixSession::ReportGnssFix(
+ _In_ PGNSS_FIXDATA GnssFix
+)
+{
+ EnterCriticalSection(&_Lock);
+
+ NTSTATUS status = STATUS_SUCCESS;
+ WDFREQUEST Request;
+ WDF_IO_QUEUE_STATE QueueStatus;
+ ULONG uRequest;
+
+ QueueStatus = WdfIoQueueGetState(_FixAcquisitionRequestQueue, &uRequest, nullptr);
+ if (!WDF_IO_QUEUE_READY(QueueStatus) || (uRequest == 0))
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto Exit;
+ }
+
+ if (STATUS_SUCCESS == WdfIoQueueRetrieveNextRequest(_FixAcquisitionRequestQueue, &Request))
+ {
+ status = CompleteRequestWithGnssFix(Request, GnssFix);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "Could not respond with fix data with %!STATUS!", status);
+ goto Exit;
+ }
+ }
+ else
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "Couldn't retrieve the next request with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ LeaveCriticalSection(&_Lock);
+
+ return status;
+}
+
+NTSTATUS
+CFixSession::CompleteRequestWithGnssFix(
+ _In_ WDFREQUEST Request,
+ PGNSS_FIXDATA GnssFix
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PVOID outputBuffer;
+ size_t outputBufferLength;
+ PGNSS_EVENT gnssEvent;
+ size_t size = FIELD_OFFSET(GNSS_EVENT, FixData) + sizeof(GNSS_FIXDATA);
+
+ status = WdfRequestRetrieveOutputBuffer(Request,
+ size,
+ &outputBuffer,
+ &outputBufferLength);
+
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_FIX, "WdfRequestRetrieveOutputBuffer() failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+ gnssEvent = ((GNSS_EVENT *)outputBuffer);
+ memset(outputBuffer, 0, size);
+ gnssEvent->Version = GNSS_DRIVER_VERSION_2;
+ gnssEvent->EventType = GNSS_Event_FixAvailable;
+ gnssEvent->EventDataSize = sizeof(GNSS_FIXDATA);
+ gnssEvent->Size = (ULONG)size;
+ memcpy_s(&gnssEvent->FixData, sizeof(GNSS_FIXDATA), GnssFix, sizeof(GNSS_FIXDATA));
+ gnssEvent->FixData.FixSessionID = _Id;
+
+ WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, outputBufferLength);
+ status = STATUS_PENDING;
+Exit:
+ return status;
+}
+
+NTSTATUS
+CFixSession::UpdateCurrentPosition(
+ _In_ PGNSS_FIXDATA GnssFix
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ EnterCriticalSection(&_Lock);
+
+ memcpy_s(&_GnssPosition, sizeof(GNSS_FIXDATA), GnssFix, sizeof(*GnssFix));
+
+ LeaveCriticalSection(&_Lock);
+
+ return status;
+}
+
+NTSTATUS
+CFixSession::GetFix(
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG sessionId = INVALID_SESSION_ID;
+ PGNSS_EVENT outputEvent = nullptr;
+ ULONG *pSessionId = nullptr;
+
+ EnterCriticalSection(&_Lock);
+
+ // Verify the size of where output goes eventually, when this IRP is serviced
+ status = WdfRequestRetrieveOutputBuffer(Request, sizeof(GNSS_EVENT), (void**)&outputEvent, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FIX, "Could not retrieve output buffer for request with %!STATUS!", status);
+ goto Exit;
+ }
+
+ // Get the session ID this get fix is for
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(sessionId), (void**)&pSessionId, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FIX, "Could not retrieve input sessionID for request");
+ goto Exit;
+ }
+
+ sessionId = *pSessionId;
+
+ // Check if the Ids match
+ if (_Id != sessionId)
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto Exit;
+ }
+ // If we have a cached fix around because we tried to respond while there
+ // weren't any getfixes around, answer immediately with it
+ if (_HasCachedFix)
+ {
+ status = CompleteRequestWithGnssFix(Request, &_GnssPosition);
+
+ _HasCachedFix = !(NT_SUCCESS(status));
+ }
+ // Otherwise, we push the request into a queue
+ else
+ {
+ status = WdfRequestForwardToIoQueue(Request, _FixAcquisitionRequestQueue);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FIX, "WdfRequestForwardToIoQueue failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+ status = STATUS_PENDING;
+ }
+
+Exit:
+ LeaveCriticalSection(&_Lock);
+
+ return status;
+}
+
+static void CALLBACK
+s_FixThreadStub(
+ _Inout_ PTP_CALLBACK_INSTANCE /*Instance*/,
+ _Inout_opt_ PVOID Context,
+ _Inout_ PTP_WORK /*Work*/
+)
+{
+ CFixSession *pFixSession = static_cast<CFixSession *>(Context);
+
+ pFixSession->AcquireSingleFix();
+}
+
+void
+CFixSession::AcquireSingleFix()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ while (true)
+ {
+ // Wait stop fix event for 1 second and then retrieve position
+ DWORD WaitCode = WaitForSingleObject(_StopFixEvent, DEFAULT_FIX_INTERVAL_SECONDS * 1000);
+ if (WaitCode == WAIT_TIMEOUT)
+ {
+ status = RetrievePosition(&_GnssPosition);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_FIX, "Fail to retrieve fix data from position source");
+ }
+
+ // Send the default fix to the session
+ status = ReportGnssFix(&_GnssPosition);
+ if (!NT_SUCCESS(status))
+ {
+ // We were not able to send the fix so cache it
+ _HasCachedFix = true;
+ }
+ else
+ {
+ if (_GnssPosition.IsFinalFix != FALSE)
+ {
+ break;
+ }
+ }
+ }
+ else if (WaitCode == WAIT_OBJECT_0)
+ {
+ // Stop session signalled
+ break;
+ }
+ }
+
+ EnterCriticalSection(&_Lock);
+
+ // Reset the StopFix Event if it is set
+ ResetEvent(_StopFixEvent);
+
+ // Update the state of the session
+ _State = STOPPED;
+
+ LeaveCriticalSection(&_Lock);
+}
+
+
+NTSTATUS
+CFixSession::RetrievePosition(
+ _Inout_ PGNSS_FIXDATA GnssFixData
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // FIX ME:
+ // You can retrieve a position from a predefined position or GPS HW.
+ // This sample code calls RetrievePositionFromPredefinedValue to give fake location.
+ // To give a real location from GPS HW, replace this function with new function that defines
+ // (1) establishing and enumerating HW interface such as Serial or Bluetooth, and
+ // (2) reading and parsing NMEA messages from the interface.
+ // You can also define a custom IOCTL instead, updating _GnssPosition directly in CQueue and skip the call below as no-op.
+ //
+ status = RetrievePositionFromPredefinedValue(GnssFixData);
+
+ return status;
+}
+
+NTSTATUS
+CFixSession::RetrievePositionFromPredefinedValue(
+ _Out_ PGNSS_FIXDATA GnssFixData
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // FIX ME:
+ // Specify user-defined GNSS_FIXDATA output based off the DDI format. The following is just an example.
+ //
+ *GnssFixData =
+ {
+ sizeof(GNSS_FIXDATA),
+ GNSS_DRIVER_DDK_VERSION,
+ INVALID_SESSION_ID,
+ { 0xCD700000, 0x1D48908 }, // an example date/time, Dec/01/2018
+ TRUE,
+ STATUS_SUCCESS,
+ GNSS_FIXDETAIL_BASIC | GNSS_FIXDETAIL_ACCURACY,
+ {
+ sizeof(GNSS_FIXDATA_BASIC),
+ GNSS_DRIVER_DDK_VERSION,
+ // Location: Mount Rainier National Park
+ 46.852273,
+ -121.757468,
+ 0.0,
+ 0.0,
+ 0.0
+ },
+ {
+ sizeof(GNSS_FIXDATA_ACCURACY),
+ GNSS_DRIVER_DDK_VERSION,
+ 10 // Meters accuracy
+ }
+ };
+ return status;
+}
diff --git a/gnss/gnssUmdf/FixSession.h b/gnss/gnssUmdf/FixSession.h
new file mode 100644
index 00000000..f8298306
--- /dev/null
+++ b/gnss/gnssUmdf/FixSession.h
@@ -0,0 +1,60 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ Fixsession.h
+
+Abstract:
+
+ This module contains the type definitions of the fix logic of the Umdf Gnss Driver.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#pragma once
+
+//
+// This class implements the Fix sessions and contains logic to provide position within GNSS driver.
+//
+class CFixSession
+{
+public:
+ CFixSession();
+ ~CFixSession();
+
+ void AcquireSingleFix();
+ NTSTATUS Initialize(_In_ WDFQUEUE Queue);
+ NTSTATUS StartAcquiringFix(_In_ PGNSS_FIXSESSION_PARAM FixSessionParameters);
+ NTSTATUS StopAcquiringFix(_In_ PGNSS_STOPFIXSESSION_PARAM StopFixSessionParam);
+ NTSTATUS ModifyAcquiringFix(_In_ PGNSS_FIXSESSION_PARAM ModifyFixSessionParam);
+ NTSTATUS GetFix(_In_ WDFREQUEST Request);
+ NTSTATUS UpdateCurrentPosition(_In_ PGNSS_FIXDATA GnssFix);
+
+ NTSTATUS RetrievePosition(_Inout_ PGNSS_FIXDATA GnssFixData);
+ NTSTATUS RetrievePositionFromPredefinedValue(_Out_ PGNSS_FIXDATA GnssFixData);
+
+private:
+ enum STATE
+ {
+ ACQUIRING = 0,
+ STOPPED
+ };
+
+ ULONG _Id = INVALID_SESSION_ID;
+ STATE _State = STOPPED;
+ GNSS_FIXSESSION_PARAM _FixParameter = {};
+ WDFQUEUE _FixAcquisitionRequestQueue = nullptr;
+ bool _HasCachedFix = false;
+ GNSS_FIXDATA _GnssPosition = {};
+ HANDLE _StopFixEvent = nullptr;
+ PTP_WORK _ThreadpoolWork = nullptr;
+ CRITICAL_SECTION _Lock;
+
+ NTSTATUS CompleteRequestWithGnssFix(_In_ WDFREQUEST Request, PGNSS_FIXDATA GnssFix);
+ NTSTATUS ReportGnssFix(_In_ PGNSS_FIXDATA GnssFix);
+};
diff --git a/gnss/gnssUmdf/Queue.cpp b/gnss/gnssUmdf/Queue.cpp
new file mode 100644
index 00000000..fdf23ab2
--- /dev/null
+++ b/gnss/gnssUmdf/Queue.cpp
@@ -0,0 +1,482 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ queue.cpp
+
+Abstract:
+
+ This file contains the queue entry points and callbacks.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#include "precomp.h"
+#include "Trace.h"
+#include "Defaults.h"
+#include "Device.h"
+#include "FixSession.h"
+#include "FixHandler.h"
+#include "Queue.h"
+
+#include "Queue.tmh"
+
+
+CQueue::CQueue(
+ WDFQUEUE Queue
+) :
+ _Queue(Queue),
+ _ForcedDriverVersion(GNSS_DRIVER_DDK_VERSION)
+{
+ InitializeCriticalSection(&_Lock);
+}
+
+CQueue::~CQueue()
+{
+ DeleteCriticalSection(&_Lock);
+ _Queue = nullptr;
+}
+
+
+void
+CQueue::OnCleanup(
+ _In_ WDFOBJECT Object
+)
+{
+ CQueue *pQueue = GetQueueObject(Object);
+
+ // Queue object constructed using placement 'new' so explicitly invoke destructor
+ pQueue->~CQueue();
+}
+
+NTSTATUS
+CQueue::Initialize()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ // Initialize the Fix Handler
+ status = _FixHandler.Initialize(_Queue);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "_FixHandler->Initialize failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+void
+CQueue::OnIoDeviceControl(
+ _In_ WDFQUEUE Queue,
+ _In_ WDFREQUEST Request,
+ _In_ size_t OutputBufferLength,
+ _In_ size_t InputBufferLength,
+ _In_ ULONG IoControlCode
+)
+{
+ CQueue *pQueue = GetQueueObject(Queue);
+
+ pQueue->OnIoDeviceControl(Request, IoControlCode, InputBufferLength, OutputBufferLength);
+}
+
+NTSTATUS
+CQueue::AddQueueToDevice(
+ _In_ WDFDEVICE Device,
+ _Outptr_ CQueue** Queue
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ // Create a sequential IO Queue for serial operation and supply all the callbacks.
+ // A sequential queue will cause all IO requests to be serialized to the device (i.e., only one request will sent at a time).
+ WDF_IO_QUEUE_CONFIG queueConfig;
+ WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig,
+ WdfIoQueueDispatchSequential);
+
+ queueConfig.PowerManaged = WdfFalse;
+ queueConfig.EvtIoDeviceControl = CQueue::OnIoDeviceControl;
+
+ WDF_OBJECT_ATTRIBUTES queueAttributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes,
+ CQueue);
+
+ queueAttributes.EvtCleanupCallback = CQueue::OnCleanup;
+
+ WDFQUEUE queue = nullptr;
+ status = WdfIoQueueCreate(Device,
+ &queueConfig,
+ &queueAttributes,
+ &queue);
+
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "WdfIoQueueCreate failed with Status %!STATUS!", status);
+ goto Exit;
+ }
+
+ // Construct a queue object on the preallocated buffer using placement new operation
+ *Queue = new (GetQueueObject(queue)) CQueue(queue);
+
+ status = (*Queue)->Initialize();
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DEVICE, "CQueue::Initialize failed with %!STATUS!", status);
+ goto Exit;
+ }
+
+Exit:
+ return status;
+}
+
+void
+CQueue::OnIoDeviceControl(
+ _In_ WDFREQUEST Request,
+ _In_ ULONG IoControlCode,
+ _In_ size_t InputBufferLength,
+ _In_ size_t OutputBufferLength)
+{
+ TraceEvents(TRACE_LEVEL_INFORMATION,
+ TRACE_QUEUE,
+ "Request = %p, IoControlCode = 0x%x InputBufferLength=%d OutputBufferLength=%d",
+ Request, IoControlCode, (int)InputBufferLength, (int)OutputBufferLength);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ switch (IoControlCode)
+ {
+ // Capability Exchange
+ case IOCTL_GNSS_SEND_PLATFORM_CAPABILITY:
+ break;
+ case IOCTL_GNSS_GET_DEVICE_CAPABILITY:
+ status = GetDeviceCapability(Request);
+ break;
+
+ case IOCTL_GNSS_GET_CHIPSETINFO:
+ status = GetChipsetInfo(Request);
+ break;
+
+ // Fix
+ case IOCTL_GNSS_START_FIXSESSION:
+ status = _FixHandler.StartFix(Request, _InternalState.SetLocationServiceEnabled);
+ break;
+ case IOCTL_GNSS_STOP_FIXSESSION:
+ status = _FixHandler.StopFix(Request);
+ break;
+ case IOCTL_GNSS_MODIFY_FIXSESSION:
+ status = _FixHandler.ModifyFix(Request);
+ break;
+ case IOCTL_GNSS_GET_FIXDATA:
+ status = _FixHandler.GetFixRequest(Request);
+ break;
+
+ // Driver Command
+ case IOCTL_GNSS_SEND_DRIVERCOMMAND:
+ status = HandleDriverCommand(Request);
+ break;
+
+ //
+ // FIX ME:
+ // The below is optional IOCTLs. Driver developer may choose to implement for advanced functionality.
+ //
+
+ // Agnss
+ case IOCTL_GNSS_INJECT_AGNSS:
+ case IOCTL_GNSS_LISTEN_AGNSS:
+ // Supl
+ case IOCTL_GNSS_SET_SUPL_HSLP:
+ case IOCTL_GNSS_CONFIG_SUPL_CERT:
+ case IOCTL_GNSS_SET_V2UPL_CONFIG:
+ //Ni
+ case IOCTL_GNSS_LISTEN_DRIVER_REQUEST:
+ case IOCTL_GNSS_RESPOND_NI:
+ case IOCTL_GNSS_LISTEN_NI:
+ //Geofence
+ case IOCTL_GNSS_LISTEN_GEOFENCE_ALERT:
+ case IOCTL_GNSS_LISTEN_GEOFENCES_TRACKINGSTATUS:
+ case IOCTL_GNSS_CREATE_GEOFENCE:
+ case IOCTL_GNSS_DELETE_GEOFENCE:
+ // Breadcrumbing
+ case IOCTL_GNSS_START_BREADCRUMBING:
+ case IOCTL_GNSS_STOP_BREADCRUMBING:
+ case IOCTL_GNSS_LISTEN_BREADCRUMBING_ALERT:
+ case IOCTL_GNSS_POP_BREADCRUMBS:
+ // Ioctls that are not implemented
+ case IOCTL_GNSS_LISTEN_ERROR:
+ case IOCTL_GNSS_EXECUTE_CWTEST:
+ case IOCTL_GNSS_EXECUTE_SELFTEST:
+ case IOCTL_GNSS_LISTEN_NMEA:
+ status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ default:
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ if (status != STATUS_PENDING)
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Completing Request with status %!STATUS!", status);
+ WdfRequestComplete(Request, status);
+ }
+}
+
+NTSTATUS
+CQueue::GetDeviceCapability(
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
+ PGNSS_DEVICE_CAPABILITY outputParam;
+
+ status = WdfRequestRetrieveOutputBuffer(Request, sizeof(*outputParam), (void**)&outputParam, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Could not retrieve output buffer for request with status = %!STATUS!", status);
+ goto Exit;
+ }
+
+ INIT_POD_GNSS_STRUCT(outputParam);
+
+ //
+ // FIX ME:
+ // The functionality below is optional. Driver developer may choose to implement for advanced functionality/better performance.
+ //
+ {
+ outputParam->SupportContinuousTracking = FALSE;
+
+ outputParam->SupportDistanceTracking = FALSE;
+
+ outputParam->GeofencingSupport = FALSE;
+ outputParam->MaxGeofencesSupported = 0;
+
+ outputParam->RequireAGnssInjection = FALSE;
+ outputParam->AgnssFormatSupported = FALSE;
+ outputParam->AgnssFormatPreferred = FALSE;
+
+ outputParam->SupportCpLocation = FALSE;
+ outputParam->SupportSuplV2 = FALSE;
+ outputParam->SupportSuplV1 = FALSE;
+ outputParam->SupportUplV2 = FALSE;
+ outputParam->SupportedSuplVersion.MajorVersion = 0;
+ outputParam->SupportedSuplVersion.MinorVersion = 0;
+
+ outputParam->MaxGnssBreadCrumbFixes = 0;
+ outputParam->GnssBreadCrumbPayloadVersion = BREADCRUMBING_UNSUPPORTED;
+
+ // Update the Driver version if forced through IOCTL
+ outputParam->Version = _ForcedDriverVersion;
+ }
+
+ WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, sizeof(*outputParam));
+ status = STATUS_PENDING;
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CQueue::GetChipsetInfo(
+ _In_ WDFREQUEST Request
+)
+{
+ //
+ // FIX ME:
+ // The following is an example. Replace the values accordingly
+ //
+ static const wchar_t s_ManufacturerID[] = L"Microsoft Test";
+ static const wchar_t s_HardwareID[] = L"UMDF Gnss";
+ static const wchar_t s_FirmwareVersion[] = L"1.0.0.0";
+
+ NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
+ PGNSS_CHIPSETINFO outputParam;
+
+ status = WdfRequestRetrieveOutputBuffer(Request, sizeof(*outputParam), (void**)&outputParam, nullptr);
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Could not retrieve output buffer for request with status = %!STATUS!", status);
+ goto Exit;
+ }
+
+ INIT_POD_GNSS_STRUCT(outputParam);
+
+ memset(&(outputParam->ManufacturerID), 0, sizeof(outputParam->ManufacturerID));
+ memset(&(outputParam->HardwareID), 0, sizeof(outputParam->HardwareID));
+ memset(&(outputParam->FirmwareVersion), 0, sizeof(outputParam->FirmwareVersion));
+
+ memcpy_s(&(outputParam->ManufacturerID), sizeof(outputParam->ManufacturerID), &s_ManufacturerID, sizeof(s_ManufacturerID));
+ memcpy_s(&(outputParam->HardwareID), sizeof(outputParam->HardwareID), &s_HardwareID, sizeof(s_HardwareID));
+ memcpy_s(&(outputParam->FirmwareVersion), sizeof(outputParam->FirmwareVersion), &s_FirmwareVersion, sizeof(s_FirmwareVersion));
+
+ WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, sizeof(*outputParam));
+ status = STATUS_PENDING;
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CQueue::HandleDriverCommand(
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
+ PGNSS_DRIVERCOMMAND_PARAM command = nullptr;
+
+ // Check that there is enough room to output the returned GNSS_DEVICE_CAPABILITY
+ status = WdfRequestRetrieveInputBuffer(Request, sizeof(*command), (void**)&command, nullptr);
+
+ if (!NT_SUCCESS(status))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "%!FUNC! Could not retrieve input buffer for DriverCommand request with status = %!STATUS!", status);
+ goto Exit;
+ }
+
+ // Check that the sizes are well-formed
+ if ((command->Size < (ULONG)FIELD_OFFSET(GNSS_DRIVERCOMMAND_PARAM, CommandData[command->CommandDataSize])))
+ {
+ TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_QUEUE, "Command is not formatted correctly : unexpected sizes specified");
+ goto Exit;
+ }
+
+ switch (command->CommandType)
+ {
+ case GNSS_ClearAgnssData:
+ status = ClearAgnssData(command);
+ break;
+ case GNSS_ResetEngine:
+ status = ResetEngine(command);
+ break;
+ case GNSS_SetLocationServiceEnabled:
+ status = SetLocationServiceStatus(command);
+ break;
+ case GNSS_ForceOperationMode:
+ status = SetOperationMode(command);
+ break;
+
+ //
+ // FIX ME:
+ // Below are optional driver commands. Driver developer may choose to implement for advanced functionality.
+ //
+ case GNSS_SetLocationNIRequestAllowed:
+ case GNSS_ResetGeofencesTracking:
+ case GNSS_SetNiTimeoutInterval:
+ case GNSS_SetSuplVersion:
+ case GNSS_SetUplServerAccessInterval:
+ status = STATUS_NOT_IMPLEMENTED;
+ break;
+ default:
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+Exit:
+ return status;
+}
+
+NTSTATUS
+CQueue::SetLocationServiceStatus(
+ _In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ status = GetDataFromCommand(CommandParam, &_InternalState.SetLocationServiceEnabled) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
+
+ if (!_InternalState.SetLocationServiceEnabled)
+ {
+ //
+ // FIX ME:
+ // We must stop any ongoing location sessions of any kind (geofence tracking, assistance data refresh, etc. if any).
+ // For example, if you have distance tracking fix session, stop the session as well.
+ //
+ status = _FixHandler.StopExistingSinglsShotFix();
+ }
+
+ return status;
+}
+
+NTSTATUS
+CQueue::ResetEngine(
+ _In_ PGNSS_DRIVERCOMMAND_PARAM /*CommandParam*/
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // FIX ME:
+ // This is mandatory command, but sample driver cannot support Reset engine command because this is vendor/HW-specific feature.
+ // You must customize this accordingly. The sample below demonstrates how it might work by resetting internal structure.
+ //
+ _AgnssNeeded[AGNSS_TIME_IDX] = TRUE;
+ _AgnssNeeded[AGNSS_POS_IDX] = TRUE;
+ _AgnssNeeded[AGNSS_BLOB_IDX] = TRUE;
+
+ return status;
+}
+
+NTSTATUS
+CQueue::ClearAgnssData(
+ _In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ DWORD data = 0;
+
+ //
+ // FIX ME:
+ // This is mandatory command, but sample driver cannot support Clear AGNSS data because this is vendor/HW-specific feature.
+ // You must customize this accordingly. The sample below demonstrates how it might work by resetting internal structure.
+ //
+ if (GetDataFromCommand(CommandParam, &data))
+ {
+ GNSS_AGNSS_REQUEST_TYPE reqType = (GNSS_AGNSS_REQUEST_TYPE)data;
+ _AgnssNeeded[reqType] = TRUE;
+ }
+ else
+ {
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ return status;
+}
+
+NTSTATUS
+CQueue::SetOperationMode(
+ _In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // FIX ME:
+ // This is mandatory only if SUPL is supported. SUPL is not mandatory unless it is required by mobile operator.
+ // You must customize this code accordingly, depending on the requirement.
+ //
+ status = GetDataFromCommand(CommandParam, &_InternalState.OperationMode) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
+
+ return status;
+}
+
+template <class DataT>
+BOOL CQueue::GetDataFromCommand(
+ _In_ PGNSS_DRIVERCOMMAND_PARAM Command,
+ _Out_ DataT* Data)
+{
+ size_t dataLen = sizeof(*Data);
+
+ memset(Data, 0, dataLen);
+
+ if (!Command || (Command->CommandDataSize != dataLen))
+ {
+ return FALSE;
+ }
+
+ memcpy_s(Data, dataLen, Command->CommandData, dataLen);
+ return TRUE;
+}
diff --git a/gnss/gnssUmdf/Queue.h b/gnss/gnssUmdf/Queue.h
new file mode 100644
index 00000000..89a105ac
--- /dev/null
+++ b/gnss/gnssUmdf/Queue.h
@@ -0,0 +1,78 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ queue.h
+
+Abstract:
+
+ This file contains the queue definitions for the Umdf Gnss Driver.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#pragma once
+
+class CFixHandler;
+
+//
+//This class sets up IO queue, performs the IOCTL operations, and implements the type definitions for the driver's device callback.
+//
+class CQueue
+{
+public:
+ static NTSTATUS AddQueueToDevice(_In_ WDFDEVICE device, _Outptr_ CQueue** queue);
+
+private:
+ enum
+ {
+ AGNSS_TIME_IDX = GNSS_AGNSS_TimeInjection,
+ AGNSS_POS_IDX = GNSS_AGNSS_PositionInjection,
+ AGNSS_BLOB_IDX = GNSS_AGNSS_BlobInjection,
+ AGNSS_MAX_IDX
+ };
+
+ typedef struct {
+ DWORD OperationMode;
+ BOOL SetLocationNiRequestAllowed;
+ BOOL SetLocationServiceEnabled;
+ } GnssInternalState;
+
+ WDFQUEUE _Queue;
+ CRITICAL_SECTION _Lock;
+ CFixHandler _FixHandler;
+ ULONG _ForcedDriverVersion = GNSS_DRIVER_DDK_VERSION;
+ GnssInternalState _InternalState = {};
+ BOOL _AgnssNeeded[AGNSS_MAX_IDX];
+
+ CQueue(WDFQUEUE Queue);
+ ~CQueue();
+
+ static EVT_WDF_OBJECT_CONTEXT_CLEANUP OnCleanup;
+ static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL OnIoDeviceControl;
+
+ template <class DataT>
+ BOOL GetDataFromCommand(_In_ PGNSS_DRIVERCOMMAND_PARAM Command,
+ _Out_ DataT* Data);
+
+ NTSTATUS Initialize();
+ void OnIoDeviceControl(_In_ WDFREQUEST Request,
+ _In_ ULONG IoControlCode,
+ _In_ size_t InputBufferLength,
+ _In_ size_t OutputBufferLength);
+ NTSTATUS GetDeviceCapability(_In_ WDFREQUEST Request);
+ NTSTATUS GetChipsetInfo(_In_ WDFREQUEST Request);
+ NTSTATUS HandleDriverCommand(_In_ WDFREQUEST Request);
+
+ NTSTATUS ResetEngine(_In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam);
+ NTSTATUS ClearAgnssData(_In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam);
+ NTSTATUS SetLocationServiceStatus(_In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam);
+ NTSTATUS SetOperationMode(_In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam);
+};
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CQueue, GetQueueObject);
diff --git a/gnss/gnssUmdf/Trace.h b/gnss/gnssUmdf/Trace.h
new file mode 100644
index 00000000..6b6af60b
--- /dev/null
+++ b/gnss/gnssUmdf/Trace.h
@@ -0,0 +1,64 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ Trace.h
+
+Abstract:
+
+ This module contains the local type definitions for the Umdf Gnss Driver.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#pragma once
+
+//
+// Define the tracing flags.
+//
+
+#define WPP_CONTROL_GUIDS \
+ WPP_DEFINE_CONTROL_GUID( \
+ GnssUmdfTraceGuid, (ceb3bf01,80e4,4dc7,b3bf,f6b5279eb8c4), \
+ \
+ WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \
+ WPP_DEFINE_BIT(TRACE_DRIVER) \
+ WPP_DEFINE_BIT(TRACE_DEVICE) \
+ WPP_DEFINE_BIT(TRACE_QUEUE) \
+ WPP_DEFINE_BIT(TRACE_FIX) \
+ )
+
+#define WPP_FLAG_LEVEL_LOGGER(flag, level) \
+ WPP_LEVEL_LOGGER(flag)
+
+#define WPP_FLAG_LEVEL_ENABLED(flag, level) \
+ (WPP_LEVEL_ENABLED(flag) && \
+ WPP_CONTROL(WPP_BIT_ ## flag).Level >= level)
+
+#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) \
+ WPP_LEVEL_LOGGER(flags)
+
+#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) \
+ (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)
+
+//
+// This comment block is scanned by the trace preprocessor to define our
+// Trace function.
+//
+// begin_wpp config
+// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...);
+// FUNC TraceEvents(LEVEL, FLAGS, MSG, ...);
+// end_wpp
+
+//
+//
+// Driver specific #defines
+//
+#if UMDF_VERSION_MAJOR == 2 && UMDF_VERSION_MINOR == 0
+ #define MYDRIVER_TRACING_ID L"Microsoft\\UMDF2.0\\gnssUmdf V1.0"
+#endif
diff --git a/gnss/gnssUmdf/gnssUmdf.inf b/gnss/gnssUmdf/gnssUmdf.inf
new file mode 100644
index 00000000..65dd5e59
--- /dev/null
+++ b/gnss/gnssUmdf/gnssUmdf.inf
Binary files differ
diff --git a/gnss/gnssUmdf/gnssUmdf.vcxproj b/gnss/gnssUmdf/gnssUmdf.vcxproj
new file mode 100644
index 00000000..bcfd27ae
--- /dev/null
+++ b/gnss/gnssUmdf/gnssUmdf.vcxproj
@@ -0,0 +1,301 @@
+<?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|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <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|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</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>
+ <ItemGroup>
+ <ClCompile Include="Device.cpp" />
+ <ClCompile Include="Driver.cpp" />
+ <ClCompile Include="FixHandler.cpp" />
+ <ClCompile Include="FixSession.cpp" />
+ <ClCompile Include="Queue.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="precomp.h" />
+ <ClInclude Include="Device.h" />
+ <ClInclude Include="Driver.h" />
+ <ClInclude Include="FixHandler.h" />
+ <ClInclude Include="FixSession.h" />
+ <ClInclude Include="Defaults.h" />
+ <ClInclude Include="Queue.h" />
+ <ClInclude Include="Trace.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Include="gnssUmdf.inf" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{AC97DD9E-781F-4FCE-8AC7-ADE57C633A13}</ProjectGuid>
+ <TemplateGuid>{32909489-7be5-497b-aafa-db6669d9b44b}</TemplateGuid>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <Configuration>Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <RootNamespace>gnssUmdf</RootNamespace>
+ <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR>
+ </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|Win32'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DebuggerFlavor>DbgengRemoteDebugger</DebuggerFlavor>
+ <OutDir>$(ProjectDir)bin\$(Platform)\$(ConfigurationName)\</OutDir>
+ <IntDir>$(ProjectDir)obj\$(Platform)\$(ConfigurationName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <ClCompile>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">trace.h</WppScanConfigurationData>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <PrecompiledHeader>Create</PrecompiledHeader>
+ <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/gnss/gnssUmdf/gnssUmdf.vcxproj.filters b/gnss/gnssUmdf/gnssUmdf.vcxproj.filters
new file mode 100644
index 00000000..15af8928
--- /dev/null
+++ b/gnss/gnssUmdf/gnssUmdf.vcxproj.filters
@@ -0,0 +1,69 @@
+<?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="gnssUmdf.inf">
+ <Filter>Driver Files</Filter>
+ </Inf>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Device.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Driver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Queue.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Trace.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Defaults.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="FixHandler.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="FixSession.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="precomp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="Device.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Driver.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Queue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="FixHandler.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="FixSession.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/gnss/gnssUmdf/precomp.h b/gnss/gnssUmdf/precomp.h
new file mode 100644
index 00000000..e07f2171
--- /dev/null
+++ b/gnss/gnssUmdf/precomp.h
@@ -0,0 +1,29 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ precomp.h
+
+Abstract:
+
+ This module contains the common type definitions and includes.
+
+Environment:
+
+ Windows User-Mode Driver Framework
+
+--*/
+
+#pragma once
+
+//
+// Include the type specific headers.
+//
+#include <windows.h>
+#include <wdf.h>
+#include <initguid.h>
+#include <sstream>
+#include <vector>
+#include <gnssdriver.h>