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

📄 uscrusb.c

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

        USCR_KdPrintCond( DBGLVL_DEFAULT,
                (!(NT_SUCCESS(ntStatus))),
                ("USCR_CreateDeviceObject() IoCreateDevice() FAILED\n"));

 
        if (!NT_SUCCESS(ntStatus))  {
             return ntStatus;
        }


        //default maximum transfer size per staged io request
        deviceExtension->MaximumTransferSize =  USCR_MAX_TRANSFER_SIZE ;

#if DBG
        // may be overridden in registry
        USCR_GetRegistryDword( USCR_REGISTRY_PARAMETERS_PATH,
                                         L"MaximumTransferSize",
                                         &(deviceExtension->MaximumTransferSize) );
#endif

        // Name buffer for our named Functional device object link
        // The name is generated based on the driver's class GUID
        RtlCopyMemory(deviceExtension->DeviceLinkNameBuffer,
                      deviceLinkUnicodeString.Buffer,
                      deviceLinkUnicodeString.Length);


        // this event is triggered when there is no pending io of any kind and device is removed
        KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent, FALSE);

        // this event is triggered when self-requested power irps complete
        KeInitializeEvent(&deviceExtension->SelfRequestedPowerIrpEvent, NotificationEvent, FALSE);

        // this event is triggered when there is no pending io  (pending io count == 1 )
        KeInitializeEvent(&deviceExtension->NoPendingIoEvent, NotificationEvent, FALSE);

	// spinlock used to protect inc/dec iocount logic
	KeInitializeSpinLock (&deviceExtension->IoCountSpinLock);

	//free buffer from unicode string we used to init interface
	RtlFreeUnicodeString(&deviceLinkUnicodeString );
	deviceExtension->UsbDeviceDescriptor = NULL;
        deviceExtension->UsbInterface = NULL;
        deviceExtension->UsbConfigurationDescriptor = NULL;
	
	InitializeSmartcardExtension(*DeviceObject);
	deviceExtension->bFileOpened = FALSE;
		
    }

    USCR_KdPrint( DBGLVL_DEFAULT,
    	("exiting USCR_CreateDeviceObject (%x) \n",ntStatus)
    	);
    return ntStatus;
}


NTSTATUS
USCR_CallUSBD(
    IN PDEVICE_OBJECT DeviceObject,
    IN PURB Urb
    )
/*++

Routine Description:

    Passes a URB to the USBD class driver
	The client device driver passes USB request block (URB) structures 
	to the class driver as a parameter in an IRP with Irp->MajorFunction
	set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location 
	Parameters.DeviceIoControl.IoControlCode field set to 
	IOCTL_INTERNAL_USB_SUBMIT_URB. 

Arguments:

    DeviceObject - pointer to the physical device object (PDO)

    Urb - pointer to an already-formatted Urb request block

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

--*/
{
    NTSTATUS ntStatus, status = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension;
    PIRP irp;
    KEVENT event;
    IO_STATUS_BLOCK ioStatus;
    PIO_STACK_LOCATION nextStack;
    USCR_KdPrint( DBGLVL_MAXIMUM,("enter USCR_CallUSBD\n"));

    deviceExtension = DeviceObject->DeviceExtension;

    //
    // issue a synchronous request
    //
    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = IoBuildDeviceIoControlRequest(
                IOCTL_INTERNAL_USB_SUBMIT_URB,
                deviceExtension->TopOfStackDeviceObject, //Points to the next-lower driver's device object
                NULL, // optional input bufer; none needed here
                0,	  // input buffer len if used
                NULL, // optional output bufer; none needed here
                0,    // output buffer len if used
                TRUE, // If InternalDeviceControl is TRUE the target driver's Dispatch
				      //  outine for IRP_MJ_INTERNAL_DEVICE_CONTROL or IRP_MJ_SCSI 
					  // is called; otherwise, the Dispatch routine for 
					  // IRP_MJ_DEVICE_CONTROL is called.
                &event,     // event to be signalled on completion
                &ioStatus);  // Specifies an I/O status block to be set when the request is completed the lower driver. 

    //
    // As an alternative, we could call KeDelayExecutionThread, wait for some
    // period of time, and try again....but we keep it simple for right now
    //
    if (!irp) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    //USCR_KdPrint(DBGLVL_DEFAULT,("irp=%p\n",irp));

    //
    // 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);

    //
    // pass the URB to the USB driver stack
    //
    nextStack->Parameters.Others.Argument1 = Urb;
    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);

    USCR_KdPrint( DBGLVL_MAXIMUM,("USCR_CallUSBD() return from IoCallDriver USBD %x\n", ntStatus));

    if (ntStatus == STATUS_PENDING) {
    	LARGE_INTEGER timeout;
	timeout.QuadPart = -USB_REQUEST_TIMEOUT;	
        status = KeWaitForSingleObject(
                       &event,
                       Executive,
                       KernelMode,
                       FALSE,
                       &timeout);
        if (status == STATUS_TIMEOUT) {
            ntStatus = STATUS_IO_TIMEOUT;

            // Cancel the Irp we just sent.
            //
            IoCancelIrp(irp);

            // And wait until the cancel completes
            //
            KeWaitForSingleObject(&event,Executive, KernelMode, FALSE,NULL);               
        }else
        	ntStatus = ioStatus.Status;
    } else {
        ioStatus.Status = ntStatus;
    }

    USCR_KdPrint( DBGLVL_MAXIMUM,("USCR_CallUSBD() URB status = %x status = %x irp status %x\n",
        Urb->UrbHeader.Status, status, ioStatus.Status));
    //
    // USBD maps the error code for us
    //
    //ntStatus = ioStatus.Status;

    USCR_KdPrintCond( DBGLVL_MAXIMUM, !NT_SUCCESS( ntStatus ), ("exit USCR_CallUSBD FAILED (%x)\n", ntStatus));

    return ntStatus;
}


NTSTATUS
USCR_ConfigureDevice(
    IN  PDEVICE_OBJECT DeviceObject
    )
/*++

Routine Description:

    Initializes a given instance of the device on the USB and
	selects and saves the configuration.

Arguments:

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


Return Value:

    NT status code

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

    USCR_KdPrint( DBGLVL_HIGH,("enter USCR_ConfigureDevice\n"));

    deviceExtension = DeviceObject->DeviceExtension;

	USCR_ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL );

    urb = USCR_ExAllocatePool(NonPagedPool,
                         sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
	if ( !urb )
		return STATUS_INSUFFICIENT_RESOURCES;

	// When USB_CONFIGURATION_DESCRIPTOR_TYPE is specified for DescriptorType
	// in a call to UsbBuildGetDescriptorRequest(),
	// all interface, endpoint, class-specific, and vendor-specific descriptors 
	// for the configuration also are retrieved. 
	// The caller must allocate a buffer large enough to hold all of this 
	// information or the data is truncated without error.
	// Therefore the 'siz' set below is just a 'good guess', and we may have to retry

    siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 128;  

	// We will break out of this 'retry loop' when UsbBuildGetDescriptorRequest()
	// has a big enough deviceExtension->UsbConfigurationDescriptor buffer not to truncate
	while( 1 ) {

		deviceExtension->UsbConfigurationDescriptor = USCR_ExAllocatePool(NonPagedPool, siz);

		if ( !deviceExtension->UsbConfigurationDescriptor ) {
		    USCR_ExFreePool(urb);
			return STATUS_INSUFFICIENT_RESOURCES;
		}

		UsbBuildGetDescriptorRequest(urb,
						(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
						USB_CONFIGURATION_DESCRIPTOR_TYPE,
						0,
						0,
						deviceExtension->UsbConfigurationDescriptor,
						NULL,
						siz,
						NULL);

		ntStatus = USCR_CallUSBD(DeviceObject, urb);

		USCR_KdPrint( DBGLVL_HIGH,("USCR_CallUSBD() Configuration Descriptor = %x, len %x\n",
						deviceExtension->UsbConfigurationDescriptor,
						urb->UrbControlDescriptorRequest.TransferBufferLength));
		//
		// if we got some data see if it was enough.
		// NOTE: we may get an error in URB because of buffer overrun
		if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&
				deviceExtension->UsbConfigurationDescriptor->wTotalLength > siz) {

			siz = deviceExtension->UsbConfigurationDescriptor->wTotalLength;
			USCR_ExFreePool(deviceExtension->UsbConfigurationDescriptor);
			deviceExtension->UsbConfigurationDescriptor = NULL;
		} else {
			break;  // we got it on the first try
		}

	} // end, while (retry loop )

    USCR_ExFreePool(urb);
	USCR_ASSERT( deviceExtension->UsbConfigurationDescriptor );

    //
    // We have the configuration descriptor for the configuration we want.
    // Now we issue the select configuration command to get
    // the  pipes associated with this configuration.
    //

    ntStatus = USCR_SelectInterface(DeviceObject,
        deviceExtension->UsbConfigurationDescriptor);


    USCR_KdPrint( DBGLVL_HIGH,("exit USCR_ConfigureDevice (%x)\n", ntStatus));

    return ntStatus;
} 


NTSTATUS
USCR_SelectInterface(
    IN PDEVICE_OBJECT DeviceObject,
    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
    )
/*++

Routine Description:

    Initializes an 82930 with (possibly) multiple interfaces;
	This minidriver only supports one interface (with multiple endpoints).

Arguments:

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

    ConfigurationDescriptor - pointer to the USB configuration
                    descriptor containing the interface and endpoint
                    descriptors.

Return Value:

    NT status code

--*/
{
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus;
    PURB urb = NULL;
    ULONG i;
    PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
	PUSBD_INTERFACE_INFORMATION Interface = NULL;
    USHORT siz;
    PUCHAR pInf;

    USCR_KdPrint( DBGLVL_MEDIUM,("enter USCR_SelectInterface\n"));

    deviceExtension = DeviceObject->DeviceExtension;


    USCR_KdPrint( DBGLVL_HIGH,("USCR_SelectInterface() called with NULL Interface\n"));
    //
    // USCR driver only supports one interface, we must parse
    // the configuration descriptor for the interface 
    // and remember the pipes.
    //

    urb = USBD_CreateConfigurationRequest(ConfigurationDescriptor, &siz);

    if (urb) {

		//
		// USBD_ParseConfigurationDescriptorEx searches a given configuration
		// descriptor and returns a pointer to an interface that matches the 
		//  given search criteria. We only support one interface on this device
		//
        interfaceDescriptor =
            USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
								  ConfigurationDescriptor, //search from start of config  descriptro
								  -1,	// interface number not a criteria; we only support one interface
								  -1,   // not interested in alternate setting here either
								  -1,   // interface class not a criteria
								  -1,   // interface subclass not a criteria
								  -1    // interface protocol not a criteria
								  );

		if ( !interfaceDescriptor ) {

			USCR_KdPrint( DBGLVL_HIGH,("USCR_SelectInterface() ParseConfigurationDescriptorEx() failed\n  returning STATUS_INSUFFICIENT_RESOURCES\n"));
			USCR_ExFreePool(urb);
			return STATUS_INSUFFICIENT_RESOURCES;
		}

        Interface = &urb->UrbSelectConfiguration.Interface;


        for (i=0; i< Interface->NumberOfPipes; i++) {
            //
            // Perform any pipe initialization here;
			// We set the max transfer size and any Pipe flags we use; USBD sets the rest
			// of the Interface struct members
            //
            Interface->Pipes[i].MaximumTransferSize = deviceExtension->MaximumTransferSize;
        }

        UsbBuildSelectConfigurationRequest(urb,
                                          (USHORT) siz,
                                          ConfigurationDescriptor);


        ntStatus = USCR_CallUSBD(DeviceObject, urb);

        deviceExtension->UsbConfigurationHandle =
            urb->UrbSelectConfiguration.ConfigurationHandle;

    } else {
        USCR_KdPrint( DBGLVL_HIGH,("USCR_SelectInterface() USBD_CreateConfigurationRequest() failed\n  returning STATUS_INSUFFICIENT_RESOURCES\n"));
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }


    if (NT_SUCCESS(ntStatus)) {

        //
        // Save the configuration handle for this device
        //

        deviceExtension->UsbConfigurationHandle =
            urb->UrbSelectConfiguration.ConfigurationHandle;

        deviceExtension->UsbInterface = USCR_ExAllocatePool(NonPagedPool,
                                                    Interface->Length);

        if (deviceExtension->UsbInterface) {
            ULONG j;

            //
            // save a copy of the interface information returned
            //
            RtlCopyMemory(deviceExtension->UsbInterface, Interface, Interface->Length);

            //
            // Dump the interface to the debugger
            //
            USCR_KdPrint( DBGLVL_MEDIUM,("---------\n"));
            USCR_KdPrint( DBGLVL_MEDIUM,("NumberOfPipes 0x%x\n", deviceExtension->UsbInterface->NumberOfPipes));
            USCR_KdPrint( DBGLVL_MEDIUM,("Length 0x%x\n", deviceExtension->UsbInterface->Length));
            USCR_KdPrint( DBGLVL_MEDIUM,("Alt Setting 0x%x\n", deviceExtension->UsbInterface->AlternateSetting));
            USCR_KdPrint( DBGLVL_MEDIUM,("Interface Number 0x%x\n", deviceExtension->UsbInterface->InterfaceNumber));
            USCR_KdPrint( DBGLVL_MEDIUM,("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
                deviceExtension->UsbInterface->Class,
                deviceExtension->UsbInterface->SubClass,
                deviceExtension->UsbInterface->Protocol));

            // Dump the pipe info

            for (j=0; j<Interface->NumberOfPipes; j++) {
                PUSBD_PIPE_INFORMATION pipeInformation;

                pipeInformation = &deviceExtension->UsbInterface->Pipes[j];

                USCR_KdPrint( DBGLVL_MEDIUM,("---------\n"));
                USCR_KdPrint( DBGLVL_MEDIUM,("PipeType 0x%x\n", pipeInformation->PipeType));
                USCR_KdPrint( DBGLVL_MEDIUM,("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
                USCR_KdPrint( DBGLVL_MEDIUM,("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
                USCR_KdPrint( DBGLVL_MEDIUM,("Interval 0x%x\n", pipeInformation->Interval));
                USCR_KdPrint( DBGLVL_MEDIUM,("Handle 0x%x\n", pipeInformation->PipeHandle));
                USCR_KdPrint( DBGLVL_MEDIUM,("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
            }

            USCR_KdPrint( DBGLVL_MEDIUM,("---------\n"));
        }
    }

    if (urb) {
		// don't call the USCR_ExFreePool since the buffer was 
		//  alloced by USBD_CreateConfigurationRequest, not USCR_ExAllocatePool()
        ExFreePool(urb);
    }
    USCR_KdPrint( DBGLVL_HIGH,("exit USCR_SelectInterface (%x)\n", ntStatus));

    return ntStatus; 
}



NTSTATUS
USCR_ResetPipe(
    IN PDEVICE_OBJECT DeviceObject,
    IN PUSBD_PIPE_INFORMATION PipeInfo
    )
/*++

Routine Description:

    Reset a given USB pipe.

    NOTES:

    This will reset the host to Data0 and should also reset the device to Data0 

Arguments:

    Ptrs to our FDO and a USBD_PIPE_INFORMATION struct

Return Value:

⌨️ 快捷键说明

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