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

📄 usb.c

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

    ASSERT(pipeHandle);
	DBGSHOWBYTES("WritePipe bytes:", data, dataLen);

    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 = dataLen;
    urb.UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
    urb.UrbBulkOrInterruptTransfer.TransferBuffer = data;
    urb.UrbBulkOrInterruptTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_OUT;
    urb.UrbBulkOrInterruptTransfer.UrbLink = NULL;

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

	return status;
}


NTSTATUS SubmitUrb( PDEVICE_OBJECT pdo, 
                    PURB urb, 
                    BOOLEAN synchronous, 
                    PVOID completionRoutine,
                    PVOID completionContext)
/*++

Routine Description:

    Send the URB to the USB device.
	If synchronous is TRUE, ignore the completion info and synchonize the IRP;
    otherwise, don't synchronize and set the provided completion routine for the IRP.

Arguments:

    
Return Value:

    NT status code

--*/
{
    PIRP irp;
    NTSTATUS status;


	/*
	 *  Allocate the IRP to send the buffer down the USB stack.
	 *
	 *  Don't use IoBuildDeviceIoControlRequest (because it queues
	 *  the IRP on the current thread's irp list and may
	 *  cause the calling process to hang if the IopCompleteRequest APC
	 *  does not fire and dequeue the IRP).
	 */
	irp = IoAllocateIrp(pdo->StackSize, FALSE);

    if (irp){
        PIO_STACK_LOCATION nextSp;

        #if STATUS_ENDPOINT
		DBGVERBOSE(("SubmitUrb: submitting URB %ph on IRP %ph (sync=%d)", urb, irp, synchronous));
        #endif

        nextSp = IoGetNextIrpStackLocation(irp);
		nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
		nextSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

		/*
		 *  Attach the URB to this IRP.
		 */
        nextSp->Parameters.Others.Argument1 = urb;

        if (synchronous){

            status = CallDriverSync(pdo, irp);

			IoFreeIrp(irp);
        }
        else {
            /*
             *  Caller's completion routine will free the irp 
             *  when it completes.
             */
            ASSERT(completionRoutine);
            ASSERT(completionContext);
            IoSetCompletionRoutine( irp, 
                                    completionRoutine, 
                                    completionContext,
                                    TRUE, TRUE, TRUE);
            status = IoCallDriver(pdo, irp);
        }
    }
    else {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

    return status;
}




NTSTATUS SelectConfiguration(PARENTFDOEXT *parentFdoExt)
{
	USBD_INTERFACE_LIST_ENTRY interfaceList[2];
	NTSTATUS status;
	
	/*
	 *  We only look at vendor-class interfaces
	 */
	// BUGBUG - limited to one interface
	interfaceList[0].InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
                parentFdoExt->configDesc,
                parentFdoExt->configDesc,
                -1,
                -1,
                USB_INTERFACE_CLASS_VENDOR,
                -1,
                -1);

	if (interfaceList[0].InterfaceDescriptor){
		PURB urb;

		interfaceList[1].InterfaceDescriptor = NULL;	

		urb = USBD_CreateConfigurationRequestEx(parentFdoExt->configDesc, &interfaceList[0]);
		if (urb){

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

            if (NT_SUCCESS(status)){
				PUSBD_INTERFACE_INFORMATION interfaceInfo;

				parentFdoExt->configHandle = urb->UrbSelectConfiguration.ConfigurationHandle;

				interfaceInfo = &urb->UrbSelectConfiguration.Interface;
				parentFdoExt->interfaceInfo = MemDup(interfaceInfo, interfaceInfo->Length);
				if (parentFdoExt->interfaceInfo){
                    DBGVERBOSE(("SelectConfiguration: got interfaceInfo @ %ph.", parentFdoExt->interfaceInfo));
				}
				else {
					status = STATUS_INSUFFICIENT_RESOURCES;
				}
			}
			else {
				DBGERR(("SelectConfiguration: URB failed w/ %xh.", status));
			}

			FREEPOOL(urb);
		}
		else {
			status = STATUS_INSUFFICIENT_RESOURCES;
		}
	}
	else {
		status = STATUS_DEVICE_DATA_ERROR;
	}


	return status;
}



NTSTATUS CreatePdoForEachEndpointPair(PARENTFDOEXT *parentFdoExt)
/*++

Routine Description:

    Walk the USB endpoints.
	For each input/output endpoint pair, create one PDO
	which will be exposed as a COM (serial) port interface.

	BUGBUG - right now, this only looks at the first interface 
			 (on the default confuguration)

Arguments:

    parentFdoExt - device extension for the targetted device object

Return Value:

    NT status code

--*/
{
    NTSTATUS status;
    ULONG maxPossiblePDOs, deviceRelationsSize;

    maxPossiblePDOs = (parentFdoExt->interfaceInfo->NumberOfPipes/2);
    deviceRelationsSize = sizeof(DEVICE_RELATIONS) + maxPossiblePDOs*sizeof(PDEVICE_OBJECT);
    parentFdoExt->deviceRelations = ALLOCPOOL(NonPagedPool, deviceRelationsSize);

    if (parentFdoExt->deviceRelations){
        ULONG inputPipeIndex = 0, outputPipeIndex = 0, statusPipeIndex = 0, comInterfaceIndex = 0;

        RtlZeroMemory(parentFdoExt->deviceRelations, deviceRelationsSize);

        status = STATUS_NO_MATCH;

        while (TRUE){
            UCHAR endPtAddr;
            USBD_PIPE_TYPE pipeType;

            #if STATUS_ENDPOINT
            /*
             *  In the case of Serial Emulation, the protocol is that all DATA endpoints
             *  will be of type BULK and all STATUS endpoints will be of type INTERRUPT.
             */
            if(parentFdoExt->posFlag & SERIAL_EMULATION) {
                while(inputPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes) {
                    endPtAddr = parentFdoExt->interfaceInfo->Pipes[inputPipeIndex].EndpointAddress;
                    pipeType = parentFdoExt->interfaceInfo->Pipes[inputPipeIndex].PipeType;
                    if((pipeType == UsbdPipeTypeBulk) && (endPtAddr & USB_ENDPOINT_DIRECTION_MASK)) 
                        break;
                    inputPipeIndex++;
                }
                while(outputPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes) {
                endPtAddr = parentFdoExt->interfaceInfo->Pipes[outputPipeIndex].EndpointAddress;
                    pipeType = parentFdoExt->interfaceInfo->Pipes[outputPipeIndex].PipeType;
                    if((pipeType == UsbdPipeTypeBulk) && !(endPtAddr & USB_ENDPOINT_DIRECTION_MASK))
	                    break;
                    outputPipeIndex++;
                }
                while(statusPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes) {
                    endPtAddr = parentFdoExt->interfaceInfo->Pipes[statusPipeIndex].EndpointAddress;
                    pipeType = parentFdoExt->interfaceInfo->Pipes[statusPipeIndex].PipeType;
                    if((pipeType == UsbdPipeTypeInterrupt) && (endPtAddr & USB_ENDPOINT_DIRECTION_MASK))
                        break;
                    statusPipeIndex++;
	            }
                if(!(statusPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes))
                    break;
            }
            else {
            #endif
                /*
                 *  No Serial Emulation required. Find only DATA endpoints
                 *  which can be of either type in this case.
                 */
                while(inputPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes) {
                    endPtAddr = parentFdoExt->interfaceInfo->Pipes[inputPipeIndex].EndpointAddress;
                    pipeType = parentFdoExt->interfaceInfo->Pipes[inputPipeIndex].PipeType;
                    if((pipeType == UsbdPipeTypeInterrupt) || (pipeType == UsbdPipeTypeBulk)) {
                        if(endPtAddr & USB_ENDPOINT_DIRECTION_MASK) {
	                        break;
                        }
                    }
                    inputPipeIndex++;
                }
                while(outputPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes) {
                    endPtAddr = parentFdoExt->interfaceInfo->Pipes[outputPipeIndex].EndpointAddress;
                    pipeType = parentFdoExt->interfaceInfo->Pipes[outputPipeIndex].PipeType;
                    if((pipeType == UsbdPipeTypeInterrupt) || (pipeType == UsbdPipeTypeBulk)) {
                        if(!(endPtAddr & USB_ENDPOINT_DIRECTION_MASK)) {
	                        break;
                        }
                    }
                    outputPipeIndex++;
                }
            #if STATUS_ENDPOINT
            }
            #endif

            if ((inputPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes) &&
	            (outputPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes)){

                /*
                 *  We've found a pair (in/out) of endpoints.
                 *  Create a PDO to represent a COM (serial) port interface on these endpoints.
                 */
                PUSBD_PIPE_INFORMATION inputPipeInfo = &parentFdoExt->interfaceInfo->Pipes[inputPipeIndex];
                PUSBD_PIPE_INFORMATION outputPipeInfo = &parentFdoExt->interfaceInfo->Pipes[outputPipeIndex];
                ENDPOINTINFO inputEndpointInfo, outputEndpointInfo, statusEndpointInfo;
                #if EPSON_PRINTER
                /*
                 *  On the EPSON printer, we want to talk to the endpoints size 0x40,
                 *  not the other pair with length 8.
                 */
                if ((inputPipeInfo->MaximumPacketSize == 8) && (outputPipeInfo->MaximumPacketSize == 8)){
                    inputPipeIndex++, outputPipeIndex++;
                    continue;
                }
                #endif

                inputEndpointInfo.pipeHandle = inputPipeInfo->PipeHandle;
                inputEndpointInfo.pipeLen = inputPipeInfo->MaximumPacketSize;
                inputEndpointInfo.endpointIsBusy = FALSE;

                outputEndpointInfo.pipeHandle = outputPipeInfo->PipeHandle;
                outputEndpointInfo.pipeLen = outputPipeInfo->MaximumPacketSize;
                outputEndpointInfo.endpointIsBusy = FALSE;

                #if STATUS_ENDPOINT
                if(parentFdoExt->posFlag & SERIAL_EMULATION) {
                    PUSBD_PIPE_INFORMATION statusPipeInfo = &parentFdoExt->interfaceInfo->Pipes[statusPipeIndex];
                    statusEndpointInfo.pipeHandle = statusPipeInfo->PipeHandle;
                    statusEndpointInfo.pipeLen = statusPipeInfo->MaximumPacketSize;
                    statusEndpointInfo.endpointIsBusy = FALSE;
                }
                #endif

                status = CreateCOMPdo(parentFdoExt, comInterfaceIndex++, &inputEndpointInfo, &outputEndpointInfo, &statusEndpointInfo);
                if (NT_SUCCESS(status)){
                    DBGVERBOSE(("CreatePdoForEachEndpointPair: created COMPdo with in/out len %xh/%xh.", inputEndpointInfo.pipeLen, outputEndpointInfo.pipeLen));
                    inputPipeIndex++, outputPipeIndex++, statusPipeIndex++; 
                }
                else {
                    DBGERR(("CreatePdoForEachEndpointPair: CreateCOMPdo failed with %xh.", status));
                    break;
                }
            }
            else {
                if((parentFdoExt->posFlag & ODD_ENDPOINT) && 
                   ((inputPipeIndex + outputPipeIndex) < (2 * parentFdoExt->interfaceInfo->NumberOfPipes))) {

                    /*
                     *  We've found an odd endpoint.
                     *  Create a PDO to represent a COM (serial) port interface on this endpoint.
                     */
                    PUSBD_PIPE_INFORMATION oddPipeInfo = &parentFdoExt->interfaceInfo->Pipes[MIN(inputPipeIndex, outputPipeIndex)];
                    ENDPOINTINFO oddEndpointInfo;

                    oddEndpointInfo.pipeHandle = oddPipeInfo->PipeHandle;
                    oddEndpointInfo.pipeLen = oddPipeInfo->MaximumPacketSize;
                    oddEndpointInfo.endpointIsBusy = FALSE;

                    if(inputPipeIndex < parentFdoExt->interfaceInfo->NumberOfPipes)
                        status = CreateCOMPdo(parentFdoExt, comInterfaceIndex++, &oddEndpointInfo, NULL, NULL);
                    else
                        status = CreateCOMPdo(parentFdoExt, comInterfaceIndex++, NULL, &oddEndpointInfo, NULL);

                    if (NT_SUCCESS(status)){
                        DBGVERBOSE(("CreatePdoForEachEndpointPair: created <odd> COMPdo with len %xh.", oddEndpointInfo.pipeLen));
                    }
                    else {
                        DBGERR(("CreatePdoForEachEndpointPair: CreateCOMPdo failed with %xh.", status));
                        break;
                    }
                }
                break;
            }
        }
    }
    else {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

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

⌨️ 快捷键说明

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