1 /*******************************************************************
4 bth_main.c - API bth library (recieve, send ...)
6 Copyright (C) 2006 by Petr Kovacik petr_kovacik@gmail.com
8 *******************************************************************/
13 #include <periph/sci_rs232.h>
14 #include <system_def.h>
25 #include "hci_event.h"
26 #include "hci_command.h"
27 #include "hci_error.h"
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>
37 /*--------BD address whitch are accept for connection-------------*/
38 bdaddr_t bth_accept_bd_addr[]={};
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};
43 /*----------------conect device info (slave) -----------------------*/
44 bths_connect_bluet* bth_connected[8];
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;
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 /***********************************************************************************/
64 /*FIXME this check synchronisation of received data using TPU unit of CPU*/
65 uint8_t bth_controll_flag=0;
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*/
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.
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
82 int bth_send_queue(void)
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
90 if(bth_com_buf_info.sent<(LENCOMMAND-2))
92 if(bth_pole_adrr_comm_packet[bth_com_buf_info.sent+1]==NULL)
93 {return 1;}; //There is certainly nothing to send
97 if(bth_pole_adrr_comm_packet[0]==NULL)
98 {return 1;}; //There is certainly nothing to send
102 /*bth_send_packet(AdrFrom,howmanyBytes;)*/
103 switch(*(uint8_t*)bth_pole_adrr_comm_packet[bth_com_buf_info.sent])
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)))
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;};
116 free(bth_pole_adrr_comm_packet[bth_com_buf_info.sent]);
117 bth_pole_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
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++)
125 if(bth_pole_adrr_check_packet[i]==NULL)
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;};
145 * Convert hexadecimal character to ASCII. It is then sent to serial line
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
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'};
157 sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
159 sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
168 *Sends data of the size hp_size from address hp to the bluetooth device (UART)
170 int bth_send_packet(uint8_t *hp, uint16_t hp_size)
173 /*is bluetooth device free, or is it busy by the previous command?*/
174 if(bth_local_info.busy==0)
177 VypisHexa(hp,hp_size);
180 for(i=0; i<hp_size;i++)
183 sci_rs232_sendch(zn,2); //bth
184 // VypisHexa((hp+i),1);
187 bth_local_info.busy=1;
188 return(0); //everything sent ==== OK =====
197 *Inserts a character to the queue
200 inline int bth_que_put(bth_que_t *q, int c)
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;
208 return 0; //in case of success return the character, otherwise -1
214 *received HCI data packet is sent as point to point
217 int bth_pkt_type_pointopoint(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
219 l2cap_hdr bth_l2cap_packet;
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);
235 switch((uint8_t)(bth_l2cap_packet.cid))
240 l2cap_signaling(((uint8_t*)bth_p+L2CAP_CMD_HDR_SIZE),(size+L2CAP_HDR____len),bth_dev_num);
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)
249 /*here are the received data, which are not used for confguration */
252 bth_data=(uint8_t*)bth_p+L2CAP_HDR_SIZE;
253 bth_size_data=size-L2CAP_HDR_SIZE;
255 // uint8_t odesli[]={'a','h','o','j'};
256 for(i=0; i<bth_size_data;i++)
258 flag=bth_inface_r_isr(0, *((uint8_t*)bth_data+i));
261 // sci_rs232_sendch(*((uint8_t*)bth_data+i),sci_rs232_chan_default); //do PC
262 // VypisHexa((void*)((uint8_t*)bth_data+i),1);
265 /*queue is full, neni schopen prijmout dalsi znaky*/
266 // sci_rs232_sendch('.',sci_rs232_chan_default); //do PC
270 // VypisHexa(bth_data,bth_size_data);
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*/
285 *Received HCI data packet is sent as broadcast (not finished function)
287 int bth_pkt_type_broadcast(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
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*/
303 *Received HCI data packet is send to piconet (not finished function)
305 int bth_pkt_type_piconet(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
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*/
321 *Reserved for future (not finished)
323 int bth_pkt_type_reserved(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
329 /****************************************************************************/
330 /****************************************************************************/
333 *pointers to functions. Functions are called according to the received HCI pakcet
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]))
342 *pointrs to functions. Functions are called according to the event code, decoded from the received HCI packet
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};
361 #define EV_SUM_FC (sizeof(bth_event_array_fce)/sizeof(bth_event_array_fce[0]))
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)
367 int bth_recieve_packet(int c)
369 hci_event_hdr bth_event_packet;
370 hci_acl_hdr bth_acl_packet;
373 uint8_t char_acl_pkt;
377 if(bth_controll_flag!=0)
379 bth_stop_TPU_counter();
380 bth_clear_TPU_counter();
381 bth_start_TPU_counter();
382 if(bth_get_timer()>0)
384 bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
391 VypisHexa((uint8_t*)&c,1);
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 ...
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));
403 if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>3)
405 if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == (bth_event_packet.plen+HCI_EVENT_HDR_SIZE+HCI_PKT_SIZE))
408 if(bth_controll_flag!=0)
410 bth_stop_TPU_counter();
414 /*pointer to the function matching the event code*/
415 if(bth_event_packet.evt<EV_SUM_FC) //check whether the function exists
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
421 bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg; //nastav se na zacatek, pro pristi event
426 // bth_error_detect_status((uint8_t)error_code); //error msg
429 {//bth_error_detect_event((uint8_t)(-error_code)); //error msg
434 case HCI_ACLDATA_PKT:
435 if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>5)
437 __bthtomc16((uint8_t*)&(bth_acl_packet.dlen),(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____dlen));
440 if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == ((bth_acl_packet.dlen)+HCI_ACL_HDR_SIZE+HCI_PKT_SIZE))
443 /* **** check the adjacency of two characters TPU3 **** */
444 if(bth_controll_flag!=0)
446 bth_stop_TPU_counter();
448 /*****************************************************/
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;
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)));
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
461 bth_char_pkt_fce[com_pr]
462 (bth_acl_packet.handle, char_acl_pkt&0x30, data_ad,bth_acl_packet.dlen);
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. */
469 bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
470 // sci_rs232_sendch('\n',sci_rs232_chan_default); //to PC
480 * Calls functions, which are necessary for setting the device to the slave mode.
482 void bth_parametr_slave(void)
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
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
498 if(bth_controll_flag>0)
501 bth_controll_flag=10;
502 bth_stop_TPU_counter();
503 bth_clear_TPU_counter();
507 bth_local_info.busy=0;
512 * Setting of the queue - initialization function
516 // bth_check_command_for_send=NULL;
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;
523 /****************************************************************************/
524 /****************************************************************************/
527 * Auxiliary function, which converts characetrs to the printable form
529 int VypisHexa(uint8_t *s, int delka)
532 uint8_t tisk[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
534 for(i=0; i<delka; i++)
538 printf("%c",tisk[((zn>>4)&0x000F)]);
539 printf("%c",tisk[zn & 0x000F]);
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