📄 i2script.cpp
字号:
//==========================================================================;
//
// 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 + -