1
2 /*
3 name: btsc.h
4 desc: 藍牙串口通信數(shù)據(jù)包裝
5 writer: zhangbin
6 date: 2007-01-25
7 history:
8 2007-0206 zhangbin
9 1. btsc_context增加 user
10 2. notifier函數(shù)原型增加 btsc_context參數(shù),便于訪問上下文
11 2008.06.16 scott
12 1. 增加crc校驗屬性
13 CRC=12345
14 crc校驗和計算: 準備發(fā)送一個數(shù)據(jù)包之前,將默認crc屬性(CRC=00000)作為屬性包加入,然后將整個屬性包進行crc計算出校驗和
15 將16位的crc sum 轉(zhuǎn)換成5字節(jié)的字符串替換包屬性CRC的值
16 <MSG=DEVICE-OPEN CRC=00000> =>計算機校驗和 45322
17 替換數(shù)據(jù)包屬性值=> <MSG=DEVICE-OPEN CRC=45322>
18 發(fā)送
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; // 外部數(shù)據(jù)傳遞
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
2 /*
3 name: btsc.h
4 desc: 藍牙串口通信數(shù)據(jù)包裝
5 writer: zhangbin
6 date: 2007-01-25
7 history:
8 2007-0206 zhangbin
9 1. btsc_context增加 user
10 2. notifier函數(shù)原型增加 btsc_context參數(shù),便于訪問上下文
11 2008.06.16 scott
12 1. 增加crc校驗屬性
13 CRC=12345
14 crc校驗和計算: 準備發(fā)送一個數(shù)據(jù)包之前,將默認crc屬性(CRC=00000)作為屬性包加入,然后將整個屬性包進行crc計算出校驗和
15 將16位的crc sum 轉(zhuǎn)換成5字節(jié)的字符串替換包屬性CRC的值
16 <MSG=DEVICE-OPEN CRC=00000> =>計算機校驗和 45322
17 替換數(shù)據(jù)包屬性值=> <MSG=DEVICE-OPEN CRC=45322>
18 發(fā)送

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; // 外部數(shù)據(jù)傳遞
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: 計算含轉(zhuǎn)義字符串長度
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: 指定內(nèi)存范圍中提取屬性 key=>value
273 搜索包含e
274 params:
275 pkt -- 消息數(shù)據(jù)包
276 s -- 起始內(nèi)存地址
277 e -- 結(jié)束地址 ,
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: 對數(shù)據(jù)包進行crc完整性檢測
310 提取屬性 CRC,填充默認的crc校驗和 00000; 校驗; 比較
311 crc_check運行完畢, s,e區(qū)段的數(shù)據(jù)被污染(CRC 屬性被清除為"CRC=00000")
312 params:
313 pkt 解析出來的數(shù)據(jù)包 <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: 分解指定內(nèi)存到包結(jié)構(gòu)
348 成功分解出包立刻回送到應(yīng)用接收者 ( btsc_Context::notifier)
349 param:
350 s,e 內(nèi)存地址 (處e)
351 s ='<'
352 e ='>'
353 ** 緩沖區(qū)還需進一步測試,包括緩沖區(qū)大小調(diào)節(jié), 不完整協(xié)議包格式的容錯
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=發(fā)送處理函數(shù),notifier=接收函數(shù)*/
465 //struct btsc_Context c={tx:tx,notifier:notifier};
466 struct btsc_Context c={tx,notifier};
467
468 /*測試數(shù)據(jù)接收并解析*/
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 /*發(fā)送處理過程*/
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 /*遍歷包內(nèi)屬性參數(shù)*/
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; /*初始化接收緩沖區(qū)大小 byte*/
501 c.packet_cached_size = 5; /*消息包緩沖屬性個數(shù)*/
502 btsc_init(&c); /*上下文初始化*/
503 //c.crc_check = 0;
504 puts("test rx()
");
505 // rx(); /*接*/
506 puts("escape testing
");
507 do{
508 /*構(gòu)造消息包,并完成發(fā)送*/
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
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: 計算含轉(zhuǎn)義字符串長度
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: 指定內(nèi)存范圍中提取屬性 key=>value
273 搜索包含e
274 params:
275 pkt -- 消息數(shù)據(jù)包
276 s -- 起始內(nèi)存地址
277 e -- 結(jié)束地址 ,
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: 對數(shù)據(jù)包進行crc完整性檢測
310 提取屬性 CRC,填充默認的crc校驗和 00000; 校驗; 比較
311 crc_check運行完畢, s,e區(qū)段的數(shù)據(jù)被污染(CRC 屬性被清除為"CRC=00000")
312 params:
313 pkt 解析出來的數(shù)據(jù)包 <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: 分解指定內(nèi)存到包結(jié)構(gòu)
348 成功分解出包立刻回送到應(yīng)用接收者 ( btsc_Context::notifier)
349 param:
350 s,e 內(nèi)存地址 (處e)
351 s ='<'
352 e ='>'
353 ** 緩沖區(qū)還需進一步測試,包括緩沖區(qū)大小調(diào)節(jié), 不完整協(xié)議包格式的容錯
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=發(fā)送處理函數(shù),notifier=接收函數(shù)*/
465 //struct btsc_Context c={tx:tx,notifier:notifier};
466 struct btsc_Context c={tx,notifier};
467
468 /*測試數(shù)據(jù)接收并解析*/
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 /*發(fā)送處理過程*/
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 /*遍歷包內(nèi)屬性參數(shù)*/
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; /*初始化接收緩沖區(qū)大小 byte*/
501 c.packet_cached_size = 5; /*消息包緩沖屬性個數(shù)*/
502 btsc_init(&c); /*上下文初始化*/
503 //c.crc_check = 0;
504 puts("test rx()

505 // rx(); /*接*/
506 puts("escape testing

507 do{
508 /*構(gòu)造消息包,并完成發(fā)送*/
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
posted on 2008-07-04 02:35 放屁阿狗 閱讀(812) 評論(0) 編輯 收藏 引用 所屬分類: unix/linux/solaris/sco-unix/novell 、OpenSource開源工程 、embbed/arm/x86