⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uscrusb.c

📁 usblsccid-0.9.2: ED1x Smart Card Reader Driver
💻 C
📖 第 1 页 / 共 4 页
字号:

    NT status code

--*/
{
    NTSTATUS ntStatus;
    PURB urb;
    PDEVICE_EXTENSION deviceExtension;

    deviceExtension = DeviceObject->DeviceExtension;

    USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetPipe() Reset Pipe %x\n", PipeInfo));

    urb = USCR_ExAllocatePool(NonPagedPool,
                         sizeof(struct _URB_PIPE_REQUEST));

    if (urb) {

        urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
        urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
        urb->UrbPipeRequest.PipeHandle =
            PipeInfo->PipeHandle;

        ntStatus = USCR_CallUSBD(DeviceObject, urb);

        USCR_ExFreePool(urb);

    } else {
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    if (!(NT_SUCCESS(ntStatus))) {
#if DBG
		if ( gpDbg )
			gpDbg->PipeErrorCount++;
#endif

        USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetPipe() FAILED, ntStatus =0x%x\n", ntStatus ));
    }
    else {
#if DBG
		if ( gpDbg )
			gpDbg->ResetPipeCount++;
#endif

        USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetPipe() SUCCESS, ntStatus =0x%x\n", ntStatus ));
    }

    return ntStatus;
}




LONG
USCR_DecrementIoCount(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

        We keep a pending IO count ( extension->PendingIoCount )  in the device extension.
        The first increment of this count is done on adding the device.
        Subsequently, the count is incremented for each new IRP received and
        decremented when each IRP is completed or passed on.

        Transition to 'one' therefore indicates no IO is pending and signals
        deviceExtension->NoPendingIoEvent. This is needed for processing
        IRP_MN_QUERY_REMOVE_DEVICE

        Transition to 'zero' signals an event ( deviceExtension->RemoveEvent )
        to enable device removal. This is used in processing for IRP_MN_REMOVE_DEVICE
 
Arguments:

        DeviceObject -- ptr to our FDO

Return Value:

        deviceExtension->PendingIoCount


--*/

{
    PDEVICE_EXTENSION deviceExtension;
    LONG ioCount;
    KIRQL             oldIrql;

    deviceExtension = DeviceObject->DeviceExtension;
	KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);

    ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
#if DBG
    InterlockedDecrement(&gpDbg->PendingIoCount);
#endif


    USCR_TrapCond( DBGLVL_HIGH,( 0 > ioCount ) );

    if (ioCount==1) {
        // trigger no pending io
        KeSetEvent(&deviceExtension->NoPendingIoEvent,
                   1,
                   FALSE);
      	//USCR_KdPrint( DBGLVL_DEFAULT,("Set NoPendingIoEvent\n"));

    }

    if (ioCount==0) {
        // trigger remove-device event
        KeSetEvent(&deviceExtension->RemoveEvent,
                   1,
                   FALSE);
    }
	KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);

    //USCR_KdPrint( DBGLVL_HIGH,("Exit USCR_DecrementIoCount() Pending io count = %x\n", ioCount));
    return ioCount;
}


VOID
USCR_IncrementIoCount(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

        We keep a pending IO count ( extension->PendingIoCount )  in the device extension.
        The first increment of this count is done on adding the device.
        Subsequently, the count is incremented for each new IRP received and
        decremented when each IRP is completed or passed on.

 
Arguments:

        DeviceObject -- ptr to our FDO

Return Value:

        None


--*/
{
    PDEVICE_EXTENSION deviceExtension;
    KIRQL             oldIrql;
    LONG ioCount;
    
    deviceExtension = DeviceObject->DeviceExtension;

    //USCR_KdPrint( DBGLVL_MAXIMUM,("Enter USCR_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));

    KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
    ioCount = InterlockedIncrement(&deviceExtension->PendingIoCount);
    //************************************************************
    //see uscrpnp.c line 273. yanglq 2005-6-25
    if(ioCount > 1)
    {
    	KeClearEvent(&deviceExtension->NoPendingIoEvent);
	//USCR_KdPrint( DBGLVL_DEFAULT,("Clear NoPendingIoEvent\n"));
    }
    //************************************************************
   
#if DBG
    InterlockedIncrement(&gpDbg->PendingIoCount);
#endif
    KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);

    //USCR_KdPrint( DBGLVL_HIGH,("Exit USCR_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
}



NTSTATUS
USCR_AbortPipes(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

	Called as part of sudden device removal handling.
    Cancels any pending transfers for all open pipes. 
	If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
	Also marks the pipe 'closed' in our saved  configuration info.

Arguments:

    Ptrs to our FDO

Return Value:

    NT status code

--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PURB urb;
    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
	ULONG i;

    PUSBD_INTERFACE_INFORMATION interface;

    interface = deviceExtension->UsbInterface;
    if(deviceExtension->OpenPipeCount)
    {
    	for (i=0; i<interface->NumberOfPipes; i++) {

			USCR_KdPrint( DBGLVL_HIGH,("USCR_AbortPipes() Aborting open  Pipe %d\n", i));

			urb = USCR_ExAllocatePool(NonPagedPool,
								 sizeof(struct _URB_PIPE_REQUEST));

			if (urb) {

				urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
				urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
				urb->UrbPipeRequest.PipeHandle =
					interface->Pipes[i].PipeHandle;

				ntStatus = USCR_CallUSBD(DeviceObject, urb);

				USCR_ExFreePool(urb);

			} else {
				ntStatus = STATUS_INSUFFICIENT_RESOURCES;
				USCR_KdPrint( DBGLVL_HIGH,("USCR_AbortPipes() FAILED urb alloc\n" ));
				break;
			}


			if (!(NT_SUCCESS(ntStatus))) {
				// if we failed, dump out
#if DBG
				if ( gpDbg )
					gpDbg->PipeErrorCount++;
#endif
				break;
			}
			else {
				deviceExtension->OpenPipeCount--;
#if DBG
				if ( gpDbg )
					gpDbg->AbortPipeCount++;
#endif


			}
		} // end, for all pipes
	}

    return ntStatus;
}


BOOLEAN
USCR_CanAcceptIoRequests(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

  Check device extension status flags; 

     Can't accept a new io request if device:
      1) is removed, 
      2) has never been started, 
      3) is stopped,
      4) has a remove request pending, or
      5) has a stop device pending


Arguments:

    DeviceObject - pointer to the device object for this instance of the 82930
                    device.


Return Value:

    return TRUE if can accept new io requests, else FALSE

--*/
{
    PDEVICE_EXTENSION deviceExtension;
	BOOLEAN fCan = FALSE;

    deviceExtension = DeviceObject->DeviceExtension;

	//flag set when processing IRP_MN_REMOVE_DEVICE
    if ( !deviceExtension->DeviceRemoved &&
		 // device must be started( enabled )
		 deviceExtension->DeviceStarted &&
 		 // flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE
		 !deviceExtension->RemoveDeviceRequested &&
		 // flag set when driver has answered success to IRP_MN_QUERY_STOP_DEVICE
		 !deviceExtension->StopDeviceRequested ){
			fCan = TRUE;
	}

    USCR_KdPrintCond( DBGLVL_MAXIMUM, !fCan, ("**** FALSE return from USCR_CanAcceptIoRequests()!\n"));

	return fCan;
}


NTSTATUS
USCR_ResetDevice(
    IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:
        Checks port status; if OK, return success and  do no more;
        If bad, attempt reset

Arguments:

    DeviceObject - pointer to the device object for this instance of the 82930
                    device.


Return Value:

    NT status code

--*/
{
    NTSTATUS ntStatus;
    ULONG portStatus;

    USCR_KdPrint(5,("Enter USCR_ResetDevice()\n"));
    
    //
    // Check the port state, if it is disabled we will need 
    // to re-enable it
    //
    ntStatus = USCR_GetPortStatus(DeviceObject, &portStatus);

    if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&
        portStatus & USBD_PORT_CONNECTED) {
        //
        // port is disabled, attempt reset
        //
                USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetDevice() will reset\n"));
        ntStatus = USCR_ResetParentPort(DeviceObject);
    }
        return ntStatus;
}



NTSTATUS
USCR_GetPortStatus(
    IN PDEVICE_OBJECT DeviceObject,
    IN PULONG PortStatus
    )
/*++

Routine Description:

    returns the port status for our device

Arguments:

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

--*/
{
    NTSTATUS ntStatus, status = STATUS_SUCCESS;
    PIRP irp;
    KEVENT event;
    IO_STATUS_BLOCK ioStatus;
    PIO_STACK_LOCATION nextStack;
    PDEVICE_EXTENSION deviceExtension;

    USCR_KdPrint( DBGLVL_DEFAULT,("enter USCR_GetPortStatus\n"));

    deviceExtension = DeviceObject->DeviceExtension;

    *PortStatus = 0;

    //
    // issue a synchronous request
    //

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    // IoBuildDeviceIoControlRequest allocates and sets up an IRP for a device control request
    irp = IoBuildDeviceIoControlRequest(
                IOCTL_INTERNAL_USB_GET_PORT_STATUS,
                deviceExtension->TopOfStackDeviceObject, //next-lower driver's device object, representing the target device.
                NULL, // no input or output buffers
                0,
                NULL,
                0,
                TRUE, // internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
                &event, // event to be signalled on completion ( we wait for it below )
                &ioStatus);

    //
    // Call the class driver to perform the operation.  If the returned status
    // is PENDING, wait for the request to complete.
    //

    // IoGetNextIrpStackLocation gives a higher level driver access to the next-lower 
    // driver's I/O stack location in an IRP so the caller can set it up for the lower driver.
    nextStack = IoGetNextIrpStackLocation(irp);
    USCR_ASSERT(nextStack != NULL);

    nextStack->Parameters.Others.Argument1 = PortStatus;

    USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() calling USBD port status api\n"));

    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
                            irp);

    USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() return from IoCallDriver USBD %x\n", ntStatus));

    if (ntStatus == STATUS_PENDING) {

        USCR_KdPrint( DBGLVL_DEFAULT,("Wait for single object\n"));

        status = KeWaitForSingleObject(
                       &event,
                       Suspended,
                       KernelMode,
                       FALSE,
                       NULL);

        USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() Wait for single object, returned %x\n", status));
        
    } else {
        ioStatus.Status = ntStatus;
    }

    USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() Port status = %x\n", *PortStatus));

    //
    // USBD maps the error code for us
    //
    ntStatus = ioStatus.Status;

    USCR_KdPrint( DBGLVL_DEFAULT,("Exit USCR_GetPortStatus (%x)\n", ntStatus));


    return ntStatus;
}


NTSTATUS
USCR_ResetParentPort(
    IN IN PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

    Reset the our parent port

Arguments:

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

--*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -