📄 pdu.c
字号:
#include "define.h"
#include "USC2GB.h"
#include "pdu.h"
//===================================================
TYP_SM_PARAM msg;
unsigned char textLength;
unsigned char asciiLength;
//编解码方式
#define GSM_7BIT 0
#define GSM_8BIT 4
#define GSM_UCS2 8
//====================================================
void gsmString2Bytes(unsigned char* pSrc, unsigned char* pDst,unsigned int nSrcLength);
void gsmSerializeNumbers(char* pSrc, char* pDst, unsigned char nSrcLength);
void USC2GB(unsigned char* p); //源和目标都是p,已0x00为结束符。
unsigned int folio_search(unsigned int x); //折半搜索,返回x的位置,失败返回0xFFFF
void Convert2USCII( unsigned char *pSrc, unsigned int *pDst );
//====================================================
// PDU解码,用于接收、阅读短消息
// pSrc: 源PDU串指针
// pDst: 目标PDU参数指针
// 返回: 最后指针的指向
char* gsmDecodePdu(char* pSrc){
unsigned char tmp;
// SMSC地址信息段
gsmString2Bytes(pSrc, &tmp, 2); // 取长度
pSrc += (2 + (unsigned char)(tmp<<1)); // 指针后移,跳过SMSC号码长度
// TPDU段基本参数、回复地址等
gsmString2Bytes(pSrc, &tmp, 2); // 取基本参数
pSrc += 2; // 指针后移
if(tmp & 0x04) //基本参数(TP-MTI/MMS/RP)有问题。24也有以下3个段
{
// 包含回复地址,取回复地址信息
gsmString2Bytes(pSrc, &tmp, 2); // 取长度
if(tmp & 1) tmp += 1; // 调整奇偶性
pSrc += 4; // 指针后移
gsmSerializeNumbers(pSrc, msg.TPA, tmp);// 取TP-RA号码,
pSrc += tmp;
}
// TPDU段协议标识、编码方式、用户信息等
gsmString2Bytes(pSrc, (unsigned char*)&msg.TP_PID, 2); // 取协议标识(TP-PID)
pSrc += 2; // 指针后移
gsmString2Bytes(pSrc, (unsigned char*)&msg.TP_DCS, 2); // 取编码方式(TP-DCS)
pSrc += 16; // 指针后移
gsmString2Bytes(pSrc, &tmp, 2); // 用户信息长度(TP-UDL)
pSrc += 2; // 指针后移
if (tmp > 142)
{
return 0;
}
if(msg.TP_DCS == GSM_UCS2)
{
// UCS2解码
gsmString2Bytes(pSrc, msg.RE_TP_UD, (unsigned int)tmp<<1); //转成二进制
*(msg.RE_TP_UD+tmp) = '\0'; //0x0000为结束符
*(msg.RE_TP_UD+tmp+1) = '\0';
*(msg.RE_TP_UD+tmp+2) = '\0';
Convert2USCII( msg.RE_TP_UD, read_data );
USC2GB(msg.RE_TP_UD); // 转换到GB2312编码
pSrc += tmp;
pSrc += tmp;
}
//else if(msg->TP_DCS == GSM_7BIT); // 7-bit解码
//else if(msg->TP_DCS == GSM_8BIT); // 8-bit解码
else pSrc = 0; //error
return pSrc;
}
// 两两颠倒的字符串转换为正常顺序的字符串
// 如:"683158812764F8" --> "8613851872468"
// pSrc: 源字符串指针
// pDst: 目标字符串指针
// nSrcLength: 源字符串长度
void gsmSerializeNumbers(char* pSrc, char* pDst, unsigned char nSrcLength){
unsigned char i; // 目标字符串长度
char ch; // 用于保存一个字符
// 两两颠倒
for(i=0; i<nSrcLength;i+=2)
{
ch = *pSrc++; // 保存先出现的字符
*pDst++ = *pSrc++; // 复制后出现的字符
*pDst++ = ch; // 复制先出现的字符
}
// 最后的字符是'F'吗?
if(*(pDst-1) == 'F')
pDst--;
*pDst = '\0'; // 输出字符串加个结束符
}
// 可打印字符串转换为字节数据
// 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
// pSrc: 源字符串指针
// pDst: 目标数据指针
// nSrcLength: 源字符串长度
void gsmString2Bytes(unsigned char* pSrc, unsigned char* pDst,unsigned int nSrcLength){
int i;
for(i=0; i<nSrcLength; i+=2)
{
// 输出高4位
if(*pSrc>='0' && *pSrc<='9')
*pDst = (*pSrc - '0') << 4;
else
*pDst = (*pSrc - 'A' + 10) << 4;
pSrc++;
// 输出低4位
if(*pSrc>='0' && *pSrc<='9')
*pDst |= *pSrc - '0';
else
*pDst |= *pSrc - 'A' + 10;
pSrc++;
pDst++;
}
}
void USC2GB(unsigned char* p){
unsigned int temp=1,position;
textLength = 0;
asciiLength = 0;
while (temp)
{
temp=((unsigned int)*p<<8); //转成int型
temp+=*(p+1);
if (temp>=0x0080) //非ASCII码要转换
{
position=folio_search(temp); //折半搜索
if (position<7445) temp=GB2312[position]; //转成GB2312
else temp=0xA3BF; //无法识别显示问号
}
else
{
asciiLength++;
}
textLength++;
*p++ = temp & 0xFF; //高低位对调,使*p直接可以int型调用
*p++ = temp >> 8;
}
asciiLength--;
textLength--;
}
unsigned int folio_search(unsigned int x){
unsigned int high=7444,low=0,mid;
while (low<=high)
{
mid=(low+high)>>1;
if (unicode[mid]<x) low=mid+1; //右缩搜索
else if (unicode[mid]>x) high=mid-1;//左缩搜索
else return mid;
}
return 0xFFFF;
}
void Convert2USCII( unsigned char *pSrc, unsigned int *pDst )
{
unsigned int temp = 1;
unsigned char i;
//增加朗读开始信息和手机号码.
//收到13XXXXXXXXX的消息:
*pDst++ = 25910;//收
*pDst++ = 21040;//到
if ((msg.TPA[0]=='8') && (msg.TPA[1]=='6')) i=2;//国际码86不念出来
else i=0;
for (; (i<16) && (msg.TPA[i]!='\0'); i++)
{
*pDst++ = msg.TPA[i];
}
*pDst++ = 30340;//的
*pDst++ = 28040;//消
*pDst++ = 24687;//息
*pDst++ = 65306;//:
while (temp)
{
temp = (unsigned int)(*pSrc++) << 8;
temp += *pSrc++;
*pDst++ = temp;
}
*(pDst - 1) = 0x1A; //朗读结束标记
*pDst = 0x00;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -