Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/windows/wdfserial/QCMAIN.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, QCReqGetContext)
// Registry Value Names
#define VEN_DEV_PORT L"AssignedPortForQCDevice"
#define VEN_DEV_TIME L"QCDeviceStamp"
#define VEN_DEV_GENERATION L"QCDeviceGeneration"
#define VEN_DEV_SERNUM L"QCDeviceSerialNumber"
#define VEN_DEV_MSM_SERNUM L"QCDeviceMsmSerialNumber"
#define VEN_DEV_PROTOC L"QCDeviceProtocol"
Expand Down
64 changes: 59 additions & 5 deletions src/windows/wdfserial/QCPNP.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,6 @@ NTSTATUS QCPNP_EvtDeviceAdd
goto exit;
}

if (pDevContext->FdoDeviceType == FILE_DEVICE_SERIAL_PORT)
{
QCPNP_ReportDeviceName(pDevContext);
}

exit:
if (!NT_SUCCESS(status))
{
Expand Down Expand Up @@ -267,6 +262,50 @@ NTSTATUS QCPNP_SetStamp
return STATUS_SUCCESS;
}

/****************************************************************************
*
* function: QCPNP_IncrementGeneration
*
* purpose: Increments QCDeviceGeneration DWORD in the driver registry key
* on every PrepareHardware so QDS can detect a re-enumeration even
* when DevDesc/DevName/SerNum are identical across reboots.
*
* arguments:pDevContext = pointer to the device context.
*
* returns: NT Status
*
****************************************************************************/
NTSTATUS QCPNP_IncrementGeneration(PDEVICE_CONTEXT pDevContext)
{
NTSTATUS status = STATUS_SUCCESS;
WDFDEVICE device = pDevContext->Device;
WDFKEY key;
ULONG genValue = 0;
DECLARE_CONST_UNICODE_STRING(valueName, VEN_DEV_GENERATION);

status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DRIVER,
KEY_QUERY_VALUE | KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &key);
if (!NT_SUCCESS(status))
{
return status;
}

WdfRegistryQueryValue(key, &valueName, REG_DWORD, &genValue, sizeof(genValue), NULL);
WdfRegistryClose(key);

genValue++;
status = QCMAIN_SetDriverRegistryDword((LPWSTR)valueName.Buffer, genValue, pDevContext);

QCSER_DbgPrint
(
QCSER_DBG_MASK_CONTROL,
QCSER_DBG_LEVEL_DETAIL,
("<%ws> QCPNP_IncrementGeneration new generation: %lu, status: 0x%x\n",
pDevContext->PortName, genValue, status)
);
return status;
}

/****************************************************************************
*
* function: QCPNP_DeviceCreate
Expand Down Expand Up @@ -1714,6 +1753,10 @@ NTSTATUS QCPNP_EvtDevicePrepareHardware
status = QCPNP_RegisterWmiPowerGuid(pDevContext);
}

// Increment QCDeviceGeneration so QDS can detect a re-enumeration even
// when the device identity (DevDesc/DevName/SerNum) is unchanged.
QCPNP_IncrementGeneration(pDevContext);

exit:
if (!NT_SUCCESS(status))
{
Expand Down Expand Up @@ -2234,6 +2277,14 @@ NTSTATUS QCPNP_EvtDeviceD0Entry
QCSER_DBG_LEVEL_TRACE,
("<%ws> QCPNP_EvtDeviceD0Entry Completed!\n", pDevContext->PortName)
);

// Re-announce diag device name to parent/filter on every D0 entry.
// EvtDeviceAdd fires only once; D0Entry fires on each re-enumeration.
if (pDevContext->FdoDeviceType == FILE_DEVICE_SERIAL_PORT)
{
QCPNP_ReportDeviceName(pDevContext);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this fix, every time a Hawi diag port wakes from idle/selective-suspend, the driver will re-send its device name to the parent filter driver, not just on true re-enumeration. That's extra IOCTL traffic to the filter driver on a cadence that could be quite frequent (every idle-in/idle-out cycle), for zero benefit in the non-re-enum case.

}

return STATUS_SUCCESS;
}

Expand Down Expand Up @@ -3280,6 +3331,9 @@ NTSTATUS QCPNP_SetupIoThreadsAndQueues
LARGE_INTEGER threadInitTimeout;
threadInitTimeout.QuadPart = WDF_REL_TIMEOUT_IN_MS(QCPNP_THREAD_INIT_TIMEOUT_MS);

// Clear stale removal signal in case we're re-entering after a removal cycle
KeClearEvent(&pDevContext->DeviceRemoveEvent);

// Init write request list, lock and events
InitializeListHead(&pDevContext->WriteRequestPendingList);
WdfSpinLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &pDevContext->WriteRequestPendingListLock);
Expand Down
5 changes: 5 additions & 0 deletions src/windows/wdfserial/QCPNP.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,4 +184,9 @@ NTSTATUS QCPNP_SetStamp
PDEVICE_CONTEXT pDevContext,
BOOLEAN Startup
);

NTSTATUS QCPNP_IncrementGeneration
(
PDEVICE_CONTEXT pDevContext
);
#endif // QCPNP_H
Loading