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

📄 usbios.c

📁 如题:POLAR LPC23XX-EK_DEMO software_Keil
💻 C
📖 第 1 页 / 共 3 页
字号:

                }

            }

        }
#endif
        if (Extension->CharsInInterruptBuffer <
            Extension->BufferSize) {

            *Extension->CurrentCharSlot = CharToPut;
            Extension->CharsInInterruptBuffer++;

            //
            // If we've become 80% full on this character
            // and this is an interesting event, note it.
            //

            if (Extension->CharsInInterruptBuffer ==
                Extension->BufferSizePt8) {

				// To remember not to submit the next read URB when back in
				// read interrupt routine.
				DbgPrint("80% full reached\n");
				Extension->ToSubmitReadUrb = FALSE;
				Extension->NoReadUrb = TRUE;


                if (Extension->IsrWaitMask &
                    SERIAL_EV_RX80FULL) {

                    Extension->HistoryMask |= SERIAL_EV_RX80FULL;

                    if (Extension->IrpMaskLocation) {

                        *Extension->IrpMaskLocation =
                         Extension->HistoryMask;
                        Extension->IrpMaskLocation = NULL;
                        Extension->HistoryMask = 0;

                        Extension->CurrentWaitIrp->
                            IoStatus.Information = sizeof(ULONG);
                        SerialInsertQueueDpc(
                            &Extension->CommWaitDpc,
                            NULL,
                            NULL,
                            Extension
                            );

                    }

                }

            }

            //
            // Point to the next available space
            // for a received character.  Make sure
            // that we wrap around to the beginning
            // of the buffer if this last character
            // received was placed at the last slot
            // in the buffer.
            //

            if (Extension->CurrentCharSlot ==
                Extension->LastCharSlot) {

                Extension->CurrentCharSlot =
                    Extension->InterruptReadBuffer;

            } else {

                Extension->CurrentCharSlot++;

            }

        } else {

            //
            // We have a new character but no room for it.
            //
			DbgPrint("Buffer Overflow\n"); 

            Extension->PerfStats.BufferOverrunErrorCount++;
            Extension->WmiPerfData.BufferOverrunErrorCount++;
            Extension->ErrorWord |= SERIAL_ERROR_QUEUEOVERRUN;

            if (Extension->HandFlow.FlowReplace &
                SERIAL_ERROR_CHAR) {

                //
                // Place the error character into the last
                // valid place for a character.  Be careful!,
                // that place might not be the previous location!
                //

                if (Extension->CurrentCharSlot ==
                    Extension->InterruptReadBuffer) {

                    *(Extension->InterruptReadBuffer+
                      (Extension->BufferSize-1)) =
                      Extension->SpecialChars.ErrorChar;

                } else {

                    *(Extension->CurrentCharSlot-1) =
                     Extension->SpecialChars.ErrorChar;

                }

            }

            //
            // If the application has requested it, abort all reads
            // and writes on an error.
            //

            if (Extension->HandFlow.ControlHandShake &
                SERIAL_ERROR_ABORT) {

                SerialInsertQueueDpc(
                    &Extension->CommErrorDpc,
                    NULL,
                    NULL,
                    Extension
                    );

            }

        }

    }

}


NTSTATUS
StartInterruptUrb(
	PDEVICE_EXTENSION Extension
	)
{							// StartInterruptUrb

	// If the interrupt polling IRP is currently running, don't try to start
	// it again.
    USBD_PIPE_HANDLE PipeHandle;
	BOOLEAN startirp;
	KIRQL oldirql;
	PIRP Irp;
	PURB urb;
	PIO_STACK_LOCATION stack;

//	KeAcquireSpinLock(&Extension->polllock, &oldirql);
	if (Extension->pollpending)
		startirp = FALSE;
	else
		startirp = TRUE, Extension->pollpending = TRUE;
//	KeReleaseSpinLock(&Extension->polllock, oldirql);

	if (!startirp)
		return STATUS_DEVICE_BUSY;	// already pending

	Irp = Extension->PollingIrp;
	urb = Extension->PollingUrb;
    PipeHandle = Extension->UsbInterface->Pipes[Extension->InterruptPipe].PipeHandle;

	ASSERT(Irp && urb);

	// Acquire the remove lock so we can't remove the device while the IRP
	// is still active.
/*henry
	NTSTATUS status = IoAcquireRemoveLock(&Extension->RemoveLock, Irp);
	if (!NT_SUCCESS(status))
		{
		Extension->pollpending = 0;
		return status;
		}
*/
	// Initialize the URB we use for reading the interrupt pipe

	UsbBuildInterruptOrBulkTransferRequest(
		urb,
		sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER),
		PipeHandle,
		&Extension->intdata,
		NULL,
		4,
		USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
		NULL);

	// Install "OnInterrupt" as the completion routine for the polling IRP.
	
	IoSetCompletionRoutine(
		Irp,
		(PIO_COMPLETION_ROUTINE) OnInterrupt,
		Extension,
		TRUE,
		TRUE,
		TRUE);

	// Initialize the IRP for an internal control request

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

	// This IRP might have been cancelled the last time it was used, in which case
	// the cancel flag will still be on. Clear it to prevent USBD from thinking that it's
	// been cancelled again! A better way to do this would be to call IoReuseIrp,
	// but that function is not declared in WDM.H.

	Irp->Cancel = FALSE;

//	UsbCom_IncrementIoCount(Extension->DeviceObject); //henry

	return IoCallDriver(Extension->TopOfStackDeviceObject, Irp);
}							// StartInterruptUrb


NTSTATUS
OnInterrupt(
	PDEVICE_OBJECT junk,
	PIRP Irp,
	PDEVICE_EXTENSION Extension
	)
{							// OnInterrupt

	KIRQL oldirql;
//	KeAcquireSpinLock(&Extension->polllock, &oldirql);
	Extension->pollpending = FALSE;		// allow another poll to be started
//	PVOID powercontext = Extension->powercontext;
//	Extension->powercontext = NULL;
//	KeReleaseSpinLock(&Extension->polllock, oldirql);

	// If the poll completed successfully, do whatever it is we do when we
	// get an interrupt (in this sample, that's answering an IOCTL) and
	// reissue the read. We're trying to have a read outstanding on the
	// interrupt pipe all the time except when power is off.

	if (NT_SUCCESS(Irp->IoStatus.Status)) {		// device signalled an interrupt
		DbgPrint(" - Interrupt!\n");

		DbgPrint("Byte 1 = 0x%x\n", Extension->intdata[0]);
		DbgPrint("Byte 2 = 0x%x\n", Extension->intdata[1]);
		DbgPrint("Byte 3 = 0x%x\n", Extension->intdata[2]);
		DbgPrint("Byte 4 = 0x%x\n", Extension->intdata[3]);

		if (Extension->DeviceIsOpened == TRUE && 	// Ensure that device is opened.
			(Extension->intdata[2] == 0x60)) {
		
			SerialHandleModemUpdate(
				Extension,
				FALSE
				);

		}

		DbgPrint("Submitting the next interrupt URB\n");

		// Unless we're in the middle of a power-off sequence, reissue the
		// polling IRP. Normally, SaveContext would have tried to cancel the
		// IRP, and we won't get to this statement because STATUS_CANCELLED
		// will fail the NT_SUCCESS test. We don't have any guarantee that the
		// IRP will actually complete with STATUS_CANCELLED, though. Hence this test.
		
//		if (!powercontext)
			StartInterruptUrb(Extension); // issue next polling request
	}						// device signalled an interrupt
#if DBG	
	else {
		DbgPrint(" - Interrupt polling IRP %X failed - %X (USBD status %X)\n",
			Irp, Irp->IoStatus.Status, URB_STATUS(Extension->PollingUrb));
	}
#endif

//	UsbCom_DecrementIoCount(Extension->DeviceObject); //henry

	// If we cancelled the poll during a power-down sequence, notify our
	// power management code that it can continue.
/*
	if (powercontext)
		GenericSaveRestoreComplete(powercontext);

	IoReleaseRemoveLock(&Extension->RemoveLock, Irp); // balances acquisition in StartInterruptUrb
*/
	return STATUS_MORE_PROCESSING_REQUIRED;
}							// OnInterrupt


NTSTATUS
StartReadUrb(
	PDEVICE_EXTENSION Extension
	)
{							// StartInterruptUrb

	// If the interrupt polling IRP is currently running, don't try to start
	// it again.
    USBD_PIPE_HANDLE PipeHandle;
	BOOLEAN startirp;
	KIRQL oldirql;
	PIRP Irp;
	PURB urb;
	PIO_STACK_LOCATION stack;

//	KeAcquireSpinLock(&Extension->polllock, &oldirql);
	if (Extension->readpending)
		startirp = FALSE;
	else
		startirp = TRUE, Extension->readpending = TRUE;
//	KeReleaseSpinLock(&Extension->polllock, oldirql);

	if (!startirp)
		return STATUS_DEVICE_BUSY;	// already pending

	Irp = Extension->ReadingIrp;
	urb = Extension->ReadingUrb;
    PipeHandle = Extension->UsbInterface->Pipes[Extension->DataInPipe].PipeHandle;

	ASSERT(Irp && urb);

	// Acquire the remove lock so we can't remove the device while the IRP
	// is still active.
/*henry
	NTSTATUS status = IoAcquireRemoveLock(&Extension->RemoveLock, Irp);
	if (!NT_SUCCESS(status))
		{
		Extension->pollpending = 0;
		return status;
		}
*/
	// Initialize the URB we use for reading the interrupt pipe

	UsbBuildInterruptOrBulkTransferRequest(
		urb,
		sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER),
		PipeHandle,
		&Extension->ReadData,
		NULL,
		64,
		USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
		NULL);

	// Install "OnInterrupt" as the completion routine for the polling IRP.
	
	IoSetCompletionRoutine(
		Irp,
		(PIO_COMPLETION_ROUTINE) OnReadInterrupt,
		Extension,
		TRUE,
		TRUE,
		TRUE);

	// Initialize the IRP for an internal control request

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

	// This IRP might have been cancelled the last time it was used, in which case
	// the cancel flag will still be on. Clear it to prevent USBD from thinking that it's
	// been cancelled again! A better way to do this would be to call IoReuseIrp,
	// but that function is not declared in WDM.H.

	Irp->Cancel = FALSE;

//	UsbCom_IncrementIoCount(Extension->DeviceObject); //henry

	return IoCallDriver(Extension->TopOfStackDeviceObject, Irp);
}							// StartInterruptUrb


NTSTATUS
OnReadInterrupt(
	PDEVICE_OBJECT junk,
	PIRP Irp,
	PDEVICE_EXTENSION Extension
	)
{							// OnInterrupt
    PURB Urb;
	KIRQL oldirql;
//	KeAcquireSpinLock(&Extension->polllock, &oldirql);
	Extension->readpending = FALSE;		// allow another read to be started
//	PVOID powercontext = Extension->powercontext;
//	Extension->powercontext = NULL;
//	KeReleaseSpinLock(&Extension->polllock, oldirql);

	// If the poll completed successfully, do whatever it is we do when we
	// get an interrupt (in this sample, that's answering an IOCTL) and
	// reissue the read. We're trying to have a read outstanding on the
	// interrupt pipe all the time except when power is off.

    Urb = Extension->ReadingUrb;

    DbgPrint("ReadInterrupt_Routine: DO=%08x Irp=%08x TransferLength=%d, Urb Status=%x, Irp Status = %x\n",
        Extension->DeviceObject,
        Irp,
        Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
        Urb->UrbHeader.Status, 
        Irp->IoStatus.Status);

	if (NT_SUCCESS(Irp->IoStatus.Status)) {		// device signalled an interrupt

		if (Urb->UrbBulkOrInterruptTransfer.TransferBufferLength &&
			(Extension->DeviceIsOpened == TRUE)) {	// Ensure that device is opened.

            KeAcquireSpinLock(
                &Extension->IntBufferLock,
                &oldirql
                );

			TransferData(Extension, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);

			KeReleaseSpinLock(
                &Extension->IntBufferLock,
                oldirql
                );

		}

		// Unless we're in the middle of a power-off sequence, reissue the
		// polling IRP. Normally, SaveContext would have tried to cancel the
		// IRP, and we won't get to this statement because STATUS_CANCELLED
		// will fail the NT_SUCCESS test. We don't have any guarantee that the
		// IRP will actually complete with STATUS_CANCELLED, though. Hence this test.
		
//		if (!powercontext)
		if (Extension->ToSubmitReadUrb) {
			//DbgPrint("Submitting the next read URB\n");
			StartReadUrb(Extension); // issue next polling request
		}
	}						// device signalled an interrupt
#if DBG	
	else {
		DbgPrint(" - Read polling IRP %X failed - %X (USBD status %X)\n",
			Irp, Irp->IoStatus.Status, URB_STATUS(Extension->ReadingUrb));
	}
#endif

//	UsbCom_DecrementIoCount(Extension->DeviceObject); //henry

	// If we cancelled the poll during a power-down sequence, notify our
	// power management code that it can continue.
/*
	if (powercontext)
		GenericSaveRestoreComplete(powercontext);

	IoReleaseRemoveLock(&Extension->RemoveLock, Irp); // balances acquisition in StartInterruptUrb
*/
	return STATUS_MORE_PROCESSING_REQUIRED;
}							// OnInterrupt


NTSTATUS
StartWriteUrb(
	PDEVICE_EXTENSION Extension
	)
{							// StartInterruptUrb

	// If the interrupt polling IRP is currently running, don't try to start
	// it again.
    USBD_PIPE_HANDLE PipeHandle;
	BOOLEAN startirp;
	KIRQL oldirql;
	PIRP Irp;
	PURB urb;
	PIO_STACK_LOCATION stack;

//	DbgPrint("Enter StartWriteUrb()\n");

//	KeAcquireSpinLock(&Extension->polllock, &oldirql);
	if (Extension->writepending)
		startirp = FALSE;
	else
		startirp = TRUE, Extension->writepending = TRUE;
//	KeReleaseSpinLock(&Extension->polllock, oldirql);

	if (!startirp)
		return STATUS_DEVICE_BUSY;	// already pending

	Irp = Extension->WritingIrp;
	urb = Extension->WritingUrb;
    PipeHandle = Extension->UsbInterface->Pipes[Extension->DataOutPipe].PipeHandle;

	ASSERT(Irp && urb);

	// Acquire the remove lock so we can't remove the device while the IRP
	// is still active.
/*henry
	NTSTATUS status = IoAcquireRemoveLock(&Extension->RemoveLock, Irp);
	if (!NT_SUCCESS(status))
		{
		Extension->pollpending = 0;
		return status;
		}
*/
	// Initialize the URB we use for reading the interrupt pipe

	UsbBuildInterruptOrBulkTransferRequest(
		urb,
		sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER),
		PipeHandle,
		Extension->WriteCurrentChar,
		NULL,
		Extension->WriteSize,
		USBD_TRANSFER_DIRECTION_OUT,
		NULL);

	// Install "OnInterrupt" as the completion routine for the polling IRP.
	
	IoSetCompletionRoutine(
		Irp,
		(PIO_COMPLETION_ROUTINE) OnWriteInterrupt,
		Extension,
		TRUE,
		TRUE,
		TRUE);

	// Initialize the IRP for an internal control request

⌨️ 快捷键说明

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