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

📄 cusbintf.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// This sends a bulk or interrupt data transfer and waits for it to complete.  
// The name is misleading.
//
// Parameters
//   pipe_number - pipe to send the transfer on
//   interface_number - interface to use
//   p_data - data to send
//   transfer_size - size of data to send in bytes
//
NTSTATUS CUsbInterface::UsbSendMcCmd(DWORD pipe_number, 
                                      UCHAR interface_number,
                                      void* p_data, 
                                      DWORD transfer_size)
{
    USBD_PIPE_INFORMATION* p_pipe = getPipe(interface_number, pipe_number);
    DbgLog(("CUsbInterface::UsbSendMcCmd:interface_num=%d,pip_num=%d\n",interface_number,pipe_number));

    // if device is surprise removed then we should not allow any call further below
    if(_bSurpriseRemoval)
    {
        DbgLogError(("CUsbInterface::UsbCall_GSPN() : Device Surprise Removal!!\n"));
        return (STATUS_DEVICE_DATA_ERROR);
    }
    
    //Make sure the pipe is valid
    if(!p_pipe)
    {
        DbgLogError(("UsbSendMcCmd on invalid pipe, interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    //Only accept commands on bulk or interrupt pipes
    if((p_pipe->PipeType != UsbdPipeTypeBulk) &&
        (p_pipe->PipeType != UsbdPipeTypeInterrupt))
    {
        DbgLogError(("UsbSendMcCmd: invalid pipe type.  Pipe type = %x\n", p_pipe->PipeType));
        return STATUS_UNSUCCESSFUL;
    }

    //Make sure the pipe has a valid handle
    if(!p_pipe->PipeHandle)
    {
        DbgLogError(("UsbSendMcCmd: invalid pipe handle.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    //Allocate a URB
    PURB p_urb = (PURB) new _URB_BULK_OR_INTERRUPT_TRANSFER;
               
    if(!p_urb)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    RtlZeroMemory(p_urb, sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER));
    
    DWORD transfer_flags = USBD_SHORT_TRANSFER_OK;
    
    if (USB_ENDPOINT_DIRECTION_IN(p_pipe->EndpointAddress))
    {
        transfer_flags |= USBD_TRANSFER_DIRECTION_IN;
    }
    
    UsbBuildInterruptOrBulkTransferRequest(
        p_urb,   // ptr to urb
        (USHORT)sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),	// size of urb
        p_pipe->PipeHandle,   // usbd pipe handle
        p_data,   // TransferBuffer
        0,   // mdl
        transfer_size,   // bufferlength
        transfer_flags,     // flags
        NULL);   // link
        
    //Send the URB
    NTSTATUS status = UsbCall_GSPN(p_urb);
    
    delete p_urb;
                
    return status;
}

/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbSendRecvCmd
//
// This sends a bulk or interrupt data transfer and waits for it to complete.  
// The name is misleading.
// 
// This function's purpose is not to create URB multiple times, and resuse the same
// URB repeatedly, so that we can save allocation and deletion times of URB although 
// it is fast.
//
// Parameters
//   pipe_number - pipe to send the transfer on
//   interface_number - interface to use
//   p_data - data to send
//   transfer_size - size of data to send in bytes
//
NTSTATUS CUsbInterface::UsbSendRecvCmd(  DWORD pipe_number, 
                                         UCHAR interface_number,
                                         void* p_data, 
                                         DWORD transfer_size)
{
    USBD_PIPE_INFORMATION* p_pipe = getPipe(interface_number, pipe_number);

    // if device is surprise removed then we should not allow any call further below
    if(_bSurpriseRemoval)
    {
        DbgLogError(("CUsbInterface::UsbCall_GSPN() : Device Surprise Removal!!\n"));
        return (STATUS_DEVICE_DATA_ERROR);
    }
    
    //Make sure the pipe is valid
    if(!p_pipe)
    {
        DbgLogError(("UsbSendMcCmd on invalid pipe, interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    //Only accept commands on bulk or interrupt pipes
    if((p_pipe->PipeType != UsbdPipeTypeBulk) &&
        (p_pipe->PipeType != UsbdPipeTypeInterrupt))
    {
        DbgLogError(("UsbSendMcCmd: invalid pipe type.  Pipe type = %x\n", p_pipe->PipeType));
        return STATUS_UNSUCCESSFUL;
    }

    //Make sure the pipe has a valid handle
    if(!p_pipe->PipeHandle)
    {
        DbgLogError(("UsbSendMcCmd: invalid pipe handle.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    // check for URB 
    PURB p_urb = (PURB) _p_cmd_urb;
    if(!p_urb)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    RtlZeroMemory(p_urb, sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER));
    
    DWORD transfer_flags = USBD_SHORT_TRANSFER_OK;
    
    if (USB_ENDPOINT_DIRECTION_IN(p_pipe->EndpointAddress))
    {
        transfer_flags |= USBD_TRANSFER_DIRECTION_IN;
    }
    
    UsbBuildInterruptOrBulkTransferRequest(
        p_urb,   // ptr to urb
        (USHORT)sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),	// size of urb
        p_pipe->PipeHandle,   // usbd pipe handle
        p_data,  // TransferBuffer
        0,       // mdl
        transfer_size,   // bufferlength
        transfer_flags,  // flags
        NULL);           // link
        
    //Send the URB
    NTSTATUS status = UsbCall_GSPN(p_urb);
               
    return status;
}

/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbAsyncIo
//
// Start an asynchronous data transfer
//
// Parameters:
//   pipe_number - pipe to use
//   interface_number - interface to use
//   p_data - data buffer to send or receive
//   data_size - number of bytes to send or recieve
//   p_mdl - unused
//   p_read_context - context structure describing the URB and callback routine
//

NTSTATUS CUsbInterface::UsbAsyncIo(DWORD pipe_number, 
                                   UCHAR interface_number,
                                   PBYTE p_data, 
                                   DWORD data_size, 
                                   PMDL p_mdl, 
                                   PREAD_CONTEXT p_read_context)
{
    USBD_PIPE_INFORMATION* p_pipe = getPipe(interface_number, pipe_number);

    // if device is surprise removed then we should not allow any call further below
    if(_bSurpriseRemoval)
    {
        DbgLogError(("CUsbInterface::UsbCall_GSPN() : Device Surprise Removal!!\n"));
        return (STATUS_DEVICE_DATA_ERROR);
    }
    
    if(!p_pipe)
    {
        DbgLogError(("UsbAsyncIo on invalid pipe, interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    switch(p_pipe->PipeType) 
    {
        case UsbdPipeTypeIsochronous:
        return UsbAsyncIo_ISO(pipe_number, interface_number, p_data, data_size, p_read_context);
        case UsbdPipeTypeBulk:
        case UsbdPipeTypeInterrupt:
        return UsbAsyncIo_BULK(pipe_number, interface_number, p_data, data_size, p_read_context);
        default:                                     
        return UsbAsyncIo_BULK_SYNC(pipe_number, interface_number, p_data, data_size, p_read_context);
    }

    UNREFERENCED_PARAMETER(p_mdl);
}



/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbResetPipe
//
// Reset a pipe. 
//
// Parameters:
//    pipe_number - pipe to reset
//    interface_number - interface the pipe is in
//
NTSTATUS CUsbInterface::UsbResetPipe(DWORD pipe_number, UCHAR interface_number)
{
    USBD_PIPE_INFORMATION* p_pipe = getPipe(interface_number, pipe_number);
    
    if(!p_pipe)
    {
        DbgLogError(("UsbResetPipe on invalid pipe, interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    PURB p_urb = (PURB) new BYTE[sizeof(struct _URB_PIPE_REQUEST)];

    if(!p_urb)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(p_urb, sizeof(struct _URB_PIPE_REQUEST));
    p_urb->UrbHeader.Length = (USHORT)sizeof(struct _URB_PIPE_REQUEST);
    p_urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
    p_urb->UrbPipeRequest.PipeHandle = p_pipe->PipeHandle;
    
    NTSTATUS status = SendCmdAndWait(p_urb);
    
    delete [] (BYTE *)p_urb;
    
    return status;
}

NTSTATUS CUsbInterface::SendCmdAndWait(PURB p_urb)
{
    NTSTATUS status;

    // if device is surprise removed then we should not allow any call further below
    if(_bSurpriseRemoval)
    {
        DbgLogError(("CUsbInterface::SendCmdAndWait : Device Surprise Removal!!\n"));
        return (STATUS_DEVICE_DATA_ERROR);
    }

    //We can't send the URB if we don't have an IRP
    if(!_p_irp)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //We must run at passive level to acquire the mutex and wait.
    if(KeGetCurrentIrql() != PASSIVE_LEVEL)
    {
        return STATUS_UNSUCCESSFUL;
    }


    //Get the mutex
    KeWaitForSingleObject(&_mutex, Executive, KernelMode, FALSE, NULL);

    //Set up the IRP
    PIRP pIrp = _p_irp;
    IoInitializeIrp(pIrp, pIrp->Size, _pdo->StackSize);

	KeClearEvent(&_event);

    //Get the next IRP stack location and set it up for the USB bus driver.
    PIO_STACK_LOCATION pNextStack= IoGetNextIrpStackLocation(pIrp);	//Setup request to lower-level driver.
    pNextStack->MajorFunction= IRP_MJ_INTERNAL_DEVICE_CONTROL;
    pNextStack->Parameters.DeviceIoControl.IoControlCode= IOCTL_INTERNAL_USB_SUBMIT_URB;
    pNextStack->Parameters.Others.Argument1= p_urb;
    
    //Set our completion routine
    IoSetCompletionRoutine(pIrp, staticUsbCallCompletion, &_event, TRUE, TRUE, TRUE);

    //Send the IRP to the USB bus driver
    status = IoCallDriver(_pdo, pIrp);

    //If the IRP is pending, wait for it to complete.
    if(STATUS_PENDING == status)
    { 
        LARGE_INTEGER timeout_period;
        timeout_period.QuadPart = -10000 * 5000;
        
        status = KeWaitForSingleObject(
            &_event,
            Executive,
            KernelMode,
            0,
            &timeout_period);

        if(STATUS_TIMEOUT == status) 
        {
            //If we timed out, try to cancel the IRP
            IoCancelIrp(pIrp);

            KeWaitForSingleObject(
                &_event,
                Executive,
                KernelMode,
                0,
                NULL);

           
            status = STATUS_IO_TIMEOUT;

            DbgLogError(( "CUsbInterface::SendCmdAndWait : Cancelled IRP !!\n"));
        } 
        else 
        {
            status = pIrp->IoStatus.Status;				  
        }
    }

    //Flag an error if we weren't successful
    if (!NT_SUCCESS(status)) 
    {
        if ((STATUS_DEVICE_DATA_ERROR == status) ||
            (STATUS_IO_TIMEOUT == status) ||
            (STATUS_DEVICE_NOT_CONNECTED == status))
        {
            _error_occured = TRUE;
            DbgLogError(( "CUsbInterface::SendCmdAndWait : Error Status = %x!!\n", status));
        }
        
    }

    KeReleaseMutex(&_mutex, FALSE);

    return status;

}

/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbAbortPipe
//
// Call this function to abort all outstanding requests on a pipe.
//
NTSTATUS CUsbInterface::UsbAbortPipe(DWORD pipe_number, UCHAR interface_number)
{
    DbgLog(("usbabortpipe\n"));
    USBD_PIPE_INFORMATION* p_pipe = getPipe(interface_number, pipe_number);
    
    if(!p_pipe)
    {
        DbgLogError(("UsbAbortPipe on invalid pipe, interface = %x, pipe = %x\n", interface_number, pipe_number));
        return STATUS_UNSUCCESSFUL;
    }

    PURB p_urb = (PURB) new BYTE[sizeof(struct _URB_PIPE_REQUEST)];
    if(!p_urb)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(p_urb, sizeof(struct _URB_PIPE_REQUEST));
    
    p_urb->UrbHeader.Length = (USHORT)sizeof(struct _URB_PIPE_REQUEST);
    p_urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
    p_urb->UrbPipeRequest.PipeHandle = p_pipe->PipeHandle;
    
    NTSTATUS status = SendCmdAndWait(p_urb);
    
    delete [] (BYTE *)p_urb;

    return status;
}



/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbGetStatusPipe

⌨️ 快捷键说明

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