1 2 /* 3 name: btsc.h 4 desc: 蓝牙串口通信数据包装 5 writer: zhangbin 6 date: 2007-01-25 7 history: 8 2007-0206 zhangbin 9 1. btsc_context增加 user 10 2. notifier函数原型增加 btsc_context参数,便于访问上下文 11 2008.06.16 scott 12 1. 增加crc校验属性 13 CRC=12345 14 crc校验和计算: 准备发送一个数据包之前,将默认crc属性(CRC=00000)作为属性包加入,然后将整个属性包进行crc计算出校验和 15 将16位的crc sum 转换成5字节的字符串替换包属性CRC的值 16 <MSG=DEVICE-OPEN CRC=00000> =>计算机校验和 45322 17 替换数据包属性值=> <MSG=DEVICE-OPEN CRC=45322> 18 发送 19 2. 增加 DataChecker 20 */ 21 22 #ifndef _BTSC_H 23 #define _BTSC_H 24 25 #include <stdio.h> 26 27 #define OUT 28 #define INOUT 29 #define IN 30 31 #define INIT_LIST_HEAD(x) 32 33 #define btsc_TRUE 0 34 #define btsc_FALSE 1 35 #define btsc_NULL 0 36 37 struct list_head{ 38 struct list_head* prev,*next; 39 }; 40 41 42 struct btsc_Property{ 43 char * name; 44 char * value; 45 }; 46 47 48 struct btsc_Packet{ 49 /*struct list_head list;*/ 50 struct btsc_Property** properties; 51 int size; 52 int capacity; 53 struct btsc_Context * ctx; 54 }; 55 56 struct btsc_Packet* btsc_Packet_Alloc(struct btsc_Context* ); 57 void btsc_Packet_Free(struct btsc_Packet*); 58 59 struct btsc_Property* btsc_Property_Alloc(struct btsc_Context* ,char * name,char * value); 60 void btsc_Property_Free(struct btsc_Property*); 61 62 63 64 struct btsc_Property* btsc_Property_Get(struct btsc_Packet* packet,char * name); 65 void btsc_Property_Append(struct btsc_Packet* packet,struct btsc_Property * ); 66 67 68 69 struct btsc_Context{ 70 void (*tx)(struct btsc_Context*,unsigned char * data,int len); 71 int (*notifier)(struct btsc_Packet* packet);/*外部释放packet,返回NULL*/ 72 int packet_cached_size; 73 int recv_cached_capacity; 74 char* recv_buff; 75 int recv_size; 76 void* user; // 外部数据传递 77 int crc_check; // 0 - nocrc, 1 crc check 78 }; 79 80 81 int btsc_init(struct btsc_Context* IN ctx); 82 void btsc_cleanup(struct btsc_Context* IN ctx); 83 int btsc_Pack(struct btsc_Context* IN ctx,struct btsc_Packet* packet,unsigned char * INOUT buff,int* INOUT size); 84 void btsc_Parse(struct btsc_Context* , char * data,int len); 85 86 87 #define BTSC_PACKET_BEGIN(ctx) {\ 88 struct btsc_Context* _ctx_internel;\ 89 struct btsc_Packet * _pkt ;\ 90 _ctx_internel= (ctx);\ 91 _pkt = btsc_Packet_Alloc(_ctx_internel); 92 93 /* key is not suitable for vairable*/ 94 #define BTSC_NEW_PROPERTY(key,value) {\ 95 struct btsc_Property * _ppt =btsc_Property_Alloc(_ctx_internel,key,value);\ 96 btsc_Property_Append(_pkt,_ppt);\ 97 } 98 #define BTSC_PACKET_END() btsc_Pack(_ctx_internel,_pkt,btsc_NULL,0);\ 99 btsc_Packet_Free(_pkt);\ 100 } 101 102 #define BTSC_FOREACH(packet,ppt) {\ 103 int n;\ 104 for(n=0;n<packet->size;n++){\ 105 ppt = packet->properties[n]; 106 #define BTSC_END_FOREACH() }\ 107 } 108 109 #endif 110 111
1 2 3 /* 4 name: btsc 5 serial communicating with bluetooth and app-user 6 desc: pair parameter codec 7 8 packet=[ key:name,] 9 10 implemented: zhangbin 11 date: 2007-01-26 12 */ 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #ifdef _UNIX 18 #include <unistd.h> 19 #endif 20 #include "btsc.h" 21 #include "crc.h" 22 23 #define CRC_DEFAULT_STRING "CRC=00000" 24 #define PACKET_HEAD '<' 25 #define PACKET_TAIL '>' 26 #define PROPERTY_DELIMITER ',' 27 #define PAIR_DELIMITER '=' 28 //#define PAIR_DELIMITER '$' 29 #define ESCAPE_CHAR '\\' 30 31 32 int calcEscapleLength(char * str); 33 char* escape_copy(char * dest,char * src); 34 void trim_escape_copy(char * dest,char * src,int size); 35 int calcPacketLength(struct btsc_Packet* pkt); 36 int is_escape_char(char c); 37 void parseProperty(struct btsc_Packet * pkt,char * s,char * e); 38 void parsePacket(struct btsc_Context* ctx,char * s,char* e); 39 char* __memchr(char * s,char* e,char c); 40 41 char escape_ch_table[]={PACKET_HEAD,PACKET_TAIL,PROPERTY_DELIMITER,PAIR_DELIMITER,ESCAPE_CHAR,'\0'}; 42 43 struct btsc_Packet* btsc_Packet_Alloc(struct btsc_Context* ctx){ 44 struct btsc_Packet * pt = malloc(sizeof(struct btsc_Packet)); 45 pt->size = 0; 46 pt->capacity = ctx->packet_cached_size; 47 pt->properties=malloc(pt->capacity*sizeof(struct btsc_Property*)); 48 pt->ctx = ctx; 49 return pt; 50 } 51 52 void btsc_Packet_Free(struct btsc_Packet* pt){ 53 struct btsc_Property** tmp; 54 if( !pt ) return ; 55 tmp = pt->properties; 56 while(pt->size--){ 57 btsc_Property_Free(*tmp++); 58 } 59 if( pt->properties){ 60 free(pt->properties); 61 } 62 free(pt); 63 } 64 65 66 struct btsc_Property* btsc_Property_Alloc(struct btsc_Context* ctx,char * name,char * value){ 67 struct btsc_Property * ppt; 68 /* printf("enter btsc_Property_Alloc()\n");*/ 69 ppt = malloc( sizeof( struct btsc_Property) ); 70 if(!ppt) printf("error: malloc failed (s1)\n"); 71 ppt->name = malloc( strlen(name)+1); 72 if( !ppt->name ) printf("error: malloc failed (s2)\n"); 73 strcpy(ppt->name,name); 74 ppt->value = malloc( strlen(value)+1); 75 if( !ppt->value) printf("error: malloc failed (s3),str:%s, len: %d\n",value,strlen(value)+1); 76 strcpy( ppt->value,value); 77 return ppt; 78 } 79 80 void btsc_Property_Free(struct btsc_Property* ppt){ 81 if( !ppt ) return; 82 free( ppt->name); 83 free( ppt->value); 84 free( ppt); 85 } 86 87 /* scan pointer array */ 88 struct btsc_Property* btsc_Property_Get(struct btsc_Packet* pkt,char * name){ 89 int size; 90 struct btsc_Property* ppt; 91 size = pkt->size; 92 while(size--){ 93 ppt = pkt->properties[size]; 94 if( !strcmp( name, ppt->name ) ){ 95 return ppt;/*that's ok */ 96 } 97 } 98 return btsc_NULL; 99 } 100 101 /* low effeciency, memory allocation,more costs*/ 102 void btsc_Property_Append(struct btsc_Packet* pt,struct btsc_Property * ppt){ 103 struct btsc_Property** tmpppt; 104 if( pt->size==pt->capacity){ 105 pt->capacity += pt->ctx->packet_cached_size; 106 tmpppt = pt->properties; 107 pt->properties = malloc( pt->capacity * sizeof( struct btsc_Property**) ); 108 memcpy( pt->properties, tmpppt, pt->size * sizeof( struct btsc_Property**)); 109 free( tmpppt); 110 } 111 pt->properties[pt->size++]=ppt; 112 } 113 114 int btsc_init(struct btsc_Context* ctx){ 115 ctx->packet_cached_size = 10; 116 if( ctx->recv_cached_capacity==0){ 117 ctx->recv_cached_capacity = 1024*2; 118 } 119 ctx->recv_buff = malloc( ctx->recv_cached_capacity ); 120 ctx->recv_size = 0; 121 ctx->crc_check = 1; 122 return btsc_TRUE; 123 } 124 125 void btsc_cleanup(struct btsc_Context* ctx){ 126 free(ctx->recv_buff); 127 } 128 129 /* 130 ** name: calcEscapleLength 131 ** desc: 计算含转义字符串长度 132 */ 133 int calcEscapleLength(char * str){ 134 int len; 135 char * pesc; 136 len = 0; 137 while( *str ){ 138 pesc = escape_ch_table; 139 while( *pesc ){ 140 if( *pesc==*str){ 141 len++; 142 break; 143 } 144 pesc++; 145 } 146 str++; 147 } 148 return len; 149 } 150 151 152 char* escape_copy(char * dest,char * src){ 153 char * pesc; 154 while( *src ){ 155 pesc = escape_ch_table; 156 while( *pesc ){ 157 if( *pesc==*src){ 158 *dest++=ESCAPE_CHAR; 159 break; 160 } 161 pesc++; 162 } 163 *dest++=*src++; 164 } 165 return dest; 166 } 167 168 void trim_escape_copy(char * dest,char * src,int size){ 169 int last_escape = btsc_FALSE; 170 while( size--){ 171 if( *src == ESCAPE_CHAR && last_escape != btsc_TRUE){ 172 last_escape = btsc_TRUE ; 173 src++; 174 continue; 175 } 176 last_escape = btsc_FALSE; 177 *dest++=*src++; 178 } 179 } 180 181 int calcPacketLength(struct btsc_Packet* pkt){ 182 int len; 183 int size; 184 struct btsc_Property* ppt; 185 len = 0; 186 size = pkt->size; 187 while( size--){ 188 ppt = pkt->properties[size]; 189 len+=strlen(ppt->name)+strlen(ppt->value); 190 191 len+= calcEscapleLength(ppt->name); 192 len+= calcEscapleLength(ppt->value); 193 } 194 len+= pkt->size*2+1; 195 return len; 196 } 197 198 199 int btsc_Pack(struct btsc_Context* ctx,struct btsc_Packet* pkt,unsigned char * obuff,int* osize){ 200 struct btsc_Property* ppt; 201 int size; 202 int len; 203 unsigned char * buff; 204 char * pbuff; 205 len = calcPacketLength( pkt); 206 /*crc scott 2008.6.16*/ 207 if( ctx->crc_check ){ 208 len += strlen(CRC_DEFAULT_STRING)+1; /*1 is ,*/ 209 } 210 /*end crc*/ 211 buff = malloc( len ); 212 size = pkt->size; 213 pbuff = (char*)buff; 214 *pbuff++=PACKET_HEAD; 215 /* crc */ 216 if( ctx->crc_check ){ 217 memcpy(pbuff,CRC_DEFAULT_STRING,strlen(CRC_DEFAULT_STRING)); 218 *(pbuff+ strlen(CRC_DEFAULT_STRING))=PROPERTY_DELIMITER; 219 pbuff+=strlen(CRC_DEFAULT_STRING)+1; 220 } 221 /*end crc*/ 222 while( size--){ 223 ppt = pkt->properties[size]; 224 pbuff = escape_copy(pbuff,ppt->name); 225 *pbuff++=PAIR_DELIMITER; 226 pbuff = escape_copy(pbuff,ppt->value); 227 if( size ){ 228 *pbuff++=PROPERTY_DELIMITER; 229 } 230 } 231 *pbuff = PACKET_TAIL; 232 /* calc crc sum*/ 233 if( ctx->crc_check ){ 234 uint16 sum ; 235 char sum_str[4+6]; 236 char * crc; 237 sum = crc16_block(buff,pbuff-buff+1); 238 sprintf(sum_str,"CRC=%05d",sum); // must be five chars 239 crc = strstr(buff,CRC_DEFAULT_STRING); 240 memcpy(crc,sum_str,strlen(sum_str)); 241 } 242 /*end crc*/ 243 if( ctx->tx ){ 244 ctx->tx(ctx,buff,len); 245 } 246 if( obuff && *osize >=len){ 247 memcpy( obuff, buff ,len); 248 *osize = len; 249 } 250 251 free(buff); 252 return btsc_TRUE; 253 } 254 255 /* e not in range*/ 256 char* __memchr(char * s,char* e,char c){ 257 while( s!=e){ 258 if( *s == c){ 259 return s; 260 } 261 s++; 262 } 263 return btsc_NULL; 264 } 265 266 int is_escape_char(char c){ 267 return btsc_FALSE; 268 } 269 270 /* 271 name: parseProperty 272 desc: 指定内存范围中提取属性 key=>value 273 搜索包含e 274 params: 275 pkt -- 消息数据包 276 s -- 起始内存地址 277 e -- 结束地址 , 278 */ 279 void parseProperty(struct btsc_Packet * pkt,char * s,char * e){ 280 char * p1,*p2; 281 int n; 282 struct btsc_Property* ppt; 283 p1 = s ; 284 p2 = e; 285 __REPEAT: 286 p1 = __memchr(p1,e+1,PAIR_DELIMITER); 287 if( p1 ){ 288 if( *(p1-1) == ESCAPE_CHAR ){ 289 p1++; 290 goto __REPEAT; 291 } 292 ppt = malloc( sizeof( struct btsc_Property )); 293 n = p1-s; 294 ppt->name = malloc( n+1 ); 295 memset(ppt->name,0,n+1); 296 trim_escape_copy(ppt->name,s,n); 297 298 n =e-p1; 299 ppt->value = malloc( n+1); 300 memset(ppt->value,0,n+1); 301 trim_escape_copy(ppt->value,p1+1,n); 302 303 btsc_Property_Append(pkt,ppt); 304 } 305 } 306 307 /* 308 func: crc_check 309 brief: 对数据包进行crc完整性检测 310 提取属性 CRC,填充默认的crc校验和 00000; 校验; 比较 311 crc_check运行完毕, s,e区段的数据被污染(CRC 属性被清除为"CRC=00000") 312 params: 313 pkt 解析出来的数据包 <MSG=XXX,MSG2=XXX2> 314 s '<' 315 e '<' 316 return: 317 btsc_TRUE/btsc_FALSE 318 编码时 CRC属性必须放于属性集的首部 319 */ 320 321 int crc_check(struct btsc_Packet * packet, char *s,char *e){ 322 struct btsc_Property * ppt; 323 char * crc; 324 uint16 sum; 325 ppt = btsc_Property_Get(packet,"CRC"); 326 if(!ppt){ 327 return -1; // no crc sum 328 } 329 if( strlen( ppt->value) != strlen("00000")){ 330 return -2; 331 } 332 sum= (uint16) atoi( ppt->value); // 333 334 //*e='\0'; // set for strstr() CRC must be existed 335 crc = strstr(s,"CRC"); 336 /*substitute default crc sum*/ 337 memcpy(crc,CRC_DEFAULT_STRING,strlen(CRC_DEFAULT_STRING)); 338 if( sum!=crc16_block(s,e-s+1)){ /*<..> pass into crc */ 339 return -3; /* crc error*/ 340 } 341 342 return btsc_TRUE; 343 } 344 345 /* 346 name: parsePacket 347 desc: 分解指定内存到包结构 348 成功分解出包立刻回送到应用接收者 ( btsc_Context::notifier) 349 param: 350 s,e 内存地址 (处e) 351 s ='<' 352 e ='>' 353 ** 缓冲区还需进一步测试,包括缓冲区大小调节, 不完整协议包格式的容错 354 */ 355 void parsePacket(struct btsc_Context* ctx,char * s,char* e){ 356 char *p,*p1,*p2; 357 struct btsc_Packet * pkt; 358 if( e-s <=1 ){ 359 return ; 360 } 361 pkt = btsc_Packet_Alloc(ctx); 362 363 p1 = s+1; 364 p2 = e-1; 365 p = p1; 366 __REPEAT: 367 p = __memchr(p,e,PROPERTY_DELIMITER); 368 if( p ){ 369 if( *(p-1)==ESCAPE_CHAR){ 370 p = p+1; 371 goto __REPEAT; 372 } 373 parseProperty(pkt,p1,p-1); 374 p1 = ++p; 375 goto __REPEAT; 376 } 377 /*allow one property reside in*/ 378 parseProperty(pkt,p1,e-1); 379 /*2008.6.16 scott add crc check*/ 380 if( ctx->crc_check ){ 381 if( crc_check(pkt,s,e)==btsc_FALSE ){ /*crc check error*/ 382 btsc_Packet_Free(pkt); 383 return ; 384 } 385 } 386 /*end crc check*/ 387 if( ctx->notifier ){ 388 if(ctx->notifier(pkt)){ /* nonzero value, delete internal*/ 389 btsc_Packet_Free(pkt); 390 } 391 }else{ 392 btsc_Packet_Free(pkt); 393 } 394 } 395 396 void btsc_Parse(struct btsc_Context* ctx, char * data,int size){ 397 int len ; 398 _RESTART: 399 while( size ){ 400 len = ctx->recv_cached_capacity - ctx->recv_size; 401 if( len >0){ 402 if( size <= len){ 403 len = size; 404 size = 0; 405 }else{ 406 size-=len; 407 } 408 memcpy( ctx->recv_buff+ctx->recv_size,data,len); 409 ctx->recv_size+=len; 410 data+=len; 411 } 412 413 { 414 char * p1,*p2; 415 _RESCAN: 416 p1 = ctx->recv_buff; 417 _RESCAN_HEAD: 418 p1 = __memchr(p1,ctx->recv_buff+ctx->recv_size,PACKET_HEAD); 419 if( !p1 ){ 420 ctx->recv_size =0; 421 if( size ){ 422 goto _RESTART; 423 }else{ 424 return ;//scott by 2007.06.15 add 425 } 426 } 427 if( p1>ctx->recv_buff && *(p1-1)==ESCAPE_CHAR){ /* "\<" */ 428 p1++; 429 goto _RESCAN_HEAD; 430 } 431 432 /*move backward*/ 433 ctx->recv_size -=(p1-ctx->recv_buff); 434 memmove(ctx->recv_buff,p1, ctx->recv_size); 435 p1=ctx->recv_buff; 436 p2 = p1+1; 437 _RESCAN_TAIL: 438 p2 = __memchr(p2,ctx->recv_buff+ctx->recv_size,PACKET_TAIL); 439 if( !p2 ){ 440 if( ctx->recv_size == ctx->recv_cached_capacity ){ 441 ctx->recv_size = 0; 442 } 443 goto _RESTART; 444 } 445 if( *(p2-1) == ESCAPE_CHAR ){ 446 p2++; 447 goto _RESCAN_TAIL; 448 } 449 450 parsePacket(ctx,p1,p2); 451 ctx->recv_size -=p2-p1+1; 452 if( ctx->recv_size ){ 453 memmove(ctx->recv_buff,p2+1,ctx->recv_size); 454 goto _RESCAN; 455 } 456 } 457 } 458 } 459 460 /* debug */ 461 #ifdef _DEBUG 462 void tx(unsigned char * data,int len); 463 void notifier(struct btsc_Packet* packet); 464 /*初始化上下文, tx=发送处理函数,notifier=接收函数*/ 465 //struct btsc_Context c={tx:tx,notifier:notifier}; 466 struct btsc_Context c={tx,notifier}; 467 468 /*测试数据接收并解析*/ 469 void rx(unsigned char * buff,int len){ 470 char * msg="<MSG=HELLO,NAME=SCOTT>" 471 "<MSG2=HELLO2,NAME2=SCOTT2>" 472 "<MSG3=HELLO3,NAME3=SCOTT3>"; /*simulating data*/ 473 //int len = strlen(msg); 474 btsc_Parse(&c,buff,len); 475 } 476 /*发送处理过程*/ 477 void tx(struct btsc_Context* ctx,unsigned char * buff,int len){ 478 char *outmsg = malloc(1024*10); 479 memset(outmsg,0,1024*10); 480 memcpy(outmsg,buff,len); 481 printf("encode str: %s\n",outmsg); 482 free(outmsg); 483 btsc_Parse(&c,buff,len); 484 } 485 486 void notifier(struct btsc_Packet* packet){ 487 struct btsc_Property * ppt; 488 ppt = btsc_Property_Get(packet,"MSG"); 489 if(ppt) 490 printf("property get: MSG=>%s\n",ppt->value); 491 /*遍历包内属性参数*/ 492 BTSC_FOREACH(packet,ppt); 493 printf("packet: %s=>%s\n",ppt->name,ppt->value); 494 BTSC_END_FOREACH(); 495 } 496 497 int test_main(){ 498 int r; 499 /*optional*/ 500 c.recv_cached_capacity = 1024; /*初始化接收缓冲区大小 byte*/ 501 c.packet_cached_size = 5; /*消息包缓冲属性个数*/ 502 btsc_init(&c); /*上下文初始化*/ 503 //c.crc_check = 0; 504 puts("test rx()"); 505 // rx(); /*接*/ 506 puts("escape testing"); 507 do{ 508 /*构造消息包,并完成发送*/ 509 BTSC_PACKET_BEGIN(&c); 510 BTSC_NEW_PROPERTY("MSG","calling"); 511 512 BTSC_PACKET_END(); 513 // usleep(1000*50); 514 printf(">>seq:%d\n",r); 515 }while(0); 516 517 btsc_cleanup(&c); 518 519 return 0; 520 } 521 522 523 #endif 524
|