]> rtime.felk.cvut.cz Git - mirosot.git/blob - bluetooth/bth_main.c
Comments translated to english
[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 /*FIXME this check synchronisation of received data using TPU unit of CPU*/
65 uint8_t bth_controll_flag=0;
66
67
68 /**-------------------------------------------------------------------------------*/
69 /*FIXME ----- sending of command, if the local bluetooth is free (ready to send)------*/
70 /*  0 = data moved to SCI buffer = they will be sent, bluetooth device is free
71     1 = it wasn't possible to move tha command to SCI bufferu, but bluet device is free
72     2 = bluetooth device is busy, ie. data were not moved to the bufferu
73     3 = there is no space left in confirmation queue*/
74
75 /**
76  * After this function is called, the packet, which is in the command queue, is sent. If there is no new 
77  * packet or the device is busy, nothing is done.
78  *
79  * Po zavolani funkce, se odesle paket, ktery je zarazen ve fronte paketu k odeslani (bth zazizeni je
80  * volne), pokud neni novy paket nebo zazizeni neni volne, nic se nevykona
81 */
82 int  bth_send_queue(void)
83 {
84   int i;
85   int hp_size;
86   if(bth_local_info.busy!=0)
87     {return 1;}; //device is busy
88   if(bth_com_buf_info.aktual==bth_com_buf_info.sent) //PRAVDEPODOBNE neni co odesilat
89   {
90     if(bth_com_buf_info.sent<(LENCOMMAND-2))
91     {
92       if(bth_pole_adrr_comm_packet[bth_com_buf_info.sent+1]==NULL)
93       {return 1;}; //There is certainly nothing to send
94     }
95     else
96     {
97       if(bth_pole_adrr_comm_packet[0]==NULL)
98       {return 1;}; //There is certainly nothing to send
99     };
100   };
101     
102   /*bth_send_packet(AdrFrom,howmanyBytes;)*/
103     switch(*(uint8_t*)bth_pole_adrr_comm_packet[bth_com_buf_info.sent])
104     {
105       case HCI_ACLDATA_PKT:
106         __bthtomc16((uint8_t*)&(hp_size),((uint8_t*)bth_pole_adrr_comm_packet[bth_com_buf_info.sent])+HCI_PKT_SIZE+HCI_ACL_HDR____dlen);
107         hp_size=hp_size+HCI_ACL_HDR_SIZE+HCI_PKT_SIZE;
108         if(!(bth_send_packet(bth_pole_adrr_comm_packet[bth_com_buf_info.sent],hp_size)))
109         {
110           free(bth_pole_adrr_comm_packet[bth_com_buf_info.sent]);
111           bth_pole_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
112           if(bth_com_buf_info.sent<(LENCOMMAND-2)){bth_com_buf_info.sent++;}
113           else{ bth_com_buf_info.sent=0;};
114           return(0);
115         };
116         free(bth_pole_adrr_comm_packet[bth_com_buf_info.sent]);
117         bth_pole_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
118         return (-6);
119       case HCI_COMMAND_PKT:
120         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);
121         if(!(bth_send_packet(bth_pole_adrr_comm_packet[bth_com_buf_info.sent],hp_size)))
122         {/*sent - add the command to allow confirmation*/
123           for(i=0; i<LENCOMMAND; i++)
124           {
125             if(bth_pole_adrr_check_packet[i]==NULL)
126             {
127               bth_pole_adrr_check_packet[i]=bth_pole_adrr_comm_packet[bth_com_buf_info.sent];
128               bth_pole_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
129               /*set the address for the next command - principle of ring buffer*/
130               if(bth_com_buf_info.sent<(LENCOMMAND-2)){bth_com_buf_info.sent++;}
131               else{ bth_com_buf_info.sent=0;};
132               return 0;
133             }
134           };
135           return(-7);
136         };
137         return(-6);
138     };
139   return (1);
140 };
141
142
143 /**
144  * Auxiliary function
145  * Convert hexadecimal character to ASCII. It is then sent to serial line
146  */
147 //*************************** bth_conv_char_text *****************************
148 // used to convers int into ascii letter and print it on serial
149 // INPUT zn: interger to convert and print
150 // OUTPUT :none
151 //*************************************************************************** 
152 void bth_conv_char_text(uint8_t zn)
153 { uint8_t map_leters[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
154   uint8_t val;
155   val=(zn&0xf0)>>4;
156 #ifdef BTH_LX
157   sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
158   val=(zn&0x0f);
159   sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
160 #endif
161   return;
162 };
163
164
165
166 /**
167   //FIXME
168  *Sends data of the size hp_size from address hp to the bluetooth device (UART)
169  */
170 int bth_send_packet(uint8_t *hp, uint16_t hp_size)
171 {  
172   int zn,i;
173   /*is bluetooth device free, or is it busy by the previous command?*/
174   if(bth_local_info.busy==0)
175   {
176 #ifndef BTH_LX
177       VypisHexa(hp,hp_size);
178 #else
179
180     for(i=0; i<hp_size;i++)
181     {
182       zn=*(hp+i);
183       sci_rs232_sendch(zn,2); //bth
184 //      VypisHexa((hp+i),1);
185     };
186 #endif
187     bth_local_info.busy=1;
188     return(0);    //everything sent ==== OK =====
189   }
190   else
191   {
192     return 2;    //busy
193   };
194 };
195
196 /**
197  *Inserts a character to the queue
198  */
199
200 inline int bth_que_put(bth_que_t *q, int c)
201 {
202   uint8_t *p;
203   p=q->ip;                       //FIXME set us to the actual position in the file
204   *(p++)=c;                      //store the character to the next byte
205   if(p==q->buf_end) return -1;//this is not the ring buffer p=q->buf_beg;
206 //  if(p==q->op) return -1;
207   q->ip=p;
208   return 0;                      //in case of success return the character, otherwise -1
209 }
210
211
212 /**
213 //FIXME
214  *received HCI data packet is sent as point to point
215 */
216
217 int bth_pkt_type_pointopoint(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
218 {
219   l2cap_hdr bth_l2cap_packet;
220   int bth_dev_num;
221   int bth_size_data;
222   uint8_t *bth_data;
223   int flag;
224
225   switch(bound_flag)
226   {
227     case 0x20:/*first data packet L2CAP*/
228       bth_dev_num=bth_find_conected_dev(handle);
229       __bthtomc16((uint8_t*)&(bth_l2cap_packet.len),(uint8_t*)bth_p+L2CAP_HDR____len);
230       __bthtomc16((uint8_t*)&(bth_l2cap_packet.cid),(uint8_t*)bth_p+L2CAP_HDR____cid);
231
232
233       if(bth_dev_num>-1)
234       {
235         switch((uint8_t)(bth_l2cap_packet.cid))
236         {
237           case 0x00:
238             return(-3);
239           case 0x01:
240             l2cap_signaling(((uint8_t*)bth_p+L2CAP_CMD_HDR_SIZE),(size+L2CAP_HDR____len),bth_dev_num);
241             return(0);
242           case 0x02:
243             return(0);
244         };
245         /*FIXME real data ...*/
246         /*We have to find the channel with the CID number for device bth_dev_num*/
247         if(bth_find_chanal(bth_dev_num, bth_l2cap_packet.cid)>-1)
248         {
249           /*here are the received data, which are not used for confguration */
250
251           
252           bth_data=(uint8_t*)bth_p+L2CAP_HDR_SIZE;
253           bth_size_data=size-L2CAP_HDR_SIZE;
254           int i;
255 //          uint8_t odesli[]={'a','h','o','j'};
256           for(i=0; i<bth_size_data;i++)
257           {
258             flag=bth_inface_r_isr(0, *((uint8_t*)bth_data+i));
259
260             if(flag>=0){
261 //              sci_rs232_sendch(*((uint8_t*)bth_data+i),sci_rs232_chan_default); //do PC
262 //              VypisHexa((void*)((uint8_t*)bth_data+i),1);
263             }else
264             {
265               /*queue is full, neni schopen prijmout dalsi znaky*/
266 //              sci_rs232_sendch('.',sci_rs232_chan_default); //do PC
267             };
268           };
269
270 //          VypisHexa(bth_data,bth_size_data);
271           return (0);
272         };
273         return(-5);
274       };
275       return(-1);
276     case 0x40: return(-3);  /*next data packet L2CAP*/ /*function is not written, I receive only one pakcet of the message*/
277     case 0x30: return (-4); /*Reserved for future use*/
278     case 0x00: return (-4); /*Reserved for future use*/
279   };
280   return(-1);
281 };
282
283
284 /**
285  *Received HCI data packet is sent as broadcast (not finished function)
286  */
287 int bth_pkt_type_broadcast(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
288 {
289   switch(bound_flag)
290   {
291     case 0x20:/*first data packet L2CAP*/
292       return(-3); /*neni napsano pro prijem znaku broadcast cestou*/
293     case 0x40: return(-3);  /*next data packet L2CAP*/ /*funkce neni rozepsana, prijmam jen 1pkt zpravy*/
294     case 0x30: return (-4); /*Reserved for future use*/
295     case 0x00: return (-4); /*Reserved for future use*/
296   };
297   return(-1);
298 };
299
300
301
302 /**
303  *Received HCI data packet is send to piconet (not finished function)
304  */
305 int bth_pkt_type_piconet(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
306 {
307   switch(bound_flag)
308   {
309     case 0x20:/*first data packet L2CAP*/
310       return(-3); /*neni napsano pro prijem znaku piconet cestou*/
311     case 0x40: return(-3);  /*next data packet L2CAP*/ /*funkce neni rozepsana, prijmam jen 1pkt zpravy*/
312     case 0x30: return (-4); /*Reserved for future use*/
313     case 0x00: return (-4); /*Reserved for future use*/
314   };
315   return(-1);
316 };
317
318
319
320 /**
321  *Reserved for future (not finished)
322  */
323 int bth_pkt_type_reserved(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
324 {
325   return(-3);
326 };
327
328
329 /****************************************************************************/
330 /****************************************************************************/
331
332 /**
333  *pointers to functions. Functions are called according to the received HCI pakcet
334  */
335 typedef int (*bth_kind_pkt)(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size);
336 bth_kind_pkt bth_char_pkt_fce[]={
337     bth_pkt_type_pointopoint, bth_pkt_type_broadcast, bth_pkt_type_piconet, bth_pkt_type_reserved};
338 #define COM_PROT_SUM_FC (sizeof(bth_char_pkt_fce)/sizeof(bth_char_pkt_fce[0]))
339
340
341 /**
342  *pointrs to functions. Functions are called according to the event code, decoded from the received HCI packet
343  */
344 typedef int (*bth_p_ivent_fce)(uint8_t *bth_p, uint8_t size);
345 bth_p_ivent_fce bth_event_array_fce[]={bth_evt_none,bth_evt_inquiry_complete, bth_evt_inquiry_result,
346                   bth_evt_conn_complete, bth_evt_conn_request, bth_evt_disconn_complete,
347                   bth_evt_auth_complete, bth_remote_name_req_complete,
348                   bth_evt_encrypt_cahnge, bth_evt_change_conn_link_key_complete,
349                   bth_evt_master_link_key_complete, bth_evt_read_remote_features_complete,
350                   bth_evt_read_remote_version_complete, bth_evt_qos_setup_complete,
351                   bth_evt_cmd_complete, bth_evt_cmd_status,  bth_evt_hardware_error,
352                   bth_evt_flush_occurred,  bth_evt_role_cahage, bth_evt_num_comp_pkts,
353                   bth_evt_mode_change, bth_evt_return_link_keys, bth_evt_pin_code_req,
354                   bth_evt_link_key_req, bth_evt_link_key_notify, bth_evt_loopback_command,
355                   bth_evt_data_buffer_overflow, bth_evt_max_slots_change,
356                   bth_evt_read_clock_offset_complete, bth_evt_conn_ptype_changed,
357                   bth_evt_qos_violation, bth_evt_page_scan_mode_change,
358                   bth_evt_pscan_rep_mode_change, bth_evt_flow_spec_complete,
359                   bth_evt_inquiry_result_with_rssi};
360
361 #define EV_SUM_FC (sizeof(bth_event_array_fce)/sizeof(bth_event_array_fce[0]))
362
363
364 /**
365  *The main function, which stores the received character "c" (from bth) to the input queue, checks if there is the whole pakcet in the queue and if so, it calls functions for processing the packet. (for ACL HCI and for Event HCI)
366  */
367 int bth_recieve_packet(int c)
368 {
369   hci_event_hdr  bth_event_packet;
370   hci_acl_hdr bth_acl_packet;
371   uint8_t *typ_paket;
372   int error_code;
373   uint8_t char_acl_pkt;
374   uint8_t *data_ad;
375   uint8_t com_pr;
376
377   if(bth_controll_flag!=0)
378   {
379       bth_stop_TPU_counter();
380       bth_clear_TPU_counter();
381       bth_start_TPU_counter();
382       if(bth_get_timer()>0)
383       {
384         bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
385         bth_nul_timer();
386       };
387   };
388   
389   
390 #ifndef BTH_LX
391   VypisHexa((uint8_t*)&c,1);
392 #endif
393   //VypisHexa((uint8_t*)&c,1);
394   bth_que_put(&bth_rs232_que_in, c); //store the received character to the queue
395   typ_paket=((uint8_t*)bth_rs232_que_in.buf_beg); //determine the type of the pakcet ACL, Even, SCO ...
396   switch(*typ_paket)
397   {
398   case HCI_EVENT_PKT:
399     /*fill in structure "hci_event_hdr" from the queue (bye by byte)*/
400     store16(bth_event_packet.evt,  *(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE));
401     store16(bth_event_packet.plen, *(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+1));
402
403       if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>3)
404     {
405       if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == (bth_event_packet.plen+HCI_EVENT_HDR_SIZE+HCI_PKT_SIZE))
406       {
407         /*****/
408         if(bth_controll_flag!=0)
409         {
410           bth_stop_TPU_counter();
411         };
412         /*******/
413     
414         /*pointer to the function matching the event code*/
415         if(bth_event_packet.evt<EV_SUM_FC) //check whether the function exists
416         {
417           data_ad=(uint8_t*)(bth_rs232_que_in.buf_beg+HCI_EVENT_HDR_SIZE+HCI_PKT_SIZE);
418           error_code=(*bth_event_array_fce[bth_event_packet.evt])(data_ad,bth_event_packet.plen);
419           bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;  //set to the beginning for the next event
420         }else{
421           bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;  //nastav se na zacatek, pro pristi event
422           return (-1);
423         };
424         if(error_code>=0)
425         {
426           // bth_error_detect_status((uint8_t)error_code); //error msg
427         }
428         else
429         {//bth_error_detect_event((uint8_t)(-error_code)); //error msg
430         };
431       };
432     };
433     return 0;
434     case HCI_ACLDATA_PKT:
435       if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>5)
436       {
437         __bthtomc16((uint8_t*)&(bth_acl_packet.dlen),(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____dlen));
438         
439
440         if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == ((bth_acl_packet.dlen)+HCI_ACL_HDR_SIZE+HCI_PKT_SIZE))
441         {
442           
443           /*  **** check the adjacency of two characters TPU3 ****   */
444           if(bth_controll_flag!=0)
445           {
446             bth_stop_TPU_counter();
447           };
448           /*****************************************************/
449           
450           __bthtomc16((uint8_t*)&(bth_acl_packet.handle),(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____handle));
451           bth_acl_packet.handle=bth_acl_packet.handle & 0x0fff;
452           
453           /*variable 'char_acl_pkt' stores the properties of the packet, if it is point to point or broadcast, or char. L2CAP*/
454           store16(char_acl_pkt, (0xf0&*(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____handle+1)));
455           
456           /*decide which packet is this (PtP,Piconet,broat...) and the type of communication (L2CAP, HCI)*/
457           data_ad=(uint8_t*)bth_rs232_que_in.buf_beg+HCI_PKT_SIZE+HCI_ACL_HDR_SIZE;
458           com_pr=char_acl_pkt&0xc0;
459           if(com_pr<COM_PROT_SUM_FC) //func exists
460           {
461             bth_char_pkt_fce[com_pr]
462                 (bth_acl_packet.handle, char_acl_pkt&0x30, data_ad,bth_acl_packet.dlen);
463           }
464           else
465           {
466             /*HCI data - not L2CAP - neither handling nor loading to data queue is not implemented. It is assumed
467               sending of data using L2CAP. See if before this else. */
468           };
469           bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
470 //        sci_rs232_sendch('\n',sci_rs232_chan_default); //to PC
471         };
472
473       };
474     };
475   return -1;
476 };
477
478
479 /**
480  * Calls functions, which are necessary for setting the device to the slave mode.
481 */
482 void bth_parametr_slave(void)
483 {
484   bth_local_info.busy=1;
485   bth_cmd_write_page_scan(0x0040, 0x0020);
486   bth_cmd_write_inquiry_scan_activity(0x0040, 0x0020);
487   bth_cmd_write_scan_enable(0x03);
488 // bth_cmd_read_bd_addr(); //funguje command event neni
489 };
490
491
492 /**
493  * Sets the MCU up, so it can send HCI packets to bth device
494  * If TPU channels are initialized, it resets and stop it
495 */
496 void bth_start(void)
497 {
498   if(bth_controll_flag>0)
499   {
500
501     bth_controll_flag=10;
502     bth_stop_TPU_counter();
503     bth_clear_TPU_counter();
504     bth_nul_timer();
505   };
506
507   bth_local_info.busy=0;
508 };
509
510
511 /**
512  * Setting of the queue - initialization function
513 */
514 void bth_init(void)
515 {
516 //  bth_check_command_for_send=NULL;
517
518   bth_rs232_que_in.buf_end=(uint8_t*)bth_pole_char_in+SCI_RS232_BUF_LEN;
519   bth_rs232_que_in.buf_beg=bth_pole_char_in;
520   bth_rs232_que_in.ip=bth_pole_char_in;
521 };
522
523 /****************************************************************************/
524 /****************************************************************************/
525
526 /**
527  * Auxiliary function, which converts characetrs to the printable form
528 */
529 int VypisHexa(uint8_t *s, int delka)
530 {
531
532   uint8_t tisk[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
533   uint8_t i,zn;
534   for(i=0; i<delka; i++)
535   {
536     zn=*(s+i);
537 #ifndef BTH_LX
538     printf("%c",tisk[((zn>>4)&0x000F)]);
539     printf("%c",tisk[zn & 0x000F]);
540 #else
541     sci_rs232_sendch(tisk[(zn&0xf0)>>4],sci_rs232_chan_default); //to PC
542     sci_rs232_sendch(tisk[(zn&0x0f)],sci_rs232_chan_default); //to PC
543 #endif
544   };
545
546   return 0;
547 };
548