Ady Wicaksono Daily Activities

Javacard code to send SMS (Unformated SMS-PP & 7Bit TP-UD)

with 2 comments

TP-UD of SMS as defined in GSM 03.40 can contain up to 140 octet/bytes. But some common people always ask, are you sure only 140 bytes? Because normally we can send 160 character. Yes, because those 160 character is actually a 7bit data (septet), means with 140 octet we can send 140 * 8/7 ~ 160 septet. I hope you know it now🙂

Ok, some javacard programmer ask how to send SMS Unformatted PP (means not include GSM 03.48 header) with 7bit TP-UD? Let me show you.

1. You need to define these variables somewhere inside your javaclass

// Variable to declare inside your class
private byte[] bSendSMSBuffer; // Buffer of TP-UD SMS
private byte[] ramUnPacked;
private byte[] ramPacked;

2. You need to allocate memory for this, normally you should put it on RAM rather on EEPROM, because do writing on EEPROM too oftenly will kill the card. Normally you will put these codes inside your javacard class constructor

try{
      // Allocate buffer on RAM and free it once the applet is deselected
      bSendSMSBuffer  = JCSystem.makeTransientByteArray( ( short )160,       
                                              JCSystem.CLEAR_ON_DESELECT );
}catch (SystemException e){
      // Allocate buffer on EEPROM, if your application will write a lot on this variable,
      // this one should be avoided if possible
      bSendSMSBuffer  = new byte[(short)160];
}

try{
   ramUnPacked		= JCSystem.makeTransientByteArray( (short)8, 
                                           JCSystem.CLEAR_ON_DESELECT);
}catch(SystemException e){
   ramUnPacked     = new byte[(short)8];
}
try{
     ramPacked		= JCSystem.makeTransientByteArray( (short)8, 
                                           JCSystem.CLEAR_ON_DESELECT);
}catch(SystemException e){
    ramPacked     = new byte[(short)8];
}

3. Add this 2 function on your javacard class code:


	
	// Send sms function
	// input: tpud, len of tpud, destination address , len of destination address
	public byte sendSMS(byte[] dataBuff, short Len,byte[] DesAdd, short DesLen) throws UserException {	
		ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
		short smstpduLength      = (short) 0;
		short numberLength       = (byte)  0;
		final byte CMD_QUALIFIER_PACKING_NOT_REQUIRED = (byte) 0;

		//Initialize the recordbuffer to Construct the Sms-TPDU Buffer
		Util.arrayFillNonAtomic(bSendSMSBuffer, (short)0, 
		            (short)bSendSMSBuffer.length, (byte)0x00);


		// Now Construct the Sms TPDU in the recordData
		// see GSM 03.40 for details
		bSendSMSBuffer[smstpduLength++] = (byte) 0x01; //SMS-Submit Type
		bSendSMSBuffer[smstpduLength++] = (byte) 0x01; //Message reference

		// TP-Destination Address
		Util.arrayCopy(DesAdd,(short)0, bSendSMSBuffer, smstpduLength,(short)DesLen);
		smstpduLength = (short) ((short) smstpduLength + (short)DesLen);
	
		bSendSMSBuffer[smstpduLength++] = (byte) 0x00; // TP-PID 0x00
		bSendSMSBuffer[smstpduLength++] = (byte) 0x00; // TP-DCS 0x00
		bSendSMSBuffer[smstpduLength++] = (byte) Len;  // TP-UDL (User Data Length)

		// Pack data to 7 bit before sending
		convert_8bit_2_7bit( dataBuff, (short)0, Len, bSendSMSBuffer, smstpduLength );
            
		short f = 0;
		f       = (short)((short)(Len * 7 )/(short)8 );
		if((short)(Len % 8 ) != (short)0){
				f++;
		}	
		
		smstpduLength+=f;                 
		
		// Sending the message
		proHdlr.init(PRO_CMD_SEND_SHORT_MESSAGE,CMD_QUALIFIER_PACKING_NOT_REQUIRED, DEV_ID_NETWORK);

		// Uncommented this one to add some text while sending sms
		//proHdlr.appendTLV((byte) (TAG_ALPHA_IDENTIFIER),SENDING, (byte)0, (short) SENDING.length);

		proHdlr.appendTLV((byte) (TAG_SMS_TPDU),bSendSMSBuffer, (byte)0, (short)smstpduLength);		
		return proHdlr.send();
	}
	
		

	private void convert_8bit_2_7bit( byte[] source,
                                      short sourceStartOfst,
                                      short sourceLen,
                                      byte[] destin,
                                      short destinOfst){
        
		// Convert 8 bytes of data at each pass
		short copyLength = (short) 8;
        
		// Pointer pointing to the start offset
		short sourcePtr = sourceStartOfst;
        
		// Calculate the end offset of the unpacked data
		short sourceEndOfst = (short) ( sourceStartOfst + sourceLen );
        
		// Loop until gone through all the data
		while ( sourcePtr < sourceEndOfst ){
			// If the remaining data in Unpacked data is less than the 8 byte unit
			if ( (short) ( sourcePtr + copyLength ) > sourceEndOfst ) {                
				// Get the remaining number of bytes
				copyLength = (short) ( sourceEndOfst - sourcePtr );                
				// Clear the RAM data
				Util.arrayFillNonAtomic( ramUnPacked, (short) 0, (short) 8, (byte) 0x00 );                
			}

			// Copy from source data to RAM unpacked data
			Util.arrayCopyNonAtomic( source, sourcePtr, ramUnPacked, (short) 0, copyLength );

			// Update Source Pointer
			sourcePtr += copyLength; 
			// Calculate 1st byte
			ramPacked[0] = (byte) ( ( ( ramUnPacked[0] << 1 ) & 0xFE) | ( ( ramUnPacked[1] >> 6 ) & 0x01 ) );		                                                                                      
			// Calculate 2nd byte
			ramPacked[1] = (byte) ( ( ( ramUnPacked[1] << 2 ) & 0xFC) | ( ( ramUnPacked[2] >> 5 ) & 0x03 ) );		                                                                                      
			// Calculate 3rd byte
			ramPacked[2] = (byte) ( ( ( ramUnPacked[2] << 3 ) & 0xF8) | ( ( ramUnPacked[3] >> 4 ) & 0x07 ) );		                                                                                      
			// Calculate 4th byte
			ramPacked[3] = (byte) ( ( ( ramUnPacked[3] << 4 ) & 0xF0) | ( ( ramUnPacked[4] >> 3 ) & 0x0F ) );		                                                                                             
			// Calculate 5th byte
			ramPacked[4] = (byte) ( ( ( ramUnPacked[4] << 5 ) & 0xE0) | ( ( ramUnPacked[5] >> 2 ) & 0x1F ) );                                                                                      
			// Calculate 6th byte
			ramPacked[5] = (byte) ( ( ( ramUnPacked[5] << 6 ) & 0xC0) | ( ( ramUnPacked[6] >> 1 ) & 0x3F ) );		                                                                                      
			// Calculate 7th byte
			ramPacked[6] = (byte) ( ( ( ramUnPacked[6] << 7 ) & 0x80) | ( ( ramUnPacked[7] >> 0 ) & 0x7F ) );
			
			// Copy the RAM packed data to destination byte array
			Util.arrayCopyNonAtomic( ramPacked, (short) 0, destin, destinOfst, (short) 7 );
		    
			// Update Destination Pointer
			destinOfst += (short) 7;                  
		}        
	}	

And you then can simply sms like this:
1. For example you want to send SMS to 12345, you will need to create TP_DA (Destination Address) byte array containing:
1. first 1 byte that inform the length of address
2. 2nd 1 byte that inform TON/NPI
3. the rest is address in BCD swapped format

e.g like this:

private byte[] TPDA       = {(byte)0x05,(byte)0x81,(byte)0x21,(byte)0x43,(byte)0xF5};
0x05 : Length of '12345' -> 5 bytes
0x81: TON/NPI
0x21 0x43 0xF5: BCD swapped format for address 12345

And then you define the SMS content like this:

private byte[] sms_content = {(byte)'T',(byte)'e',(byte)'s',(byte)'t')};

And then you send it like this

try{
sendSMS(sms_content,(short)sms_content.length, TPDA, (short)TPDA.length);
}catch(Exception e){
}

Good luck🙂

Written by adywicaksono

October 24, 2007 at 2:54 pm

Posted in SmartCard

2 Responses

Subscribe to comments with RSS.

  1. Hi ,

    Any one knows of any java utilities which convert a phone number – ‘252525254’ to BCD swapped format ?
    from byte b= {2, 5, 2, 5 2, 5,2 5};

    to
    private byte[] TPDA = {(byte)0x08,(byte)0x81,(byte)0x52,(byte)0x52,(byte)0x52}, (byte) 0x52;

    Dhatri Velpucharla

    August 7, 2009 at 3:36 pm

  2. halo mas adi
    salam kenal
    saya mau tanya langkah bagaimana cara membaca
    atr using pcs reader menggunakan bahasa java
    mohon bantuannya ya mas

    best regards

    sariffudin

    sariffudin

    May 12, 2010 at 9:15 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: