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

📄 usb.c

📁 微软的point of sale的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1999  Microsoft Corporation

Module Name:

    usb.c

Abstract: ESC/POS (serial) interface for USB Point-of-Sale devices

Author:

    ervinp

Environment:

    Kernel mode

Revision History:


--*/

#include <WDM.H>

#include <usbdi.h>
#include "usbdlib.h"
#include <usbioctl.h>

#include "escpos.h"
#include "debug.h"


NTSTATUS InitUSB(PARENTFDOEXT *parentFdoExt)
/*++

Routine Description:

    Intialize USB-related data

Arguments:

    parentFdoExt - device extension for targetted device object

Return Value:

    NT status code

--*/
{
	NTSTATUS status;

	status = GetDeviceDescriptor(parentFdoExt);
	if (NT_SUCCESS(status)){
		status = GetConfigDescriptor(parentFdoExt);
		if (NT_SUCCESS(status)){
			status = SelectConfiguration(parentFdoExt);
		}
	}

	return status;
}




NTSTATUS GetConfigDescriptor(PARENTFDOEXT *parentFdoExt)
/*++

Routine Description:

    Function retrieves the configuration descriptor from the device

Arguments:

    parentFdoExt - device extension for targetted device object

Return Value:

    NT status code

--*/
{
    URB urb = { 0 };
    USB_CONFIGURATION_DESCRIPTOR configDescBase = { 0 };
    NTSTATUS status;

    PAGED_CODE();

    /*
     *  Get the first part of the configuration descriptor.
     *  It will tell us the size of the full configuration descriptor, 
     *  including all the following interface descriptors, etc.
     */

    UsbBuildGetDescriptorRequest(&urb,
                                 (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                 USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                 0,
                                 0,
                                 (PVOID)&configDescBase,
                                 NULL,
                                 sizeof(USB_CONFIGURATION_DESCRIPTOR),
                                 NULL);

    status = SubmitUrb(parentFdoExt->topDevObj, &urb, TRUE, NULL, NULL);

    if (NT_SUCCESS(status)) {

        ULONG configDescLen = configDescBase.wTotalLength;
 
        /*
         *  Now allocate the right-sized buffer for the full configuration descriptor.
         */
        ASSERT(configDescLen < 0x1000);
        parentFdoExt->configDesc = ALLOCPOOL(NonPagedPool, configDescLen);
        if (parentFdoExt->configDesc) {

            RtlZeroMemory(parentFdoExt->configDesc, configDescLen);

            UsbBuildGetDescriptorRequest(&urb,
                                         (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                         USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                         0,
                                         0,
                                         parentFdoExt->configDesc,
                                         NULL,
                                         configDescLen,
                                         NULL);

            status = SubmitUrb(parentFdoExt->topDevObj, &urb, TRUE, NULL, NULL);

            if (NT_SUCCESS(status)) {
                DBGVERBOSE(("Got config desc @ %ph, len=%xh.", parentFdoExt->configDesc, urb.UrbControlDescriptorRequest.TransferBufferLength));
                ASSERT(urb.UrbControlDescriptorRequest.TransferBufferLength == configDescLen);
            }
        }
        else {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    ASSERT(NT_SUCCESS(status));
    return status;
}



NTSTATUS GetDeviceDescriptor(PARENTFDOEXT *parentFdoExt)
/*++

Routine Description:

    Function retrieves the device descriptor from the device

Arguments:

    parentFdoExt - device extension for targetted device object

Return Value:

    NT status code

--*/
{
    URB urb;
    NTSTATUS status;

    PAGED_CODE();

    RtlZeroMemory(&parentFdoExt->deviceDesc, sizeof(parentFdoExt->deviceDesc));

    UsbBuildGetDescriptorRequest(&urb,
                                 (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                 USB_DEVICE_DESCRIPTOR_TYPE,
                                 0,
                                 0,
                                 (PVOID)&parentFdoExt->deviceDesc,
                                 NULL,
                                 sizeof(parentFdoExt->deviceDesc),
                                 NULL);

    status = SubmitUrb(parentFdoExt->topDevObj, &urb, TRUE, NULL, NULL);

    if (NT_SUCCESS(status)){
        DBGVERBOSE(("Got device desc @ %ph, len=%xh (should be %xh).", (PVOID)&parentFdoExt->deviceDesc, urb.UrbControlDescriptorRequest.TransferBufferLength, sizeof(parentFdoExt->deviceDesc)));
    }

    ASSERT(NT_SUCCESS(status));
    return status;
}





NTSTATUS ReadPipe(	PARENTFDOEXT *parentFdoExt, 
			USBD_PIPE_HANDLE pipeHandle, 
			READPACKET *readPacket,
			BOOLEAN synchronous
			)
{
    PURB urb;
    NTSTATUS status;

    ASSERT(pipeHandle);
    DBGVERBOSE(("ReadPipe: dataLen=%xh, sync=%xh", readPacket->length, (ULONG)synchronous));

    urb = ALLOCPOOL(NonPagedPool, sizeof(URB));
    if (urb){
        RtlZeroMemory(urb, sizeof(URB));

        urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
        urb->UrbBulkOrInterruptTransfer.Hdr.Length = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
        urb->UrbBulkOrInterruptTransfer.PipeHandle = pipeHandle;
        urb->UrbBulkOrInterruptTransfer.TransferBufferLength = readPacket->length;
        urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
        urb->UrbBulkOrInterruptTransfer.TransferBuffer = readPacket->data;
        urb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN;
        urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;

        if (synchronous){
            /*
             *  Synchronous read.
             */
            status = SubmitUrb(parentFdoExt->topDevObj, urb, TRUE, NULL, 0);
            readPacket->length = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
            FREEPOOL(urb);
        }
        else {
            /*
             *  Asynchronous read.
             *  Completion routine will free URB.
             */
            IncrementPendingActionCount(parentFdoExt);
            readPacket->urb = urb;
            status = SubmitUrb(	parentFdoExt->topDevObj, 
					            urb, 
					            FALSE,					// asynchronous
					            ReadPipeCompletion,		// completion routine
					            readPacket				// completion context
					            );
        }
    }
    else {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return status;
}



NTSTATUS ReadPipeCompletion(IN PDEVICE_OBJECT devObj, IN PIRP irp, IN PVOID context)
{
    READPACKET *readPacket = (READPACKET *)context;
    NTSTATUS status = irp->IoStatus.Status;
    POSPDOEXT *pdoExt;
    KIRQL oldIrql;

    ASSERT(readPacket->signature == READPACKET_SIG);
    pdoExt = readPacket->context;


    /*
     *  Set the readPacket's length to the actual length returned by the device.
     */
    ASSERT(readPacket->urb->UrbBulkOrInterruptTransfer.TransferBufferLength <= readPacket->length);
    readPacket->length = readPacket->urb->UrbBulkOrInterruptTransfer.TransferBufferLength;

    DBGVERBOSE(("ReadPipeCompletion: irp=%ph, status=%xh, data=%ph, len=%xh, context=%ph.", irp, status, readPacket->data, readPacket->length, readPacket->context)); 

    FREEPOOL(readPacket->urb);
    readPacket->urb = BAD_POINTER;

    if (NT_SUCCESS(status)){

	    DBGSHOWBYTES("READ PIPE result", readPacket->data, readPacket->length);

	    if (pdoExt){

		    KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);

		    ASSERT(pdoExt->inputEndpointInfo.endpointIsBusy);
		    pdoExt->inputEndpointInfo.endpointIsBusy = FALSE;

		    /*
		     *  Queue this completed readPacket
		     */
		    ASSERT(readPacket->offset == 0);

		    /*
		     *  Do NOT queue empty readPackets.
		     */
            if(readPacket->length == 0)
                FreeReadPacket(readPacket);
            else {
                InsertTailList(&pdoExt->completedReadPacketsList, &readPacket->listEntry);
                pdoExt->totalQueuedReadDataLength += readPacket->length;
            }

		    KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

		    /*
		     *  Now try to satisfy pending read IRPs with the completed readPacket data.
		     */
		    SatisfyPendingReads(pdoExt);
	    }
	    else {
		    DBGVERBOSE(("Just debug testing -- not processing read result"));
		    FreeReadPacket(readPacket);
	    }
    }
    else {
	    FreeReadPacket(readPacket);
    }


    /*
     *  If there are more read IRPs pending, issue another read.
     */
    if (pdoExt){
	    BOOLEAN scheduleAnotherRead;

	    KeAcquireSpinLock(&pdoExt->devExtSpinLock, &oldIrql);
	    scheduleAnotherRead = !IsListEmpty(&pdoExt->pendingReadIrpsList);
	    KeReleaseSpinLock(&pdoExt->devExtSpinLock, oldIrql);

	    if (scheduleAnotherRead){
		    DBGVERBOSE(("ReadPipeCompletion: scheduling read workItem"));
		    ExQueueWorkItem(&pdoExt->readWorkItem, DelayedWorkQueue);
	    }
    }


    /*
     *  This IRP was allocated by SubmitUrb().  Free it here.
     *  Return STATUS_MORE_PROCESSING_REQUIRED so the kernel does not
     *  continue processing this IRP.
     */
    IoFreeIrp(irp);
    DecrementPendingActionCount(pdoExt->parentFdoExt);
    return STATUS_MORE_PROCESSING_REQUIRED;
}


NTSTATUS WritePipe(PARENTFDOEXT *parentFdoExt, USBD_PIPE_HANDLE pipeHandle, PUCHAR data, ULONG dataLen)
{
	URB urb;
	NTSTATUS status;

⌨️ 快捷键说明

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