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

📄 cusbintf.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::IsoTransferComplete
//
// This is a completion routine for asynchronous isochronous transfer requests.
// It calculates the size transfered, and then calls the user completion routine
//
NTSTATUS CUsbInterface::IsoTransferComplete(PIRP p_irp, PREAD_CONTEXT p_read_context)
{
    NTSTATUS status = STATUS_SUCCESS;
    struct _URB_ISOCH_TRANSFER	*pIso = (struct _URB_ISOCH_TRANSFER *)p_read_context->pUrb;

    //Get the total transfer size by adding the sizes of any individual packets
    ULONG transfer_size = 0;
    for(ULONG i = 0; i < pIso->NumberOfPackets; i++)
    {
        if (!NT_SUCCESS(pIso->IsoPacket[i].Status))
        {
            if((USBD_STATUS_XACT_ERROR != pIso->IsoPacket[i].Status) &&
               (USBD_STATUS_ISO_NOT_ACCESSED_BY_HW != pIso->IsoPacket[i].Status))
               {
                   status = pIso->IsoPacket[i].Status; // Send the result back to the caller
                   break;
               }
        }

        transfer_size += pIso->IsoPacket[i].Length;
    }

    p_irp->IoStatus.Information = transfer_size;


    //Call the user's completion routine
    if(p_read_context->pCompletion)
    {
        (*p_read_context->pCompletion)(
            p_read_context->UserContext, 
            status, 
            transfer_size,
            p_read_context);
    }

    //NOTE: Even though it would seem logical to return STATUS_SUCCESS at this point,
    //      there seems to be a bug in the W98 NTKERN where it will try to call
    //      IoCompleteRequest on the IRP after returning from here. Since I allocated
    //      the IRP and I need to free it, it makes no sense for NTKERN to do this.
    //      Returning STATUS_MORE_PROCESSING_REQUIRED prevents NTKERN from doing this.
    return (STATUS_MORE_PROCESSING_REQUIRED);	//Must return this or Windows will crash!
}



/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbReadComplete
//
//This is a completion routine for asynchronous bulk/interrupt transfer requests.
//
NTSTATUS CUsbInterface::UsbReadComplete(IRP* p_irp, PREAD_CONTEXT p_read_context)
{
    NTSTATUS status = STATUS_SUCCESS;
    struct _URB_BULK_OR_INTERRUPT_TRANSFER* p_bulk = (struct _URB_BULK_OR_INTERRUPT_TRANSFER *)p_read_context->pUrb;

    p_irp->IoStatus.Information = p_bulk->TransferBufferLength;
    ULONG transfer_size = p_bulk->TransferBufferLength;

    status = p_irp->IoStatus.Status; // Send the result back to the caller

    //Flag an error if we got a 'Device data error'
    if(STATUS_DEVICE_DATA_ERROR == status)
    {
        _error_occured = TRUE;
        DbgLogError(( "CUsbInterface::UsbReadComplete() : STATUS_DEVICE_DATA_ERROR\n"));
    }

    //Call the user's completion routine
    if(p_read_context->pCompletion)
    {
        (*p_read_context->pCompletion)(
            p_read_context->UserContext, 
            status, 
            transfer_size,
            p_read_context);
    }

    //NOTE: Even though it would seem logical to return STATUS_SUCCESS at this point,
    //      there seems to be a bug in the W98 NTKERN where it will try to call
    //      IoCompleteRequest on the IRP after returning from here. Since I allocated
    //      the IRP and I need to free it, it makes no sense for NTKERN to do this.
    //      Returning STATUS_MORE_PROCESSING_REQUIRED prevents NTKERN from doing this.
    return (STATUS_MORE_PROCESSING_REQUIRED);	//Must return this or Windows will crash!
}


/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbAsyncIo_ISO
//
// Send a URB to the device to perform an isochronous transfer.
//
// Parameters
//  pipe_number - USB pipe number to use for the transfer
//  interface_number - USB interface to use for the transfer
//  p_buffer - Buffer to receive the data from the transfer (Or containing data to send)
//  buffer_size - Size of the buffer in pBuff
//  p_read_context - User context - specifies the IRP, URB, and user completion routine
//
NTSTATUS CUsbInterface::UsbAsyncIo_ISO(DWORD pipe_number, 
                                       UCHAR interface_number,
                                       PBYTE p_buffer, 
                                       DWORD buffer_size, 
                                       PREAD_CONTEXT p_read_context)
{
    struct _URB_ISOCH_TRANSFER* p_iso = (struct _URB_ISOCH_TRANSFER *)p_read_context->pUrb;

    //Return immediately if an error occured previously.
    if (_error_occured)
    {
        DbgLogError(("CUsbInterface::UsbAsyncIo_ISO() : device IO error occured before, need to reset device!!"));

        NTSTATUS status = STATUS_SUCCESS;
        if(UsbGetStatusPipe(pipe_number, interface_number) != STATUS_SUCCESS)
        {
            // abort MPEG data pipe
            status = UsbAbortPipe(pipe_number,interface_number);      //PIPE_STREAMING
            if (!NT_SUCCESS(status))
            {
                 DbgLogError(("CUsbInterface::UsbAsyncIo_ISO, Failed to abort firmware download pipe %x\n", status));
            }

            // reset MPEG data pipe
            status = UsbResetPipe(pipe_number,interface_number);      //PIPE_STREAMING
            if (!NT_SUCCESS(status))
            {
                 DbgLogError(("CUsbInterface::UsbAsyncIo_ISO, Failed to reset firmware download pipe %x\n", status));
            }
        }
        if (!NT_SUCCESS(status))
        {
            return (STATUS_DEVICE_DATA_ERROR);
        }
    }
    
    //Get the pipe
    PUSBD_PIPE_INFORMATION p_pipe = getPipe(interface_number, pipe_number);
    if(!p_pipe)
    {
       DbgLogError(("CUsbInterface::UsbAsyncIo_ISO(): Invalid Interface Info"));
       return STATUS_UNSUCCESSFUL;
    }
    
    //Make sure the pipe type is isochronous
    if(UsbdPipeTypeIsochronous != p_pipe->PipeType)
    {
        DbgLogError(("CUsbInterface::UsbAsyncIo_ISO(): Invalid Pipe Type"));
        return STATUS_UNSUCCESSFUL;
    }

    //Make sure we have a handle to the pipe
    if(!p_pipe->PipeHandle)
    {
        DbgLogError(("CUsbInterface::UsbAsyncIo_ISO(): Invalid pipe handle or no memory"));
        return STATUS_UNSUCCESSFUL;
    }

    //Get some parameters needed to fill in the URB
    DWORD packet_size = p_pipe->MaximumPacketSize;
    DWORD num_packets = buffer_size / packet_size;
    
    DWORD transfer_flags = USBD_SHORT_TRANSFER_OK | USBD_START_ISO_TRANSFER_ASAP;
    if (USB_ENDPOINT_DIRECTION_IN(p_pipe->EndpointAddress))
    {
        transfer_flags |= USBD_TRANSFER_DIRECTION_IN;
    }
    
    USHORT urb_size = (USHORT)GET_ISO_URB_SIZE(num_packets);

    //Zero the URB
    RtlZeroMemory(p_iso, urb_size);

    //Fill in the URB parameters
    p_iso->Hdr.Length = urb_size;
    p_iso->Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
    p_iso->Hdr.Status = 0x0;
    p_iso->PipeHandle = p_pipe->PipeHandle;
    p_iso->TransferFlags = transfer_flags;
    p_iso->TransferBufferLength = num_packets * packet_size;
    p_iso->TransferBuffer = p_buffer;
    p_iso->TransferBufferMDL = NULL;
    
    p_iso->NumberOfPackets = num_packets;
    
    DWORD i;
    for ( i = 0; i < num_packets; i++)
    {
        p_iso->IsoPacket[i].Offset = i * packet_size;
        p_iso->IsoPacket[i].Length = packet_size;
    }
    
    // Save context information.
    p_read_context->pUsb = this;
    p_read_context->Pipe = pipe_number;
    p_read_context->Interface = (DWORD)interface_number & 0xff;
    p_read_context->dwXferSize = p_iso->TransferBufferLength;
    
    // re-initialize the Irp
    IoInitializeIrp(p_read_context->pIrp, p_read_context->pIrp->Size, _pdo->StackSize);
    
    //Set up information for lower-level driver.
    IO_STACK_LOCATION* p_stack = IoGetNextIrpStackLocation(p_read_context->pIrp);
    
    p_stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    p_stack->Parameters.Others.Argument1 = p_read_context->pUrb;
    p_stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
    
    //Set our completion routine
    IoSetCompletionRoutine(p_read_context->pIrp, staticIsoTransferComplete, p_read_context, TRUE, TRUE, TRUE);
    
    //Send the IRP to the USB bus driver
    return IoCallDriver(_pdo, p_read_context->pIrp);
}


/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbAsyncIo_BULK_SYNC
//
// Start a SYNCHRONOUS bulk transfer using the asynchronous read_context callback routine
//
// Parameters
//  pipe_number - pipe to do the transfer on 
//  interface_number - interface the pipe belongs to
//  p_buffer - buffer to transfer
//  buffer_size - size of the buffer to transfer
//  p_read_context - context structure containing the URB and callback routine
//
                                 
NTSTATUS CUsbInterface::UsbAsyncIo_BULK_SYNC(DWORD pipe_number, 
                                             UCHAR interface_number,
                                             PBYTE p_buffer, 
                                             DWORD buffer_size, 
                                             PREAD_CONTEXT p_read_context)
{
    DbgLog(("UsbAsyncIo_BULK_SYNC\n"));
    NTSTATUS	status;

    if (_error_occured)
    {
        DbgLogError(("UsbAsyncIo_BULK_SYNC() : device IO error occured before!!\n"));
        return (STATUS_DEVICE_DATA_ERROR);
    }

    //UsbSendMcCmd sends a bulk or interrupt command synchronously
    status = UsbSendMcCmd(pipe_number, interface_number, p_buffer, buffer_size);

    //Call the user's completion routine
    if(p_read_context->pCompletion)
    {
        (p_read_context->pCompletion)(
            p_read_context->UserContext, 
            status,
            buffer_size,
            p_read_context);
    }

    return (status);
}



/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbAsyncIo_BULK
//
// Start an asynchronous bulk transfer
//
// Parameters:
//  pipe_number - pipe to do the transfer on 
//  interface_number - interface the pipe belongs to
//  p_buffer - buffer to transfer
//  buffer_size - size of the buffer in bytes
//  p_read_context - context containing a URB and a callback routine.
//
NTSTATUS CUsbInterface::UsbAsyncIo_BULK(DWORD pipe_number, 
                                        UCHAR interface_number,
                                        PBYTE p_buffer, 
                                        DWORD buffer_size, 
                                        PREAD_CONTEXT p_read_context)
{
    if(_error_occured)
    {
        DbgLogError(("UsbAsyncIo_BULK() : device IO error occured before!!\n"));
        NTSTATUS status = STATUS_SUCCESS;
        if(UsbGetStatusPipe(pipe_number, interface_number) != STATUS_SUCCESS)
        {
            // abort MPEG data pipe
            status = UsbAbortPipe(pipe_number,interface_number);      //PIPE_STREAMING
            if (!NT_SUCCESS(status))
            {
                 DbgLogError(("CUsbInterface::UsbAsyncIo_BULK, Failed to abort firmware download pipe %x\n", status));
            }

            // reset MPEG data pipe
            status = UsbResetPipe(pipe_number,interface_number);      //PIPE_STREAMING
            if (!NT_SUCCESS(status))
            {
                 DbgLogError(("CUsbInterface::UsbAsyncIo_BULK, Failed to reset firmware download pipe %x\n", status));
            }
        }
        if (!NT_SUCCESS(status))
        {
            return (STATUS_DEVICE_DATA_ERROR);
        }
    }

    //Check that the pipe is valid
    PUSBD_PIPE_INFORMATION	p_pipe = getPipe(interface_number, pipe_number);
    if(!p_pipe)
    {
        DbgLogError(("UsbAsyncIo_BULK: Invalid pipe; interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    //Check that the pipe type is bulk or interrupt
    if ((UsbdPipeTypeBulk != p_pipe->PipeType) &&
        (UsbdPipeTypeInterrupt != p_pipe->PipeType)) 
    {
        DbgLogError(("UsbAsyncIo_BULK: Invalid pipe type; interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    //Check that we have a valid pipe handle
    if(!p_pipe->PipeHandle)
    {
        DbgLogError(("UsbAsyncIo_BULK: Invalid pipe handle; interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    //Build the URB
    DWORD transfer_flags = USBD_SHORT_TRANSFER_OK;
    if (USB_ENDPOINT_DIRECTION_IN(p_pipe->EndpointAddress))
    {
        transfer_flags |= USBD_TRANSFER_DIRECTION_IN;
    }

    UsbBuildInterruptOrBulkTransferRequest(
        p_read_context->pUrb,	// ptr to urb
        (USHORT)sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),	// size of urb
        p_pipe->PipeHandle,   // usbd pipe handle
        p_buffer,    // TransferBuffer
        NULL,        // mdl
        buffer_size, // bufferlength
        transfer_flags,   // flags
        NULL);  // link

    
    // Save context information.
    p_read_context->pUsb = this;
    p_read_context->Pipe = pipe_number;
    p_read_context->Interface = (DWORD)interface_number & 0xff;
    p_read_context->dwXferSize = buffer_size;
                
    // re-initialize the Irp
    IoInitializeIrp(p_read_context->pIrp, p_read_context->pIrp->Size, _pdo->StackSize);

    //Set up information for lower-level driver.
    PIO_STACK_LOCATION p_stack = IoGetNextIrpStackLocation(p_read_context->pIrp);

    p_stack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    p_stack->Parameters.Others.Argument1 = p_read_context->pUrb;
    p_stack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

    IoSetCompletionRoutine(
        p_read_context->pIrp,
        staticUsbReadComplete,
        p_read_context,
        TRUE,
        TRUE,
        TRUE);

    //Send the IRP to the USB bus driver
    return IoCallDriver(_pdo, p_read_context->pIrp);
}



/////////////////////////////////////////////////////////////////////////////////////////
void CUsbInterface::DumpUsbDevDescriptor(USB_DEVICE_DESCRIPTOR* p_descriptor) 
{
    DbgLogTrace(("  USB_DEVICE_DESCRIPTOR     0x%08p\n", p_descriptor));
    DbgLogTrace(("  bLength %u\n", p_descriptor->bLength));
    DbgLogTrace(("  bDescriptorType  %u\n", p_descriptor->bDescriptorType));
    DbgLogTrace(("  bcdUSB  %04X\n", p_descriptor->bcdUSB));
    DbgLogTrace(("  bDeviceClass  %u\n", p_descriptor->bDeviceClass));
    DbgLogTra

⌨️ 快捷键说明

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