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

📄 uscrusb.c

📁 usblsccid-0.9.2: ED1x Smart Card Reader Driver
💻 C
📖 第 1 页 / 共 4 页
字号:
{
    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_ResetParentPort\n"));

    deviceExtension = DeviceObject->DeviceExtension;

    //
    // issue a synchronous request
    //

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = IoBuildDeviceIoControlRequest(
                IOCTL_INTERNAL_USB_RESET_PORT,
                deviceExtension->TopOfStackDeviceObject,
                NULL,
                0,
                NULL,
                0,
                TRUE, // internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
                &event,
                &ioStatus);

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

    nextStack = IoGetNextIrpStackLocation(irp);
    USCR_ASSERT(nextStack != NULL);

    USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetParentPort() calling USBD enable port api\n"));

    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
                            irp);
                            
    USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetParentPort() return from IoCallDriver USBD %x\n", ntStatus));

    if (ntStatus == STATUS_PENDING) {

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

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

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

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

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

    return ntStatus;
}

NTSTATUS
USCR_USBIoctl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    Dispatch table handler for IRP_MJ_DEVICE_CONTROL; 
    Handle DeviceIoControl() calls  from User mode


Arguments:

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


Return Value:

    NT status code

--*/
{
    PIO_STACK_LOCATION irpStack;
    PVOID ioBuffer;
    ULONG inputBufferLength;
    ULONG outputBufferLength;
    PDEVICE_EXTENSION deviceExtension;
    ULONG ioControlCode;
    NTSTATUS ntStatus;
    ULONG length;
    PUCHAR pch;
    PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;

    USCR_KdPrint( DBGLVL_DEFAULT,("USCR_USBIoctl\n"));

   // USCR_IncrementIoCount(DeviceObject);

    //
    // Get a pointer to the current location in the Irp. This is where
    //     the function codes and parameters are located.
    //

    deviceExtension = DeviceObject->DeviceExtension;
    

    // Can't accept a new io request if:
    //  1) device is removed, 
    //  2) has never been started, 
    //  3) is stopped,
    //  4) has a remove request pending,
    //  5) has a stop device pending
    //if ( !USCR_CanAcceptIoRequests( DeviceObject ) ) {
    //    ntStatus = STATUS_DELETE_PENDING;
    //    Irp->IoStatus.Status = ntStatus;
    //    Irp->IoStatus.Information = 0;

    //   IoCompleteRequest( Irp, IO_NO_INCREMENT );

    //    USCR_DecrementIoCount(DeviceObject);                          
    //    return ntStatus;
    //}

    irpStack = IoGetCurrentIrpStackLocation (Irp);

    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    // get pointers and lengths of the caller's (user's) IO buffer
    ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;

    //
    // Handle Ioctls from User mode
    //

    switch (ioControlCode) {

    case IOCTL_USCR_RESET_PIPE:
        {
            PUSBD_PIPE_INFORMATION pipe;
                PFILE_OBJECT fileObject;

                    // get our context and see if it is a pipe
                fileObject = irpStack->FileObject;

                    pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext;    

                    if(pipe == NULL) {
                            // error, this is not a pipe
                    ntStatus =
                            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                    } else {            
                USCR_ResetPipe(DeviceObject, pipe );
            
                ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
            }
        }
        break;


     case IOCTL_USCR_GET_CONFIG_DESCRIPTOR:

        //
        // This api returns a copy of the configuration descriptor
        // and all endpoint/interface descriptors.
        //

        //
        // inputs  - none
        // outputs - configuration descriptor plus interface
        //          and endpoint descriptors
        //

        pch = (PUCHAR) ioBuffer;

        configurationDescriptor =
            deviceExtension->UsbConfigurationDescriptor;

        if (configurationDescriptor) {
            
            length = configurationDescriptor->wTotalLength;

            if (outputBufferLength >= length) {

                RtlCopyMemory(pch,
                              (PUCHAR) configurationDescriptor,
                              length);
                
                Irp->IoStatus.Information = length;
                
                ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
            }
            else {
        
                Irp->IoStatus.Information = 0;
    
                ntStatus = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
            }    
        }
        else {

            Irp->IoStatus.Information = 0;

            ntStatus = Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
        }

        break;



     case IOCTL_USCR_RESET_DEVICE:
        
                ntStatus = USCR_ResetDevice( DeviceObject );
        break;               

    default:

        ntStatus =
            Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
    }

    //IoCompleteRequest (Irp,
    //                   IO_NO_INCREMENT
    //                  );

    //USCR_DecrementIoCount(DeviceObject);                       

    return ntStatus;

}

NTSTATUS
UsbDoInterruptOrBulkTransfer(
	IN PDEVICE_OBJECT DeviceObject,
	IN USBD_PIPE_HANDLE PipeHandle,
	IN ULONG TransferFlags,
	IN PVOID UserBuffer,
	ULONG *UserBufferSize)
{
	ULONG		InputBufferSize;
	NTSTATUS	status = STATUS_SUCCESS;
	USHORT		UrbSize;
	PURB		urb;
	LARGE_INTEGER	StartTickCount;
	LARGE_INTEGER	TickCountNow;
	ULONG 		UnitsOf100ns;
	ULONG 		ticks;
	ULONG 		nRetries = 10000;

    	
    	USCR_KdPrint( DBGLVL_MEDIUM,("enter UsbDoInterruptOrBulkTransfer\n"));
	// Check we're selected
	if( PipeHandle == NULL)
		return STATUS_INVALID_HANDLE;

	// Check input parameters
	InputBufferSize = *UserBufferSize;
RetryCallUSBD:
	*UserBufferSize = 0;
	if( UserBuffer==NULL || InputBufferSize <= 0)
		return STATUS_INVALID_PARAMETER;

	// Allocate memory for URB
	UrbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
	urb = (PURB)USCR_ExAllocatePool(NonPagedPool, UrbSize);
	if( urb == NULL)
	{
		USCR_KdPrint( DBGLVL_HIGH,("No URB memory\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	// Remember when we started
	// Get start tick count and length of tick in 100ns units
	
	KeQueryTickCount( &StartTickCount);
	UnitsOf100ns = KeQueryTimeIncrement();
	USCR_KdPrint( DBGLVL_MEDIUM,("Time increment %d\n", UnitsOf100ns));

	USCR_KdPrint(DBGLVL_MEDIUM,("Request len=%d\n",InputBufferSize));
	// Build Do Bulk or Interrupt transfer request
	UsbBuildInterruptOrBulkTransferRequest(
		urb, UrbSize,
		PipeHandle,
		UserBuffer, NULL, InputBufferSize,
		TransferFlags,
		NULL);

		// Call the USB driver
	status = USCR_CallUSBD(DeviceObject, urb);
	// Check statuses
	if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
	{
		USCR_KdPrint(
			DBGLVL_HIGH,
			("status %x URB status %x\n", status, urb->UrbHeader.Status)
			);
		status = STATUS_UNSUCCESSFUL;
	}

	USCR_KdPrint(
		DBGLVL_MEDIUM,
		("TransferBufferLength = %d\n",
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
		);

	// Check for timeout
	
	KeQueryTickCount( &TickCountNow);
	ticks = (ULONG)(TickCountNow.QuadPart - StartTickCount.QuadPart);
	USCR_KdPrint(
		DBGLVL_MEDIUM,
		("Time elapsed: %d us\n",
		ticks*UnitsOf100ns/10)
		); 
		
	*UserBufferSize = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;

	if( NT_SUCCESS(status))
	{
		HEXDUMP((PUCHAR)UserBuffer,*UserBufferSize);
	}

    	if(USBD_STATUS_DEV_NOT_RESPONDING == urb->UrbHeader.Status ||
    		urb->UrbHeader.Status == 0x80000005)//for win2k
    	{
		USCR_ExFreePool(urb);
    		if( KeGetCurrentIrql() < DISPATCH_LEVEL ){
        		LARGE_INTEGER delay;
        		delay.QuadPart = - 10 * 1000 * 5; // 5 ms
        		KeDelayExecutionThread( KernelMode, TRUE, &delay );
        		USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding sleep 10 ms\n"));
    		}else{
         		USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding want sleep but KeGetCurrentIrql() >= DISPATCH_LEVEL\n"));
		}
		if(--nRetries)
    			goto RetryCallUSBD;
    	}else
    		USCR_ExFreePool(urb);
	USCR_KdPrint( DBGLVL_MEDIUM,("leave UsbDoInterruptOrBulkTransfer status=%x\n",status));

	return status;
}

NTSTATUS
UsbDoControlTransfer(
	IN PDEVICE_OBJECT DeviceObject,
	IN PSETUP_PACKET SetupPacket,
	IN ULONG TransferFlags,
	IN PVOID UserBuffer,
	ULONG *UserBufferSize)
{
	ULONG		InputBufferSize;
	NTSTATUS	status = STATUS_SUCCESS;
	USHORT		UrbSize;
	PURB		urb;
	LARGE_INTEGER	StartTickCount;
	LARGE_INTEGER	TickCountNow;
	ULONG 		UnitsOf100ns;
	ULONG 		ticks;
	ULONG 		nRetries = 1000000;

    	USCR_KdPrint( DBGLVL_MEDIUM,("enter UsbDoControlTransfer\n"));
	// Check input parameters
	InputBufferSize = *UserBufferSize;
RetryCallUSBD:
	*UserBufferSize = 0;
	if( UserBuffer==NULL)
		return STATUS_INVALID_PARAMETER;

	// Allocate memory for URB
	UrbSize = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
	urb = (PURB)USCR_ExAllocatePool(NonPagedPool, UrbSize);
	if( urb == NULL)
	{
		USCR_KdPrint( DBGLVL_HIGH,("No URB memory\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	// Remember when we started
	// Get start tick count and length of tick in 100ns units
	
	KeQueryTickCount( &StartTickCount);
	UnitsOf100ns = KeQueryTimeIncrement();
	//USCR_KdPrint( DBGLVL_MEDIUM,("Time increment %d\n", UnitsOf100ns));

	// Build Do Control transfer request
	UsbBuildVendorRequest(
		urb,
		URB_FUNCTION_CLASS_DEVICE,
		UrbSize, 
		TransferFlags,
		0,//Specifies a value, from 4 to 31 inclusive, 
		  //that becomes part of the request type code in the USB-defined setup packet. 
	    	SetupPacket->bRequest,
    		SetupPacket->wValue,
    		SetupPacket->wIndex,
    		UserBuffer,
    		NULL,
    		SetupPacket->wLength,
    		NULL
    	);
		// Call the USB driver
	status = USCR_CallUSBD(DeviceObject, urb);
	// Check statuses
	if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
	{
		USCR_KdPrint(
			DBGLVL_HIGH,
			("status %x URB status %x\n", status, urb->UrbHeader.Status)
			);
		status = STATUS_UNSUCCESSFUL;
	}

	USCR_KdPrint(
		DBGLVL_MEDIUM,
		("TransferBufferLength = %d\n",
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
		);

	// Check for timeout
	
	KeQueryTickCount( &TickCountNow);
	ticks = (ULONG)(TickCountNow.QuadPart - StartTickCount.QuadPart);
	//USCR_KdPrint(
	//	DBGLVL_MEDIUM,
	//	("Time elapsed: %d us\n",
	//	ticks*UnitsOf100ns/10)
	//	); 
		
	*UserBufferSize = urb->UrbControlVendorClassRequest.TransferBufferLength;

	if( NT_SUCCESS(status))
	{
		HEXDUMP((PUCHAR)UserBuffer,*UserBufferSize);
	}

    	if(USBD_STATUS_DEV_NOT_RESPONDING == urb->UrbHeader.Status ||
    		urb->UrbHeader.Status == 0x80000005)//for win2k
    	{
   		USCR_ExFreePool(urb);
    		if( KeGetCurrentIrql() < DISPATCH_LEVEL ){
        		LARGE_INTEGER delay;
        		delay.QuadPart = - 10 * 1000 * 5; // 5 ms
        		KeDelayExecutionThread( KernelMode, TRUE, &delay );
        		USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding sleep 10 ms\n"));
    		}else{
         		USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding want sleep but KeGetCurrentIrql() >= DISPATCH_LEVEL\n"));
				}
			if(--nRetries)
    			goto RetryCallUSBD;
    	}else
					USCR_ExFreePool(urb);
	USCR_KdPrint( DBGLVL_MEDIUM,("leave UsbDoControlTransfer status=%x\n",status));

	return status;
}

⌨️ 快捷键说明

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