diff options
| author | Cheoljin Lee <[email protected]> | 2018-11-28 11:08:27 -0800 |
|---|---|---|
| committer | Cheoljin Lee <[email protected]> | 2018-11-28 11:08:27 -0800 |
| commit | 964d0d1e461e7a9af0f9045a7f192acd74999843 (patch) | |
| tree | b8169004db5fc67fd4f45b2f7999ea6e70865ab4 /gnss/gnssUmdf/Queue.cpp | |
| parent | 0990b0cbbd460336036dc6ec71cb8e2a8403e287 (diff) | |
Initial version of GPS/GNSS UMDF Sample Driver (UMDF Version 2)
Diffstat (limited to 'gnss/gnssUmdf/Queue.cpp')
| -rw-r--r-- | gnss/gnssUmdf/Queue.cpp | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/gnss/gnssUmdf/Queue.cpp b/gnss/gnssUmdf/Queue.cpp new file mode 100644 index 00000000..b964a100 --- /dev/null +++ b/gnss/gnssUmdf/Queue.cpp @@ -0,0 +1,439 @@ +/*++ + +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 "HelperUtility.h" +#include "Device.h" +#include "NmeaProcessor.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; + + // Setup IO queue + // + // 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: + // + // TODO: If Agnss is supported, check for Agnss data here + // + status = _FixHandler.StartFix(Request); + 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; + + // 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); + + // + // TODO: Set functionality according to what we currently support in the driver + // + { + 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 +) +{ + // + // TODO: 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 = ForceOperationMode(command); + break; + case GNSS_SetLocationNIRequestAllowed: + case GNSS_ResetGeofencesTracking: + case GNSS_SetNiTimeoutInterval: + case GNSS_SetSuplVersion: + case GNSS_SetUplServerAccessInterval: + // + // TODO: Not implemented in the sample, to be implemented by the driver owners + // + 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; + + return status; +} + +NTSTATUS +CQueue::ResetEngine( + _In_ PGNSS_DRIVERCOMMAND_PARAM /*CommandParam*/ +) +{ + NTSTATUS status = STATUS_SUCCESS; + + _AgnssNeeded[FAKE_AGNSS_TIME_IDX] = TRUE; + _AgnssNeeded[FAKE_AGNSS_POS_IDX] = TRUE; + _AgnssNeeded[FAKE_AGNSS_BLOB_IDX] = TRUE; + + return status; +} + +NTSTATUS +CQueue::ClearAgnssData( + _In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam +) +{ + NTSTATUS status = STATUS_SUCCESS; + DWORD data = 0; + + 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::ForceOperationMode( + _In_ PGNSS_DRIVERCOMMAND_PARAM CommandParam +) +{ + NTSTATUS status = STATUS_SUCCESS; + + status = GetDataFromCommand(CommandParam, &_InternalState.OperationMode) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; + + return status; +} |
