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

📄 intrwr.c

📁 学习usb编程很好的例子 自己学习用的。
💻 C
📖 第 1 页 / 共 2 页
字号:
    //

    if(deviceExtension->SSEnable) {

        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent, 
                              Executive, 
                              KernelMode, 
                              FALSE, 
                              NULL);
    }

    if(fileObject && fileObject->FsContext) {

        pipeInformation = fileObject->FsContext;

        if(UsbdPipeTypeInterrupt != pipeInformation->PipeType) {
            
            KdPrint( ("Usbd pipe type is not int\n"));

            ntStatus = STATUS_INVALID_HANDLE;
            goto IntUsb_DispatchReadWrite_Exit;
        }
    }
    else {

        KdPrint( ("Invalid handle\n"));

        ntStatus = STATUS_INVALID_HANDLE;
        goto IntUsb_DispatchReadWrite_Exit;
    }

    rwContext = (PINTUSB_RW_CONTEXT)
                ExAllocatePool(NonPagedPool,
                               sizeof(INTUSB_RW_CONTEXT));

    if(rwContext == NULL) {
        
        KdPrint( ("Failed to alloc mem for rwContext\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        goto IntUsb_DispatchReadWrite_Exit;
    }

	// Get the length from the current Write Request
    if(Irp->AssociatedIrp.SystemBuffer) {

        Length = IrpStack->Parameters.Write.Length;
    }

    if(Length > INTUSB_TEST_BOARD_TRANSFER_BUFFER_SIZE) {

        KdPrint( ("Transfer length > buffer\n"));

        ntStatus = STATUS_INVALID_PARAMETER;

        ExFreePool(rwContext);

        goto IntUsb_DispatchReadWrite_Exit;
    }

    urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
    KdPrint( ("Write operation\n"));
    

    
    
    urb = ExAllocatePool(NonPagedPool,
                         sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));

    if(urb == NULL) {

        KdPrint( ("Failed to alloc mem for urb\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;

        ExFreePool(rwContext);
        
        goto IntUsb_DispatchReadWrite_Exit;
    }

    UsbBuildInterruptOrBulkTransferRequest(
                            urb,
                            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                            pipeInformation->PipeHandle,
                            Irp->AssociatedIrp.SystemBuffer,
                            NULL,
                            Length,
                            urbFlags,
                            NULL);

    //
    // set INTUSB_RW_CONTEXT parameters.
    //
    
    rwContext->Urb             = urb;
    rwContext->Length          = Length;
    rwContext->Numxfer         = 0;
    rwContext->DeviceExtension = deviceExtension;

    //
    // use the original read/write irp as an internal device control irp
    //

    nextStack = IoGetNextIrpStackLocation(Irp);
    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    nextStack->Parameters.Others.Argument1 = (PVOID) urb;
    nextStack->Parameters.DeviceIoControl.IoControlCode = 
                                             IOCTL_INTERNAL_USB_SUBMIT_URB;

    IoSetCompletionRoutine(Irp, 
                           (PIO_COMPLETION_ROUTINE)IntUsb_WriteCompletion,
                           rwContext,
                           TRUE,
                           TRUE,
                           TRUE);

    //
    // since we return STATUS_PENDING call IoMarkIrpPending.
    //

    IoMarkIrpPending(Irp);

    KdPrint( ("IntUsb_DispatchReadWrite::"));
    IntUsb_IoIncrement(deviceExtension);

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

    if(!NT_SUCCESS(ntStatus)) {

        KdPrint( ("IoCallDriver fails with status %X\n", ntStatus));

        //
        // if the device was removed, then the pipeInformation 
        // field is invalid.
        // similarly if the request was cancelled, then we need not
        // invoked reset pipe/device.
        //
        if((ntStatus != STATUS_CANCELLED) && 
           (ntStatus != STATUS_DEVICE_NOT_CONNECTED)) {
            
            ntStatus = IntUsb_ResetPipe(DeviceObject,
                                     pipeInformation);
    
            if(!NT_SUCCESS(ntStatus)) {

                KdPrint( ("IntUsb_ResetPipe failed\n"));

                ntStatus = IntUsb_ResetDevice(DeviceObject);
            }
        }
        else {

            KdPrint( ("ntStatus is STATUS_CANCELLED or "
                                 "STATUS_DEVICE_NOT_CONNECTED\n"));
        }
    }

    //
    // we return STATUS_PENDING and not the status returned by the lower layer.
    //
    return STATUS_PENDING;

IntUsb_DispatchReadWrite_Exit:

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

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    KdPrint( ("IntUsb_DispatchReadWrite - ends\n"));

    return ntStatus;
}

NTSTATUS
IntUsb_WriteCompletion(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp,
    IN PVOID          Context
    )
/*++
 
Routine Description:

    This is the completion routine for writes
    
Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet
    Context - context passed to the completion routine.

Return Value:

    NT status value

--*/
{
    ULONG               stageLength;
    NTSTATUS            ntStatus;
    PIO_STACK_LOCATION  nextStack;
    PINTUSB_RW_CONTEXT rwContext;

    //
    // initialize variables
    //
    rwContext = (PINTUSB_RW_CONTEXT) Context;
    ntStatus = Irp->IoStatus.Status;

    UNREFERENCED_PARAMETER(DeviceObject);
    KdPrint( ("IntUsb_WriteCompletion - begins\n"));

	//
    // successfully performed a transfer.
    //
    if(NT_SUCCESS(ntStatus)) 
		Irp->IoStatus.Information = rwContext->Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
	else
		KdPrint( ("ReadWriteCompletion - failed with status = %X\n", 
							ntStatus));
        
    if(rwContext) {

        //
        // dump rwContext
        //
        KdPrint( ("rwContext->Urb             = %X\n", 
                             rwContext->Urb));
        KdPrint( ("rwContext->Mdl             = %X\n", 
                             rwContext->Mdl));
        KdPrint( ("rwContext->Length          = %d\n", 
                             rwContext->Length));
        KdPrint( ("rwContext->Numxfer         = %d\n", 
                             rwContext->Numxfer));
        KdPrint( ("rwContext->DeviceExtension = %X\n", 
                             rwContext->DeviceExtension));

        KdPrint( ("IntUsb_ReadWriteCompletion::"));
        IntUsb_IoDecrement(rwContext->DeviceExtension);

        ExFreePool(rwContext->Urb);
        ExFreePool(rwContext);
    }

    KdPrint( ("IntUsb_WriteCompletion - ends\n"));

    return ntStatus;
}

NTSTATUS
IntUsb_DispatchRead(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++
 
Routine Description:

    Dispatch routine for read requests.
    
Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet

Return Value:

    NT status value

--*/
{
	NTSTATUS				status;
	PDEVICE_EXTENSION       deviceExtension;
	UCHAR					localBuffer[12];
	ULONG info = 0;


	KdPrint( ("IntUsb_DispatchRead - begins\n"));

	deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

	IntUsb_IoIncrement(deviceExtension);


	// If an interrupt request is already outstanding, use that interrupt to service
	// this IRP instead of waiting for another interrupt.
	// The deviceExtension variable numintsIN tracks the number of interrupts 
	// which have occurred but not been serviced.

	if (InterlockedDecrement(&deviceExtension->numintsIN) >= 0)
	{					
		// Exchange data between the Polling URB and the Servicing IRP
		RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&deviceExtension->intdataIN,deviceExtension->intdataLength);
		RtlZeroMemory(&deviceExtension->intdataIN, MAX_TRANSFER_SIZE);
		info  = deviceExtension->intdataLength;  // Length is always 12 bytes when successful
		       		
		status = STATUS_SUCCESS;
	}					
	else		// Pend this Read Request until an interrupt occurs
	{
		InterlockedIncrement(&deviceExtension->numintsIN);
		if(deviceExtension->NumCachedRequests <= 4)
			status = CacheReadRequest(deviceExtension, Irp, &deviceExtension->InterruptIrp);
		else
			status = STATUS_DEVICE_BUSY;
	}
	
	//IoCompleteRequest(Irp, IO_NO_INCREMENT);

    KdPrint( ("IntUsb_DispatchRead - ends\n"));
    IntUsb_IoDecrement(deviceExtension);


    return status == STATUS_PENDING ? status : CompleteRequest(Irp, status, info);;
}


PIRP UncacheReadRequest(
	PDEVICE_EXTENSION DeviceExtension, 
	PIRP* pIrp
	)
/*++
 
Routine Description:

    This routine will return a pointer to a Cached Read Request
	if such a request has been cached.

Arguments:

    deviceExtension - Pointer to the device Extension
    pIrp - Where to save pointer to uncached IRP
Return Value:

    None

--*/
{
	KIRQL oldirql;
	PIRP Irp;
	KeAcquireSpinLock(&(DeviceExtension->Cachelock), &oldirql);
	Irp = (PIRP) InterlockedExchangePointer(pIrp, NULL);
	if(Irp)
	{
		// If an IRP has been cached then a Cancel routine
		// has already been set, and this call to IoSetCancelRoutine
		// will return that Cancel routine. 
		if(IoSetCancelRoutine(Irp, NULL))
		{
			// Since we now know we have a Cached IRP we can
			// now retrieve it.
			RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
		}
		else
			Irp = NULL;
	}

	DeviceExtension->NumCachedRequests--;
	KeReleaseSpinLock(&(DeviceExtension->Cachelock), oldirql);
	return Irp;
}


NTSTATUS CacheReadRequest(
	PDEVICE_EXTENSION DeviceExtension, 
	PIRP Irp, 
	PIRP* pIrp
	)
/*++
 
Routine Description:

    This routine will cache a Read Request until it can
	be serviced by an interrupt in the OnInterruptIN routine.

Arguments:

    deviceExtension - Pointer to the device Extension
	Irp - IRP to cache
    pIrp - Where to save pointer to cached IRP

Return Value:

    NTSTATUS value.
www.
--*/
{						
	KIRQL oldirql;
	NTSTATUS status;
	PIO_STACK_LOCATION stack;
	PFILE_OBJECT fileObject;


	
	ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

	// Make sure there's an extra stack location for us to use

	if (Irp->CurrentLocation <= 1)
		return STATUS_INVALID_PARAMETER;	// no stack for us

	// Acquire a lock on cache access.

	KeAcquireSpinLock(&(DeviceExtension->Cachelock), &oldirql);

	
	if (*pIrp)
		status = STATUS_UNSUCCESSFUL;	// something already cached here
	else
		{						// try to cache IRP

		// Install a cancel routine

		IoSetCancelRoutine(Irp, OnCancelReadRequest);
		
		// Check to see if this Irp has already been cancelled

		if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
			status = STATUS_CANCELLED;	// already cancelled

		// Cache this IRP in our list of Pending Read Requests. 

		else
			{					// cache it
			IoMarkIrpPending(Irp);
			status = STATUS_PENDING;

			stack = IoGetCurrentIrpStackLocation(Irp);
			stack->Parameters.Others.Argument1 = (PVOID) pIrp;
			
			//Install a completion routine to nullify the cache pointer.

			IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnCompleteReadRequest, (PVOID) DeviceExtension, TRUE, TRUE, TRUE);
			IoSetNextIrpStackLocation(Irp);	// so our completion routine will get called
			fileObject = stack->FileObject;
			stack = IoGetCurrentIrpStackLocation(Irp);
			stack->DeviceObject = DeviceExtension->FunctionalDeviceObject;	// so CancelIrp can give us right ptr
			stack->FileObject = fileObject;	// for cleanup
			*pIrp = Irp;

			// Add this request to our list of Read Requests
 			InsertTailList(&DeviceExtension->Pending_IOCTL_READINT_List, &Irp->Tail.Overlay.ListEntry);
			DeviceExtension->NumCachedRequests++;
			}					// cache it
		}						// try to cache IRP
	
	KeReleaseSpinLock(&(DeviceExtension->Cachelock), oldirql);

	return status;
}							


//////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

NTSTATUS OnCompleteReadRequest(
	PDEVICE_OBJECT DeviceObject, 
	PIRP Irp, 
	PDEVICE_EXTENSION DeviceExtension
	)
/*++
 
Routine Description:

	This routine is called upon completion of an IRP associated
	with a Read Request.

Arguments:

    DeviceObject - pointer to device object
    Irp - IRP which has finished
    deviceExtension - Pointer to the device Extension
	
Return Value:

    NTSTATUS value.

--*/
{							
	KIRQL oldirql;
	PIRP* pIrp;

	KeAcquireSpinLock(&DeviceExtension->Cachelock, &oldirql);
	pIrp = (PIRP*) IoGetCurrentIrpStackLocation(Irp)->Parameters.Others.Argument1;
	if (*pIrp == Irp)
		*pIrp = NULL;
	KeReleaseSpinLock(&DeviceExtension->Cachelock, oldirql);
	return STATUS_SUCCESS;
}							



///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

VOID OnCancelReadRequest(
	PDEVICE_OBJECT DeviceObject, 
	PIRP Irp
	)
/*++
 
Routine Description:

	This routine is called upon cancellation of an IRP associated
	with a Read Request.

Arguments:

    DeviceObject - pointer to device object
    Irp - IRP which has been cancelled
    	
Return Value:

    NTSTATUS value.

--*/
{							
	PDEVICE_EXTENSION deviceExtension;
	KIRQL oldirql;
	
	oldirql= Irp->CancelIrql;
	IoReleaseCancelSpinLock(DISPATCH_LEVEL);

	deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

	// Remove this request to our list of Read Requests

	KeAcquireSpinLockAtDpcLevel(&deviceExtension->Cachelock);
	RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
	KeReleaseSpinLock(&deviceExtension->Cachelock, oldirql);

	// Complete the IRP

	Irp->IoStatus.Status = STATUS_CANCELLED;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
}				

⌨️ 快捷键说明

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