Protocol description
From GnokiiWiki
This page contains souce code in C/C++ for the FBUS protocol used by 6210 Nokia phones.
/*
some questions or comments send to <zecarlos1957@hotmail.com>
my thanks to web, i am learning width them
my bad ingles!!!!!!!!!!!!????????????
thanks to Justin Karneges who was the ward whork
I am Jose Jesus from Portugal
*/
#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <mem.h>
#include <dos.h>
#include <time.h>
#include <string.h>
#include "rs232.h" //or some else serial driver
#define N61MAXSIZE 120
#define BUF_SIZ 1024
typedef unsigned char uchar;
typedef unsigned short ushort;
uchar input_buffer[1024],output_buffer[1024];
unsigned char transtable[]={
'@' ,0xa3,'§' ,0xa5,0xe8,0xe9,0xf9,0xec,
0xf2,0xc7,'\n',0xd8,0xf8,'\r',0xc5,0xe5,
'?' ,'_' ,'?' ,'?' ,'?' ,'?' ,'?' ,'?' ,
'?' ,'?' ,'?' ,'?' ,0xc6,0xe6,0xdf,0xc9,
' ' ,'!' ,'\"','#' ,0xa4,'%' ,'&' ,'\'',
'(' ,')' ,'*' ,'+' ,',' ,'-' ,'.' ,'/' ,
'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,
'8' ,'9' ,':' ,';' ,'<' ,'=' ,'>' ,'?' ,
0xa1,'A' ,'B' ,'C' ,'D' ,'E' ,'F' ,'G' ,
'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O' ,
'P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,
'X' ,'Y' ,'Z' ,0xc4,0xd6,0xd1,0xdc,0xa7,
0xbf,'a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'g' ,
'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o' ,
'p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v' ,'w' ,
'x' ,'y' ,'z' ,0xe4,0xf6,0xf1,0xfc,0xe0
};
struct Message{
uchar id;
uchar dest;
uchar source;
uchar type;
uchar unknown;
uchar size;
uchar dat[256];
uchar cs[2];
}message;
int firsttime=1;
class TM{
protected:
int seqnum,prevseq,ack,inbox,done,nsms;
uchar memtype;
uchar version[80];
uchar smsc[80];
int sendframe(int,int,uchar*);
int nextseq();
// void sinc();
void smssendfull(char *smsc,char *dest,char *msg);
void sendack(int type,int seqnum);
void bcd(char *dst,char *s);
void bcd2(char *dst,char *s);
// char *unbcd(unsigned char *dat);
// char *unbcd2(unsigned char *dat);
void pack7(char *dst,char *s);
char *unpack7(unsigned char *dat,int len);
unsigned char gettrans(unsigned char c);
int process(Message*);
public:
void addchar(char *str,char c){
int n=strlen(str); str[n]=c; str[n+1]=0;
}
int sendmsg(int type,int len,uchar*buf);
char *unbcd(unsigned char *dat);
char *unbcd2(unsigned char *dat);
TM();
~TM();
void sinc();
int ackwait(int x);
int wait(int x);
int send(uchar *,uchar*);
int update();
int gettxt(uchar*);
void show(Message*);
void ver();
int getmail(){return inbox;}
void savemsg(char *sender,char *d,char *t,char *m);
};
int off=0,mode=0,datp=0,multiple=0,readsize=0;
char Paulo[]={"918617088"};
uchar msg[512];
uchar msg2[512];
uchar Date[10];
uchar Time[10];
char sender[15];
uchar s1[50];
uchar Imei[50];
uchar Operator[50];
uchar SmsC[15];
int NetStatus=0;
int Battery=0;
uchar index=0;
uchar memtype=0x02;
/*
this is a part of a frame.this frame is complet wen sending
to the function TM::sendmsg(getver[0],getver[1],&getver[2])
*/
uchar getver[] = {0xd1,0x05,0x00,0x01,0x00,0x03,0x00};
uchar getsmsc[]= {0x02,0x06,0x00,0x01,0x00,0x33,0x64,0x01};
uchar getimei[]= {0x1b,0x04,0x00,0x01,0x00,0x01};
uchar getbatt[]= {0x17,0x04,0x00,0x01,0x00,0x02};
uchar getrf[] = {0x0a,0x04,0x00,0x01,0x00,0x81};
uchar getnetwork[]={0x0a,0x04,0x00,0x01,0x00,0x70};
uchar readsms[]= {0x14,0x0a,0x00,0x01,0x01,0x07,memtype,0x00,index,0x01,0x65,0x01};
uchar getalarm[]= {0x11,0x04,0x00,0x01,0x00,0x6d};
uchar delsms[] = {0x14,0x08,0x00,0x01,0x00,0x0a,memtype,0x00,index,0x00};
uchar smsstatus[]= {0x14,0x05,0x00,0x01,0x00,0x36,0x64};
class App:public TM{
int status,todo,old;
char port;
uchar *doit;
uchar *tarefa[255];
public:
App():status(0),port('1'),todo(0),old(0){}
int init(){
if( rs_initport(port,RS_B115K,RS_NOPAR,RS_DBIT8,RS_SBIT1,
BUF_SIZ,input_buffer,BUF_SIZ,output_buffer)>0){
status=0;
rs_modctrl(RS_WRTMCR,RS_MCRDTR,RS_LINON);
cprintf("Terminal mode active \r\n");
}
else{
status=1;
cprintf("Unable to open COM port\r\n");
return status;
}
tarefa[6]=::getver;
tarefa[5]=::getsmsc;
tarefa[4]=::getimei;
tarefa[3]=::getbatt;
tarefa[2]=::getrf;
tarefa[1]=::getnetwork;
tarefa[0]=::smsstatus;
todo=7;
return status;
}
~App(){
if(status==0)rs_modctrl(RS_WRTMCR,RS_MCRDTR,RS_LINOFF);
rs_close();
}
int upload(){
int r;
if(todo!=old && todo){
doit=tarefa[todo-1];
sendmsg(doit[0],doit[1],&doit[2]);
old=todo;r=0;
}else{
if(old>0){
printf("Comando [%s] ",itoa((int)doit[0],s1,16));
printf("Nao Executado. Repetir? esc:space\r\n");
old=0;
r=27;
}
}
return r;
}
int getstatus(){
if(done && todo==old && todo ){
todo--;old=0;done=0;
return ((message.type<<8)|message.dat[3]);
}
return 0;
}
void insertcmd(uchar * cmd){
if(todo<255){tarefa[todo++]=cmd;}
else printf("Error to mutch tarefas\r\n");
}
int getarefa(){return todo;}
void sendsms(uchar *dst,uchar *m){
if(smsc==0 || dst==0){
printf("Falta o numero do Centro de mensagens\r\n");
return;
}
smssendfull(smsc,dst,m);
}
void savemsg(uchar *s,uchar *d,uchar *t,uchar *mess){
FILE *f=fopen("backup.dat","at");
if(!f)return;
strcat(s,d);
strcat(s,t);
strcat(s,mess);
fwrite(s,strlen(s),1,f);
fclose(f);
}
};
void main(){
int end=0,c=0,er=0,type,mail=0;
App app;
long t1=0,t2,t3=8000;
char *dst;
if(app.init()==0){
t1=clock();
while(!end){
t2=clock();
if(t2>t1){
t1=t2+t3;
if(app.getarefa()==0){
app.insertcmd(smsstatus);
// see if there is sms to send ? send it
if(app.loadnet());
}
c=app.upload();
}
if(kbhit())c=getch();
if(c){
if(c==27){
while(!kbhit());
if((c=getch())==27)break;
c=0;
}
if(c==0x52){
if(app.gettxt(msg)){
dst=Paulo;
app.sendsms(dst,msg);
}
}
}
delay(1);
if((er=app.update())){
if(er&0x01)printf("Receive overrun(buffer) ");
if(er&0x02)printf("Receive overrun(UART) ");
if(er&0x04)printf("Parity error ");
if(er&0x08)printf("Framing error ");
if(er&0x10)printf("Break detected ");
if(er&0x20)printf("Error in receive FIFO ");
printf(" Esc-ABort : Else-Continue \r\n");
c=27;
}
if((type=app.getstatus())){
if(type==0x1437){
//if status report a sms message
if(index==0)index=message.dat[15];
mail=index;
if(mail ){
printf("%sª Messagem nova ",itoa(mail,s1,10));
readsms[8]=mail;t1=0;
app.insertcmd(readsms); // read it
}
}
if(type==0x1408){
//if there is a sms mark as read
mail=message.dat[7];
if(mail){
printf("%s %s\r\n",sender,::msg);
// app.show(&message);
printf("\r\n");
if(index)index--;
readsms[8]=mail;t1=0;
// app.insertcmd(delsms); // delete it
// app.savemsg(sender,Date,Time,msg);
}
}
if(app.getarefa()>1)t1=0;
}
}
}
}
TM::TM():seqnum(0),prevseq(0),ack(0),memtype(0x02),inbox(0),done(0),nsms(0){
smsc[0]=0;version[0]=0;Imei[0]=0;Operator[0]=0;SmsC[0]=0;
}
TM::~TM(){}
int TM::send(uchar *num,uchar *msg){
if(smsc[0]==0)return 0x300;
printf("Waiting...");
smssendfull(smsc,num,msg);
return 0;
}
int TM::sendmsg(int type,int size,unsigned char *data){
unsigned char buf[N61MAXSIZE+2];
unsigned char num,lastsize;
int n,len,er;
num=(size+N61MAXSIZE-1)/N61MAXSIZE;
lastsize=size%N61MAXSIZE;
sinc();
for(n=0;n<num;++n){
if(n+1==num) len=lastsize;
else len=N61MAXSIZE;
memcpy(buf,data+(n*N61MAXSIZE),len);
buf[len++]=num-n; // multiple framed msg
buf[len++]=nextseq(); // sequenci
if(n) buf[len-1]&=7;
ack=0;
if((er=sendframe(type,len,buf)))break;
}
return er;
}
int TM::sendframe(int type,int size,uchar *data){
unsigned char buf[256];
int at,n,check,len;
unsigned short *p;
at=0;
buf[at++]=0x1e; // id comunication 0x1e cable=0x1e infred=0x1c
buf[at++]=0x00; // dest 0x00=mobil
buf[at++]=0x0c; // source 0x0c=pc
buf[at++]=type; // comand type see below
buf[at++]=0; // multiple sms
buf[at++]=size; // size of data
for(n=0;n<size;n++) buf[at++]=data[n];
if(size%2)buf[at++]=0;
check=0;
p=(unsigned short *)buf;
len=at/2;
for(n=0;n<len;n++) check ^=p[n];
p[n]=check;
at+=2;
int er;
er=rs_sndstr(at,buf);
// printf(" send "); show((Message*)buf);
if(er>0)er|=0x500;
return er;
}
int TM::update(){
int n,er=0;
uchar c;
while(rs_inrcvd()){
c=rs_getbyt();
if(er=rs_error())break;
message.cs[(off&1)]^=c;
switch (mode){
case 0:
if(c==0x1e){
if(!multiple){
memset(message.dat,0,255);}
message.id=message.cs[0]=0x1e;message.cs[1]=0;
mode=1;off=0;
}
break;
case 1:
if((message.dest=c)==0x0c)mode=2; else mode=0;
break;
case 2: message.source=c;mode=3;break;
case 3: message.type=c;mode=4;break;
case 4: message.unknown=c;mode=5;break;
case 5:
if(multiple) { message.size+=c-2; }
else {message.size=c;datp=0;}
mode=6;n=message.size%2;
readsize=message.size+n+2;break;
case 6:
n=datp++;
if(n>255){
multiple=0;mode=0;
printf("Data to long \r\n");break;
}
message.dat[n]=c;
if(n>=readsize-1){
if(message.cs[0]==message.cs[1] && message.cs[0]==0){
if(message.type!=0x7f ){
sendack(message.type,message.dat[message.size-1]&0x0f);
if(message.size>1 && message.dat[message.size-2]!=0x01){
datp-=4;
++multiple;
}else multiple=0;
}
if(!multiple || message.type==0x7f){
printf("Accept ");show(&message);
multiple=0;
process(&message);
}
}else{ multiple=0;printf("CheckSum Error\r\n");show(&message);}
mode=0;
}
default:break;
}
off++;
}
return er;
}
void TM::smssendfull(char *smsc,char *dest,char *msg){
unsigned char buf[256];
int n;
//short Message Service Frame header
buf[0]=0x00; // \
buf[1]=0x01; // > SMS Frame header
buf[2]=0x00; // /
buf[3]=0x01; // \
buf[4]=0x02; // > Send SMS Message
buf[5]=0x00; // /
memset(buf+6,0,12);
bcd(buf+6,smsc); //Short Message Service Center 12 bytes
buf[18]=0x11; // Message type
buf[19]=0x00; // SMS reference
buf[20]=0x00; // Protocol ID
buf[21]=0xf1; // Data coding scheme
buf[22]=strlen(msg); //message size
memset(buf+23,0,12);
bcd2(buf+23,dest); /// 12 bytes
buf[35]=0xa7; // valid period code
buf[36]=0x00;
buf[37]=0x00;
buf[38]=0x00;
buf[39]=0x00; //
buf[40]=0x00; //
buf[41]=0x00; //
pack7(buf+42,msg); // 44 bytes
sendmsg(0x02,42+strlen(msg),buf);
}
void TM::sendack(int type,int seqnum){
char buf[2];
buf[0]=type;
buf[1]=seqnum; // sequenci
sendframe(0x7f,2,buf);
}
int TM::ackwait(int x){
int n;
for(n=0;n<x;n++){
delay(1);
update();
if(ack)return 1;
}
return 0;
}
int TM::nextseq(){
int n,n1;
n=seqnum;
prevseq=n;
++seqnum;
seqnum&=7;
if(::firsttime){::firsttime=0;n1=0x60;}else n1=0x40;
return (n+n1);
}
void TM::bcd(char *dst,char *s){
int size,x,y,n,hi,lo;
if(s[0]=='+'){ dst[1]=0x91;++s;}
else dst[1]=0xa1;//unknown 0x81;
x=0;y=2;
while(s[x]){
lo=s[x++]-'0';
if(s[x])hi=s[x++]-'0';
else hi=0x0f;
n=(hi<<4)+lo;
dst[y++]=n;
}
dst[0]=y-1;
}
void TM::bcd2(char *dst,char *s){
int size,x,y,n,hi,lo;
if(s[0]=='+'){ dst[1]=0x91;++s;}
else dst[1]=0x81;
x=0;y=2;
while(s[x]){
lo=s[x++]-'0';
if(s[x])hi=s[x++]-'0';
else hi=0x0f;
n=(hi<<4)+lo;
dst[y++]=n;
}
dst[0]=strlen(s);
}
char *TM::unbcd(unsigned char *dat){
static char buf[32];
int len,n,x;
buf[0]=0;
len=dat[0];
if(dat[1]==0x91) addchar(buf,'+');
for(n=0;n<len-1;n++){
x=dat[n+2]&0x0f;
if(x<10) addchar(buf,'0'+x);
x=(dat[n+2]>>4)&0x0f;
if(x<10) addchar(buf+1,'0'+x);
}
return buf;
}
char *TM::unbcd2(unsigned char *dat){
static char buf[32];
int len,n,x,at=2;
buf[0]=0;
len=dat[0];
if(dat[1]==0x91) addchar(buf,'+');
for(n=0;n<len;n++){
x=dat[at]&0x0f;
if(x<10) addchar(buf,'0'+x);
++n;
if(!(n<len))break;
x=(dat[at]>>4)&0x0f;
if(x<10) addchar(buf+1,'0'+x);
++at;
}
return buf;
}void TM::pack7(char *dst,char *s){
int len,at,shift,n,x;
unsigned char c;
unsigned short *p;
unsigned short w;
len=strlen(s);
x=(len*8)/7;
for(n=0;n<len;n++)dst[n]=0;
shift=at=w=0;
for(n=0;n<len;n++){
p=(unsigned short*)(dst+at);
w=gettrans(s[n])&0x7f;
w<<=shift;
*p|=w;
shift+=7;
if(shift>=8){shift&=0x07;++at; }
}
}
char * TM::unpack7(unsigned char *dat,int len){
static char buf[256];
unsigned short *p;
unsigned short w;
unsigned char c;
int n,shift,at;
shift=at=buf[0]=0;
for(n=0;n<len;n++){
p=(unsigned short *)(dat+at);
w=*p;
w>>=shift;
c=w&0x7f;
shift+=7;
if(shift &8){ shift&=0x07; ++at; }
addchar(buf,transtable[c]);
}
buf[n]=0;
return buf;
}
unsigned char TM::gettrans(unsigned char c){
unsigned char n;
if(c=='?')return 0x3f;
for(n=0;n<128;n++)
if(transtable[n]==c)
return n;
return 0x3f;
}
void TM::show(Message *head){
int i=0;
printf("%s ",itoa((int)head->id,s1,16));
printf("%s ",itoa((int)head->dest,s1,16));
printf("%s ",itoa((int)head->source,s1,16));
printf("%s ",itoa((int)head->type,s1,16));
printf("%s ",itoa((int)head->unknown,s1,16));
printf("%s ",itoa((int)head->size,s1,16));
for(int n=0;n<head->size+2;n++)
printf("%s ",itoa(head->dat[n],s1,16));
printf("\r\n");
}
int TM::process(Message *msg){
int n,stype;
switch(msg->type){
case 0x02:
if(msg->dat[3]==0x02){printf("Mensagem Entrege\r\n");done=1;}
if(msg->dat[3]==0x03){printf("BAD\r\n");done=1;}
if(msg->dat[3]==0x10){
printf("%s %s\r\n",unbcd(msg->dat+23),unpack7(msg->dat+42,msg->dat[22]));
// if(mess->dat[5])delsms(mess->dat[5]);
done=1;
}
if(msg->dat[3]==0x34) { // recev sms center
strcpy(smsc,unbcd(msg->dat+21));
printf("SMS Center: %s \r\n",smsc);
done=1;
}
break;
case 0x0a:
if(msg->dat[3]==0x71){ // Get Network Operator
for(n=0;n<msg->dat[16];n++)
addchar(Operator,msg->dat[n+17]);
printf("NetWork %s\r\n",Operator);
done=1;
}
if(msg->dat[3]==0x82){ // Get Network Status RF
NetStatus=msg->dat[4];
done=1;
printf("RF signal %s Percent\r\n",itoa((int)NetStatus,s1,10));
}
break;
case 0x14:
if(msg->dat[3]==0x08){ //ler mensagem
int at=0,x;
for(n=2;n>=0;n--){
x=(msg->dat[37+n]&0x0f);
if(x<10)Date[at++]=x+'0';
x=(msg->dat[37+n]>>4);
if(x<10)Date[at++]=x+'0';
Date[at++]='-';
}
Date[at-1]=0;at=0;
for(n=0;n<3;n++){
Time[at++]='0'+(msg->dat[40+n]&0x0f);
Time[at++]='0'+(msg->dat[40+n]>>4);
Time[at++]=':';
}
Time[at-1]=0;
/* if(msg->dat[42]==0x34){
printf("_ %s_ \r\n",unbcd(&msg->dat[44]));
}
*/ strcpy(::msg,unpack7(msg->dat+44,msg->dat[24]));
strcpy(sender,unbcd2(msg->dat+25));
if(nsms){
// printf("%s ",itoa((int)msg->dat[49],s1,16));
// printf("%s \r\n",itoa((int)msg->dat[48],s1,16));
if(msg->dat[49]==(nsms>>8))strcpy(msg2,::msg+7);
else {strcat(::msg,msg2);strcpy(msg2,::msg+7);}
if(msg->dat[49]==1){strcpy(::msg,msg2);nsms=0;}
}
done=1;
}
else if(msg->dat[3]==0x09){done=1;} // nao ha mensagens novas
else if(msg->dat[3]==0x0b){done=1;printf("Mensagem Apagada\r\n");}
else if(msg->dat[3]==0x37){done=1;} //memsagen nova recebida
break;
case 0x17:
if(msg->dat[3]=0x03){ // Battery charge
Battery=msg->dat[5];
printf("Battery %s Percent\r\n",itoa((int)Battery,s1,10));
done=1;
}
break;
case 0x1b: // Imei
if(msg->dat[3]==0x02){
n=4;
while(msg->dat[n])addchar(Imei,msg->dat[n++]);
printf("Imei: %s\r\n",Imei);
done=1;
}
break;
case 0x1f:
done=1;
break;
case 0xd0:
break;
case 0xd2:
version[0]=0; //recev software & hardware versin
for(n=4;n<35;n++)
addchar(version,msg->dat[n]);
printf("Version: %s\r\n",version);
done=1;
break;
case 0x40:
if(msg->dat[2]==0xca){ //ProducteCode
done=1;
}
break;
case 0x7f: // acknoledg previos command
if((msg->dat[1]&7)==prevseq) ack=1;
break;
default:break;
}
}
void TM::savemsg(char *sender,char *d,char *t,char *m){
printf("Sender: %s ",sender);
printf("date: %s ",d);
printf("time: %s ",t);
printf(": %s ",m);
}
int TM::gettxt(uchar *msg){
int off=0;uchar c=0;
printf("Enter text\r\n");
while(1){
if (kbhit()){
c=getch();
if(c==13 || c==27)break;
msg[off++]=c;
msg[off]=0;
printf(&msg[off-1]);
c=0;
}
}
printf("\r\n");
if(c==27) return 0;
else return 1;
}
void TM::sinc(){
for(int n=0;n<128;n++) //55
rs_sndbyt(0x55);
delay(5);
}

