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