]> rtime.felk.cvut.cz Git - mirosot.git/blob - bluetooth/bth_main.c
b48e8de99c1ff171f71e603ec989ed9531ca02db
[mirosot.git] / bluetooth / bth_main.c
1 /*******************************************************************
2   bluetooth library
3
4   bth_main.c -  API bth library (recieve, send ...)
5
6   Copyright (C) 2006 by Petr Kovacik petr_kovacik@gmail.com
7
8  *******************************************************************/
9 #ifdef BTH_LX
10 #include <types.h>
11 #include <cpu_def.h>
12 #include <h8s2638h.h>
13 #include <periph/sci_rs232.h>
14 #include <system_def.h>
15 #include <string.h>
16 #else
17 #include "types.h"
18 #include <stdio.h>
19 #endif
20
21 #include <stdlib.h>
22
23 #include "hci.h"
24 #include "l2cap.h"
25 #include "hci_event.h"
26 #include "hci_command.h"
27 #include "hci_error.h"
28
29 //#include "hci_lib.h"
30 #include "bth_receive.h"
31 #include "inline_fce.h"
32 #include "bth_inface.h"
33 #include "bth_fce_out.h"
34 #include "bth_h8s2638.h"
35 #include <periph/sci_rs232.h>
36
37 /*--------BD address whitch are accept for connection-------------*/
38 bdaddr_t bth_accept_bd_addr[]={};
39
40 /*----------------local device info (master) -----------------------*/
41 bths_dev_info  bth_local_info;//={0,{0,0,0,0,0,0,0,0},{0,0,0},0,{0,0,0},0};
42
43 /*----------------conect device info (slave) -----------------------*/
44 bths_connect_bluet* bth_connected[8];
45
46 /*-------------------------------- recieve data buffer -----------------------------*/
47 uint8_t  bth_pole_char_in[SCI_BTH_BUF_LEN];
48 bth_que_t bth_rs232_que_in;
49 uint8_t bth_rs232_buf_in[SCI_BTH_BUF_LEN];
50 //-- --- ----- ----- ---- ------ ----- -- ---- --
51 //-- --- ----- ----- ---- ------ ----- -- ---- --
52 bth_que_t bth_inface_que_in;
53 bth_que_t bth_inface_que_out;
54
55
56
57 void  *bth_pole_adrr_comm_packet[LENCOMMAND]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
58 bths_command_buf_info bth_com_buf_info={LENCOMMAND,0,0};
59 /***********************************************************************************/
60 void  *bth_pole_adrr_check_packet[LENCOMMAND]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
61 bths_command_buf_info bth_check_buf_info={LENCOMMAND,0,0};
62 /***********************************************************************************/
63
64 /*kontroluje synchoronizaci prijimanych dat pomoci TPU jednotky*/
65 uint8_t bth_controll_flag=0;
66
67
68 /**-------------------------------------------------------------------------------*/
69 /*----- odeslani command prikazu, pokud je local bluetooth volny k odeslani------*/
70 /*  0 = data presunuta do SCI bufferu = budou odeslana, bluetooth zarizeni je volne
71     1 = prikaz se nepovedlo presunout do SCI bufferu, ale bluet device je volne
72     2 = bluetooth zarizeni je zamestnane, tj. data se nepresunula do bufferu
73     3 = v potvrzovacim zasobniku neni uz misto*/
74
75 /**
76  * Po zavolani funkce, se odesle paket, ktery je zarazen ve fronte paketu k odeslani (bth zazizeni je
77  * volne), pokud neni novy paket nebo zazizeni neni volne, nic se nevykona
78 */
79 int  bth_send_queue(void)
80 {
81   int i;
82   int hp_size;
83   if(bth_local_info.busy!=0)
84     {return 1;}; //zarizeni neni volne
85   if(bth_com_buf_info.aktual==bth_com_buf_info.sent) //PRAVDEPODOBNE neni co odesilat
86   {
87     if(bth_com_buf_info.sent<(LENCOMMAND-2))
88     {
89       if(bth_pole_adrr_comm_packet[bth_com_buf_info.sent+1]==NULL)
90       {return 1;}; //URCITE neni co odesilat
91     }
92     else
93     {
94       if(bth_pole_adrr_comm_packet[0]==NULL)
95       {return 1;}; //URCITE neni co odesilat
96     };
97   };
98     
99   /*bth_send_packet(AdrOdkud,kolikBytu;)*/
100     switch(*(uint8_t*)bth_pole_adrr_comm_packet[bth_com_buf_info.sent])
101     {
102       case HCI_ACLDATA_PKT:
103         __bthtomc16((uint8_t*)&(hp_size),((uint8_t*)bth_pole_adrr_comm_packet[bth_com_buf_info.sent])+HCI_PKT_SIZE+HCI_ACL_HDR____dlen);
104         hp_size=hp_size+HCI_ACL_HDR_SIZE+HCI_PKT_SIZE;
105         if(!(bth_send_packet(bth_pole_adrr_comm_packet[bth_com_buf_info.sent],hp_size)))
106         {
107           free(bth_pole_adrr_comm_packet[bth_com_buf_info.sent]);
108           bth_pole_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
109           if(bth_com_buf_info.sent<(LENCOMMAND-2)){bth_com_buf_info.sent++;}
110           else{ bth_com_buf_info.sent=0;};
111           return(0);
112         };
113         free(bth_pole_adrr_comm_packet[bth_com_buf_info.sent]);
114         bth_pole_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
115         return (-6);
116       case HCI_COMMAND_PKT:
117         hp_size=((uint16_t)*(((uint8_t*)bth_pole_adrr_comm_packet[bth_com_buf_info.sent])+HCI_PKT_SIZE+2)+HCI_COMMAND_HDR_SIZE+HCI_PKT_SIZE);
118         if(!(bth_send_packet(bth_pole_adrr_comm_packet[bth_com_buf_info.sent],hp_size)))
119         {/*odeslano - zaradim prikaz k moznosti potvrzeni*/
120           for(i=0; i<LENCOMMAND; i++)
121           {
122             if(bth_pole_adrr_check_packet[i]==NULL)
123             {
124               bth_pole_adrr_check_packet[i]=bth_pole_adrr_comm_packet[bth_com_buf_info.sent];
125               bth_pole_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
126               /*nastavim adresu pro pristi command prikaz - princip kruhove zasobniku*/
127               if(bth_com_buf_info.sent<(LENCOMMAND-2)){bth_com_buf_info.sent++;}
128               else{ bth_com_buf_info.sent=0;};
129               return 0;
130             }
131           };
132           return(-7);
133         };
134         return(-6);
135     };
136   return (1);
137 };
138
139
140 /**
141  * Pomocna funkce
142  * Prevod hexa znaku do tisknutelne podoby. V tomto tvaru se odesle po seriov. rozhranni do PC
143  */
144
145 void bth_conv_char_text(uint8_t zn)
146 { uint8_t map_leters[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
147   uint8_t val;
148   val=(zn&0xf0)>>4;
149 #ifdef BTH_LX
150   sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
151   val=(zn&0x0f);
152   sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
153 #endif
154   return;
155 };
156
157
158
159 /**
160  *Funkce odesle data o velikosti hp_size od adresy hp do bth (UART)
161  */
162 int bth_send_packet(uint8_t *hp, uint16_t hp_size)
163 {  
164   int zn,i;
165   /*je bluetooth zarizeni volne, nebo zamestnano predchozim prikazem?*/
166   if(bth_local_info.busy==0)
167   {
168 #ifndef BTH_LX
169       VypisHexa(hp,hp_size);
170 #else
171
172     for(i=0; i<hp_size;i++)
173     {
174       zn=*(hp+i);
175       sci_rs232_sendch(zn,2); //bth
176 //      VypisHexa((hp+i),1);
177     };
178 #endif
179     bth_local_info.busy=1;
180     return(0);    //vsechno odeslano ==== OK =====
181   }
182   else
183   {
184     return 2;    //zamestnane
185   };
186 };
187
188 /**
189  *Funkce vlozi znak do fronty
190  */
191
192 inline int bth_que_put(bth_que_t *q, int c)
193 {
194   uint8_t *p;
195   p=q->ip;                       //nastav se na aktual pozici v souboru
196   *(p++)=c;                      //na nasledujici pam. bunku uloz znak
197   if(p==q->buf_end) return -1;//buffer neni kruhovy p=q->buf_beg;
198 //  if(p==q->op) return -1;
199   q->ip=p;
200   return 0;                      //pokud nejsou problemy, vrat znak, jinak -1
201 }
202
203
204 /**
205  *prijaty HCI datovy paket je zaslan jako point to point
206 */
207
208 int bth_pkt_type_pointopoint(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
209 {
210   l2cap_hdr bth_l2cap_packet;
211   int bth_dev_num;
212   int bth_size_data;
213   uint8_t *bth_data;
214   int flag;
215
216   switch(bound_flag)
217   {
218     case 0x20:/*first data packet L2CAP*/
219       bth_dev_num=bth_find_conected_dev(handle);
220       __bthtomc16((uint8_t*)&(bth_l2cap_packet.len),(uint8_t*)bth_p+L2CAP_HDR____len);
221       __bthtomc16((uint8_t*)&(bth_l2cap_packet.cid),(uint8_t*)bth_p+L2CAP_HDR____cid);
222
223
224       if(bth_dev_num>-1)
225       {
226         switch((uint8_t)(bth_l2cap_packet.cid))
227         {
228           case 0x00:
229             return(-3);
230           case 0x01:
231             l2cap_signaling(((uint8_t*)bth_p+L2CAP_CMD_HDR_SIZE),(size+L2CAP_HDR____len),bth_dev_num);
232             return(0);
233           case 0x02:
234             return(0);
235         };
236         /*skutecna nefalcovana data ...*/
237         /*musim najit kanal s cislem cid pro zarizeni bth_dev_num*/
238         if(bth_find_chanal(bth_dev_num, bth_l2cap_packet.cid)>-1)
239         {
240           /*TADY JSOU DOSLA DATA, KTERA UZ NEJSOU KONFIGURACNI*/
241
242           
243           bth_data=(uint8_t*)bth_p+L2CAP_HDR_SIZE;
244           bth_size_data=size-L2CAP_HDR_SIZE;
245           int i;
246 //          uint8_t odesli[]={'a','h','o','j'};
247           for(i=0; i<bth_size_data;i++)
248           {
249             flag=bth_inface_r_isr(0, *((uint8_t*)bth_data+i));
250
251             if(flag>=0){
252 //              sci_rs232_sendch(*((uint8_t*)bth_data+i),sci_rs232_chan_default); //do PC
253 //              VypisHexa((void*)((uint8_t*)bth_data+i),1);
254             }else
255             {
256               /*zasobnik plny, neni schopen prijmout dalsi znaky*/
257 //              sci_rs232_sendch('.',sci_rs232_chan_default); //do PC
258             };
259           };
260
261 //          VypisHexa(bth_data,bth_size_data);
262           return (0);
263         };
264         return(-5);
265       };
266       return(-1);
267     case 0x40: return(-3);  /*next data packet L2CAP*/ /*funkce neni rozepsana, prijmam jen 1pkt zpravy*/
268     case 0x30: return (-4); /*Reserved for future use*/
269     case 0x00: return (-4); /*Reserved for future use*/
270   };
271   return(-1);
272 };
273
274
275 /**
276  *prijaty HCI datovy paket je zaslan jako broadcast (nedopsana funkce)
277  */
278 int bth_pkt_type_broadcast(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
279 {
280   switch(bound_flag)
281   {
282     case 0x20:/*first data packet L2CAP*/
283       return(-3); /*neni napsano pro prijem znaku broadcast cestou*/
284     case 0x40: return(-3);  /*next data packet L2CAP*/ /*funkce neni rozepsana, prijmam jen 1pkt zpravy*/
285     case 0x30: return (-4); /*Reserved for future use*/
286     case 0x00: return (-4); /*Reserved for future use*/
287   };
288   return(-1);
289 };
290
291
292
293 /**
294  *prijaty HCI datovy paket je zaslan vramci picosite (nedopsana funkce)
295  */
296 int bth_pkt_type_piconet(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
297 {
298   switch(bound_flag)
299   {
300     case 0x20:/*first data packet L2CAP*/
301       return(-3); /*neni napsano pro prijem znaku piconet cestou*/
302     case 0x40: return(-3);  /*next data packet L2CAP*/ /*funkce neni rozepsana, prijmam jen 1pkt zpravy*/
303     case 0x30: return (-4); /*Reserved for future use*/
304     case 0x00: return (-4); /*Reserved for future use*/
305   };
306   return(-1);
307 };
308
309
310
311 /**
312  *budouci vyuziti (nedopsana funkce)
313  */
314 int bth_pkt_type_reserved(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
315 {
316   return(-3);
317 };
318
319
320 /****************************************************************************/
321 /****************************************************************************/
322
323 /**
324  *pointry na funkce. Funkce jsou volany podle prijateho datoveho HCI peketu
325  */
326 typedef int (*bth_kind_pkt)(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size);
327 bth_kind_pkt bth_char_pkt_fce[]={
328     bth_pkt_type_pointopoint, bth_pkt_type_broadcast, bth_pkt_type_piconet, bth_pkt_type_reserved};
329 #define COM_PROT_SUM_FC (sizeof(bth_char_pkt_fce)/sizeof(bth_char_pkt_fce[0]))
330
331
332 /**
333  *pointry na funkce. Funkce jsou volany podle event codu, dekodovaneho z  prijateho event HCI peketu
334  */
335 typedef int (*bth_p_ivent_fce)(uint8_t *bth_p, uint8_t size);
336 bth_p_ivent_fce bth_event_array_fce[]={bth_evt_none,bth_evt_inquiry_complete, bth_evt_inquiry_result,
337                   bth_evt_conn_complete, bth_evt_conn_request, bth_evt_disconn_complete,
338                   bth_evt_auth_complete, bth_remote_name_req_complete,
339                   bth_evt_encrypt_cahnge, bth_evt_change_conn_link_key_complete,
340                   bth_evt_master_link_key_complete, bth_evt_read_remote_features_complete,
341                   bth_evt_read_remote_version_complete, bth_evt_qos_setup_complete,
342                   bth_evt_cmd_complete, bth_evt_cmd_status,  bth_evt_hardware_error,
343                   bth_evt_flush_occurred,  bth_evt_role_cahage, bth_evt_num_comp_pkts,
344                   bth_evt_mode_change, bth_evt_return_link_keys, bth_evt_pin_code_req,
345                   bth_evt_link_key_req, bth_evt_link_key_notify, bth_evt_loopback_command,
346                   bth_evt_data_buffer_overflow, bth_evt_max_slots_change,
347                   bth_evt_read_clock_offset_complete, bth_evt_conn_ptype_changed,
348                   bth_evt_qos_violation, bth_evt_page_scan_mode_change,
349                   bth_evt_pscan_rep_mode_change, bth_evt_flow_spec_complete,
350                   bth_evt_inquiry_result_with_rssi};
351
352 #define EV_SUM_FC (sizeof(bth_event_array_fce)/sizeof(bth_event_array_fce[0]))
353
354
355 /**
356  *Hlavni funkce, ktera ulozi prijaty znak "c" (od bth) ulozi ho do vstupni fronty, zkontroluje zda-li
357  * je paekt cely a pokud ano, tak zavola funkce pro jeho zpracovani (pro ACL HCI a pro Event HCI)
358  */
359 int bth_recieve_packet(int c)
360 {
361   hci_event_hdr  bth_event_packet;
362   hci_acl_hdr bth_acl_packet;
363   uint8_t *typ_paket;
364   int error_code;
365   uint8_t char_acl_pkt;
366   uint8_t *data_ad;
367   uint8_t com_pr;
368
369   if(bth_controll_flag!=0)
370   {
371       bth_stop_TPU_counter();
372       bth_clear_TPU_counter();
373       bth_start_TPU_counter();
374       if(bth_get_timer()>0)
375       {
376         bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
377         bth_nul_timer();
378       };
379   };
380   
381   
382 #ifndef BTH_LX
383   VypisHexa((uint8_t*)&c,1);
384 #endif
385   //VypisHexa((uint8_t*)&c,1);
386   bth_que_put(&bth_rs232_que_in, c); //ulozim prijaty znak do zasobniku
387   typ_paket=((uint8_t*)bth_rs232_que_in.buf_beg); //zjistim tzp paketu ACL, Even, SCO ...
388   switch(*typ_paket)
389   {
390   case HCI_EVENT_PKT:
391     /*naplnim strukturu "hci_event_hdr" ze zasobniku - po bytech*/
392     store16(bth_event_packet.evt,  *(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE));
393     store16(bth_event_packet.plen, *(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+1));
394
395       if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>3)
396     {
397       if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == (bth_event_packet.plen+HCI_EVENT_HDR_SIZE+HCI_PKT_SIZE))
398       {
399         /*****/
400         if(bth_controll_flag!=0)
401         {
402           bth_stop_TPU_counter();
403         };
404         /*******/
405     
406         /*pointer na fci prislusenijici  even codu*/
407         if(bth_event_packet.evt<EV_SUM_FC) //overeni existence fce
408         {
409           data_ad=(uint8_t*)(bth_rs232_que_in.buf_beg+HCI_EVENT_HDR_SIZE+HCI_PKT_SIZE);
410           error_code=(*bth_event_array_fce[bth_event_packet.evt])(data_ad,bth_event_packet.plen);
411           bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;  //nastav se na zacatek, pro pristi event
412         }else{
413           bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;  //nastav se na zacatek, pro pristi event
414           return (-1);
415         };
416         if(error_code>=0)
417         {
418           // bth_error_detect_status((uint8_t)error_code); //error vypisy
419         }
420         else
421         {//bth_error_detect_event((uint8_t)(-error_code)); //error vypisy
422         };
423       };
424     };
425     return 0;
426     case HCI_ACLDATA_PKT:
427       if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>5)
428       {
429         __bthtomc16((uint8_t*)&(bth_acl_packet.dlen),(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____dlen));
430         
431
432         if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == ((bth_acl_packet.dlen)+HCI_ACL_HDR_SIZE+HCI_PKT_SIZE))
433         {
434           
435           /*  **** kontrola sousednosti dvou znaku TPU3 ****   */
436           if(bth_controll_flag!=0)
437           {
438             bth_stop_TPU_counter();
439           };
440           /*****************************************************/
441           
442           __bthtomc16((uint8_t*)&(bth_acl_packet.handle),(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____handle));
443           bth_acl_packet.handle=bth_acl_packet.handle & 0x0fff;
444           
445           /*prom 'char_acl_pkt' vyjadruje vlastnosti paketu, if point to point nebo broadcast, or char. L2CAP*/
446           store16(char_acl_pkt, (0xf0&*(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____handle+1)));
447           
448           /*rozhodnuti o jaky paket se jedna (PtP,Piconet,broat...) a o jaky typ komunikace se zarizenim (L2CAP, HCI)*/
449           data_ad=(uint8_t*)bth_rs232_que_in.buf_beg+HCI_PKT_SIZE+HCI_ACL_HDR_SIZE;
450           com_pr=char_acl_pkt&0xc0;
451           if(com_pr<COM_PROT_SUM_FC) //fce existuje
452           {
453             bth_char_pkt_fce[com_pr]
454                 (bth_acl_packet.handle, char_acl_pkt&0x30, data_ad,bth_acl_packet.dlen);
455           }
456           else
457           {
458             /*HCI data - nikoliv L2CAP - obsluha ani nahravani do
459             datoveho zas. neni napsano - predpoklada se zasilani dat pres L2CAP
460             viz. if pred timto else */
461           };
462           bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
463 //        sci_rs232_sendch('\n',sci_rs232_chan_default); //do PC
464         };
465
466       };
467     };
468   return -1;
469 };
470
471
472 /**
473  * Funkce vola funkce, ktere jsou potrebne pro nastaveni zarizeni do slave rezimu
474 */
475 void bth_parametr_slave(void)
476 {
477   bth_local_info.busy=1;
478   bth_cmd_write_page_scan(0x0040, 0x0020);
479   bth_cmd_write_inquiry_scan_activity(0x0040, 0x0020);
480   bth_cmd_write_scan_enable(0x03);
481 // bth_cmd_read_bd_addr(); //funguje command event neni
482 };
483
484
485 /**
486  * Funkce nastavi MC, aby mohl zasilat HCI pakety do bth zarizeni
487  * Pokud jsou inicializovany TPU kanal, tak ho vynuluje a zastavi
488 */
489 void bth_start(void)
490 {
491   if(bth_controll_flag>0)
492   {
493
494     bth_controll_flag=10;
495     bth_stop_TPU_counter();
496     bth_clear_TPU_counter();
497     bth_nul_timer();
498   };
499
500   bth_local_info.busy=0;
501 };
502
503
504 /**
505  * nastaveni zasobniku - inicializacni funkce
506 */
507 void bth_init(void)
508 {
509 //  bth_check_command_for_send=NULL;
510
511   bth_rs232_que_in.buf_end=(uint8_t*)bth_pole_char_in+SCI_RS232_BUF_LEN;
512   bth_rs232_que_in.buf_beg=bth_pole_char_in;
513   bth_rs232_que_in.ip=bth_pole_char_in;
514 };
515
516 /****************************************************************************/
517 /****************************************************************************/
518
519 /**
520  * Pomocna funce, ktera slouzi k prevodum znaku an tisknutelne znaky
521 */
522 int VypisHexa(uint8_t *s, int delka)
523 {
524
525   uint8_t tisk[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
526   uint8_t i,zn;
527   for(i=0; i<delka; i++)
528   {
529     zn=*(s+i);
530 #ifndef BTH_LX
531     printf("%c",tisk[((zn>>4)&0x000F)]);
532     printf("%c",tisk[zn & 0x000F]);
533 #else
534     sci_rs232_sendch(tisk[(zn&0xf0)>>4],sci_rs232_chan_default); //do PC
535     sci_rs232_sendch(tisk[(zn&0x0f)],sci_rs232_chan_default); //do PC
536 #endif
537   };
538
539   return 0;
540 };
541