bool IRAConvertGsm7Bit(const u8 *iraData, u16 iraLen, u8 *gsmData, u16 *gsmLen, bool dropInconvertible)
{
bool result = TRUE;
u8 gsmValue = 0;
u16 i = 0;
*gsmLen = 0;
for (i = 0; i < iraLen; i++)
{
gsmValue = ira_to_gsm7[*iraData];
if (gsmValue != INVALID_CHAR)
{
*gsmData++ = gsmValue;
(*gsmLen)++;
}
else if ((gsmValue = ira_to_ext_gsm7[*iraData]) != INVALID_CHAR)
{
*gsmData++ = 0x1B;
*gsmData++ = gsmValue;
*gsmLen += 2;
}
else if (!dropInconvertible)
{
result = FALSE;
break;
}
else
{
/* Replace inconvertible char with a space */
*gsmData++ = REPLACEMENT_CHAR;
(*gsmLen)++;
}
iraData++;
}
return result;
}
s32 gsmInvertNumbers(const char* pSrc, char* pDst, s32 nSrcLength)
{
s32 nDstLength;
u8 ch;
s32 i;
nDstLength = nSrcLength;
for(i=0; i<nSrcLength;i+=2)
{
ch = *pSrc++;
*pDst++ = *pSrc++;
*pDst++ = ch;
}
if(nSrcLength & 1)
{
*(pDst-2) = 'F';
nDstLength++;
}
*pDst = '\0';
return nDstLength;
}
s32 gsmSerializeNumbers(const char* pSrc, char* pDst, s32 nSrcLength)
{
s32 nDstLength;
s32 i = 0;
u8 ch;
nDstLength = nSrcLength;
for(i=0; i<nSrcLength;i+=2)
{
ch = *pSrc++;
*pDst++ = *pSrc++;
*pDst++ = ch;
}
if(*(pDst-1) == 'F')
{
pDst--;
nDstLength--;
}
*pDst = '\0';
return nDstLength;
}
s32 gsmBytes2String(const u8 *pSrc, char *pDst, s32 nSrcLength)
{
const u8 tab[]="0123456789ABCDEF";
s32 i = 0;
for (i=0; i < nSrcLength; i++)
{
*pDst++ = tab[*pSrc >> 4];
*pDst++ = tab[*pSrc & 0x0f];
pSrc++;
}
*pDst = '\0';
return nSrcLength * 2;
}
s32 gsmString2Bytes(const char* pSrc, u8* pDst, s32 nSrcLength)
{
s32 i = 0;
for (i=0; i<nSrcLength; i+=2)
{
if(*pSrc>='0' && *pSrc<='9')
{
*pDst = (*pSrc - '0') << 4;
}
else
{
*pDst = (*pSrc - 'A' + 10) << 4;
}
pSrc++;
if(*pSrc>='0' && *pSrc<='9')
{
*pDst |= *pSrc - '0';
}
else
{
*pDst |= *pSrc - 'A' + 10;
}
pSrc++;
pDst++;
}
return nSrcLength / 2;
}
s32 gsmEncode8bit(const char* pSrc,u8 *pDst, s32 nSrcLength)
{
s32 i = 0;
for(i=0; i<nSrcLength; i++)
{
*pDst++ = *pSrc++;
}
return nSrcLength;
}
s32 gsmDecode7bit(const u8* pSrc, char *pDst, s32 nSrcLength)
{
s32 nSrc;
s32 nDst;
s32 nByte;
u8 nLeft;
nSrc = 0;
nDst = 0;
nByte = 0;
nLeft = 0;
while(nSrc<nSrcLength)
{
*pDst = ((*pSrc << nByte) | nLeft) & 0x7f;
nLeft = *pSrc >> (7-nByte);
pDst++;
nDst++;
nByte++;
if(nByte == 7)
{
*pDst = nLeft;
pDst++;
nDst++;
nByte = 0;
nLeft = 0;
}
pSrc++;
nSrc++;
}
*pDst = 0;
return nDst;
}
s32 gsmEncode7bit(const char* pSrc, u8* pDst, s32 nSrcLength)
{
s32 nSrc;
s32 nDst;
s32 nChar;
u8 nLeft = 0;
u8 cSrc;
nSrc = 0;
nDst = 0;
while(nSrc<nSrcLength)
{
nChar = nSrc & 7;
cSrc = *pSrc;
if(nChar == 0)
{
nLeft = cSrc;
}
else
{
*pDst++ = (cSrc << (8-nChar)) | nLeft;
nLeft = cSrc >> nChar;
nDst++;
}
pSrc++; nSrc++;
}
return nDst;
}
s32 gsmDecode8bit(const u8* pSrc, char * pDst, s32 nSrcLength)
{
s32 i = 0;
for(i=0; i<nSrcLength; i++)
{
*pDst++ = *pSrc++;
}
return nSrcLength;
}
u8 gsmDecodeSmsValidity(const u8 *data,SmsValidityFormatType validityFormat)
{
u8 pos = 0;
if (data == NULL )
{
return 0;
}
else
{
switch(validityFormat)
{
case SMS_VALIDITY_NONE:
break;
case SMS_VALIDITY_RELATIVE:
pos ++;
break;
case SMS_VALIDITY_ABSOLUTE:
pos += 7;
break;
case SMS_VALIDITY_ENHANCED:
break;
}
}
return pos*2;
}
u8 SmsDecodeDcs(const u8 *data, SmsDcsType *dcs)
{
u8 pos = 0;
u8 i;
if (data == NULL || dcs == NULL)
{
return 0;
}
dcs->msgClass = SMS_MSG_CLASS_NONE;
dcs->msgWaiting = SMS_MSG_WAITING_NONE;
dcs->alphabet = SMS_ALPHABET_7_BIT_DEFAULT;
dcs->isCompressed = FALSE;
/* bits 7-6 */
i = ( data[pos] & 0xC0 ) >> 6;
switch( i )
{
case 0:
/* pattern 00xx xxxx */
dcs->isCompressed = data[pos] & 0x20;
if( data[pos] & 0x10 )
{
dcs->msgClass = (SmsMsgClassType) (data[pos] & 0x03);
}
else
{
/* no class information */
dcs->msgClass = SMS_MSG_CLASS_NONE;
}
dcs->alphabet = (SmsAlphabetType) (( data[pos] & 0x0C ) >> 2);
break;
case 3:
/* bits 5-4 */
if( (data[pos] & 0x30) == 0x30 )
{
/* pattern 1111 xxxx */
/* bit 3 is reserved */
/* bit 2 */
dcs->alphabet = (data[pos] & 0x04 ) ? SMS_ALPHABET_8_BIT:
SMS_ALPHABET_7_BIT_DEFAULT;
/* bits 1-0 */
dcs->msgClass = (SmsMsgClassType) (data[pos] & 0x03);
/* set remaining fields */
dcs->isCompressed = FALSE;
dcs->msgWaiting = SMS_MSG_WAITING_NONE_1111;
}
else
{
/* Message waiting groups
*/
dcs->isCompressed = FALSE;
dcs->msgClass = SMS_MSG_CLASS_NONE;
/* bits 5-4 */
if( (data[pos] & 0x30) == 0x00 )
{
dcs->msgWaiting = SMS_MSG_WAITING_DISCARD;
dcs->alphabet = SMS_ALPHABET_7_BIT_DEFAULT;
}
else if( (data[pos] & 0x30) == 0x10 )
{
dcs->msgWaiting = SMS_MSG_WAITING_STORE;
dcs->alphabet = SMS_ALPHABET_7_BIT_DEFAULT;
}
else
{
dcs->msgWaiting = SMS_MSG_WAITING_STORE;
dcs->alphabet = SMS_ALPHABET_UCS2;
}
/* bit 3 */
dcs->msgWaitingActive = ( data[pos] & 0x08 ) ? TRUE : FALSE;
/* bit 2 is reserved */
/* bits 1-0 */
dcs->msgWaitingKind = (SmsMsgWaitingKindType) (data[pos] & 0x03);
}
break;
default:
dcs->alphabet = SMS_ALPHABET_7_BIT_DEFAULT;
dcs->isCompressed = FALSE;
dcs->msgWaiting = SMS_MSG_WAITING_NONE;
dcs->msgClass = SMS_MSG_CLASS_NONE;
break;
}
if ( dcs->alphabet > SMS_ALPHABET_UCS2 )
{
dcs->alphabet = SMS_ALPHABET_7_BIT_DEFAULT;
}
dcs->rawDcsData = data[pos];
pos ++;
return pos;
}
bool gsmEncodePdu( SM_PARAM* pSrc, char* pDst, u16 *dstLen)
{
#define MAX_GSM7BIT_SMS_LEN 160
s32 nDstLength = 0;
u8 buf[256] = { 0 };
bool result = TRUE;
s32 nLength;
/* SMSC address field */
nLength = strlen(pSrc->SCA);
if( nLength )
{
buf[0] = (s8)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1;
buf[1] = 0x81;
nDstLength = gsmBytes2String(buf, pDst, 2);
nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength);
}
else
{
pDst[nDstLength++]='0';
pDst[nDstLength++]='0';
}
nLength = strlen(pSrc->TPA);
buf[0] = 0x11;
buf[1] = 0;
if( '+' == pSrc->TPA[0] )
{
memmove( pSrc->TPA, pSrc->TPA+1, nLength );
nLength -= 1;
buf[3] = 0x91;
}
else
{
buf[3] = 0x81;
}
buf[2] = (s8)nLength;
nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4);
nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength);
nLength = strlen(pSrc->TP_UD);
buf[0] = pSrc->TP_PID;
buf[1] = pSrc->TP_DCS;
/*
VP Value Validity period value
0-143 (VP + 1) x 5 minutes (i.e 5 minutes intervals up to 12 hours)
144-167 12 hours + ((VP-143) x 30 minutes)
168-196 (VP-166) x 1 day
197-255 (VP - 192) x 1 week
*/
buf[2] = g_sms_vp; /* 4 days */
if(pSrc->TP_DCS == GSM_7BIT)
{
char tmpGsm[260];
s32 nSrcLength;
nSrcLength = strlen((char *)pSrc->TP_UD);
IRAConvertGsm7Bit((const u8 *)(pSrc->TP_UD), nSrcLength, (u8 *)tmpGsm, (u16 *)&nLength,TRUE);
buf[3] = nLength;
nLength = gsmEncode7bit(tmpGsm, &buf[4], nLength+1) + 4;
}
else if (pSrc->TP_DCS == GSM_8BIT)
{
buf[3] = gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength);
nLength = buf[3] + 4;
}
else if (pSrc->TP_DCS == GSM_UCS2)
{
*dstLen = 0;
return FALSE;
}
nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength);
*dstLen = nDstLength;
return result;
}
bool gsmDecodePdu(const char* pSrc, SM_PARAM* pDst, u16 *dstLen)
{
SmsValidityFormatType validityFormat;
SmsDcsType dcs;
bool result = TRUE;
u16 nDstLength;
u8 tmp;
u8 buf[256];
u8 TP;
*dstLen = 0;
memset( pDst, 0, sizeof(SM_PARAM) );
gsmString2Bytes(pSrc, &tmp, 2);
if (tmp)
{
tmp = (tmp - 1) * 2;
pSrc += 4;
gsmSerializeNumbers(pSrc, pDst->SCA, tmp);
pSrc += tmp;
}
else
{
pSrc += 2;
}
gsmString2Bytes(pSrc, &TP, 2);
pSrc += 2;
validityFormat = (SmsValidityFormatType) (( TP & 0x18 ) >> 3); /* bits 3, 4 */
if( TP & 0x1 )
{
pSrc += 2;
}
/* the long sms.Discard it */
if (TP & 0x40)
{
return FALSE;
}
/* the status reprt.Discard it */
if (( TP & 0x3 ) == 0x2)
{
return FALSE;
}
gsmString2Bytes(pSrc, &tmp, 2);
if(tmp & 1)
{
tmp += 1;
}
pSrc += 2;
gsmString2Bytes(pSrc, &pDst->TPATP, 2);
pSrc += 2;
if( 0x91 == pDst->TPATP )
{
pDst->TPA[0] = '+';
gsmSerializeNumbers(pSrc, pDst->TPA+1, tmp);
}
else if( 0xD0 == pDst->TPATP)
{
nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4);
nDstLength = tmp *4 /7;
gsmDecode7bit(buf, pDst->TPA, nDstLength);
}
else
{
gsmSerializeNumbers(pSrc, pDst->TPA, tmp);
}
pSrc += tmp;
gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2);
pSrc += 2;
gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2);
SmsDecodeDcs( (unsigned char*)&pDst->TP_DCS, &dcs );
pSrc += 2;
if( TP & 0x1 )
{
pSrc += gsmDecodeSmsValidity( (u8 *)pSrc, validityFormat);
}
else
{
gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14);
pSrc += 14;
}
gsmString2Bytes(pSrc, &tmp, 2);
pSrc += 2;
if (dcs.alphabet == SMS_ALPHABET_7_BIT_DEFAULT)
{
char tmpGsm[260] = { 0 };
u16 gsmLen = 0;
nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (s32)tmp * 7 / 4 + 2 : (s32)tmp * 7 / 4);
gsmDecode7bit(buf, tmpGsm, nDstLength);
tmpGsm[tmp] = '\0';
gsmLen = strlen(tmpGsm);
gsm7BitConvertIRA((const u8 *)tmpGsm, gsmLen, (u8 *)pDst->TP_UD, &nDstLength, TRUE);
pDst->TP_UD[nDstLength] = '\0';
}
else if (dcs.alphabet == SMS_ALPHABET_8_BIT)
{
nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2);
nDstLength = gsmDecode8bit(buf, pDst->TP_UD, nDstLength);
*dstLen = nDstLength;
}
else if(dcs.alphabet == SMS_ALPHABET_UCS2)
{
result = FALSE;
}
return result;
}
|