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

📄 i2script.cpp

📁 winddk src目录下的WDM源码压缩!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//==========================================================================;
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//  PURPOSE.
//
//  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
//
//  I2CSCRPT.C
//  I2CScript class implementation. 
//      Main Include Module.
//
//==========================================================================;

extern "C"
{
#define INITGUID

#include "strmini.h"
#include "ksmedia.h"
#include "wdm.h"

#include "wdmdebug.h"
}

#include "i2script.h"
#include "wdmdrv.h"


/*^^*
 *      operator new
 * Purpose  : CI2CScript class overloaded operator new.
 *              Provides placement for a CI2CScript class object from the PADAPTER_DEVICE_EXTENSION
 *              allocated by the StreamClassDriver for the MiniDriver.
 *
 * Inputs   :   UINT size_t         : size of the object to be placed
 *              PVOID pAllocation   : casted pointer to the CI2CScript allocated data
 *
 * Outputs  : PVOID : pointer of the CI2CScript class object
 * Author   : IKLEBANOV
 *^^*/
PVOID CI2CScript::operator new( size_t stSize,  PVOID pAllocation)
{

    if( stSize != sizeof( CI2CScript))
    {
        OutputDebugError(( "CI2CScript: operator new() fails\n"));
        return( NULL);
    }
    else
        return( pAllocation);
}



/*^^*
 *      CI2CScript()
 * Purpose  : CI2CScript class constructor.
 *              Performs checking of the I2C provider presence. Sets the script in the initial state.
 *
 * Inputs   :   PUINT puiError                      : pointer to return a completion error code
 *              PHW_STREAM_REQUEST_BLOCK    pSrb    : pointer to HW_INITIALIZE SRB
 *
 * Outputs  : none
 * Author   : IKLEBANOV
 *^^*/
CI2CScript::CI2CScript( PPORT_CONFIGURATION_INFORMATION pConfigInfo,
                        PUINT puiErrorCode)
{
    m_dwI2CAccessKey = 0;

    m_i2cProviderInterface.i2cOpen = NULL;
    m_i2cProviderInterface.i2cAccess = NULL;

    m_pdoDriver = NULL;

    if( !InitializeAttachI2CProvider( &m_i2cProviderInterface, pConfigInfo->PhysicalDeviceObject))
        * puiErrorCode = WDMMINI_ERROR_NOI2CPROVIDER;
    else
    {
        // there was no error to get I2CInterface from the MiniVDD
        m_pdoDriver = pConfigInfo->RealPhysicalDeviceObject;
        m_ulI2CAccessClockRate = I2C_FIXED_CLOCK_RATE;
        * puiErrorCode = WDMMINI_NOERROR;
    }

    OutputDebugTrace(( "CI2CScript:CI2CScript() exit Error = %x\n", * puiErrorCode));
}



/*^^*
 *      LockI2CProvider()
 * Purpose  : locks the I2CProvider for exclusive use
 *
 * Inputs   : none
 *
 * Outputs  : BOOL : retunrs TRUE, if the I2CProvider is locked
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::LockI2CProvider( void)
{
    BOOL        bResult;
    I2CControl  i2cAccessBlock;

    bResult = FALSE;

    ENSURE
    {
        if(( m_i2cProviderInterface.i2cOpen == NULL)    || 
            ( m_i2cProviderInterface.i2cAccess == NULL) ||
            ( m_pdoDriver == NULL))
            FAIL;

        i2cAccessBlock.Status = I2C_STATUS_NOERROR;
        if( m_i2cProviderInterface.i2cOpen( m_pdoDriver, TRUE, &i2cAccessBlock) != STATUS_SUCCESS)
        {
            OutputDebugError(( "CI2CScript: LockI2CProvider() bResult = %x\n", bResult));
            FAIL;
        }

        if( i2cAccessBlock.Status != I2C_STATUS_NOERROR)
        {
            OutputDebugError(( "CI2CScript: LockI2CProvider() Status = %x\n", i2cAccessBlock.Status));
            FAIL;
        }

        // the I2C Provider has granted access - save dwCookie for further use
        m_dwI2CAccessKey = i2cAccessBlock.dwCookie;

        bResult = TRUE;

    } END_ENSURE;

    return( bResult);
}



/*^^*
 *      LockI2CProvider()
 * Purpose  : locks the I2CProvider for exclusive use. Provides attempts to lock the
 *              provider unless either the time-out condition or the attempt succeeded.
 *
 * Inputs   : none
 *
 * Outputs  : BOOL : retunrs TRUE, if the I2CProvider is locked
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::LockI2CProviderEx( void)
{
    LARGE_INTEGER liTime, liOperationStartTime;

    liOperationStartTime.QuadPart = 0;

    while( !LockI2CProvider())
    {
        KeQuerySystemTime( &liTime);

        if( !liOperationStartTime.QuadPart)
            liOperationStartTime.QuadPart = liTime.QuadPart;
        else
            if( liTime.QuadPart - liOperationStartTime.QuadPart >
                I2CSCRIPT_TIMELIMIT_OPENPROVIDER)
            {
                // the time is expired - abort the initialization
                return( FALSE);
            }

        liTime.QuadPart = I2CSCRIPT_DELAY_OPENPROVIDER;
        KeDelayExecutionThread( KernelMode, FALSE, &liTime);
    }

    return( TRUE);
}




/*^^*
 *      GetI2CProviderLockStatus()
 * Purpose  : retrieves I2CProvider lock status
 *
 * Inputs   : none
 *
 * Outputs  : BOOL : retunrs TRUE, if the I2CProvider has been locked
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::GetI2CProviderLockStatus( void)
{

    return( m_dwI2CAccessKey);
}




/*^^*
 *      ReleaseI2CProvider()
 * Purpose  : releases the I2CProvider for other clients' use
 *
 * Inputs   : none
 *
 * Outputs  : BOOL : retunrs TRUE, if the I2CProvider is released
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::ReleaseI2CProvider( void)
{
    BOOL        bResult;
    I2CControl  i2cAccessBlock;

    bResult = FALSE;

    ENSURE
    {
        if(( m_i2cProviderInterface.i2cOpen == NULL)    ||
            ( m_i2cProviderInterface.i2cAccess == NULL) ||
            ( m_pdoDriver == NULL))
            // the I2CProvider was not found
            FAIL;

        i2cAccessBlock.Status = I2C_STATUS_NOERROR;
        i2cAccessBlock.dwCookie = m_dwI2CAccessKey;
        i2cAccessBlock.ClockRate = m_ulI2CAccessClockRate;
        if( m_i2cProviderInterface.i2cOpen( m_pdoDriver, FALSE, &i2cAccessBlock) != STATUS_SUCCESS)
        {
            OutputDebugError(( "CI2CScript: ReleaseI2CProvider() bResult = %x\n", bResult));
            FAIL;
        }

        if( i2cAccessBlock.Status != I2C_STATUS_NOERROR)
        {
            OutputDebugError(( "CI2CScript: ReleaseI2CProvider() bResult = %x\n", bResult));
            FAIL;
        }

        m_dwI2CAccessKey = 0;
        bResult = TRUE;

    } END_ENSURE;

    return( bResult);
}



/*^^*
 *      PerformI2CPacketOperation()
 * Purpose  : synchronosly executes I2C access packet. It assumed to be executed at Low priority.
 *              The function does not return until the I2C session is done. The execution
 *              is not dependent on the I2C Provider lock status
 *      
 * Inputs   :   PI2CPacket pI2CPacket : pointer to I2C access packet
 *
 * Outputs  : BOOL : returns TRUE, if I2C operation was carried out successfuly
 *              The error status is returned via uchI2CResult field of the PI2CPacket
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::PerformI2CPacketOperation( IN OUT PI2CPacket pI2CPacket)
{
    BOOL bResult;

    if( GetI2CProviderLockStatus())
        // the Provider was locked before and we're not going to change it
        bResult = ExecuteI2CPacket( pI2CPacket);
    else
    {
        // the Provider was not locked and it's our responsibility to lock it first,
        // execute I2C operation and release it after the use
        if( LockI2CProviderEx())
        {
            bResult = ExecuteI2CPacket( pI2CPacket);
            ReleaseI2CProvider();
        }
        else
            bResult = FALSE;
    }

    return( bResult);
}



/*^^*
 *      ExecuteI2CPacket()
 * Purpose  : synchronosly executes I2C access packet. It assumed to be executed at Low priority.
 *              The function does not return until the I2C session is done. This kind of access
 *              is used during initialization ( boot up) time only. This function should be
 *              called only after the I2CProvider was locked for exclusive service
 *      
 * Inputs   :   PI2CPacket pI2CPacket : pointer to I2C access packet
 *
 * Outputs  : BOOL : returns TRUE, if I2C operation was carried out successfuly
 *              The error status is returned via uchI2CResult field of the PI2CPacket
 * Author   : IKLEBANOV
 *^^*/
BOOL CI2CScript::ExecuteI2CPacket( IN OUT PI2CPacket pI2CPacket)
{
    UINT    nError, cbCount;
    UCHAR   uchValue;
    UCHAR   uchI2CResult = I2C_STATUS_ERROR;

    ENSURE
    {
        I2CControl  i2cAccessBlock;

        if(( nError = CheckI2CScriptPacket( pI2CPacket)) != I2CSCRIPT_NOERROR)
            FAIL;

        // we'll use I2CProvider interface, assuming there is a syncronous provider
        // for asynchronous provider some work has to be added. 16 bits emulation is
        // not supported at this time either. This implementation does not support
        // Read-Modify-Write request either
        ENSURE
        {
            UINT        nIndex;

            i2cAccessBlock.dwCookie = m_dwI2CAccessKey;
            i2cAccessBlock.ClockRate = m_ulI2CAccessClockRate;

            // We assume the last byte in the buffer belongs to the Write operation 
            // after Read-Modify, is specified.
            cbCount = ( pI2CPacket->usFlags & I2COPERATION_READWRITE) ?
                            ( pI2CPacket->cbWriteCount - 1) : ( pI2CPacket->cbWriteCount);

            if( cbCount)
            {
                // implement a write request
                // apply START condition with the I2C chip address first
                i2cAccessBlock.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK;
                i2cAccessBlock.Command = I2C_COMMAND_WRITE;
                i2cAccessBlock.Data = pI2CPacket->uchChipAddress & 0xFE;
                if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
                    FAIL;

                i2cAccessBlock.Flags = I2C_FLAGS_ACK;
                for( nIndex = 0; nIndex < cbCount; nIndex ++)
                {
                    // write the data from the buffer
                    i2cAccessBlock.Data = pI2CPacket->puchWriteBuffer[nIndex];
                    if(( nIndex == cbCount - 1) &&
                        !( pI2CPacket->usFlags & I2COPERATION_RANDOMACCESS))
                        // the last byte to write - apply STOP condition, if no
                        // I2COPERATION_RANDOMACCESS flag is specified
                        i2cAccessBlock.Flags |= I2C_FLAGS_STOP;

                    if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)
                        break;
                }
                if( nIndex != cbCount)
                    FAIL;
/*  // STOP condition is applied withe the last byte to be written
                // apply stop condition as the end of write operation
                i2cAccessBlock.Flags = I2C_FLAGS_STOP;
                i2cAccessBlock.Command = I2C_COMMAND_NULL;
                m_i2cProviderInterface.i2cAccess( m_pdoDriver, &i2cAccessBlock);
*/
            }

            if( pI2CPacket->cbReadCount)
            {
                // implement a read request
                // apply START condition with the I2C chip address first
                i2cAccessBlock.Flags = I2C_FLAGS_START | I2C_FLAGS_ACK;
                i2cAccessBlock.Command = I2C_COMMAND_WRITE;
                i2cAccessBlock.Data = pI2CPacket->uchChipAddress | 0x01;
                if( AccessI2CProvider( m_pdoDriver, &i2cAccessBlock) != I2C_STATUS_NOERROR)

⌨️ 快捷键说明

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