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

📄 i2script.cpp

📁 winddk src目录下的WDM源码压缩!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            // check the Script length
            if( ++ nScriptIndex >= I2CSCRIPT_LENGTH_MAXIMUM)
                FAIL;
            pI2CPrimitive ++;
*/
        }

        // the Packet was added succesfully to the Script. Modify the Script propertirs
        m_nExecutionIndex = nScriptIndex;
        m_nScriptLength = nScriptIndex;
        return( TRUE);

    } END_ENSURE;

    OutputDebugTrace(( "CI2CScript:AppendToScript() nError = %x", nError));
    return( FALSE);
}



/*^^*
 *      ExecuteScript()
 * Purpose  : triggers the execution of previously built I2CScript. This function is also
 *              responsible for allocating I2CProvider for its own exclusive use.
 *
 * Inputs   :   PHW_STREAM_REQUEST_BLOCK    pSrb        : pointer to the current SRB
 *              PHWCompletionRoutine pfnScriptCompletion: function pointer will be called,
 *                  when the script execution is completed. Indicates the Script execution
 *                  is to be carried out asynchronously.
 *
 * Outputs  : BOOL : returns TRUE, if the execution was successfully triggered.
 *              FALSE might happend if the Script has not been built by the time of the call
 *
 * Note     : if pfnScriptExecuted is NULL pointer, the Script will be executed synchronously
 *
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::ExecuteScript( IN PHW_STREAM_REQUEST_BLOCK pSrb,
                                IN PHWCompletionRoutine     pfnScriptCompletion)
{

    ENSURE
    {
        if( pfnScriptCompletion != NULL)
            // not supported at this point. The idea is to create a new system thread,
            // where the Script to be executed. When the Script will be copleted,
            // call-back is called and the thred terminates itself.
            FAIL;

        if( !m_nExecutionIndex)
            FAIL;

        // there is not a NULL Script - proceed
        m_nScriptLength = m_nExecutionIndex;
        m_nExecutionIndex = m_nCompletionIndex = 0;

        if( !GetI2CProviderLockStatus())
            // The provider was not locked prior the Script execution
            if( !LockI2CProviderEx())
                FAIL;

        InterpreterScript();

        ReleaseI2CProvider();
    
        return( TRUE);

    } END_ENSURE;

    return( FALSE);
}



/*^^*
 *      InterpreterScript()
 * Purpose  : interpreters the I2CScript line by line. The Script is not cleaned up 
 *              after the completion to allow to client retrive the results of 
 *              the script execution. It's the client responsibility to clean it up
 *              upon the results retrieving
 *
 * Inputs   : none
 * Outputs  : none
 *
 * Author   : IKLEBANOV
 *^^*/
void CI2CScript::InterpreterScript( void)
{
    UINT        nScriptIndex, nIndex;
    I2CControl  i2cAccessBlock;

    m_bExecutionInProcess = TRUE;
    
    i2cAccessBlock.dwCookie = m_dwI2CAccessKey;
    i2cAccessBlock.ClockRate = m_ulI2CAccessClockRate;
        
    // We'll interpreter every line of the Script and call the I2C Provider to
    // execute it. It's assumed the I2CProvider is a syncronous one. If it's not the
    // case, the special care should be taken of based upon returned value I2C_STATUS_BUSY
    // in the Status.
    for( nScriptIndex = 0; nScriptIndex < m_nScriptLength; nScriptIndex ++)
    {
        i2cAccessBlock.Command = m_i2cScript[nScriptIndex].ulCommand;
        i2cAccessBlock.Flags = m_i2cScript[nScriptIndex].ulProviderFlags;
        if( i2cAccessBlock.Command == I2C_COMMAND_WRITE)
        {
            i2cAccessBlock.Data = m_i2cScript[nScriptIndex].byData;
            i2cAccessBlock.Data &= m_i2cScript[nScriptIndex].byANDData;
            i2cAccessBlock.Data |= m_i2cScript[nScriptIndex].byORData;
        }

        if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) == I2C_STATUS_ERROR)
            break;

        // check, wether it's a Read operation - save result
        if( i2cAccessBlock.Command == I2C_COMMAND_READ)
        {
            m_i2cScript[nScriptIndex].byData = i2cAccessBlock.Data;
            // check, if this data belongs to Read-Modify-Write operation
            if( m_i2cScript[nScriptIndex].byFlags & I2COPERATION_READWRITE)
            {
                // let's look for the next I2COPERATION_READWRITE flag - it is the pair
                for( nIndex = nScriptIndex; nIndex < m_nScriptLength; nIndex ++)
                    if(( m_i2cScript[nIndex].ulCommand == I2C_COMMAND_WRITE) &&
                        ( m_i2cScript[nIndex].byFlags & I2COPERATION_READWRITE))
                        break;

                if( nIndex >= m_nScriptLength)
                    // the Script got corrupted
                    break;

                m_i2cScript[nIndex].byData = i2cAccessBlock.Data;
            }
        }
    }

    m_nCompletionIndex = nScriptIndex;

    m_bExecutionInProcess = FALSE;
}



/*^^*
 *      AccessI2CProvider()
 * Purpose  : provide synchronous type of access to I2CProvider
 *
 * Inputs   :   PDEVICE_OBJECT pdoDriver    : pointer to the client's device object
 *              PI2CControl pi2cAccessBlock : pointer to a composed I2C access block
 *
 * Outputs  : UINT : status of the I2C operation I2C_STATUS_NOERROR or I2C_STATUS_ERROR
 *
 * Author   : IKLEBANOV
 *^^*/
UINT CI2CScript::AccessI2CProvider( PDEVICE_OBJECT pdoClient, PI2CControl pi2cAccessBlock)
{
    UINT            uiStatus;
    LARGE_INTEGER   liTime;

    do
    {
        // this loop is infinitive. It has to be taken care of
        if( m_i2cProviderInterface.i2cAccess( pdoClient, pi2cAccessBlock) != STATUS_SUCCESS)
        {
            uiStatus = I2C_STATUS_ERROR;
            break;
        }

        if( pi2cAccessBlock->Status != I2C_STATUS_BUSY)
        {
            uiStatus = pi2cAccessBlock->Status;
            break;
        }

        liTime.QuadPart = I2CSCRIPT_DELAY_GETPROVIDERSTATUS;
        ::KeDelayExecutionThread( KernelMode, FALSE, &liTime);

        pi2cAccessBlock->Command = I2C_COMMAND_STATUS;

    } while( TRUE);

    return( uiStatus);
}



/*^^*
 *      GetScriptResults()
 * Purpose  : returns result of the executed Script
 *              This function idealy is called twice:
 *                  first time with the puchReadBuffer = NULL to retrive the number of bytes read
 *                  second time - to fill in the pointer
 * Inputs   :   PUINT puiReadCount  : pointer to the counter of the bytes were read
 *              PUCH puchReadBuffer : pointer to the buffer to put the data
 *
 * Outputs  : UINT : status of the I2C operation
 *              If the status is I2C_STATUS_ERROR, puiReadCount will contain the step, where
 *              I2CScript failed
 * Author   : IKLEBANOV
 *^^*/
UINT CI2CScript::GetScriptResults( PUINT puiReadCount, PUCHAR puchReadBuffer)
{
    UINT nScriptIndex, nCount;

    ASSERT( puiReadCount != NULL);

    if( m_bExecutionInProcess)
        return( I2C_STATUS_BUSY);

    if( m_nScriptLength != m_nCompletionIndex)
    {
        // if the case of failure, step where I2CScript failed is return
        // instead of Read Counter. The returned status indicates the
        // failure
        * puiReadCount = m_nCompletionIndex;

        return( I2C_STATUS_ERROR);
    }
    else
    {
        nCount = 0;

        for( nScriptIndex = 0; nScriptIndex < m_nCompletionIndex; nScriptIndex ++)
        {
            if( m_i2cScript[nScriptIndex].ulCommand == I2C_COMMAND_READ)
            {
                if( puchReadBuffer != NULL)
                    // fill in the supplied buffer
                    puchReadBuffer[nCount] = m_i2cScript[nScriptIndex].byData;
                nCount ++;
            }
        }

        * puiReadCount = nCount;

        return( I2C_STATUS_NOERROR);
    }
}



/*^^*
 *      InitializeAttachI2CProvider()
 * Purpose  : gets the pointer to the parent I2C Provider interface using
 *              several IRP_MJ_??? functions.
 *              This function will be called at Low priority
 *
 * Inputs   :   I2CINTERFACE * pI2CInterface    : pointer to the Interface to be filled in
 *              PDEVICE_OBJECT pDeviceObject    : MiniDriver device object, which is a child of I2C Master
 *
 * Outputs  : BOOL  - returns TRUE, if the interface was found
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::InitializeAttachI2CProvider( I2CINTERFACE * pI2CInterface, PDEVICE_OBJECT pDeviceObject)
{
    BOOL bResult;

    bResult = LocateAttachI2CProvider( pI2CInterface, pDeviceObject, IRP_MJ_PNP);
    if(( pI2CInterface->i2cOpen == NULL) || ( pI2CInterface->i2cAccess == NULL))
    {
        TRAP;
        OutputDebugError(( "CI2CScript(): interface has NULL pointers\n"));
        bResult = FALSE;
    }

    return( bResult);
}



/*^^*
 *      LocateAttachI2CProvider()
 * Purpose  : gets the pointer to the parent I2C Provider interface
 *              This function will be called at Low priority
 *
 * Inputs   :   I2CINTERFACE * pI2CInterface    : pointer to the Interface to be filled in
 *              PDEVICE_OBJECT pDeviceObject    : MiniDriver device object, which is a child of I2C Master
 *              int         nIrpMajorFunction   : IRP major function to query the I2C Interface
 *
 * Outputs  : BOOL  - returns TRUE, if the interface was found
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::LocateAttachI2CProvider( I2CINTERFACE * pI2CInterface, PDEVICE_OBJECT pDeviceObject, int nIrpMajorFunction)
{
    PIRP    pIrp;
    BOOL    bResult = FALSE;

    ENSURE
    {
        PIO_STACK_LOCATION  pNextStack;
        NTSTATUS            ntStatus;
        KEVENT              Event;
            
            
        pIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE);
        if( pIrp == NULL)
        {
            TRAP;
            OutputDebugError(( "CI2CScript(): can not allocate IRP\n"));
            FAIL;
        }

        pNextStack = IoGetNextIrpStackLocation( pIrp);
        if( pNextStack == NULL)
        {
            TRAP;
            OutputDebugError(( "CI2CScript(): can not allocate NextStack\n"));
            FAIL;
        }

        pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
        pNextStack->MajorFunction = (UCHAR)nIrpMajorFunction;
        pNextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;
        KeInitializeEvent( &Event, NotificationEvent, FALSE);

        IoSetCompletionRoutine( pIrp,
                                I2CScriptIoSynchCompletionRoutine,
                                &Event, TRUE, TRUE, TRUE);

        pNextStack->Parameters.QueryInterface.InterfaceType = ( struct _GUID *)&GUID_I2C_INTERFACE;
        pNextStack->Parameters.QueryInterface.Size = sizeof( I2CINTERFACE);
        pNextStack->Parameters.QueryInterface.Version = 1;
        pNextStack->Parameters.QueryInterface.Interface = ( PINTERFACE)pI2CInterface;
        pNextStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;

        ntStatus = IoCallDriver( pDeviceObject, pIrp);

        if( ntStatus == STATUS_PENDING)
            KeWaitForSingleObject(  &Event,
                                    Suspended, KernelMode, FALSE, NULL);
        if(( pI2CInterface->i2cOpen == NULL) || ( pI2CInterface->i2cAccess == NULL))
            FAIL;

        bResult = TRUE;

    } END_ENSURE;
 
    if( pIrp != NULL)
        IoFreeIrp( pIrp);

    return( bResult);
}


/*^^*
 *      I2CScriptIoSynchCompletionRoutine()
 * Purpose  : This routine is for use with synchronous IRP processing.
 *              All it does is signal an event, so the driver knows it and can continue.
 *
 * Inputs   :   PDEVICE_OBJECT DriverObject : Pointer to driver object created by system
 *              PIRP pIrp                   : Irp that just completed
 *              PVOID Event                 : Event we'll signal to say Irp is done
 *
 * Outputs  : none
 * Author   : IKLEBANOV
 *^^*/
extern "C"
NTSTATUS I2CScriptIoSynchCompletionRoutine( IN PDEVICE_OBJECT pDeviceObject,
                                            IN PIRP pIrp,
                                            IN PVOID Event)
{

    KeSetEvent(( PKEVENT)Event, 0, FALSE);
    return( STATUS_MORE_PROCESSING_REQUIRED);
}

⌨️ 快捷键说明

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