📄 smsenc.cpp
字号:
//
// Encode the ProtocolID for an outgoing message
// see GSM 03.40 section 9.2.3.9
//
static HRESULT EncodeMsgProtocolID(const DWORD dwProtocolID, BYTE* const pbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgProtocolID);
DEBUGCHK(NULL != pbOut);
HRESULT hr = S_OK;
rcbUsed = 0;
if (dwProtocolID >= NUM_PROTOCOLIDS) {
hr = E_INVALIDARG;
goto Error;
}
if (dwProtocolID == RIL_MSGPROTOCOL_SMETOSME) {
*pbOut = 0x00;
} else {
DEBUGCHK(0x100 > g_rgdwProtocolIDs[dwProtocolID]);
*pbOut = (BYTE)g_rgdwProtocolIDs[dwProtocolID];
}
rcbUsed = 1;
Error:
return hr;
}
//
// calculate the total length of the user data in an outgoing message
// if fGSMDefault is trure, then the length is measured in septets, otherwise in octets
//
static void EncodeEncDataLength(const DWORD cchMsgLength, const DWORD cbHdrLength, const DWORD dwAlphabet, BYTE* const pbOut,
UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeEncDataLength);
DEBUGCHK(NULL != pbOut);
UINT cchUserData;
rcbUsed = 0;
if (!cchMsgLength && !cbHdrLength) {
// Neither header nor body are specified
cchUserData = 0;
} else {
if (RIL_DCSALPHABET_UCS2 == dwAlphabet) {
// Account for the fact that every UCS2 char takes up 2 bytes
cchUserData = cchMsgLength * 2;
} else {
cchUserData = cchMsgLength;
}
if (cbHdrLength) {
// Add the size of the header, and a byte for the header-length indicator, plus any fill-bits
// (for GSM default alpabet)
if (RIL_DCSALPHABET_DEFAULT == dwAlphabet) {
cchUserData += (DIVIDE_ROUNDING_UP((1 + cbHdrLength) * 8, 7));
} else {
cchUserData += (1 + cbHdrLength);
}
}
}
*pbOut = cchUserData;
rcbUsed = 1;
}
//
// Fill out a BYTE array for the header of an outgoing message
//
static void EncodeMsgHdr(const BYTE* const pbIn, const cbHdrLength, const DWORD dwAlphabet, BYTE* const pbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgHdr);
DEBUGCHK(NULL != pbIn);
DEBUGCHK(NULL != pbOut);
BYTE* pbWalk = pbOut;
rcbUsed = 0;
if (cbHdrLength) {
*pbWalk++ = cbHdrLength;
memcpy(pbWalk, pbIn, min(cbHdrLength, MAXLENGTH_ADDRESS));
pbWalk += cbHdrLength;
}
rcbUsed = pbWalk - pbOut;
}
//
//
//
static HRESULT EncodeMsgDlvStatus(const DWORD dwStatus, BYTE* const pbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgDlvStatus);
DEBUGCHK(NULL != pbOut);
HRESULT hr = S_OK;
rcbUsed = 0;
if (NUM_DLVSTATUS <= dwStatus) {
hr = E_INVALIDARG;
goto Error;
}
*pbOut = (BYTE) g_rgdwDlvStatus[dwStatus];
rcbUsed = 1;
Error:
return hr;
}
void ShiftPackedBufferNBitsLeft(BYTE *pbyBuffer, DWORD cBufferBytes, DWORD cShiftRightBits)
{
if (0 != cBufferBytes)
{
BYTE *pbyCurrentByte = pbyBuffer + cBufferBytes - 1;
while (pbyCurrentByte > pbyBuffer )
{
*pbyCurrentByte-- = ((*pbyCurrentByte << cShiftRightBits) |
(*(pbyCurrentByte - 1) >> (8 - cShiftRightBits)));
}
*pbyCurrentByte = (*pbyCurrentByte << cShiftRightBits);
}
}
//
//
//
static void EncodeMsgHeaderAndBody(const DWORD dwParams, const DWORD dwFlags, const DWORD cchMsgLength, const DWORD cbHdrLength,
const BYTE* const pbHdr, const BYTE* const pbMsg, const RILMSGDCS* const prmdDataCoding,
BYTE* const pbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeMsgHeaderAndBody);
DEBUGCHK(NULL != pbOut);
BYTE* pbWalk = pbOut;
DWORD dwAlphabet;
UINT cbMsgBytes;
UINT cbAdvancedBy;
DWORD dwBitsToShift = 0;
rcbUsed = 0;
if (!(dwFlags & RIL_MSGFLAG_HEADER) && !cchMsgLength) {
// There is no header or data for this message, so set the data length to zero,
// and skip the rest of the function
*pbWalk++ = 0;
} else {
if (prmdDataCoding && (prmdDataCoding->dwParams & RIL_PARAM_MDCS_ALPHABET)) {
dwAlphabet = prmdDataCoding->dwAlphabet;
} else {
// Default to 8-bit alphabet
dwAlphabet = RIL_DCSALPHABET_8BIT;
}
// Calculate the length of the user data in the message
EncodeEncDataLength(cchMsgLength, (dwFlags & RIL_MSGFLAG_HEADER) ? cbHdrLength : 0, dwAlphabet, pbWalk, cbAdvancedBy);
pbWalk += cbAdvancedBy;
// Set the header, if it exists
if ((dwParams & RIL_PARAM_M_HDRLENGTH) && (dwParams & RIL_PARAM_M_HDR)) {
// Encode message header
EncodeMsgHdr(pbHdr, cbHdrLength, dwAlphabet, pbWalk, cbAdvancedBy);
pbWalk += cbAdvancedBy;
if (RIL_DCSALPHABET_DEFAULT == dwAlphabet) {
dwBitsToShift = 7-((cbAdvancedBy * 8) % 7);
if (dwBitsToShift == 7) dwBitsToShift = 0;
}
}
// Set the message data
if (cchMsgLength) {
// Figure out the number of bytes the body would occupy
if (RIL_DCSALPHABET_DEFAULT == dwAlphabet) {
cbMsgBytes = (cchMsgLength * 7 + 7) / 8;
} else if (RIL_DCSALPHABET_UCS2 == dwAlphabet) {
cbMsgBytes = cchMsgLength * 2;
} else {
cbMsgBytes = cchMsgLength;
}
cbAdvancedBy = min(cbMsgBytes, MAXLENGTH_MSG);
memcpy(pbWalk, pbMsg, cbAdvancedBy);
// make sure any GSM characters start on the septet boundry, not on the byte boundry.
if (dwBitsToShift) {
if (((cchMsgLength * 7 + 7 + dwBitsToShift) / 8) > cbMsgBytes)
{
ASSERT(cbAdvancedBy < MAXLENGTH_MSG);
if(cbAdvancedBy < MAXLENGTH_MSG)
{
// our shift will overflow into the next byte
pbWalk[cbAdvancedBy++] = 0;
}
}
ShiftPackedBufferNBitsLeft(pbWalk, cbAdvancedBy, dwBitsToShift);
}
pbWalk += cbAdvancedBy;
}
else
{
// If there is no message body then we may need to walk one more byte to make it to snag
// the next septet boundry.
if (dwBitsToShift)
{
pbWalk++;
}
}
}
rcbUsed = pbWalk - pbOut;
}
//
// Fill out a BYTE array for a Submit message
//
static HRESULT EncodeSubmitMsg(const RILMESSAGE& rmMsg, BYTE* const pbOut, const UINT cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeSubmitMsg);
DEBUGCHK(NULL != pbOut);
BYTE* pbWalk = pbOut;
BYTE* pbEnd = pbOut + cbOut;
UINT cbAdvancedBy;
HRESULT hr = S_OK;
(void)memset(pbOut, 0, cbOut);
// These parameters are mandatory, and if not present, we error out
if (!(rmMsg.dwParams & RIL_PARAM_M_TYPE) || !(rmMsg.dwParams & RIL_PARAM_M_DESTADDRESS) ||
!(rmMsg.dwParams & RIL_PARAM_M_PROTOCOLID) || !(rmMsg.dwParams & RIL_PARAM_M_MSGLENGTH) ||
!(rmMsg.dwParams & RIL_PARAM_M_FLAGS) || !(rmMsg.dwParams & RIL_PARAM_M_VPFORMAT) ||
!(rmMsg.dwParams & RIL_PARAM_M_DATACODING)) {
hr = E_INVALIDARG;
goto Error;
}
// Set Type, per GSM 03.40 section 9.2.3.1
*pbWalk |= 0x01;
// RIL_MSGFLAGS_REJECTDUPS, GSM 03.40 section 9.2.3.25
if (rmMsg.dwFlags & RIL_MSGFLAG_REJECTDUPS) {
*pbWalk |= 0x04;
}
// Validity Period Format, GSM 03.40 section 9.2.3.3
switch (rmMsg.msgOutSubmit.dwVPFormat)
{
case RIL_MSGVP_NONE:
*pbWalk |= 0x00;
break;
case RIL_MSGVP_ENHANCED:
//*pbWalk |= 0x08;
ASSERT(FALSE); // not supported, treat SYSTEMTIME as relative
// fall through...
case RIL_MSGVP_RELATIVE:
*pbWalk |= 0x10;
break;
case RIL_MSGVP_ABSOLUTE:
*pbWalk |= 0x18;
break;
default:
hr = E_INVALIDARG;
goto Error;
}
// RIL_MSGFLAG_STATUSREPORTREQUESTED, GSM 03.40 section 9.2.3.5
if (rmMsg.dwFlags & RIL_MSGFLAG_STATUSREPORTREQUESTED) {
*pbWalk |= 0x20;
}
// RIL_MSGFLAG_HEADER, GSM 03.40 section 9.2.3.23
if (rmMsg.dwFlags & RIL_MSGFLAG_HEADER) {
*pbWalk |= 0x40;
}
// RIL_MSGFLAG_REPLYPATH, GSM 03.40 section 9.2.3.17
if (rmMsg.dwFlags & RIL_MSGFLAG_REPLYPATH) {
*pbWalk |= 0x80;
}
pbWalk++;
DEBUGCHK(pbWalk <= pbEnd);
// RIL_PARAM_M_MSGREFERENCE, GSM 03.40 section 9.2.3.6
// NOTE: it appears that we can put anything into this field -- the radio generates correct msg reference for us
pbWalk++;
DEBUGCHK(pbWalk <= pbEnd);
// Encode the destination address. pbWalk should be set properly by the function
hr = EncodeMsgAddress(rmMsg.msgOutSubmit.raDestAddress, FALSE, pbWalk, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
// Set ProtocolID, see GSM 03.40 section 9.2.3.9
hr = EncodeMsgProtocolID(rmMsg.msgOutSubmit.dwProtocolID, pbWalk, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
// Reconstruct DCS, see GSM 03.40 section 9.2.3.10
hr = EncodeMsgDCS(rmMsg.msgOutSubmit.rmdDataCoding, pbWalk, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
if (rmMsg.dwParams & RIL_PARAM_M_VP) {
DEBUGCHK(0 != (rmMsg.dwParams & RIL_PARAM_M_VPFORMAT));
// See GSM 03.40 section 9.2.3.12
hr = EncodeMsgValidityPeriod(rmMsg.msgOutSubmit.stVP, rmMsg.msgOutSubmit.dwVPFormat, pbWalk, cbAdvancedBy);
if (FAILED(hr)) {
goto Error;
}
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
}
// Encode header and body
EncodeMsgHeaderAndBody(rmMsg.dwParams, rmMsg.dwFlags, rmMsg.msgOutSubmit.cchMsgLength,
rmMsg.msgOutSubmit.cbHdrLength, rmMsg.msgOutSubmit.rgbHdr, rmMsg.msgOutSubmit.rgbMsg,
&rmMsg.msgOutSubmit.rmdDataCoding, pbWalk, cbAdvancedBy);
pbWalk += cbAdvancedBy;
DEBUGCHK(pbWalk <= pbEnd);
rcbUsed = pbWalk - pbOut;
Error:
return hr;
}
//
// Fill out a BYTE array for a Command message
//
static HRESULT EncodeCmdMsg(const RILMESSAGE& rmMsg, BYTE* const pbOut, const UINT cbOut, UINT& rcbUsed)
{
FUNCTION_TRACE(EncodeCmdMsg);
DEBUGCHK(NULL != pbOut);
BYTE* pbWalk = pbOut;
BYTE* pbEnd = pbOut + cbOut;
UINT cbAdvancedBy;
HRESULT hr = S_OK;
(void)memset(pbOut, 0, cbOut);
// These parameters are mandatory, and if not present, we error out.
if (!(rmMsg.dwParams & RIL_PARAM_M_TYPE) || !(rmMsg.dwParams & RIL_PARAM_M_DESTADDRESS) ||
!(rmMsg.dwParams & RIL_PARAM_M_PROTOCOLID) || !(rmMsg.dwParams & RIL_PARAM_M_COMMANDTYPE) ||
!(rmMsg.dwParams & RIL_PARAM_M_TGTMSGREFERENCE) || !(rmMsg.dwParams & RIL_PARAM_M_CMDLENGTH) ||
!(rmMsg.dwParams & RIL_PARAM_M_FLAGS)) {
hr = E_INVALIDARG;
goto Error;
}
// Set Type, per GSM 03.40 section 9.2.3.1
*pbWalk |= 0x02;
// See GSM 03.40 section 9.2.3.5
if (rmMsg.dwFlags & RIL_MSGFLAG_STATUSREPORTREQUESTED) {
*pbWalk |= 0x20;
}
// See GSM 03.40 section 9.2.3.23
if (rmMsg.dwFlags & RIL_MSGFLAG_HEADER) {
*pbWalk |= 0x40;
}
pbWalk++;
DEBUGCHK(pbWalk <= pbEnd);
// Add a zero for the message reference (see GSM 03.40 section 9.2.3.6)
// NOTE: it appears that we can put anything into this field -- the module generates correct msg reference for us
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -