📄 eons.cpp
字号:
{
for( int i = 1; i <= (int)dwItemCount; i++ )
{
DWORD dw = 0;
memset( pBuf, 0, dwSize );
CRSMRecord kk( EFopl, i, dwSize );
hr2 = kk.Read();
kk.Dump();
if ( SUCCEEDED( hr2 ) )
{
dw = dwSize;
BOOL fOk = kk.GetRecord( (BYTE*)pBuf, dw );
hr2 = ( fOk ? S_OK : E_FAIL );
}
if ( SUCCEEDED( hr2 ) && pBuf[0] != (char)0xff )
{
const char *cptr = pBuf;
/* 3GPP TS 31.102 version 5.7.0 section 4.2.59 */
int b[6];
for( int j = 0; j < 3; j++ )
{
char x = pBuf[j];
b[j*2] = ( 0x0f & ( x >> 4 ) );
b[j*2+1] = ( 0x0f & x );
}
/* BCD offset */
int bindex[] = { 1, 0, 3, 5, 4, 2 };
BOOL fDeleted = FALSE;
char szPLMN[ARRAY_LENGTH(b)+1];
for( int j = 0; j < ARRAY_LENGTH(b) && !fDeleted; j++ )
{
szPLMN[j] = NULL;
if ( 0 <= b[bindex[j]] && b[bindex[j]] < 10 )
{
/* digits 0-9 */
szPLMN[j] = ( '0'+b[bindex[j]] );
}
else if ( b[bindex[j]] == 0x0d )
{
/* wildcard */
szPLMN[j] = WILDCARD;
}
else if ( b[bindex[j]] == 0x0f )
{
/* dontcare */
szPLMN[j] = DONTCARE;
}
else
{
/* deleted entry */
fDeleted = TRUE;
}
}
szPLMN[ARRAY_LENGTH(szPLMN)-1] = NULL;
OPLStruct opl;
memset( &opl, 0, sizeof(opl) );
if ( !fDeleted )
{
long lacA = ( ( 0x0ff & pBuf[3] ) << 8 ) + ( 0x0ff & pBuf[4] );
long lacZ = ( ( 0x0ff & pBuf[5] ) << 8 ) + ( 0x0ff & pBuf[6] );
long idx = ( 0x0ff & pBuf[7] );
ASSERT( idx > 0 );
strncpyz( opl.szPLMN, szPLMN, ARRAY_LENGTH(opl.szPLMN) );
opl.dwLACa = lacA;
opl.dwLACz = lacZ;
opl.dwIndex = idx;
}
else
{
/* index of 0 means deleted entry */
opl.dwIndex = 0;
}
m_opl.AddThing( opl );
}
}
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
if ( pBuf != NULL )
{
delete[] pBuf;
pBuf = NULL;
}
}
}
return hr;
}
HRESULT
EONS::ReadPNNData()
{
/* assumption -- m_cs has been acquired */
HRESULT hr = E_FAIL;
CRSMStatus k( EFpnn );
HRESULT hr2 = k.Read();
k.Dump();
if ( SUCCEEDED( hr2 ) )
{
RILSIMRECORDSTATUS rsrs = k.GetStatus();
if ( ( rsrs.dwParams & RIL_PARAM_SRS_SIZE ) &&
( rsrs.dwParams & RIL_PARAM_SRS_ITEMCOUNT ) )
{
const DWORD dwSize = rsrs.dwSize;
const DWORD dwItemCount = rsrs.dwItemCount;
char *pBuf = new char[ dwSize ];
if ( pBuf != NULL )
{
for( int i = 1; i <= (int)dwItemCount; i++ )
{
DWORD dw = 0;
memset( pBuf, 0, dwSize );
CRSMRecord kk( EFpnn, i, dwSize );
hr2 = kk.Read();
kk.Dump();
if ( SUCCEEDED( hr2 ) )
{
dw = dwSize;
BOOL fOk = kk.GetRecord( (BYTE*)pBuf, dw );
hr2 = ( fOk ? S_OK : E_FAIL );
}
RILOPERATORNAMES ron;
memset( &ron, 0, sizeof(ron) );
ron.cbSize = sizeof(ron);
if ( SUCCEEDED( hr2 ) && pBuf[0] != (char)0xff )
{
const char *cptr = pBuf;
/* 3GPP TS 31.102 version 5.7.0 section 4.2.58 */
const char *Ftlv = NULL;
int Fiei = 0;
int Flen = 0;
if ( cptr != NULL && dw >= 2 )
{
Fiei = (int)( 0x0ff & cptr[0] );
Flen = (int)( 0x0ff & cptr[1] );
if ( (int)dw >= 2+Flen )
{
Ftlv = cptr;
cptr += ( 2+Flen );
dw -= ( 2+Flen );
}
else
{
cptr = NULL;
dw = 0;
}
}
const char *Stlv = NULL;
int Siei = 0;
int Slen = 0;
if ( cptr != NULL && dw >= 2 )
{
Siei = (int)( 0x0ff & cptr[0] );
Slen = (int)( 0x0ff & cptr[1] );
if ( (int)dw >= 2+Slen )
{
Stlv = cptr;
}
}
/* long name */
if ( Fiei == IEIfullname && Ftlv != NULL )
{
BOOL fLong = DecodeNetworkNameTLV( Ftlv, ron.szLongName, ARRAY_LENGTH(ron.szLongName) );
if ( fLong )
{
ron.dwParams |= RIL_PARAM_ON_LONGNAME;
}
}
/* short name */
if ( Siei == IEIshortname && Stlv != NULL )
{
BOOL fShort = DecodeNetworkNameTLV( Stlv, ron.szShortName, ARRAY_LENGTH(ron.szShortName) );
if ( fShort )
{
ron.dwParams |= RIL_PARAM_ON_SHORTNAME;
}
}
}
/* add to maintain PNN order regardless of read/parse status */
m_pnn.AddThing( ron );
}
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
if ( pBuf != NULL )
{
delete[] pBuf;
pBuf = NULL;
}
}
}
return hr;
}
BOOL
EONS::DecodeNetworkNameTLV( const char *cptr, char *pszOUT, DWORD dwOut ) const
{
BOOL fOk = FALSE;
if ( cptr[0] != (char)0xff )
{
/* 3GPP TS 24.008 version 3.2.1 section 10.5.3.5a */
int iei = ( 0x07f & cptr[0] );
int len = ( 0x0ff & cptr[1] );
int ext = ( 0x01 & ( cptr[2] >> 7 ) );
int cs = ( 0x07 & ( cptr[2] >> 4 ) );
int ci = ( 0x01 & ( cptr[2] >> 3 ) );
int spr = ( 0x07 & cptr[2] );
#if 0
_tprintf(TEXT("iei [%d]"), iei );
_tprintf(TEXT("len [%d]"), len );
_tprintf(TEXT("ext [%d] cs [%d] ci [%d] spr [%d]"), ext, cs, ci, spr );
#endif
if ( len > 0 )
{
TCHAR szBuf[128];
memset( szBuf, 0, sizeof(szBuf) );
if ( cs == 0 )
{
/* cell broadcast data coding scheme, GSM default alphabet */
/* GSM 03.38 */
int offset = 3;
const char *pcszA = cptr+offset;
/* adjust */
--len;
UINT lenZ = 0;
ConvertToUnicode( ENCODING_GSMDEFAULT, pcszA, (UINT)len, szBuf, ARRAY_LENGTH(szBuf), lenZ );
pszOUT[lenZ] = 0;
AnsiString as(szBuf);
strncpyz( pszOUT, (const char *)as, dwOut );
}
else if ( cs == 1 )
{
/* UCS2 (16bit) */
int offset = 3;
const char *pcszA = cptr+offset;
/* adjust */
--len;
ASSERT( len % 2 == 0 );
int iNum = ( len / 2 );
for( int i = 0; i < iNum && i < ARRAY_LENGTH(szBuf)-1; i++ )
{
szBuf[i] = (TCHAR)( ( 0x0ff00 & ( pcszA[i*2] << 8 ) ) | ( 0x0ff & pcszA[i*2+1] ) );
}
AnsiString as(szBuf);
strncpyz( pszOUT, (const char *)as, dwOut );
}
else
{
/* reserved coding scheme */
ASSERT( FALSE );
pszOUT[0] = 0;
}
fOk = ( pszOUT[0] != NULL );
}
}
return fOk;
}
BOOL
EONS::Match( DWORD dwPLMN, DWORD dwLAC, RILOPERATORNAMES *pRON ) const
{
BOOL fMatched = FALSE;
BOOL fHasLAC = ( dwLAC != 0xFFFFFFFF );
ASSERT( dwPLMN <= 999999 );
ASSERT( dwLAC <= 0x0ffff || dwLAC == 0xFFFFFFFF );
/* only support 6-digit PLMN */
if ( dwPLMN <= 999999 && ( dwLAC <= 0x0ffff || dwLAC == 0xFFFFFFFF ) )
{
SYNCBLOCK( m_cs );
if ( m_fDoneReading )
{
DWORD entries[2] = { dwPLMN, 0xFFFFFFFF };
if ( dwPLMN <= 99999 )
{
/* normalize to 6-digit PLMN */
/* this follows how network.cpp:GetLongOperatorName() expands 5-digit PLMN to 6-digit */
DWORD YYY = ( dwPLMN / 100 );
DWORD XX = ( dwPLMN % 100 );
entries[0] = ( YYY * 1000 + XX ); /* YYY0XX */
entries[1] = ( dwPLMN * 10 ); /* YYYXX0 */
}
for( int i = 0; i < ARRAY_LENGTH(entries) && entries[i] != 0xFFFFFFFF && !fMatched; i++ )
{
DWORD dwEntry = entries[i];
int digits[] =
{
( dwEntry / 100000 ),
( ( dwEntry / 10000 ) % 10 ),
( ( dwEntry / 1000 ) % 10 ),
( ( dwEntry / 100 ) % 10 ),
( ( dwEntry / 10 ) % 10 ),
( dwEntry % 10 )
};
#ifdef DEBUG
/* at least as large as dwPLMN to catch problem with normalizing */
ASSERT( dwEntry >= dwPLMN );
/* should not process this marker entry */
ASSERT( dwEntry != 0xFFFFFFFF );
/* enforce 6-digit PLMN */
ASSERT( dwEntry <= 999999 );
/* ensure digits[] is setup right */
ASSERT( ARRAY_LENGTH(digits) == 6 );
for( int j = 0; j < ARRAY_LENGTH(digits); j++ )
{
ASSERT( 0 <= digits[j] && digits[j] <= 9 );
}
#endif
int iPNN = -1;
int c = const_cast<GrowableThingCollection<OPLStruct>*>( &m_opl )->GetSize();
for( int j = 0; j < c && !fMatched; j++ )
{
OPLStruct opl = const_cast<GrowableThingCollection<OPLStruct>*>( &m_opl )->GetThingAtIndex( j );
/* PLMN match */
BOOL fMatchedPLMN = TRUE;
for( int k = 0; k < 6 && fMatchedPLMN; k++ )
{
if ( opl.szPLMN[k] == WILDCARD )
{
/* always match */
}
else if ( opl.szPLMN[k] == DONTCARE )
{
/* 3GPP TS 24.008 version 3.2.1 Release 1999 Table 10.5.3 */
/* handling the case for YYYXX0 */
fMatchedPLMN = ( k == 5 && dwPLMN <= 99999 && digits[k] == 0 );
}
else
{
/* match exact digit */
fMatchedPLMN = ( opl.szPLMN[k]-'0' == digits[k] );
}
}
/* LAC match */
BOOL fMatchedLAC = ( opl.dwLACa == 0x0000 && opl.dwLACz == 0xfffe );
if ( !fMatchedLAC && fHasLAC )
{
fMatchedLAC = ( opl.dwLACa <= dwLAC && dwLAC <= opl.dwLACz );
}
fMatched = ( fMatchedPLMN && fMatchedLAC );
if ( fMatched )
{
iPNN = static_cast<int>( opl.dwIndex );
/* skip deleted entry */
fMatched = ( iPNN != 0 );
}
}
if ( fMatched )
{
if ( iPNN > 0 )
{
int c2 = const_cast<GrowableThingCollection<RILOPERATORNAMES>*>( &m_pnn )->GetSize();
if ( iPNN-1 < c2 )
{
RILOPERATORNAMES ron = const_cast<GrowableThingCollection<RILOPERATORNAMES>*>( &m_pnn )->GetThingAtIndex( iPNN-1 );
/* consider matched IFF there is a long name */
fMatched = ( ( ron.dwParams & RIL_PARAM_ON_LONGNAME ) != 0 );
if ( fMatched && pRON != NULL )
{
memcpy( pRON, &ron, sizeof(RILOPERATORNAMES) );
}
}
else
{
ASSERT( FALSE );
fMatched = FALSE;
}
}
else
{
ASSERT( FALSE );
fMatched = FALSE;
}
}
}
}
}
return fMatched;
}
void
EONS::Validate() const
{
#ifdef DEBUG
/* normally everything from SIM should be fine, right? */
{
SYNCBLOCK( m_cs );
int iOPL = const_cast<GrowableThingCollection<OPLStruct>*>( &m_opl )->GetSize();
int iPNN = const_cast<GrowableThingCollection<RILOPERATORNAMES>*>( &m_pnn )->GetSize();
if ( iOPL > 0 )
{
ASSERT( iPNN > 0 );
}
/* 3GPP TS 31.102 version 5.7.0 release 5 section 4.2.59 EFOPL */
/* PNN record identifier is of size 1 byte -- maximum 2^8 PNN entries */
ASSERT( 0 <= iPNN && iPNN < 256 );
for( int i = 0; i < iOPL; i++ )
{
OPLStruct opl = const_cast<GrowableThingCollection<OPLStruct>*>( &m_opl )->GetThingAtIndex( i );
for( int j = 0; j < (int)strlen(opl.szPLMN); j++ )
{
/* make sure the DONTCARE is in the MNC3 position */
if ( opl.szPLMN[j] == DONTCARE )
{
ASSERT( j == 5 );
}
}
}
#ifdef CHECK
for( int i = 0; i < iOPL; i++ )
{
OPLStruct opl = const_cast<GrowableThingCollection<OPLStruct>*>( &m_opl )->GetThingAtIndex( i );
/* 6-digit PLMN for not-deleted entry */
if ( opl.dwIndex != 0 )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -