📄 pnputils.c
字号:
#include "pch.h"
VOID
P5WorkItemFreePort( PDEVICE_OBJECT Fdo, PFDO_EXTENSION Fdx ) {
PIO_WORKITEM workItem;
UNREFERENCED_PARAMETER( Fdo );
workItem = InterlockedExchangePointer( &Fdx->FreePortWorkItem, NULL );
if( workItem ) {
IoFreeWorkItem( workItem );
}
PptFreePort( Fdx );
}
BOOLEAN
P5SelectDaisyChainDevice(
IN PUCHAR Controller,
IN UCHAR DeviceId
)
{
const ULONG maxRetries = 4;
ULONG retryCount = 0;
BOOLEAN selected = FALSE;
DD(NULL,DDE,"P5SelectDaisyChainDevice %x %d\n",Controller,DeviceId);
while( !selected && retryCount < maxRetries ) {
selected = PptSend1284_3Command( Controller, (UCHAR)(CPP_SELECT | DeviceId) );
++retryCount;
}
return selected;
}
BOOLEAN
P5DeselectAllDaisyChainDevices(
IN PUCHAR Controller
)
{
const ULONG maxRetries = 4;
ULONG retryCount = 0;
BOOLEAN deselected = FALSE;
DD(NULL,DDE,"P5DeselectAllDaisyChainDevices %x\n",Controller);
while( !deselected && retryCount < maxRetries ) {
deselected = PptSend1284_3Command( Controller, (UCHAR)CPP_DESELECT );
++retryCount;
}
return deselected;
}
VOID
P5DeletePdoSymLink(
IN PDEVICE_OBJECT Pdo
)
//
// clean up symbolic link so we can reuse it immediately for a new PDO
//
{
PPDO_EXTENSION pdx = Pdo->DeviceExtension;
if( pdx->SymLinkName ) {
UNICODE_STRING uniSymLinkName;
NTSTATUS status;
DD((PCE)pdx,DDE,"P5DeletePdoSymLink\n");
RtlInitUnicodeString( &uniSymLinkName, pdx->SymLinkName );
status = IoDeleteSymbolicLink( &uniSymLinkName );
PptAssert( STATUS_SUCCESS == status );
ExFreePool( pdx->SymLinkName );
pdx->SymLinkName = NULL;
}
return;
}
VOID
P5MarkPdoAsHardwareGone(
IN PDEVICE_OBJECT Fdo,
IN enum _PdoType PdoType,
IN ULONG DaisyChainId OPTIONAL // ignored if PdoType != PdoTypeDaisyChain
)
{
PFDO_EXTENSION fdx = Fdo->DeviceExtension;
PPDO_EXTENSION pdx;
PDEVICE_OBJECT pdo;
switch( PdoType ) {
case PdoTypeRawPort:
DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeRawPort\n");
pdo = fdx->RawPortPdo;
fdx->RawPortPdo = NULL;
break;
case PdoTypeEndOfChain:
DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeEndOfChain\n");
pdo = fdx->EndOfChainPdo;
fdx->EndOfChainPdo = NULL;
break;
case PdoTypeDaisyChain:
PptAssert( (0 == DaisyChainId) || (1 == DaisyChainId) );
DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeDaisyChain - %d\n",DaisyChainId);
pdo = fdx->DaisyChainPdo[ DaisyChainId ];
fdx->DaisyChainPdo[ DaisyChainId ] = NULL;
break;
case PdoTypeLegacyZip:
DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - PdoTypeLegacyZip\n");
pdo = fdx->LegacyZipPdo;
fdx->LegacyZipPdo = NULL;
break;
default:
DD((PCE)fdx,DDE,"P5MarkPdoAsHardwareGone - Invalid PdoType parameter\n",FALSE);
PptAssertMsg("P5MarkPdoAsHardwareGone - Invalid PdoType parameter",FALSE);
return;
}
pdx = pdo->DeviceExtension;
P5DeletePdoSymLink( pdo );
InsertTailList( &fdx->DevDeletionListHead, &pdx->DevDeletionList );
pdx->DeleteOnRemoveOk = TRUE;
return;
}
BOOLEAN
P5IsDeviceStillThere(
IN PDEVICE_OBJECT Fdo,
IN PDEVICE_OBJECT Pdo
)
//
// Is the Pdo device still connected to the port represented by the Fdo?
//
// N.B. Fdo must own (have locked for exclusive access) the port before calling this function
// or we can corrupt the data stream and hang devices connected to the port
//
{
PFDO_EXTENSION fdx = Fdo->DeviceExtension;
PPDO_EXTENSION pdx = Pdo->DeviceExtension;
BOOLEAN deviceStillThere = FALSE;
PCHAR devIdString = NULL;
PUCHAR controller = fdx->PortInfo.Controller;
PptAssert( DevTypeFdo == fdx->DevType );
PptAssert( DevTypePdo == pdx->DevType );
//
// Select device if needed, pull a fresh 1284 device ID string
// from the device, and compare the Mfg and Mdl from the fresh
// device ID with those stored in our extension. If the Mfg and
// Mdl fields match then the device is still there.
//
switch( pdx->PdoType ) {
case PdoTypeRawPort:
// raw port is always present - it's a virtual device
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeRawPort - StillThere\n");
deviceStillThere = TRUE;
break;
case PdoTypeLegacyZip:
deviceStillThere = P5LegacyZipDetected( fdx->PortInfo.Controller );
if( deviceStillThere ) {
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeLegacyZip - StillThere\n");
} else {
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeLegacyZip - Gone\n");
}
break;
case PdoTypeDaisyChain:
//
// Select device, pull a fresh 1284 device ID string
// from the device, and compare the Mfg and Mdl from the fresh
// device ID with those stored in our extension. If the Mfg and
// Mdl fields match then the device is still there.
//
{
UCHAR daisyChainId = pdx->Ieee1284_3DeviceId;
// select device
if( P5SelectDaisyChainDevice( controller, daisyChainId ) ) {
BOOLEAN bBuildStlDeviceId = FALSE;
PPDO_EXTENSION dummyPdx = NULL;
devIdString = NULL;
// do a check to see if this is an SCM Micro device
dummyPdx = ExAllocatePool( PagedPool, sizeof(PDO_EXTENSION) );
if( dummyPdx != NULL ) {
RtlZeroMemory( dummyPdx, sizeof(PDO_EXTENSION) );
dummyPdx->Controller = fdx->PortInfo.Controller;
bBuildStlDeviceId = ParStlCheckIfStl( dummyPdx, daisyChainId );
if( bBuildStlDeviceId ) {
// SCM Micro device
ULONG DeviceIdSize;
devIdString = ParStlQueryStlDeviceId( dummyPdx, NULL, 0,&DeviceIdSize, TRUE );
} else {
// non-SCM Micro device
devIdString = P4ReadRawIeee1284DeviceId( controller );
}
ExFreePool( dummyPdx );
}
if( devIdString ) {
// got a 1284 device ID string from the device
PCHAR mfg, mdl, cls, des, aid, cid;
ParPnpFindDeviceIdKeys( &mfg, &mdl, &cls, &des, &aid, &cid, devIdString+2 );
if( mfg && mdl ) {
// we have a device, is it the same device?
if( (0 == strcmp( mfg, pdx->Mfg )) && (0 == strcmp( mdl, pdx->Mdl )) ) {
// same device
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - StillThere\n",daisyChainId);
deviceStillThere = TRUE;
} else {
// different device - IDs don't match
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - diff 1284 ID\n",daisyChainId);
deviceStillThere = FALSE;
}
} else {
// either mfg or mdl field not found
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - bad 1284 ID\n",daisyChainId);
deviceStillThere = FALSE;
}
// don't forget to free temp pool
ExFreePool( devIdString );
} else {
// unable to get a 1284 device ID string from the device
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - no 1284 ID\n",daisyChainId);
deviceStillThere = FALSE;
}
// don't forget to deselect device
P5DeselectAllDaisyChainDevices( controller );
} else {
// unable to select device
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeDaisyChain %d - Gone - unable to select\n",daisyChainId);
deviceStillThere = FALSE;
}
} // end new scope for case PdoTypeDaisyChain
break;
case PdoTypeEndOfChain:
//
// Pull a fresh 1284 device ID string from the device, and
// compare the Mfg and Mdl from the fresh device ID with
// those stored in our extension. If the Mfg and Mdl
// fields match then the device is still there.
//
{
ULONG tryNumber = 0;
const ULONG maxTries = 5; // arbitrary number
do {
++tryNumber;
devIdString = P4ReadRawIeee1284DeviceId( controller );
if( devIdString ) {
PCHAR mfg, mdl, cls, des, aid, cid;
ParPnpFindDeviceIdKeys( &mfg, &mdl, &cls, &des, &aid, &cid, devIdString+2 );
if( mfg && mdl ) {
// we have a device, is it the same device?
if( (0 == strcmp( mfg, pdx->Mfg )) && (0 == strcmp( mdl, pdx->Mdl )) ) {
// same device
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - StillThere\n");
deviceStillThere = TRUE;
} else {
// different device - IDs don't match
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - Gone - diff 1284 ID\n");
deviceStillThere = FALSE;
}
} else {
// either mfg or mdl field not found
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - Gone - bad 1284 ID\n");
deviceStillThere = FALSE;
}
// don't forget to free temp pool
ExFreePool( devIdString );
} else {
// unable to get a 1284 device ID string from the device
DD((PCE)pdx,DDE,"P5IsDeviceStillThere - PdoTypeEndOfChain - Gone - no 1284 ID\n");
deviceStillThere = FALSE;
}
if( (FALSE == deviceStillThere ) && (PASSIVE_LEVEL == KeGetCurrentIrql()) ) {
LARGE_INTEGER delay;
delay.QuadPart = - 10 * 1000 * 120; // 120 ms - 3x the usual arbitrary delay
KeDelayExecutionThread( KernelMode, FALSE, &delay);
}
} while( (FALSE == deviceStillThere) && (tryNumber < maxTries) );
}
break;
default:
PptAssertMsg("P5IsDeviceStillThere - invalid PdoType",FALSE);
DD((PCE)Fdo,DDE,"P5IsDeviceStillThere - invalid PdoType\n");
deviceStillThere = TRUE; // don't know what to do here - so, guess
}
return deviceStillThere;
}
NTSTATUS
PptAcquirePortViaIoctl(
IN PDEVICE_OBJECT PortDeviceObject,
IN PLARGE_INTEGER Timeout OPTIONAL
)
/*++dvdf
Routine Description:
This routine acquires the specified parallel port from the parallel
port arbiter ParPort via an IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE.
Arguments:
PortDeviceObject - points to the ParPort device to be acquired
Return Value:
STATUS_SUCCESS - if the port was successfully acquired
!STATUS_SUCCESS - otherwise
--*/
{
LARGE_INTEGER localTimeout;
if( Timeout ) {
localTimeout = *Timeout; // caller specified
} else {
localTimeout = AcquirePortTimeout; // driver global variable default
}
return ParBuildSendInternalIoctl(IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE,
PortDeviceObject, NULL, 0, NULL, 0, &localTimeout);
}
NTSTATUS
PptReleasePortViaIoctl(
IN PDEVICE_OBJECT PortDeviceObject
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -