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

📄 isousb.c

📁 Pc板与DNW的USB驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
        Urb->UrbHeader.Status, status, ioStatus.Status));

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

    ISOUSB_KdPrintCond( DBGLVL_MAXIMUM, !NT_SUCCESS( ntStatus ), ("exit IsoUsb_CallUSBD FAILED (%x)\n", ntStatus));

    return ntStatus;
}


NTSTATUS
IsoUsb_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;

    ISOUSB_KdPrint( DBGLVL_HIGH,("enter IsoUsb_ConfigureDevice\n"));

    deviceExtension = DeviceObject->DeviceExtension;

	ISOUSB_ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL );

    urb = 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) + 512;  

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

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

		if ( !deviceExtension->UsbConfigurationDescriptor ) {
		    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 = IsoUsb_CallUSBD(DeviceObject, urb);

		ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_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;
			ExFreePool(deviceExtension->UsbConfigurationDescriptor);
			deviceExtension->UsbConfigurationDescriptor = NULL;
		} else {
			break;  // we got it on the first try
		}

	} // end, while (retry loop )

    ExFreePool(urb);
	ISOUSB_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 = IsoUsb_SelectInterface(DeviceObject,
        deviceExtension->UsbConfigurationDescriptor);


    ISOUSB_KdPrint( DBGLVL_HIGH,("exit IsoUsb_ConfigureDevice (%x)\n", ntStatus));

    return ntStatus;
} 


NTSTATUS
IsoUsb_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;

    ISOUSB_KdPrint( DBGLVL_MEDIUM,("enter IsoUsb_SelectInterface\n"));

    deviceExtension = DeviceObject->DeviceExtension;


    ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_SelectInterface() called with NULL Interface\n"));
    //
    // IsoUsb 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 ) {

			ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_SelectInterface() ParseConfigurationDescriptorEx() failed\n  returning STATUS_INSUFFICIENT_RESOURCES\n"));
			ExFreePool(urb);
			return STATUS_INSUFFICIENT_RESOURCES;
		}

        Interface = &urb->UrbSelectConfiguration.Interface;


        // allocate space for an array of pipe information structs;
        //  in this basic sample, just used to track if opened/closed
        deviceExtension->PipeInfo = ExAllocatePool(
            NonPagedPool, 
            Interface->NumberOfPipes * sizeof ( ISOUSB_PIPEINFO ) );
    
        if ( !deviceExtension->PipeInfo ) {
		    return STATUS_INSUFFICIENT_RESOURCES;
        }

        RtlZeroMemory(deviceExtension->PipeInfo,
            Interface->NumberOfPipes * sizeof ( ISOUSB_PIPEINFO ) );

        pInf = (PUCHAR ) deviceExtension->PipeInfo;

        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;
            ( (PISOUSB_PIPEINFO) pInf)->fPipeOpened = FALSE;
            pInf += sizeof ( ISOUSB_PIPEINFO );
        }

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


        ntStatus = IsoUsb_CallUSBD(DeviceObject, urb);

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

    } else {
        ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_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 = 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
            //
            ISOUSB_KdPrint( DBGLVL_MEDIUM,("---------\n"));
            ISOUSB_KdPrint( DBGLVL_MEDIUM,("NumberOfPipes 0x%x\n", deviceExtension->UsbInterface->NumberOfPipes));
            ISOUSB_KdPrint( DBGLVL_MEDIUM,("Length 0x%x\n", deviceExtension->UsbInterface->Length));
            ISOUSB_KdPrint( DBGLVL_MEDIUM,("Alt Setting 0x%x\n", deviceExtension->UsbInterface->AlternateSetting));
            ISOUSB_KdPrint( DBGLVL_MEDIUM,("Interface Number 0x%x\n", deviceExtension->UsbInterface->InterfaceNumber));
            ISOUSB_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];

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

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

    if (urb) {
		// don't call the ISOUSB_ExFreePool since the buffer was 
		//  alloced by USBD_CreateConfigurationRequest, not ISOUSB_ExAllocatePool()
        ExFreePool(urb);
    }
    ISOUSB_KdPrint( DBGLVL_HIGH,("exit IsoUsb_SelectInterface (%x)\n", ntStatus));

    return ntStatus; 
}


NTSTATUS
IsoUsb_ResetPipe(
    IN PDEVICE_OBJECT DeviceObject,
    IN PUSBD_PIPE_INFORMATION Pipe,
    IN BOOLEAN IsoClearStall
    )
/*++

Routine Description:

    Reset a given USB pipe.
    
    NOTES:

    This will reset the host to Data0 and should also reset the device
    to Data0 for Bulk and Interrupt pipes.

    For Iso pipes this will set the virgin state of pipe so that ASAP
    transfers begin with the current bus frame instead of the next frame
    after the last transfer occurred.

Arguments:

Return Value:


--*/
{
    NTSTATUS ntStatus;
    PURB urb;

    ISOUSB_KdPrint ( DBGLVL_MEDIUM, (" Reset Pipe %x\n", Pipe));

    urb = 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 =
            Pipe->PipeHandle;

        ntStatus = IsoUsb_CallUSBD(DeviceObject, urb);

        ExFreePool(urb);

    } else {
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Memphis RESET_PIPE will send a Clear-Feature Endpoint Stall to
    // reset the data toggle of non-Iso pipes as part of a RESET_PIPE
    // request.  It does not do this for Iso pipes as Iso pipes do not use
    // the data toggle (all Iso packets are Data0).  However, we also use
    // the Clear-Feature Endpoint Stall request in our device firmware to
    // reset data buffer points inside the device so we explicitly send
    // this request to the device for Iso pipes if desired.
    //
    if (NT_SUCCESS(ntStatus) && IsoClearStall &&
        (Pipe->PipeType == UsbdPipeTypeIsochronous)) {
        
        urb = ExAllocatePool(NonPagedPool,
                             sizeof(struct _URB_CONTROL_FEATURE_REQUEST));

        if (urb) {

            UsbBuildFeatureRequest(urb,
                                   URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT,
                                   USB_FEATURE_ENDPOINT_STALL,
                                   Pipe->EndpointAddress,
                                   NULL);

            ntStatus = IsoUsb_CallUSBD(DeviceObject, urb);

            ExFreePool(urb);
        } else {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    return ntStatus;
}




LONG
IsoUsb_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;

    deviceExtension = DeviceObject->DeviceExtension;

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


    ISOUSB_KdPrint( DBGLVL_MAXIMUM,("IsoUsb_DecrementIoCount() Pending io count = %x\n", ioCount));
    ISOUSB_TrapCond( DBGLVL_HIGH,( 0 > ioCount ) );

    if (ioCount==1) {
        // trigger no pending io
        ISOUSB_KdPrint( DBGLVL_MAXIMUM,("IsoUsb_DecrementIoCount() setting NoPendingIoEvent\n"));

        KeSetEvent(&deviceExtension->NoPendingIoEvent,
                   1,
                   FALSE);
    }

    if (ioCount==0) {
        // trigger remove-device event
        ISOUSB_KdPrint( DBGLVL_HIGH,("IsoUsb_DecrementIoCount() setting RemoveEvent\n"));

        KeSetEvent(&deviceExtension->RemoveEvent,
                   1,
                   FALSE);
    }

    return ioCount;
}


VOID
IsoUsb_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;

    deviceExtension = DeviceObject->DeviceExtension;

    InterlockedIncrement(&deviceExtension->PendingIoCount);
#if DBG
    InterlockedIncrement(&gpDbg->PendingIoCount);
#endif
    ISOUSB_KdPrint( DBGLVL_MAXIMUM,("Exit IsoUsb_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
}


⌨️ 快捷键说明

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