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

📄 cusbintf.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*+++ *******************************************************************\ 
* 
*  Copyright and Disclaimer: 
*  
*     --------------------------------------------------------------- 
*     This software is provided "AS IS" without warranty of any kind, 
*     either expressed or implied, including but not limited to the 
*     implied warranties of noninfringement, merchantability and/or 
*     fitness for a particular purpose.
*     --------------------------------------------------------------- 
*   
*     Copyright (c) 2008 Conexant Systems, Inc. 
*     All rights reserved. 
*
\******************************************************************* ---*/ 

extern "C" 
{
    #include <wdm.h>
    #include <usb.h>
    #include <usbdrivr.h>
}



#include <windef.h>

#include "cusbintf.h"

#include "debug.h"

#include "device.h"

/////////////////////////////////////////////////////////////////////////////
//
//
CUsbInterface::CUsbInterface(PDEVICE_OBJECT pdo):
    _pdo(pdo),
    _p_configs(NULL),
    _config_index(0),
    _p_interfaces(NULL),
    _config_handle(NULL),
    _error_occured(FALSE),
    _is_initialized(FALSE),
    _is_descriptor_available(FALSE),
    _bSurpriseRemoval(FALSE),
    _p_irp(NULL),
    _p_cmd_urb(NULL)
{


    KeInitializeEvent(&_event, NotificationEvent, 0);

    KeInitializeMutex(&_mutex, 1);

    KeInitializeEvent(&_usb_config_event, NotificationEvent, TRUE);

    KeClearEvent(&_usb_config_event);

#if DBG
    USBD_VERSION_INFORMATION version_info;

    RtlZeroMemory(&version_info, sizeof(USBD_VERSION_INFORMATION));
    USBD_GetUSBDIVersion(&version_info);

    DbgLogInfo(("CUsbInterface::CUsbInterface() USBDI_Version(0x%x) Supported_USB_Version(0x%x)\n",
    version_info.USBDI_Version, 
    version_info.Supported_USB_Version));
#endif


}


/////////////////////////////////////////////////////////////////////////////////////////
CUsbInterface::~CUsbInterface()
{
    if (_is_initialized)
    {
        Release();
    }

    UnConfigDevice();

    if(_p_cmd_urb)
    {
        delete _p_cmd_urb;
        _p_cmd_urb = NULL;
    }

    if (_p_irp)
    {
        IoFreeIrp(_p_irp);
        _p_irp = NULL;
    }
}


/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::InitDevice()
//
// Note that actual initialization occurs in ConfigDevice(), called from the constructor
//
NTSTATUS CUsbInterface::InitDevice()
{
    if (_is_initialized)
    {
        DbgLogError(("CUsbInterface::InitDevice() Already Initialized. Skipping...\n"));
        return STATUS_SUCCESS;
    }

    if (!_p_irp)
    {
        _p_irp = IoAllocateIrp(_pdo->StackSize, FALSE);
        if (!_p_irp)
        {
            DbgLogError(("CUsbInterface::InitDevice() Unable to allocate IRP\n"));
            return STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    if(!_p_cmd_urb)
    {
        //Allocate a URB
        _p_cmd_urb = (PURB) new _URB_BULK_OR_INTERRUPT_TRANSFER;
        if(!_p_cmd_urb)
        {
            DbgLogError(("CUsbInterface::InitDevice() Unable to allocate command URB\n"));
            return STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    
    NTSTATUS status = ConfigDevice();
    DbgLogInfo(("CUsbInterface::ConfigDevice() Status(0x%x)\n", status));
    if (!NT_SUCCESS(status))
    {
         DbgLogError(("CUsbInterface::InitDevice() Unable to ConfigDevice\n"));
         return STATUS_INSUFFICIENT_RESOURCES;
    }

    if(!_p_configs || !_p_interfaces)
    {
        DbgLogError((
            "CUsbInterface::InitDevice() Failed _p_configs(0x%p) _p_interfaces(0x%p)\n", 
            _p_configs,
            _p_interfaces));
        return STATUS_UNSUCCESSFUL;
    }
    
    // clear error condition
    _error_occured = FALSE;

    _is_initialized = TRUE;

    return STATUS_SUCCESS;
}


/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::waitForConfigDevice
//
NTSTATUS CUsbInterface::waitForConfigDevice()
{
    //Wait for the acknowledge interrupt 
    LARGE_INTEGER timeout;
    timeout.QuadPart = -10000*10000; //10000 ms timeout

    DbgLogInfo(("CUsbInterface: waitForConfigDevice: Starting Usb Config Device wait Event\n"));

    NTSTATUS status = KeWaitForSingleObject(
        &_usb_config_event,
        Executive,
        KernelMode,
        TRUE,
        &timeout);

    return status;
}

/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::setUsbConfigEvent
//
void CUsbInterface::setUsbConfigEvent()
{
    DbgLogInfo(("CUsbInterface: setUsbConfigEvent: Clearing  Usb Config Device wait Event\n"));

    //Set the event to notify the waiting thread that the command is compelte
    KeSetEvent(
        &_usb_config_event,
        IO_NO_INCREMENT,
        FALSE);
}

/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::Release
//
// This performs the opposite task of InitDevice
//
NTSTATUS CUsbInterface::Release(void)
{
    _is_initialized = FALSE;
    _is_descriptor_available = FALSE;

    KeClearEvent(&_usb_config_event);

    return (STATUS_SUCCESS);
}


/////////////////////////////////////////////////////////////////////////////////////////
// CUsbInterface::UsbCall_GSPN
//
// Send a URB to the USB bus driver and wait for it to complete.  The function name 
// is not very descriptive.
//
NTSTATUS CUsbInterface::UsbCall_GSPN(URB* p_urb)
{
    NTSTATUS status = STATUS_SUCCESS;
    DWORD function_id = p_urb->UrbHeader.Function;

    // 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);
    }

    //Exit early if an error occured in an earlier transfer.
    if (_error_occured)
    {
        if ((URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER == function_id) ||
            (URB_FUNCTION_ISOCH_TRANSFER == function_id) ||
            (URB_FUNCTION_CONTROL_TRANSFER == function_id) ||
            (URB_FUNCTION_RESET_PIPE == function_id)
           )
        {
            DbgLogError(( "CUsbInterface::UsbCall_GSPN() : Func(%d) Rejecting, device IO error occured before!!\n", function_id ));
            switch(function_id)
            {
            case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:


                if(UsbGetStatusPipe(0, 0) != STATUS_SUCCESS)
                {
                    // abort command pipe in
                    status = UsbAbortPipe(0,0);      //PIPE_CMD_IN
                    if (!NT_SUCCESS(status))
                    {
                         DbgLogError(("CUsbInterface::UsbCall_GSPN, Failed to abort cmd IN pipe %x\n", status));
                    }

                    // reset command pipe in
                    status = UsbResetPipe(0,0);      //PIPE_CMD_IN
                    if (!NT_SUCCESS(status))
                    {
                         DbgLogError(("CUsbInterface::UsbCall_GSPN, Failed to reset cmd IN pipe %x\n", status));
                    }
                }

                if(UsbGetStatusPipe(1, 0) != STATUS_SUCCESS)
                {

                    // abort command pipe OUT
                    status = UsbAbortPipe(1,0);      //PIPE_CMD_OUT
                    if (!NT_SUCCESS(status))
                    {
                         DbgLogError(("CUsbInterface::UsbCall_GSPN, Failed to abort cmd OUT pipe %x\n", status));
                    }

                    // reset command pipe OUT
                    status = UsbResetPipe(1,0);      //PIPE_CMD_OUT
                    if (!NT_SUCCESS(status))
                    {
                         DbgLogError(("CUsbInterface::UsbCall_GSPN, Failed to reset cmd OUT pipe %x\n", status));
                    }
                }                
                break;

            case URB_FUNCTION_ISOCH_TRANSFER:
                if(UsbGetStatusPipe(2, 0) != STATUS_SUCCESS)
                {
                    // abort MPEG data pipe
                    status = UsbAbortPipe(2,0);      //PIPE_STREAMING
                    if (!NT_SUCCESS(status))
                    {
                         DbgLogError(("CUsbInterface::UsbCall_GSPN, Failed to abort firmware download pipe %x\n", status));
                    }

                    // reset MPEG data pipe
                    status = UsbResetPipe(2,0);      //PIPE_STREAMING
                    if (!NT_SUCCESS(status))
                    {
                         DbgLogError(("CUsbInterface::UsbCall_GSPN, Failed to reset firmware download pipe %x\n", status));
                    }
                }
                break;

            case URB_FUNCTION_CONTROL_TRANSFER:
            case URB_FUNCTION_RESET_PIPE:
            default:
                status = ResetDevice();
            }

            if (!NT_SUCCESS(status))
            {
                if( (status == STATUS_DEVICE_NOT_CONNECTED) || (status == STATUS_NO_SUCH_DEVICE) )
                {
                    // if the device status is not connected, set removal flag
                    DbgLogError(("CUsbInterface::UsbCall_GSPN, Setting surprise removal flag\n"));
                    _bSurpriseRemoval = TRUE;
                }

                status = ResetDevice();
                if (!NT_SUCCESS(status))
                {                     
                     DbgLogError(("CUsbInterface::UsbCall_GSPN, Failed to reset Device %x\n", status));
                     return (STATUS_DEVICE_DATA_ERROR);
                }
                DbgLogInfo(("CUsbInterface::UsbCall_GSPN, Successfully reset the pipes and Device\n"));
                _error_occured = FALSE;
    
            }
            else
            {
                DbgLogInfo(("CUsbInterface::UsbCall_GSPN, Successfully reset the pipes\n"));
                _error_occured = FALSE;
            }
        }
        else
        {
            DbgLogError(("CUsbInterface::UsbCall_GSPN() : Func(%d) Allowed, device IO error occured before!!\n", function_id));
        }
    }

    // send command and wait until it completes
    status = SendCmdAndWait(p_urb);

    return (status);
}

/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::EzUsb_VendorRequest
//
// Send a vendor-specific request to an EZ-USB device (FX2 is an EZ-USB device)
//
NTSTATUS CUsbInterface::Ezusb_VendorRequest(PVENDOR_REQUEST_IN p_request)
{
    // 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);
    }

    //Allocate a URB for the transfer
    PURB p_urb = (PURB) new _URB_CONTROL_VENDOR_OR_CLASS_REQUEST;

    if(!p_urb) 
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //Zero the URB and the buffer
    RtlZeroMemory(p_urb, sizeof(_URB_CONTROL_VENDOR_OR_CLASS_REQUEST));

    //Fill in the URB    
    p_urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
    p_urb->UrbHeader.Function = URB_FUNCTION_VENDOR_DEVICE;
    p_urb->UrbControlVendorClassRequest.TransferBufferLength = p_request->wLength;
    p_urb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
    p_urb->UrbControlVendorClassRequest.Request = p_request->bRequest;
    p_urb->UrbControlVendorClassRequest.Value = p_request->wValue;
    p_urb->UrbControlVendorClassRequest.Index = p_request->wIndex;
    p_urb->UrbControlVendorClassRequest.TransferBuffer = p_request->pBuff;
    
    if(p_request->direction) 
    {
        p_urb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN;
    } 
    
    //Send the URB    
    NTSTATUS status = UsbCall_GSPN(p_urb);
  
    delete p_urb;

    return status;
}



/////////////////////////////////////////////////////////////////////////////////////////
//CUsbInterface::UsbSendMcCmd
//

⌨️ 快捷键说明

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