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

📄 dataformat.c

📁 在GPRS或者CDMA modem上实现发送/接收短信的C代码;支持Siemens
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>

#include "sms.h"
#include "dataformat.h"
#include "errordef.h"
#include "smshandle.h"
#include "typedef.h"

int convsmsdata(const uchar* from, int fromlen, uchar* to, int* tolen, char flag);
int procpdudata(const uchar* indata, int inlen, PDU* pdu, uchar* outdata, int* outlen);

/************************************************************************/
/* Internal Functions
/************************************************************************/

/* 7-bit encoding and decoding */
int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength);
int gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength);
/* 8-bit encoding and decoding */
int gsmEncode8bit(const uchar * pSrc, uchar * pDst, int nSrcLen);
int gsmDecode8bit(const uchar * pSrc, uchar * pDst, int nSrcLen);
/* UCS16-bit encoding to and decoding from GB coding */
int gsmEncodeGb2Uni(const uchar* pSrc,  uchar* pDst, int nSrcLen);
int gsmDecodeUni2Gb(const uchar* pSrc, uchar* pDst, int nSrcLen);

char HexToChr(char ch);
char ChrToHex(char ch);
int  reversedata(const char* pSrc, char* pDst, int nSrcLen);

int packpdudata(const uchar* indata, int inlen, PDU* inPdu, char* outdata, int* outlen);

int gsmEncodeUniNum(uchar *dest, const uchar *src, int len);
int gsmDecodeUniNum(uchar *dest, const uchar *src, int len);

extern void uni2gb(unsigned char *target,unsigned char *out);
extern void fast_gb2uni(unsigned char *target,unsigned char *out);

/*
* function: convert data format according to flag
* input params: 
*     from: input data buffer
*  fromlen: the length of from
*     flag: converting flag
* output params:
*       to: output data buffer
*    tolen: to's length after converting datas in input buffer
* return value:
*   equal to 0: success to convert data
*  less than 0: fail
*/
int convsmsdata(const uchar* from, int fromlen, uchar* to, int* tolen, char flag)
{
    int outdatalen;
    int ret;
    
    switch(flag)
    {
        case ENCODE_7BIT:
            outdatalen = gsmEncode7bit(from, to, fromlen);
            break;
        case CHAR_TO_HEX:
            outdatalen = gsmEncode8bit(from, to, fromlen);
            break;
        case GB_TO_UCS16:
            outdatalen = gsmEncodeGb2Uni(from, to, fromlen);
            break;
        case DECODE_7BIT:
            outdatalen = gsmDecode7bit(from, to, fromlen);
            break;
        case HEX_TO_CHAR:
            outdatalen = gsmDecode8bit(from, to, fromlen);
            break;
        case UCS16_TO_GB:
            outdatalen = gsmDecodeUni2Gb(from, to, fromlen);
            break;
		case TO_UNI_NUM:
            outdatalen = gsmEncodeUniNum(to, from, fromlen);
			break;
		case FR_UNI_NUM:
			outdatalen = gsmDecodeUniNum(to, from, fromlen);
			break;
        default:
            break;
    }
    
    if(outdatalen < 0)
    {
        WMMP_TRACE(debugType, "\r\nError: Convert data %d", outdatalen);
        ret = -SMS_ERR_CONV_DATA;
        goto convsmsdata_fail;
    }
    
    //get converted data length
    *tolen = outdatalen;
    return 0;

convsmsdata_fail:
    return ret;
}

/*
* function: process PDU format data to PDU structure,
*           and get the data and data's length.
* PDU data example:
* 0891 683108501945F4 040D91 685169005953F1 001560 016161651023 02FF00
* 0891+短信中心+消息类型+源址+编码方式+时间戳+短信内容
* 0891 683108501945F4 040D91 685169005953F1 00F060 016151615423 02421C
*/
int procpdudata(const uchar* indata, int inlen, PDU* pdu, uchar* outdata, int* outlen)
{
    const uchar* pInData;
	int    nAddrLen, nLeftDataLen;
	int    nInDataInx;
	uchar  phase;
	int    ret;
	uchar  temp[3];
#define PDU_SMSC_LEN_PHASE  0x01
#define PDU_SMSC_TYPE_PHASE 0x02
#define PDU_SMSC_ADDR_PHASE 0x03
#define PDU_MSG_REF_PHASE   0x04
#define PDU_SRCADDR_LEN_PHASE  0x05
#define PDU_SRCADDR_TYPE_PHASE 0x06
#define PDU_SRCADDR_DATA_PHASE 0x07
#define PDU_PROTOID_PHASE     0x08
#define PDU_DCS_PHASE         0x09
#define PDU_VALID_PERI_PHASE  0x0A
#define PDU_TIME_STAMP_PHASE  0x0B
#define PDU_DATA_LEN_PHASE    0x0C
#define PDU_DATA_PHASE        0x0D
#define PDU_OVER_PHASE        0xFF
#define PDU_ERROR_PHASE       0xFE         

	pInData = indata;
	nInDataInx = 0;
	nLeftDataLen = inlen;
    phase = PDU_SMSC_LEN_PHASE;
	
	while (nLeftDataLen > 0)
	{
		switch(phase)
		{
			//08--SMSC address length 91--SMSC address type
	       //683108501945F4--SMSC address
		case PDU_SMSC_LEN_PHASE:
			memset(temp, 0, sizeof(temp));
            ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
            pdu->sc_addr_len = temp[0]; //get SMSC address length
	        pInData += 2; //move pInData forward 2
			nLeftDataLen -= 2;
			phase = PDU_SMSC_TYPE_PHASE; 
			break;
		case PDU_SMSC_TYPE_PHASE:
            memset(temp, 0, sizeof(temp));
			ret = gsmDecode8bit(pInData, temp, 2);
            if (ret < 0)
            {
				goto procpdudata_fail;
            }
			pdu->sc_addr_type = temp[0]; //get SMSC address type
			pInData += 2;
			nLeftDataLen -= 2;
			phase = PDU_SMSC_ADDR_PHASE; 
			break;
		case PDU_SMSC_ADDR_PHASE:
			nAddrLen = pdu->sc_addr_len - 2; //get real SMS center address length, sc_addr_len must be even number
			pInData += 2; //point to the first number of SMS center address
			nLeftDataLen -= 2;
			memset(pdu->sc_addr, 0, sizeof(pdu->sc_addr));
            ret = reversedata(pInData, pdu->sc_addr, nAddrLen*2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			if (pdu->sc_addr[nAddrLen*2 - 1] == 'F')
			{
				pdu->sc_addr[nAddrLen*2 - 1] = '\0'; //remove the last number'F'
			}
			pInData += nAddrLen*2; //move the pointer to the message reference
			nLeftDataLen -= nAddrLen*2;
			phase = PDU_MSG_REF_PHASE; 
			break;
		//040D91  04--TP Message Reference  0D--source address length
		//91--source address type
	    //685169005953F1--source address(important)
		case PDU_MSG_REF_PHASE:
            memset(temp, 0, sizeof(temp));
            ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			pdu->tp_msg_refer = temp[0]; //get the TP Message Reference
			pInData += 2; // move 2 bytes forwards
			nLeftDataLen -= 2;
			phase = PDU_SRCADDR_LEN_PHASE; 
			break;
		case PDU_SRCADDR_LEN_PHASE:
            memset(temp, 0, sizeof(temp));
			ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			pdu->tp_da_len = temp[0]; //get the source address length
			pInData += 2;
			nLeftDataLen -= 2;
            phase = PDU_SRCADDR_TYPE_PHASE; 
			break;
		case PDU_SRCADDR_TYPE_PHASE:
            memset(temp, 0, sizeof(temp));
			ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			pdu->tp_da_type = temp[0]; //get the source address type
			pInData += 2; //point to "68" of source address
			nLeftDataLen -= 2;
			phase = PDU_SRCADDR_DATA_PHASE; 
			break;
		case PDU_SRCADDR_DATA_PHASE:
			if (pdu->tp_da_len%2 == 0)
			{
				nAddrLen = pdu->tp_da_len - 2;
			}
			else
            {
				nAddrLen = pdu->tp_da_len - 1; //
            }
			pInData += 2; //point to the real first number of source addres
			nLeftDataLen -= 2;
			ret = reversedata(pInData, pdu->tp_daddr, nAddrLen);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			if (pdu->tp_daddr[nAddrLen - 1] == 'F')
			{
				pdu->tp_daddr[nAddrLen - 1] = '\0'; //remove the last 'F'
			}
			pInData += nAddrLen; //move pInData nAddrLen bytes forwards
			nLeftDataLen -= nAddrLen;
			phase = PDU_PROTOID_PHASE; 
			break;
		//001560
		//00--TP Protocol identifier   15--TP Data Coding Scheme(important)
	    //60--TP Valid Period
		case PDU_PROTOID_PHASE:
            memset(temp, 0, sizeof(temp));
			ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			pdu->tp_pid = temp[0];//get TP Protocol identifier
			pInData += 2;
			nLeftDataLen -= 2;
			phase = PDU_DCS_PHASE; 
			break;
		case PDU_DCS_PHASE:
            memset(temp, 0, sizeof(temp));
			ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			pdu->tp_dcs = temp[0];//get TP data coding scheme
			pInData += 2;
			nLeftDataLen -= 2;
			phase = PDU_VALID_PERI_PHASE; 
			break;
		case PDU_VALID_PERI_PHASE:
            memset(temp, 0, sizeof(temp));
			ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			pdu->tp_vp = temp[0];//get TP valid period
			pInData += 2;
			nLeftDataLen -= 2;
            phase = PDU_TIME_STAMP_PHASE; 
			break;
		case PDU_TIME_STAMP_PHASE:
            pInData += 12;  //016161651023--time stamp(can be ignored)
			nLeftDataLen -= 12;
            phase = PDU_DATA_LEN_PHASE; 
			break;
		//02FF00(important)
		//02--data length    FF00--data
		case PDU_DATA_LEN_PHASE:
            memset(temp, 0, sizeof(temp));
			ret = gsmDecode8bit(pInData, temp, 2);
			if (ret < 0)
			{
				goto procpdudata_fail;
			}
			*outlen = temp[0]*2;//get data length(real bytes)
			pInData += 2;
			nLeftDataLen -= 2;
			phase = PDU_DATA_PHASE; 
			break;
		case PDU_DATA_PHASE:
			memcpy(outdata, pInData, *outlen);
			nLeftDataLen -= *outlen;
			phase = PDU_OVER_PHASE;
			break;
		default:
			WMMP_TRACE(debugType, "\r\nError: unknown PDU phase");
			break;
		}

		if (nLeftDataLen < 0)
		{
			WMMP_TRACE(debugType, "\r\nError: entire PDU data length");
			goto procpdudata_fail;
		}

		if (phase == PDU_OVER_PHASE)
		{
			break;
		}

	}

    return 0;

procpdudata_fail:
	return ret;
}

/*
*  Functions: package PDU-format data 
*  Input Params: 
*      indata: sending data; converted data 2-digit Hex
*       inlen: length of sending data
*       inPdu: pdu structure
*  Output Params:
*     outdata: packaged PDU-format data
*      outlen: length of packaged PDU-format data not including SMSC 00
*  Example: 00 11000D91 683106869031F5 0000A7 0431D98C06
*/
int packpdudata(const uchar* indata, int inlen, PDU* inPdu, char* outdata, int* outlen)
{
    uchar* pOutData;
	char   dstaddr[20];
	char   indatalen;
	int    dstlen;
	int    ret, iOutLen;
		
	pOutData = outdata;
	iOutLen  = 0;
	//SMSC 
	//to do: test if SMSC is counted in total length
	//SMSC is zero, because we have set is when call setsmsconfig()	
    *(pOutData + iOutLen) = 0x30;
	*(pOutData + iOutLen + 1) = 0x30;
    pOutData += 2;
	
	//11--file header
    ret = gsmEncode8bit(&(inPdu->tp_head), pOutData, 1);
	if (ret < 0)
	{
         WMMP_TRACE(debugType, "\r\nError: tp_head");
		 goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;

	//00--message reference
	ret = gsmEncode8bit(&(inPdu->tp_msg_refer), pOutData, 1);
	if (ret < 0)
	{
		WMMP_TRACE(debugType, "\r\nError: tp_msg_refer");
		goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;

	//0D--destination length
	ret = gsmEncode8bit(&(inPdu->tp_da_len), pOutData, 1);
    if (ret < 0)
	{
		WMMP_TRACE(debugType, "\r\nError: tp_da_len");
		goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;

	//91--destination type
    ret = gsmEncode8bit(&(inPdu->tp_da_type), pOutData, 1);
    if (ret < 0)
	{
		WMMP_TRACE(debugType, "\r\nError: tp_da_type");
		goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;

	//68+phone number
    memset(dstaddr, 0, sizeof(dstaddr));
	dstlen = strlen(inPdu->tp_daddr);
	if (dstlen%2 == 0)
	{
        sprintf(dstaddr, "86%s", inPdu->tp_daddr);
	}
	else
	{
		sprintf(dstaddr, "86%sF", inPdu->tp_daddr);
	}
	ret = reversedata(dstaddr, pOutData, strlen(dstaddr));
	if (ret < 0)
	{
		WMMP_TRACE(debugType, "\r\nError: tp_daddr");
		goto packpdudata_fail;
	}
	iOutLen += strlen(dstaddr);
	pOutData += strlen(dstaddr);

	//00-message reference
	ret = gsmEncode8bit(&(inPdu->tp_msg_refer), pOutData, 1);
	if (ret < 0)
	{
        WMMP_TRACE(debugType, "\r\nError: tp_msg_refer");
		goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;

	//08--Data Codeing Scheme
	ret = gsmEncode8bit(&(inPdu->tp_dcs), pOutData, 1);
    if (ret < 0)
	{
		WMMP_TRACE(debugType, "\r\nError: tp_dcs");
		goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;

	//A7--valid periods
	ret = gsmEncode8bit(&(inPdu->tp_vp), pOutData, 1);
    if (ret < 0)
	{
		WMMP_TRACE(debugType, "\r\nError: tp_vp");
		goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;
    
	//copy transformed data
	//sms data length, Notion: 7-bit is different from 8-bit and UCS2 coding!!!
	if (inPdu->tp_dcs == 0x00)
	{
		indatalen = inlen;
	}
	else
	{
        indatalen = strlen(indata)/2;
	}
	ret = gsmEncode8bit(&indatalen, pOutData, 1);
	if (ret < 0)
	{
		WMMP_TRACE(debugType, "\r\nError: encode data length field");
		goto packpdudata_fail;
	}
	iOutLen += 2;
	pOutData += 2;
	//sms data, transformed data(2-digit HEX)
	memcpy(pOutData, indata, strlen(indata));
	iOutLen += strlen(indata);
	pOutData += strlen(indata);

	//get outlen
    *outlen = iOutLen/2;

	return 0;

packpdudata_fail:
	return ret;
}

char HexToChr(char ch)
{
    if (ch <= 0x09 && ch>= 0x00)
    {
        ch = ch + 0x30;
    }
    else if (ch <= 0x0F && ch >= 0x0A)
    {

⌨️ 快捷键说明

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