]> rtime.felk.cvut.cz Git - mirosot.git/blobdiff - bth_tests/bluetooth/bth_main.c
Added bth_test application. Not finished.
[mirosot.git] / bth_tests / bluetooth / bth_main.c
diff --git a/bth_tests/bluetooth/bth_main.c b/bth_tests/bluetooth/bth_main.c
new file mode 100644 (file)
index 0000000..4a049ca
--- /dev/null
@@ -0,0 +1,518 @@
+/*******************************************************************
+  bluetooth library
+
+  bth_main.c -  API bth library (recieve, send ...)
+
+  Copyright (C) 2006 by Petr Kovacik petr_kovacik@gmail.com
+
+ *******************************************************************/
+#include <bth_config.h>
+#include <types.h>
+#ifdef BTH_LX
+#include <cpu_def.h>
+#include <h8s2638h.h>
+#include <periph/sci_rs232.h>
+#include <system_def.h>
+#include <string.h>
+#else
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+
+#include "hci.h"
+#include "l2cap.h"
+#include "hci_event.h"
+#include "hci_command.h"
+#include "hci_error.h"
+
+//#include "hci_lib.h"
+#include "bth_receive.h"
+#include "inline_fce.h"
+#include "bth_inface.h"
+#include "bth_fce_out.h"
+#include "bth_h8s2638.h"
+
+
+#define BTH_BUF_LEN 300
+
+/*--------BD address whitch are accept for connection-------------*/
+bdaddr_t bth_accept_bd_addr[]={};
+
+/*----------------local device info (master) -----------------------*/
+bths_dev_info  bth_local_info;//={0,{0,0,0,0,0,0,0,0},{0,0,0},0,{0,0,0},0};
+
+/*----------------conect device info (slave) -----------------------*/
+bths_connect_bluet* bth_connected[8];
+
+/*-------------------------------- recieve data buffer -----------------------------*/
+bth_que_t bth_rs232_que_in;
+//bth_que_t bth_inface_que_in;
+//bth_que_t bth_inface_que_out;
+
+
+
+void  *bth_array_adrr_comm_packet[LENCOMMAND]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+bths_command_buf_info bth_com_buf_info={LENCOMMAND,0,0};
+/***********************************************************************************/
+void  *bth_array_adrr_check_packet[LENCOMMAND]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+bths_command_buf_info bth_check_buf_info={LENCOMMAND,0,0};
+/***********************************************************************************/
+
+/*FIXME this check synchronisation of received data using TPU unit of CPU*/
+uint8_t bth_controll_flag=0;
+
+
+/**-------------------------------------------------------------------------------*/
+/*FIXME ----- sending of command, if the local bluetooth is free (ready to send)------*/
+/*  0 = data moved to SCI buffer = they will be sent, bluetooth device is free
+    1 = it wasn't possible to move tha command to SCI bufferu, but bluet device is free
+    2 = bluetooth device is busy, ie. data were not moved to the bufferu
+    3 = there is no space left in confirmation queue*/
+
+/**
+ * After this function is called, the packet, which is in the command queue, is sent. If there is no new 
+ * packet or the device is busy, nothing is done.
+ *
+ * Po zavolani funkce, se odesle paket, ktery je zarazen ve fronte paketu k odeslani (bth zazizeni je
+ * volne), pokud neni novy paket nebo zazizeni neni volne, nic se nevykona
+*/
+int  bth_send_queue(void)
+{
+  int i;
+  int hp_size;
+  if(bth_local_info.busy!=0)
+  {return 1;}; //device is busy
+  if(bth_com_buf_info.aktual==bth_com_buf_info.sent) //PRAVDEPODOBNE neni co odesilat
+  {
+    if(bth_com_buf_info.sent<(LENCOMMAND-2))
+    {
+      if(bth_array_adrr_comm_packet[bth_com_buf_info.sent+1]==NULL)
+      {return 1;}; //There is certainly nothing to send
+    }
+    else
+    {
+      if(bth_array_adrr_comm_packet[0]==NULL)
+      {return 1;}; //There is certainly nothing to send
+    };
+  };
+    
+  /*bth_send_packet(AdrFrom,howmanyBytes;)*/
+  switch(*(uint8_t*)bth_array_adrr_comm_packet[bth_com_buf_info.sent])
+  {
+    case HCI_ACLDATA_PKT:
+      __bthtomc16((uint8_t*)&(hp_size),((uint8_t*)bth_array_adrr_comm_packet[bth_com_buf_info.sent])+HCI_PKT_SIZE+HCI_ACL_HDR____dlen);
+      hp_size=hp_size+HCI_ACL_HDR_SIZE+HCI_PKT_SIZE;
+      if(!(bth_send_packet(bth_array_adrr_comm_packet[bth_com_buf_info.sent],hp_size)))
+      {
+        free(bth_array_adrr_comm_packet[bth_com_buf_info.sent]);
+        bth_array_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
+        if(bth_com_buf_info.sent<(LENCOMMAND-2)){bth_com_buf_info.sent++;}
+        else{ bth_com_buf_info.sent=0;};
+        return(0);
+      };
+      free(bth_array_adrr_comm_packet[bth_com_buf_info.sent]);
+      bth_array_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
+      return (-6);
+    case HCI_COMMAND_PKT:
+      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);
+      if(!(bth_send_packet(bth_array_adrr_comm_packet[bth_com_buf_info.sent],hp_size)))
+      {/*sent - add the command to allow confirmation*/
+        for(i=0; i<LENCOMMAND; i++)
+        {
+          if(bth_array_adrr_check_packet[i]==NULL)
+          {
+            bth_array_adrr_check_packet[i]=bth_array_adrr_comm_packet[bth_com_buf_info.sent];
+            bth_array_adrr_comm_packet[bth_com_buf_info.sent]=NULL;
+            /*set the address for the next command - principle of ring buffer*/
+            if(bth_com_buf_info.sent<(LENCOMMAND-2)){bth_com_buf_info.sent++;}
+            else{ bth_com_buf_info.sent=0;};
+            return 0;
+          }
+        };
+        return(-7);
+      };
+      return(-6);
+  };
+  return (1);
+};
+
+
+/**
+ * Auxiliary function
+ * Convert hexadecimal character to ASCII. It is then sent to serial line
+ */
+//*************************** bth_conv_char_text *****************************
+// used to convers int into ascii letter and print it on serial
+// INPUT zn: interger to convert and print
+// OUTPUT :none
+//*************************************************************************** 
+void bth_conv_char_text(uint8_t zn)
+{
+  uint8_t val;
+  val=(zn&0xf0)>>4;
+#ifdef BTH_LX
+  uint8_t map_leters[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+  sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
+  val=(zn&0x0f);
+  sci_rs232_sendch(map_leters[val],sci_rs232_chan_default);
+#endif
+  return;
+};
+
+
+
+/**
+ *Inserts a character to the queue
+ */
+
+static inline int bth_que_put(bth_que_t *q, int c)
+{
+  uint8_t *p;
+  p=q->ip;                       //FIXME set us to the actual position in the file
+  *(p++)=c;                      //store the character to the next byte
+  if(p==q->buf_end) return -1;//this is not the ring buffer p=q->buf_beg;
+//  if(p==q->op) return -1;
+  q->ip=p;
+  return 0;                      //in case of success return the character, otherwise -1
+}
+
+
+/**
+//FIXME
+ *received HCI data packet is sent as point to point
+*/
+
+int bth_pkt_type_pointopoint(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
+{
+  l2cap_hdr bth_l2cap_packet;
+  int bth_dev_num;
+  int bth_size_data;
+  uint8_t *bth_data;
+  int flag;
+
+  switch(bound_flag)
+  {
+    case 0x20:/*first data packet L2CAP*/
+      bth_dev_num=bth_find_conected_dev(handle);
+      __bthtomc16((uint8_t*)&(bth_l2cap_packet.len),(uint8_t*)bth_p+L2CAP_HDR____len);
+      __bthtomc16((uint8_t*)&(bth_l2cap_packet.cid),(uint8_t*)bth_p+L2CAP_HDR____cid);
+
+
+      if(bth_dev_num>-1)
+      {
+        switch((uint8_t)(bth_l2cap_packet.cid))
+        {
+          case 0x00:
+            return(-3);
+          case 0x01:
+            l2cap_signaling(((uint8_t*)bth_p+L2CAP_CMD_HDR_SIZE),(size+L2CAP_HDR____len),bth_dev_num);
+            return(0);
+          case 0x02:
+            return(0);
+        };
+        /*FIXME real data ...*/
+        /*We have to find the channel with the CID number for device bth_dev_num*/
+        if(bth_find_chanal(bth_dev_num, bth_l2cap_packet.cid)>-1)
+        {
+          /*here are the received data, which are not used for confguration */
+
+          
+          bth_data=(uint8_t*)bth_p+L2CAP_HDR_SIZE;
+          bth_size_data=size-L2CAP_HDR_SIZE;
+          int i;
+//          uint8_t odesli[]={'a','h','o','j'};
+          for(i=0; i<bth_size_data;i++)
+          {
+            flag=bth_inface_r_isr(0, *((uint8_t*)bth_data+i));
+
+            if(flag>=0){
+//              sci_rs232_sendch(*((uint8_t*)bth_data+i),sci_rs232_chan_default); //do PC
+//              VypisHexa((void*)((uint8_t*)bth_data+i),1);
+            }else
+            {
+              /*queue is full, neni schopen prijmout dalsi znaky*/
+//              sci_rs232_sendch('.',sci_rs232_chan_default); //do PC
+            };
+          };
+
+//          VypisHexa(bth_data,bth_size_data);
+          return (0);
+        };
+        return(-5);
+      };
+      return(-1);
+    case 0x40: return(-3);  /*next data packet L2CAP*/ /*function is not written, I receive only one pakcet of the message*/
+    case 0x30: return (-4); /*Reserved for future use*/
+    case 0x00: return (-4); /*Reserved for future use*/
+  };
+  return(-1);
+};
+
+
+/**
+ *Received HCI data packet is sent as broadcast (not finished function)
+ */
+int bth_pkt_type_broadcast(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
+{
+  switch(bound_flag)
+  {
+    case 0x20:/*first data packet L2CAP*/
+      return(-3); /*neni napsano pro prijem znaku broadcast cestou*/
+    case 0x40: return(-3);  /*next data packet L2CAP*/ /*funkce neni rozepsana, prijmam jen 1pkt zpravy*/
+    case 0x30: return (-4); /*Reserved for future use*/
+    case 0x00: return (-4); /*Reserved for future use*/
+  };
+  return(-1);
+};
+
+
+
+/**
+ *Received HCI data packet is send to piconet (not finished function)
+ */
+int bth_pkt_type_piconet(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
+{
+  switch(bound_flag)
+  {
+    case 0x20:/*first data packet L2CAP*/
+      return(-3); /*neni napsano pro prijem znaku piconet cestou*/
+    case 0x40: return(-3);  /*next data packet L2CAP*/ /*funkce neni rozepsana, prijmam jen 1pkt zpravy*/
+    case 0x30: return (-4); /*Reserved for future use*/
+    case 0x00: return (-4); /*Reserved for future use*/
+  };
+  return(-1);
+};
+
+
+
+/**
+ *Reserved for future (not finished)
+ */
+int bth_pkt_type_reserved(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size)
+{
+  return(-3);
+};
+
+
+/****************************************************************************/
+/****************************************************************************/
+
+/**
+ *pointers to functions. Functions are called according to the received HCI pakcet
+ */
+typedef int (*bth_kind_pkt)(uint16_t handle, uint8_t bound_flag, uint8_t *bth_p, uint16_t size);
+bth_kind_pkt bth_char_pkt_fce[]={
+    bth_pkt_type_pointopoint, bth_pkt_type_broadcast, bth_pkt_type_piconet, bth_pkt_type_reserved};
+#define COM_PROT_SUM_FC (sizeof(bth_char_pkt_fce)/sizeof(bth_char_pkt_fce[0]))
+
+
+/**
+ *pointrs to functions. Functions are called according to the event code, decoded from the received HCI packet
+ */
+typedef int (*bth_p_ivent_fce)(uint8_t *bth_p, uint8_t size);
+bth_p_ivent_fce bth_event_array_fce[]={bth_evt_none,bth_evt_inquiry_complete, bth_evt_inquiry_result,
+                  bth_evt_conn_complete, bth_evt_conn_request, bth_evt_disconn_complete,
+                  bth_evt_auth_complete, bth_remote_name_req_complete,
+                  bth_evt_encrypt_cahnge, bth_evt_change_conn_link_key_complete,
+                  bth_evt_master_link_key_complete, bth_evt_read_remote_features_complete,
+                  bth_evt_read_remote_version_complete, bth_evt_qos_setup_complete,
+                  bth_evt_cmd_complete, bth_evt_cmd_status,  bth_evt_hardware_error,
+                  bth_evt_flush_occurred,  bth_evt_role_cahage, bth_evt_num_comp_pkts,
+                  bth_evt_mode_change, bth_evt_return_link_keys, bth_evt_pin_code_req,
+                  bth_evt_link_key_req, bth_evt_link_key_notify, bth_evt_loopback_command,
+                  bth_evt_data_buffer_overflow, bth_evt_max_slots_change,
+                  bth_evt_read_clock_offset_complete, bth_evt_conn_ptype_changed,
+                  bth_evt_qos_violation, bth_evt_page_scan_mode_change,
+                  bth_evt_pscan_rep_mode_change, bth_evt_flow_spec_complete,
+                  bth_evt_inquiry_result_with_rssi};
+
+#define EV_SUM_FC (sizeof(bth_event_array_fce)/sizeof(bth_event_array_fce[0]))
+
+
+/**
+ *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)
+ */
+int bth_recieve_packet(int c)
+{
+  hci_event_hdr  bth_event_packet;
+  hci_acl_hdr bth_acl_packet;
+  uint8_t *typ_paket;
+  int error_code;
+  uint8_t char_acl_pkt;
+  uint8_t *data_ad;
+  uint8_t com_pr;
+
+  if(bth_controll_flag!=0)
+  {
+      bth_stop_TPU_counter();
+      bth_clear_TPU_counter();
+      bth_start_TPU_counter();
+      if(bth_get_timer()>0)
+      {
+        bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
+        bth_nul_timer();
+      };
+  };
+  
+  
+#ifndef BTH_LX
+  VypisHexa((uint8_t*)&c,1);
+#endif
+  //VypisHexa((uint8_t*)&c,1);
+  bth_que_put(&bth_rs232_que_in, c); //store the received character to the queue
+  typ_paket=((uint8_t*)bth_rs232_que_in.buf_beg); //determine the type of the pakcet ACL, Even, SCO ...
+  switch(*typ_paket)
+  {
+  case HCI_EVENT_PKT:
+    /*fill in structure "hci_event_hdr" from the queue (bye by byte)*/
+    store8(bth_event_packet.evt,  *(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE));
+    store8(bth_event_packet.plen, *(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+1));
+
+      if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>3)
+    {
+      if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == (bth_event_packet.plen+HCI_EVENT_HDR_SIZE+HCI_PKT_SIZE))
+      {
+        /*****/
+        if(bth_controll_flag!=0)
+        {
+          bth_stop_TPU_counter();
+        };
+        /*******/
+    
+        /*pointer to the function matching the event code*/
+        if(bth_event_packet.evt<EV_SUM_FC) //check whether the function exists
+        {
+          data_ad=(uint8_t*)(bth_rs232_que_in.buf_beg+HCI_EVENT_HDR_SIZE+HCI_PKT_SIZE);
+          error_code=(*bth_event_array_fce[bth_event_packet.evt])(data_ad,bth_event_packet.plen);
+          bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;  //set to the beginning for the next event
+        }else{
+          bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;  //nastav se na zacatek, pro pristi event
+          return (-1);
+        };
+        if(error_code>=0)
+        {
+          // bth_error_detect_status((uint8_t)error_code); //error msg
+        }
+        else
+        {//bth_error_detect_event((uint8_t)(-error_code)); //error msg
+        };
+      };
+    };
+    return 0;
+    case HCI_ACLDATA_PKT:
+      if(bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg>5)
+      {
+        __bthtomc16((uint8_t*)&(bth_acl_packet.dlen),(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____dlen));
+        
+
+        if((bth_rs232_que_in.ip-bth_rs232_que_in.buf_beg) == ((bth_acl_packet.dlen)+HCI_ACL_HDR_SIZE+HCI_PKT_SIZE))
+        {
+          
+          /*  **** check the adjacency of two characters TPU3 ****   */
+          if(bth_controll_flag!=0)
+          {
+            bth_stop_TPU_counter();
+          };
+          /*****************************************************/
+          
+          __bthtomc16((uint8_t*)&(bth_acl_packet.handle),(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____handle));
+          bth_acl_packet.handle=bth_acl_packet.handle & 0x0fff;
+          
+          /*variable 'char_acl_pkt' stores the properties of the packet, if it is point to point or broadcast, or char. L2CAP*/
+          store8(char_acl_pkt, (0xf0&*(((uint8_t*)bth_rs232_que_in.buf_beg)+HCI_PKT_SIZE+HCI_ACL_HDR____handle+1)));
+          
+          /*decide which packet is this (PtP,Piconet,broat...) and the type of communication (L2CAP, HCI)*/
+          data_ad=(uint8_t*)bth_rs232_que_in.buf_beg+HCI_PKT_SIZE+HCI_ACL_HDR_SIZE;
+          com_pr=char_acl_pkt&0xc0;
+          if(com_pr<COM_PROT_SUM_FC) //func exists
+          {
+            bth_char_pkt_fce[com_pr]
+                (bth_acl_packet.handle, char_acl_pkt&0x30, data_ad,bth_acl_packet.dlen);
+          }
+          else
+          {
+            /*HCI data - not L2CAP - neither handling nor loading to data queue is not implemented. It is assumed
+              sending of data using L2CAP. See if before this else. */
+          };
+          bth_rs232_que_in.ip=bth_rs232_que_in.buf_beg;
+//        sci_rs232_sendch('\n',sci_rs232_chan_default); //to PC
+        };
+
+      };
+    };
+  return -1;
+};
+
+
+/**
+ * Calls functions, which are necessary for setting the device to the slave mode.
+*/
+void bth_parametr_slave(void)
+{
+  bth_local_info.busy=1;
+  bth_cmd_write_page_scan(0x0040, 0x0020);
+  bth_cmd_write_inquiry_scan_activity(0x0040, 0x0020);
+  bth_cmd_write_scan_enable(0x03);
+// bth_cmd_read_bd_addr(); //funguje command event neni
+};
+
+
+/**
+ * Sets the MCU up, so it can send HCI packets to bth device
+ * If TPU channels are initialized, it resets and stop it
+*/
+void bth_start(void)
+{
+  if(bth_controll_flag>0)
+  {
+
+    bth_controll_flag=10;
+    bth_stop_TPU_counter();
+    bth_clear_TPU_counter();
+    bth_nul_timer();
+  };
+
+  bth_local_info.busy=0;
+};
+
+
+/**
+ * Setting of the queue - initialization function
+*/
+void bth_init(void)
+{
+  static uint8_t  bth_array_char_in[70];
+//  bth_check_command_for_send=NULL;
+
+  bth_rs232_que_in.buf_end=(uint8_t*)bth_array_char_in+BTH_BUF_LEN;
+  bth_rs232_que_in.buf_beg=bth_array_char_in;
+  bth_rs232_que_in.ip=bth_array_char_in;
+};
+
+/****************************************************************************/
+/****************************************************************************/
+
+/**
+ * Auxiliary function, which converts characetrs to the printable form
+*/
+int VypisHexa(uint8_t *s, int delka)
+{
+
+  uint8_t tisk[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+  uint8_t i,zn;
+  for(i=0; i<delka; i++)
+  {
+    zn=*(s+i);
+#ifndef BTH_LX
+    printf("%c",tisk[((zn>>4)&0x000F)]);
+    printf("%c",tisk[zn & 0x000F]);
+#else
+    sci_rs232_sendch(tisk[(zn&0xf0)>>4],sci_rs232_chan_default); //to PC
+    sci_rs232_sendch(tisk[(zn&0x0f)],sci_rs232_chan_default); //to PC
+#endif
+  };
+
+  return 0;
+};
+