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

📄 usb.c

📁 usb to rs232 虚拟RS232串口驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
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;

    USB2COM_KdPrint( DBGLVL_MAXIMUM,("enter USB2COM_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;
    }

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

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

    //
    // pass the URB to the USB driver stack
    //
    nextStack->Parameters.Others.Argument1 = Urb;

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

    USB2COM_KdPrint( DBGLVL_MAXIMUM,("USB2COM_CallUSBD() return from IoCallDriver USBD %x\n", ntStatus));

    if (ntStatus == STATUS_PENDING) {

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

    } else {
        ioStatus.Status = ntStatus;
    }

    USB2COM_KdPrint( DBGLVL_MAXIMUM,("USB2COM_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;

    USB2COM_KdPrintCond( DBGLVL_MAXIMUM, !NT_SUCCESS( ntStatus ), ("exit USB2COM_CallUSBD FAILED (%x)\n", ntStatus));

    return ntStatus;
}

NTSTATUS
UsbDoControlTransfer(
	IN PDEVICE_OBJECT DeviceObject,
	IN USHORT  Function,
	IN ULONG TransferFlags,
	IN UCHAR  bRequest,
  	IN USHORT  wValue,
   	IN USHORT  wIndex,
   	IN USHORT wLength,
	IN PVOID UserBuffer,
	ULONG *UserBufferSize)
{
	ULONG		InputBufferSize;
	NTSTATUS	status = STATUS_SUCCESS;
	USHORT		UrbSize;
	PURB		urb;
	ULONG 		nRetries = 3;

    	USB2COM_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)USB2COM_ExAllocatePool(NonPagedPool, UrbSize);
	if( urb == NULL)
	{
		USB2COM_KdPrint( DBGLVL_HIGH,("No URB memory %d\n",UrbSize));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	// Build Do Control transfer request
	UsbBuildVendorRequest(
		urb,
		Function,
		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. 
	    	bRequest,
    		wValue,
    		wIndex,
    		UserBuffer,
    		NULL,
    		wLength,
    		NULL
    	);
		// Call the USB driver
	status = USB2COM_CallUSBD(DeviceObject, urb);
	// Check statuses
	if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
	{
		USB2COM_KdPrint(
			DBGLVL_HIGH,
			("status %x URB status %x\n", status, urb->UrbHeader.Status)
			);
		status = STATUS_UNSUCCESSFUL;
	}

	*UserBufferSize = urb->UrbControlVendorClassRequest.TransferBufferLength;
	USB2COM_KdPrint(
		DBGLVL_MEDIUM,
		("TransferBufferLength = %d\n",
		*UserBufferSize)
		);
		

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

	return status;
}

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

    USB2COM_KdPrint( DBGLVL_HIGH,("enter USB2COM_ConfigureDevice\n"));

    deviceExtension = DeviceObject->DeviceExtension;

	USB2COM_ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL );

    urb = USB2COM_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 = USB2COM_ExAllocatePool(NonPagedPool, siz);

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

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

	} // end, while (retry loop )

    USB2COM_ExFreePool(urb);
	USB2COM_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 = USB2COM_SelectInterface(DeviceObject,
        deviceExtension->UsbConfigurationDescriptor);


    USB2COM_KdPrint( DBGLVL_HIGH,("exit USB2COM_ConfigureDevice (%x)\n", ntStatus));

    return ntStatus;
} 


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

    USB2COM_KdPrint( DBGLVL_MEDIUM,("enter USB2COM_SelectInterface\n"));

    deviceExtension = DeviceObject->DeviceExtension;


    USB2COM_KdPrint( DBGLVL_HIGH,("USB2COM_SelectInterface() called with NULL Interface\n"));

⌨️ 快捷键说明

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