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

📄 ir_control.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*+++ *******************************************************************\ 
* 
*  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. 
*
\******************************************************************* ---*/ 

#include "Ir_control.h"
#include "PolarisUsbInterface.h"
#include "miscfuncs.h"


/////////////////////////////////////////////////////////////////////////////////////////
IR_Control::IR_Control( CUsbInterface* p_usb, PolarisUsbInterface* p_firmware,
						UsbI2cInterface* p_i2c_interface,
						PDEVICE_OBJECT pdo,
						PcbConfig* p_current_config) :
_p_usb(p_usb),
_p_usb_firmware(p_firmware),
_p_i2c_interface(p_i2c_interface),
_p_thread_object(NULL),
_p_queue_thread(NULL),
_key_queue(16),
_last_command(0xFFFFFFFF),
_was_started(FALSE),
_queue_started(FALSE),
_pdo(pdo),
_buffer_count(0),
_pipe(0),
_interface(1), ///default is index 0
_p_current_config(p_current_config),
_config_index(0)
{
    DbgLogInfo(("ir_control::ir_control constructor\n"));
    _data_queue.count =0;
    _free_queue.count = 0;

    KeInitializeEvent(
        &_thread_event,
        SynchronizationEvent,       // single wait satisfied resets it
        FALSE);                     // not signaled 

    KeInitializeEvent(
        &_queue_event,
        SynchronizationEvent,       // single wait satisfied resets it
        FALSE);                     // not signaled 

    InitializeListHead (&_data_queue.queue_head);
    InitializeListHead (&_free_queue.queue_head);

    KeInitializeSpinLock (&_data_queue.spin_lock);
    KeInitializeSpinLock (&_free_queue.spin_lock);

    _urb_size = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
    _p_current_pcb = _p_current_config->getCurrentPcb();

}
/////////////////////////////////////////////////////////////////////////////////////////
IR_Control::~IR_Control()
{

}

/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS IR_Control::start()
{
    NTSTATUS status =STATUS_SUCCESS;

    for(int i=0;i<IR_BUFFER_NUM;i++)
    {
        PBUFFER_ENTRY_MINI p_buffer = allocateBuffer();
        if(p_buffer)
        {
            p_buffer->buffer_id=i;
            sendBuffer(p_buffer);
        }
        else
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
        }

        if(!NT_SUCCESS(status))
            break;
    }

    if(_buffer_count)
    {
        status = startQueueThread();
    }
	
    if(status == STATUS_SUCCESS)
    {
        _queue_started = TRUE;
    }

    status = startThread();

    if(status == STATUS_SUCCESS)
    {
        _was_started = TRUE;
    }

    return status;
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::stop()
{
    _was_started = FALSE;
    _queue_started = FALSE;
    stopThread();
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::powerDown()
{
    stopThread();
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::powerUp()
{
    if(_was_started)
    {
        startThread();
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS IR_Control::startThread()
{
    if (_p_thread_object)
    {
        return STATUS_UNSUCCESSFUL;
    }

    KeClearEvent(&_thread_event);

    HANDLE thread_handle;
    NTSTATUS status = PsCreateSystemThread(
        &thread_handle,
        THREAD_ALL_ACCESS,
        NULL,
        NULL,
        NULL,
        (PKSTART_ROUTINE) IR_Control::static_ThreadFunction,   // Thread routine
        this);                                                 // Context

    if(!NT_SUCCESS(status))
        return status;

    return ObReferenceObjectByHandle(
            thread_handle,
            THREAD_ALL_ACCESS,
            NULL,
            KernelMode,
            &_p_thread_object,
            NULL);
}

/////////////////////////////////////////////////////////////////////////////////////////
NTSTATUS IR_Control::startQueueThread()
{
    if (_p_queue_thread)
    {
        return STATUS_UNSUCCESSFUL;
    }

    KeClearEvent(&_queue_event);

    HANDLE thread_handle;
    NTSTATUS status = PsCreateSystemThread(
        &thread_handle,
        THREAD_ALL_ACCESS,
        NULL,
        NULL,
        NULL,
        (PKSTART_ROUTINE) IR_Control::static_ThreadQueue,   // Thread routine
        this);                                                 // Context

    if(!NT_SUCCESS(status))
        return status;

    return ObReferenceObjectByHandle(
            thread_handle,
            THREAD_ALL_ACCESS,
            NULL,
            KernelMode,
            &_p_queue_thread,
            NULL);
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::stopThread()
{

    PBUFFER_ENTRY_MINI p_buffer;

    if(_p_thread_object)
    {
        KeSetEvent(&_thread_event, IO_NO_INCREMENT, TRUE);
        
        //Wait for the buffer complete thread to exit
        KeWaitForSingleObject(
            _p_thread_object,
            Executive,
            KernelMode,
            TRUE,
            NULL);
        
        _p_thread_object = NULL;
    }

    while(_data_queue.count)
    {    	
        p_buffer = getBuffer(&_data_queue);

        while(p_buffer)
        {
            freeBuffer(p_buffer);
            p_buffer = getBuffer(&_data_queue);
        }
        
        if(_data_queue.count && !p_buffer)
        {
            waitForTimes(500);
            p_buffer = getBuffer(&_data_queue);
        }
       
    }

    if(_p_queue_thread)
    {
        KeSetEvent(&_queue_event, IO_NO_INCREMENT, TRUE);
        
        //Wait for the buffer complete thread to exit
        KeWaitForSingleObject(
            _p_queue_thread,
            Executive,
            KernelMode,
            TRUE,
            NULL);
        
        _p_queue_thread = NULL;
    }

    while(_free_queue.count)
    {
        p_buffer = getBuffer(&_free_queue);

        while(p_buffer)
        {
            freeBuffer(p_buffer);
            p_buffer = getBuffer(&_data_queue);
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::static_ThreadFunction(IR_Control* p_this)
{
    p_this->threadFunction();
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::static_ThreadQueue(IR_Control* p_this)
{
    p_this->threadQueue();
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::threadQueue()
{
    PBUFFER_ENTRY_MINI p_buffer = NULL;
    while(_queue_started)
    {
        p_buffer = getBuffer(&_free_queue);

        if(p_buffer)
        {
            sendBuffer(p_buffer);
        }		
    }
    PsTerminateSystemThread(STATUS_SUCCESS);
}

/////////////////////////////////////////////////////////////////////////////////////////
///jerry_xu 2007-03-20, modify to delete IR control
VOID IR_Control::threadFunction()
{
    PBUFFER_ENTRY_MINI p_buffer = NULL;
    PBYTE p_ir = new BYTE[IR_LENGTH*DATA_BLOCK_NUM];
    PBYTE p_event = new BYTE[EVENT_LENGTH*DATA_BLOCK_NUM];
    PBYTE p_pre_event = new BYTE[EVENT_LENGTH]; //TO store pre-event
    RtlZeroMemory(p_pre_event,EVENT_LENGTH);

    while(_was_started)
    {
        RtlZeroMemory(p_ir,IR_LENGTH*DATA_BLOCK_NUM);
        RtlZeroMemory(p_event,EVENT_LENGTH*DATA_BLOCK_NUM);
        p_buffer = getBuffer(&_data_queue);
	
        if(p_buffer)
        {
            sliced_data(p_buffer->p_buffer, p_ir,p_event);
            ProcessEvent(p_event,p_pre_event);
            sendFreeBuffer(p_buffer);
        }

    }
    delete [] p_ir;
    delete [] p_event;
    delete [] p_pre_event;
    p_ir = NULL;
    p_event = NULL;
    p_pre_event = NULL;
    PsTerminateSystemThread(STATUS_SUCCESS);
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::flushQueue()
{

    _key_queue.Flush();

    //TODO: Flush the firmware's queue
	
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::getKeystroke(DWORD* p_command, DWORD* p_address)
{
    if(!_key_queue.IsEmpty())
    {
        KEYSTROKE keystroke = _key_queue.Remove();
        *p_command = keystroke.dwCommand;
        *p_address = keystroke.dwAddress;
    }
    else
    {
        *p_command = 0;
        *p_address = 0;
    }
}

/////////////////////////////////////////////////////////////////////////////////////////
PBUFFER_ENTRY_MINI IR_Control::allocateBuffer()
{
    PBUFFER_ENTRY_MINI p_buffer = new BUFFER_ENTRY_MINI;

    if(!p_buffer)
    {
        return NULL;
    }

    p_buffer->p_buffer = new BYTE[IR_BUFFER_SIZE];
    p_buffer->p_irp = IoAllocateIrp(_pdo->StackSize, FALSE);
    p_buffer->p_urb = (PURB) new BYTE[_urb_size];

    if(!p_buffer->p_buffer ||
       !p_buffer->p_irp ||
       !p_buffer->p_urb)
    {
        if(p_buffer->p_irp) IoFreeIrp(p_buffer->p_irp);
        delete [] p_buffer->p_buffer;
        delete [] p_buffer->p_urb;
        delete p_buffer;
        return NULL;
    }
    
    RtlZeroMemory(p_buffer->p_urb, _urb_size);

    p_buffer->buffer_in_list = FALSE;
    p_buffer->buffer_dirty = FALSE;

    InterlockedIncrement(&_buffer_count);

    return p_buffer;
}

/////////////////////////////////////////////////////////////////////////////////////////
VOID IR_Control::sendBuffer(PBUFFER_ENTRY_MINI p_buffer)
{
    //Initialize our completion context
	
    p_buffer->p_data_transfer = (DWORD*)this;
    p_buffer->read_context.pIrp = p_buffer->p_irp;
    p_buffer->read_context.pUrb = p_buffer->p_urb;
    p_buffer->read_context.pCompletion = (USBCOMPLETION)static_BufferComplete;
    p_buffer->read_context.UserContext = p_buffer;    
    p_buffer->bytes_completed = 0;

    //Start a data transfer
   
    NTSTATUS status =  _p_usb->UsbAsyncIo(

⌨️ 快捷键说明

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