2 * Telephony test application
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Ja-young Gu <jygu@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
27 void reverse(char* x, int len)
31 for (i = 0; i < j; i++)
39 char* AcItoa(int n, char* str, int b)
44 str[i++] = "0123456789ABCDEF"[n%b];
55 return (('a' <= (ch) && (ch) <= 'z')? ((ch) - ('a'-'A')) : (ch));
58 char* SmsUtilUnpackGSMCode(char* szData, const char* pIn, int in_len )
64 /* If the number of fill bits != 0, then it would cause an additional shift */
73 for ( i = 0; i < in_len; i++, pos++ )
75 szData[i] = ( pIn[pos] << shift ) & 0x7F;
79 /* except the first byte, a character contains some bits
80 ** from the previous byte.
82 szData[i] |= pIn[pos-1] >> (8-shift);
91 /* a possible extra complete character is available */
93 szData[i] = pIn[pos] >> 1;
97 /* this is the end of the input, quit */
106 int SmsUtilPackGSMCode( unsigned char *pOut, const char* szData, int in_len )
113 // memset( out, 0, out_len_max );
115 /* pack the ASCII characters
122 for( pos = 0, i = 0; /*pos < out_len_max &&*/ i < in_len; pos++, i++ )
124 /* pack the low bits */
125 pOut[pos] = szData[i] >> shift;
127 if ( i + 1 < in_len )
129 /* pack the high bits using the low bits of the next character */
130 pOut[pos] |= szData[i+1] << ( 7 - shift );
147 void SmsUtilConvertBCD2Digit( char* pDigits, char* pBCD, int digitLen )
151 unsigned char higher, lower;
153 if ( pBCD == NULL || pDigits == NULL )
155 printf("__SmsConvertBCD2Digit: pBCD == NULL || pDigits == NULL. return.\n" );
161 //printf("__SmsConvertBCD2Digit: digitLen == 0. return.\n" );
169 bcdLen = digitLen / 2 + 1;
171 bcdLen = digitLen / 2;
173 memset( pDigits, 0, bcdLen * 2 );
175 for ( i = 0; i < bcdLen; i++ )
177 lower = pBCD[i] & 0x0F; // get low nibble
181 else if ( lower == 0x0B )
183 else if ( lower == 0x0C )
184 lower = 'p'; //DTMF Control pDigits seperator
185 else if ( lower == 0x0F )
189 AcItoa( lower, c, 16 );
190 lower = (char) AcToupper(c[0]);
193 higher = ( pBCD[i] >> 4 ) & 0x0F; // get high nibble
195 if ( higher == 0x0A )
196 higher = '*'; // =0x2A
197 else if ( higher == 0x0B )
198 higher = '#'; // =0x23
199 else if ( higher == 0x0C )
200 higher = 'p'; // =0x70, DTMF Control pDigits seperator
201 else if ( higher == 0x0F ) // if higher semi-octet is 0x0F, filled bits.
204 sprintf(pDigits + strlen(pDigits), "%c", lower);
205 pDigits[/*digitLen-1*/bcdLen*2-1] = '\0';
207 //printf("__SmsConvertBCD2Digit: pDigits [%s].\n", pDigits );
213 AcItoa(higher, c, 16);
214 higher = (char) AcToupper(c[0]);
217 //sprintf(pDigits, "%s%c%c", pDigits, lower, higher);
218 sprintf(pDigits + strlen(pDigits), "%c%c", lower, higher);
221 pDigits[digitLen] = '\0';
223 //printf("__SmsConvertBCD2Digit: pDigits [%s].\n", pDigits );
227 void SmsUtilConvertDigit2BCD( char* pBCD, char* pDigits, int digitLen )
231 unsigned char higher, lower;
233 if ( pBCD == NULL || pDigits == NULL )
236 // 0123456789 -> 1032547698
237 for ( i = 0, j = 0; i < digitLen; i = i + 2, j++ )
239 if ( pDigits[i] == '*' )
241 else if ( pDigits[i] == '#' )
243 else if ( AcToupper( pDigits[i] ) == 'P' )
246 digit = (int) ( pDigits[i] - '0' );
248 lower = digit & 0x0F;
250 if ( digitLen != i + 1 )
252 if ( pDigits[i+1] == '*' )
254 else if ( pDigits[i+1] == '#' )
256 else if ( AcToupper( pDigits[i+1] ) == 'P' )
259 digit = (int) ( pDigits[i+1] - '0' );
261 higher = digit & 0x0F;
268 pBCD[j] = ( higher << 4 ) | lower;
273 TmDateTime* SmsUtilDecodeTimeStamp(char * pTimeStamp, TmDateTime *tmDateTime )
275 //TmDateTime tmDateTime;
279 if ( pTimeStamp == NULL )
282 SmsUtilConvertBCD2Digit( szBuf, (char*) &pTimeStamp[0], 2 );
283 tmDateTime->year = atoi( szBuf ) + 2000;
284 if ( ( tmDateTime->year >= 1900 + MAX_YEAR )/* && ( tmDateTime->year < 2000 + BASE_YEAR )*/ )
285 tmDateTime->year -= 100;
286 SmsUtilConvertBCD2Digit( szBuf, (char*) &pTimeStamp[1], 2 );
287 tmDateTime->month = atoi( szBuf );
288 SmsUtilConvertBCD2Digit( szBuf, (char*) &pTimeStamp[2], 2 );
289 tmDateTime->day = atoi( szBuf );
290 SmsUtilConvertBCD2Digit( szBuf, (char*) &pTimeStamp[3], 2 );
291 tmDateTime->hour = atoi( szBuf );
292 SmsUtilConvertBCD2Digit( szBuf, (char*) &pTimeStamp[4], 2 );
293 tmDateTime->minute = atoi( szBuf );
294 SmsUtilConvertBCD2Digit( szBuf, (char*) &pTimeStamp[5], 2 );
295 tmDateTime->second = atoi( szBuf );
297 if ( ( tmDateTime->year < 1900 + BASE_YEAR ) || ( tmDateTime->year > 1900 + MAX_YEAR ) )
298 tmDateTime->year = 1900 + BASE_YEAR;
301 time = TmDateTimeToSeconds( &tmDateTime );
302 if ( time > MAX_SECONDS )
310 unsigned char* SmsUtilEncodeTimeStamp( TmDateTime* tmDateTime, unsigned char* pTimeStamp )
312 //TmDateTime tmDateTime;
316 if ( pTimeStamp == NULL )
319 memset( (void*) pTimeStamp, 0x00, sizeof ( unsigned char ) * 7 );
321 //TmSecondsToDateTime( timeStamp, &tmDateTime );
323 year = tmDateTime->year - 2000;
326 sprintf( szBuf, "%02d", year );
327 SmsUtilConvertDigit2BCD( (char*) &pTimeStamp[0], szBuf, 2 );
328 sprintf( szBuf, "%02d", tmDateTime->month );
329 SmsUtilConvertDigit2BCD( (char*) &pTimeStamp[1], szBuf, 2 );
330 sprintf( szBuf, "%02d", tmDateTime->day );
331 SmsUtilConvertDigit2BCD( (char*) &pTimeStamp[2], szBuf, 2 );
332 sprintf( szBuf, "%02d", tmDateTime->hour );
333 SmsUtilConvertDigit2BCD( (char*) &pTimeStamp[3], szBuf, 2 );
334 sprintf( szBuf, "%02d", tmDateTime->minute );
335 SmsUtilConvertDigit2BCD( (char*) &pTimeStamp[4], szBuf, 2 );
336 sprintf( szBuf, "%02d", tmDateTime->second );
337 SmsUtilConvertDigit2BCD( (char*) &pTimeStamp[5], szBuf, 2 );
340 /* ignore Time zone (assume it is using 0x00 as default)
341 timeZone = TmGetTimeZoneOffset() /15;
343 absTimeZone = -timeZone;
345 absTimeZone = timeZone;
348 sprintf( szBuf, "%02d", 0);
349 SmsUtilConvertDigit2BCD( (char*) &pTimeStamp[6], szBuf, 2 );
351 //if ( timeZone < 0 )
352 // pTimeStamp[6] |= 0x80;
359 int SmsUtilDecodeAddrField(char *diallingNum, char* pAddrField, int *result_ton, int *result_npi )
365 ton = ( pAddrField[index+1] & 0x70 ) >> 4;
366 npi = pAddrField[index+1] & 0x0F;
368 if ( ton != SMS_TON_ALPHA_NUMERIC )
370 // Origination/Destination address �ʵ忡���� length�� ���� address length
371 // origination/destination address �ʵ��� ��� length�� 0 �� ���� number type/plan �ʵ�� 0xFF ���� ���´�.
372 DialNumLen = pAddrField[index++];
376 DialNumLen = ( ( ( pAddrField[index++] + 1 ) / 2 ) * 8 ) / 7;
382 // SIM_SMSP_ADDRESS_LEN ���� address length �� ũ�� SIM_SMSP_ADDRESS_LEN ��Å�� ��ȯ�� �Ѵ�.
384 if ( DialNumLen > SMS_ADDRESS_LEN_MAX )
386 DialNumLen = SMS_ADDRESS_LEN_MAX;
389 printf(" DialNumLen = %d\n", DialNumLen );
391 index++; /* ignore Type of Address field */
393 if (ton != SMS_TON_ALPHA_NUMERIC )
395 SmsUtilConvertBCD2Digit( diallingNum, (char*) &pAddrField[index],DialNumLen );
399 SmsUtilUnpackGSMCode( diallingNum, &pAddrField[index],DialNumLen );
402 printf( "__SmsDecodeAddrField: diallingNum [%s].\n", (char*) diallingNum );
407 printf("ton %d npi %d\n",ton,npi);
414 int SmsUtilEncodeAddrField(unsigned char* pAddrField, char* diallingNum, int DialNumLen, int ton, int npi )
418 if ( diallingNum == NULL || pAddrField == NULL )
421 if ( diallingNum[0] == '+' )
425 ton = SMS_TON_INTERNATIONAL;
428 if ( ton != SMS_TON_ALPHA_NUMERIC )
430 // Origination/Destination address �ʵ忡���� length�� ���� address length
431 pAddrField[index++] = (unsigned char)DialNumLen;
432 //printf(" addr len packet: %d\n", pAddrField[index]);
436 pAddrField[index] = (unsigned char) ( ( ( DialNumLen * 7 + 7 ) / 8 ) * 2 );
438 // ������ ����Ʈ���� ���� 4��Ʈ�� ������ ������ length �ʵ尪�� -1�� �Ѵ�.
439 if ( ( ( DialNumLen * 7 ) % 8 ) <= 4 )
442 printf(" addr len packet: %d out of SMS_TON_ALPAHA\n", pAddrField[index]);
447 SET_TON_NPI( pAddrField[index], ton, npi );
449 index++; // SET_TON_NPI �� MACRO �̹Ƿ� ���ο��� ������Ű�� ����
451 if ( ton != SMS_TON_ALPHA_NUMERIC )
453 SmsUtilConvertDigit2BCD( (char*) &pAddrField[index], (char*) diallingNum, DialNumLen );
455 if ( DialNumLen % 2 )
456 index += DialNumLen / 2 + 1;
458 index += DialNumLen / 2;
462 index += SmsUtilPackGSMCode( &pAddrField[index], diallingNum, (int) DialNumLen );
467 int SmsUtilDecodeScAddrField( SmsAddressInfo_t* pSmsAddrField, unsigned char* pAddrField )
469 printf("SmsUtilDecodeScAddrField\n");
473 if ( pSmsAddrField == NULL || pAddrField == NULL )
475 printf( "SmsUtilDecodeScAddrField: pSimAddrField or pAddrField is NULL.\n" );
480 // Service Center address �ʵ忡���� length�� �ڿ� ������ byte�� ��
481 // -> ���� address ���̴� TON/API ����Ʈ�� �����ϰ� ������ ����Ʈ�� 2�� or 2�� - 1(���� ���̰� Ȧ���ΰ��)
482 length = pAddrField[index];
483 // ������ ���� �޽����� ��쿡�� service center address�� ���� ���� �ִ�.
484 // �� ��쿡 length �� 0 �̸� number type, plan �� ��� ���
485 // length �� 1 �̸� type, plan �� �ִ� ���
488 pSmsAddrField->DialNumLen = ( pAddrField[index++] - 1 ) * 2; // -1�� TON/API �ʵ�
490 // SMS_SMSP_ADDRESS_LEN ���� address length �� ũ�� SMS_SMSP_ADDRESS_LEN ��Å�� ��ȯ�� �Ѵ�.
491 if ( pSmsAddrField->DialNumLen > SMS_ADDRESS_LEN_MAX )
493 pSmsAddrField->DialNumLen = SMS_ADDRESS_LEN_MAX;
496 pSmsAddrField->Ton = ( pAddrField[index] & 0x70 ) >> 4;
497 pSmsAddrField->Npi = pAddrField[index] & 0x0F;
499 index++; /* ignore Type of Address field */
501 SmsUtilConvertBCD2Digit( (char*) pSmsAddrField->DialNumLen, (char*) &pAddrField[index], pSmsAddrField->DialNumLen );
503 printf( "SmsUtilDecodeScAddrField: diallingNum [%s].\n", (char*) pSmsAddrField->DialNumLen );
505 printf( "length=%d , ton %d, npi =%d\n",pSmsAddrField->DialNumLen, pSmsAddrField->Ton,pSmsAddrField->Npi );
511 int SmsUtilEncodeScAddrField( unsigned char* pAddrField, SmsAddressInfo_t * pSmsAddrField )
515 if ( pSmsAddrField == NULL || pAddrField == NULL )
518 // Service Center address �ʵ忡���� length�� �ڿ� ������ byte�� ��
519 // -> ���� address ���̴� TON/API ����Ʈ�� �����ϰ� ������ ����Ʈ�� 2�� or 2�� - 1(���� ���̰� Ȧ���ΰ��)
520 if ( pSmsAddrField->DialNumLen % 2 )
522 pAddrField[index++] = pSmsAddrField->DialNumLen / 2 + 1 + 1; // +1 �� TON/NPI �ʵ�, Ȧ������ ���� ������ ���߱� ���� �ѹ� �� +1
526 pAddrField[index++] = pSmsAddrField->DialNumLen / 2 + 1; // +1 �� TON/NPI �ʵ�
529 SET_TON_NPI( pAddrField[index], pSmsAddrField->Ton, pSmsAddrField->Npi );
531 index++; // SET_TON_NPI �� MACRO �̹Ƿ� ���ο��� ������Ű�� ���׹߻�
533 SmsUtilConvertDigit2BCD( (char*) &pAddrField[index], (char*) pSmsAddrField->DialNumLen, pSmsAddrField->DialNumLen );
535 if ( pSmsAddrField->DialNumLen % 2 )
536 index += pSmsAddrField->DialNumLen / 2 + 1;
538 index += pSmsAddrField->DialNumLen / 2;
543 void SmsUtilDecodeDCS( Sms_coding_scheme* pCodingScheme, unsigned char dcs )
545 assert( pCodingScheme != NULL );
547 memset( pCodingScheme, 0, sizeof ( Sms_coding_scheme ) );
549 if ( dcs < 0x40 ) // bits 7..4 = 00xx : general data coding indication
551 pCodingScheme->coding_group_type = SMS_CODGRP_SM_GENERAL_DCS;
553 if ( dcs & 0x20 ) // bit 5 = 1 : indicates the text is compressed
554 pCodingScheme->bCompressed = TRUE;
556 if ( dcs & 0x10 ) // bit 4 = 1 : indicates that bits 1 to 0 have a message class meaning
558 pCodingScheme->bmsg_class_set = TRUE;
560 switch ( dcs & 0x03 ) // bits 1 to 0 : message class
563 pCodingScheme->class_type = SMS_CLASS_0;
566 pCodingScheme->class_type = SMS_CLASS_1;
569 pCodingScheme->class_type = SMS_CLASS_2;
572 pCodingScheme->class_type = SMS_CLASS_3;
576 else // bit 4 = 0 : indicates that bits 1 to 0 are reserved and have no message class meaning
577 pCodingScheme->class_type = SMS_CLASS_NONE;
579 switch ( dcs & 0x0C ) // bits 4 to 3 : character set
582 pCodingScheme->alphabet_type = SMS_ALPHABET_DEFAULT;
585 pCodingScheme->alphabet_type = SMS_ALPHABET_8BIT;
588 pCodingScheme->alphabet_type = SMS_ALPHABET_UCS2;
591 pCodingScheme->alphabet_type = SMS_ALPHABET_MAX;
595 else if ( dcs >= 0x40 && dcs < 0x80 ) // bits 7..4 = 01xx : message marked for automatic deletion group. bits 5..0 are coded exactly the same as group 00xx
597 pCodingScheme->coding_group_type = SMS_CODGRP_SM_AUTO_DELETION;
599 if ( dcs & 0x20 ) // bit 5 = 1 : indicates the text is compressed
600 pCodingScheme->bCompressed = TRUE;
602 if ( dcs & 0x10 ) // bit 4 = 1 : indicates that bits 1 to 0 have a message class meaning
604 pCodingScheme->bmsg_class_set = TRUE;
606 switch ( dcs & 0x03 ) // bits 1 to 0 : message class
609 pCodingScheme->class_type = SMS_CLASS_0;
612 pCodingScheme->class_type = SMS_CLASS_1;
615 pCodingScheme->class_type = SMS_CLASS_2;
618 pCodingScheme->class_type = SMS_CLASS_3;
622 else // bit 4 = 0 : indicates that bits 1 to 0 are reserved and have no message class meaning
623 pCodingScheme->class_type = SMS_CLASS_NONE;
625 switch ( dcs & 0x0C ) // bits 4 to 3 : character set
628 pCodingScheme->alphabet_type = SMS_ALPHABET_DEFAULT;
631 pCodingScheme->alphabet_type = SMS_ALPHABET_8BIT;
634 pCodingScheme->alphabet_type = SMS_ALPHABET_UCS2;
637 pCodingScheme->alphabet_type = SMS_ALPHABET_MAX;
641 // bits 7..4 = 1000 ~ 1011 : reserved
642 else if ( dcs == 0xC0 ) // bits 7..4 = 1100 : message waiting indication group, discard message
644 pCodingScheme->coding_group_type = SMS_CODGRP_SM_WAITING_DISCARD;
646 else if ( dcs < 0xE0 )
648 pCodingScheme->coding_group_type = SMS_CODGRP_SM_WAITING_STORE;
651 pCodingScheme->bmsg_ind_active = TRUE;
653 switch ( dcs & 0x03 )
656 pCodingScheme->waiting_type = SMS_WAITING_VOICE_MSG;
659 pCodingScheme->waiting_type = SMS_WAITING_FAX_MSG;
662 pCodingScheme->waiting_type = SMS_WAITING_EMAIL_MSG;
665 pCodingScheme->waiting_type = SMS_WAITING_OTHER_MSG;
669 else if ( dcs < 0xF0 )
671 pCodingScheme->coding_group_type = SMS_CODGRP_SM_WAITING_STORE_UCS2;
674 pCodingScheme->bmsg_ind_active = TRUE;
676 switch ( dcs & 0x03 )
679 pCodingScheme->waiting_type = SMS_WAITING_VOICE_MSG;
682 pCodingScheme->waiting_type = SMS_WAITING_FAX_MSG;
685 pCodingScheme->waiting_type = SMS_WAITING_EMAIL_MSG;
688 pCodingScheme->waiting_type = SMS_WAITING_OTHER_MSG;
694 pCodingScheme->coding_group_type = SMS_CODGRP_SM_CLASS_CODING;
697 pCodingScheme->alphabet_type = SMS_ALPHABET_8BIT;
699 switch ( dcs & 0x03 )
702 pCodingScheme->class_type = SMS_CLASS_0;
705 pCodingScheme->class_type = SMS_CLASS_1;
708 pCodingScheme->class_type = SMS_CLASS_2;
711 pCodingScheme->class_type = SMS_CLASS_3;
717 void SmsUtilEncodeDCS( unsigned char* pDCS, Sms_coding_scheme* pCodingScheme )
719 printf("SmsUtilEncodeDCS Start\n");
720 unsigned char dcs = 0x00;
722 assert( pCodingScheme != NULL );
724 if( pCodingScheme->coding_group_type == SMS_CODGRP_SM_GENERAL_DCS ) // bit 7..4 is 00xx
726 if ( pCodingScheme->bCompressed )
727 dcs |= 0x20; // bit 5 is 1
729 if ( pCodingScheme->bmsg_class_set )
731 dcs |= 0x10; // bit 4 is 1
733 if( pCodingScheme->class_type== SMS_CLASS_0 )
736 else if ( pCodingScheme->class_type == SMS_CLASS_1 )
739 else if ( pCodingScheme->class_type == SMS_CLASS_2 )
742 else if ( pCodingScheme->class_type == SMS_CLASS_3 )
746 switch ( pCodingScheme->alphabet_type )
748 case SMS_ALPHABET_DEFAULT: // bit 3..2 is 00
753 case SMS_ALPHABET_8BIT: // bit 3..2 is 01
758 case SMS_ALPHABET_UCS2: // bit 3..2 is 10
763 default: // bit 3..2 is 11
770 else if ( pCodingScheme->coding_group_type == SMS_CODGRP_SM_WAITING_DISCARD ) // bit 7..4 is 1100
774 else if ( pCodingScheme->coding_group_type == SMS_CODGRP_SM_WAITING_STORE ) // bit 7..4 is 1101
778 if ( pCodingScheme->bmsg_ind_active ) // bit 3..2 is 10
781 else if( pCodingScheme->waiting_type == SMS_WAITING_VOICE_MSG)
784 else if( pCodingScheme->waiting_type == SMS_WAITING_FAX_MSG)
787 else if( pCodingScheme->waiting_type == SMS_WAITING_EMAIL_MSG) // bit 1..0 is 10
790 else if( pCodingScheme->waiting_type == SMS_WAITING_OTHER_MSG) // bit 1..0 is 11
794 else if ( pCodingScheme->coding_group_type == SMS_CODGRP_SM_WAITING_STORE_UCS2 ) // bit 7..4 is 1110
798 if ( pCodingScheme->bmsg_ind_active ) // bit 3..2 is 10
801 if( pCodingScheme->waiting_type == SMS_WAITING_VOICE_MSG ) // bit 1..0 is 00
804 else if( pCodingScheme->waiting_type == SMS_WAITING_FAX_MSG )
807 else if( pCodingScheme->waiting_type == SMS_WAITING_EMAIL_MSG )
810 else if( pCodingScheme->waiting_type == SMS_WAITING_OTHER_MSG )
813 else if ( pCodingScheme->coding_group_type == SMS_CODGRP_SM_CLASS_CODING ) // bit 7..4 is 1111
817 if( pCodingScheme->alphabet_type == SMS_ALPHABET_DEFAULT ) // bit 2 is 0
819 else if( pCodingScheme->alphabet_type == SMS_ALPHABET_8BIT ) // bit 2 is 1
822 if( pCodingScheme->class_type == SMS_CLASS_0) // bit 1..0 is 00
825 else if( pCodingScheme->class_type == SMS_CLASS_1) // bit 1..0 is 01
828 else if( pCodingScheme->class_type == SMS_CLASS_2) // bit 1..0 is 10
831 else if( pCodingScheme->class_type == SMS_CLASS_3) // bit 1..0 is 11
835 memcpy( pDCS, &dcs, sizeof ( unsigned char ) );
837 printf("SmsUtilEncodeDCS End\n");
840 unsigned char SmsUtilEncodeValidity( unsigned char* pValidity, Sms_vp* pVP )
842 unsigned char pos = 0;
844 switch( pVP->vp_type )
846 case SMS_VP_NOT_USED:
849 case SMS_VP_RELATIVE:
850 pValidity[pos] = (unsigned char) pVP->vpValue;
854 case SMS_VP_ABSOLUTE:
856 //SmsUtilEncodeTimeStamp( pValidity, pVP->vpValue );
860 case SMS_VP_ENHANCED: