btstreamer/streamer/btstreamer.c

Date:
2004/04/18 21:37:09
Author:
Mathias Payer <payerm@student.ethz.ch>
Example application to show the use of the bt stack

00001 /*
00002  * Copyright (C) 2000-2005 by ETH Zurich
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY ETH ZURICH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ETH ZURICH
00021  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  * $Id: btstreamer.c,v 1.19 2007/02/15 16:30:51 freckle Exp $
00033  * 
00034  */
00035 
00084 #ifdef __BTN_UNIX__
00085 #include <dev/unix_devs.h>
00086 #include <unistd.h>
00087 #endif
00088 
00089 #ifdef __linux__
00090 #include <sys/timeb.h>
00091 #else
00092 struct timeb {
00093     long time;
00094     long millitm;
00095 };
00096 #endif
00097 
00098 #include <string.h>
00099 #include <io.h>
00100 #include <stdlib.h>
00101 #include <dev/debug.h>
00102 #include <sys/timer.h>
00103 #include <sys/event.h>
00104 #include <dev/uartavr.h>
00105 #include <dev/usartavr.h>
00106 #include <bt/bt_hci_cmds.h>
00107 #include <hardware/btn-hardware.h>
00108 #include <sys/types.h>
00109 #include <led/btn-led.h>
00110 #include <debug/toolbox.h>
00111 
00116 #define HCI_MAX_ACL_DATA_PKT    0x08
00117 
00118 #define HCI_MAX_SCO_DATA_PKT    0x01
00119 
00120 #define HCI_PACKET_TYPE BT_HCI_PACKET_TYPE_DM3
00121 
00122 // Average of HIST_SIZE measurements will be printed.
00123 #define HIST_SIZE   100
00124 
00125 //Global variables on the heap
00126 struct btstack *stack;
00127 struct bt_hci_inquiry_result inqres[5];
00128 struct bt_hci_pkt_acl *aclpkt;
00129 
00130 bt_hci_con_handle_t THE_handle;
00131 HANDLE table_changed_event;
00132 
00133 
00134 void con_table_cb(u_char type, u_char reason, bt_hci_con_handle_t con_handle, void* cb_arg)
00135 { 
00136     printf("\nconnection table changed!\n");
00137     switch (type) {
00138         case BT_HCI_MY_ROLE_MASTER:
00139             printf("CB: My role switched to master (%d)\n",con_handle);
00140             break;
00141         case BT_HCI_MY_ROLE_SLAVE:
00142             printf("CB: My role switched to slave (%d)\n",con_handle);
00143             break;
00144         case BT_HCI_CONNECTION:
00145             printf("CB: Connection opened (%d)\n",con_handle);
00146             THE_handle = con_handle;
00147             NutEventPostAsync(&table_changed_event);
00148             break;
00149         case BT_HCI_DISCONNECTION:
00150             printf("CB: Disconnected (%d)\n",con_handle);
00151             break;
00152         default:
00153             printf("Illegal type entered! (%d)\n",type);
00154     }
00155 }
00156 
00157 int myftime( struct timeb *pt){
00158 
00159 #ifdef __AVR_ATmega128__
00160     pt->time = NutGetSeconds();
00161     pt->millitm = NutGetMillis() % 1000;
00162     return 0;
00163 #endif
00164 
00165 #ifdef __APPLE__
00166     pt->time = time( NULL );
00167     pt->millitm = 0;
00168     return 0;
00169 #endif
00170 
00171 #ifdef __linux__
00172     return ftime( pt );
00173 #endif
00174 
00175 }
00176 
00177 
00178 int main(void)
00179 {
00180     long retval;
00181     long read[3];
00182     struct timeb times[2];
00183     long timediff; 
00184     u_short history[HIST_SIZE];
00185     u_short counter;
00186     long histcounter;
00187     u_long myTime;
00188     u_long slaveTime;
00189     
00190     // serial baud rate
00191     u_long baud = 57600;
00192     char name[64];
00193     bt_addr_t addr;
00194     u_char i, nr_devices, dataRead;
00195     bt_hci_con_handle_t con_handle;
00196 
00197     // hardware init
00198     btn_hardware_init();
00199     btn_led_init(1);
00200     
00201     // init app uart
00202     NutRegisterDevice(&APP_UART, 0, 0);
00203     freopen(APP_UART.dev_name, "r+", stdout);
00204     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00205     
00206     // Debug-Output
00207     printf("Main initialization about to start...\n");
00208     
00209     // bluetooth module on (takes a while)
00210     btn_hardware_bt_on();
00211 
00212     // Start the stack and let the initializaiton begin
00213     stack = bt_hci_init(&BT_UART);
00214     
00215     
00216     // add connection handling to allow role change
00217     bt_hci_register_con_table_cb(stack, &con_table_cb, NULL);
00218     
00219     // reserve data acl pkt
00220     aclpkt =(struct bt_hci_pkt_acl *) malloc( 200 );
00221     
00222     // From now on the stack should be working...
00223     
00224     strcpy(name, "BT-Streamer");
00225     retval = bt_hci_write_local_name(stack, BT_HCI_SYNC, (u_char*) name);
00226     printf("Setting the btname: %ld\n", retval);
00227     
00228     retval = bt_hci_read_local_name(stack, BT_HCI_SYNC, (u_char*) name, 64);
00229     printf("Getting the btname: %ld ('%s')\n", retval, name);
00230     
00231     bt_hci_get_local_bt_addr(stack, addr);
00232     printf("Getting the local address bt_addr: "ADDR_FMT"\n", ADDR(addr));
00233     
00234     retval = bt_hci_read_connection_accept_timeout(stack, BT_HCI_SYNC);
00235     printf("read_connection_accept_timeout: (0x%lX * 0.625 msec)\n", retval);
00236     
00237     retval = bt_hci_read_page_timeout(stack, BT_HCI_SYNC);
00238     printf("read_page_timeout: (0x%lX * 0.625 msec)\n", retval);
00239     
00240     retval = bt_hci_read_scan_enable(stack, BT_HCI_SYNC);
00241     switch (retval) {
00242         case BT_HCI_SCAN_MODE_OFF:
00243             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_OFF)\n", retval);
00244             break;
00245         case BT_HCI_SCAN_MODE_INQUIRY:
00246             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_INQUIRY)\n", retval);
00247             break;
00248         case BT_HCI_SCAN_MODE_PAGE:
00249             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_PAGE)\n", retval);
00250             break;
00251         case BT_HCI_SCAN_MODE_INQUIRY_PAGE:     
00252             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_INQUIRY_PAGE)\n", retval);
00253             break;
00254         default:
00255             printf("read_scan_enable: %ld (error)\n", retval);
00256     }
00257     
00258     //cod = bt_hci_read_local_cod(stack, BT_HCI_SYNC);
00259     //printf("Reading local COD: 0x%lX\n",cod);
00260     
00261     //retval = bt_hci_write_local_cod(stack, BT_HCI_SYNC, cod);
00262     //printf("Writing local COD: %ld, 0x%lX\n",retval,cod);
00263     
00264     //retval = bt_hci_write_default_link_policy_settings(stack, BT_HCI_SYNC, BT_HCI_LINK_POLICY_ROLE_SWITCH);
00265     //printf("Change default link policy: %ld\n", retval);
00266     
00267     printf("Starting an inquiry inside the application (may take some time...):\n");
00268     // duration to wait for devices, max. number of devies to find
00269     retval = bt_hci_inquiry(stack, BT_HCI_SYNC, 0x08, 0x5, inqres);
00270     printf("Inquiry: %ld\n", retval);
00271     if (retval<0) retval=0;
00272     
00273     nr_devices = retval;
00274     for (i=0; i<nr_devices; i++) {
00275         printf("Device [%d]: %2.x:%2.x:%2.x:%2.x:%2.x:%2.x (Class of device: 0x%lX)\n", i, inqres[i].bdaddr[5], inqres[i].bdaddr[4], inqres[i].bdaddr[3], inqres[i].bdaddr[2], inqres[i].bdaddr[1], inqres[i].bdaddr[0], inqres[i].cod);
00276         printf("Now we try to get the name of this device... (may take a moment)\n");
00277         // Set default as 0-string
00278         name[0]='\0';
00279         retval = bt_hci_remote_name_request(stack, inqres[i].bdaddr, inqres[i].clock_offset, inqres[i].page_scan_rep_mode, name, 64);
00280         printf("Remote name request: '%s', Ret.Value: %ld Clock Offset: %d\n", name, retval, inqres[i].clock_offset);
00281         if (strncmp(name, "BT-Receiver", 11)==0) {
00282             printf("Ok, we found a device that is capable to receive streamed data.\n");
00283             printf("Now we try to open a connection to this device...\n");
00284             retval = bt_hci_create_connection(stack, BT_HCI_SYNC, inqres[i].bdaddr, BT_HCI_PACKET_TYPE_DH3, inqres[i].page_scan_rep_mode, inqres[i].clock_offset, BT_HCI_ROLE_SWITCH_MASTER);
00285             printf("Open connection: %ld\n", retval);
00286             
00287             read[0] = 0;
00288             read[1] = 0;
00289             read[2] = 0;
00290             if (retval>=0) {
00291                 printf("Connection accepted!\n");
00292                 // hooray, a connection exists, now let's do some mischief with it!
00293                 con_handle = retval;
00294                 
00295                 retval = bt_hci_write_link_policy_settings(stack, BT_HCI_SYNC, con_handle, BT_HCI_LINK_POLICY_ROLE_SWITCH);
00296                 printf("Set link policy parameters: %ld\n", retval);
00297 
00298                 printf("Ready to send data!\n");
00299                 
00300                 // Set pkt. to smth ;)
00301                 for (dataRead=0; dataRead<183; dataRead++)
00302                     aclpkt->payload[dataRead] = dataRead-2;
00303                 
00304                 // Data-Payload of the packet
00305                 dataRead=181;
00306                 
00307                 // Init History
00308                 for (counter=0; counter<HIST_SIZE; counter++)
00309                     history[counter]=0;
00310                     
00311                 histcounter=0;
00312                 
00313                 // get time in secs + millis
00314                 retval = myftime(&times[0]);
00315                 if (retval!=0)
00316                     printf("Error reading time: %ld\n", retval);
00317 
00318                 while (1) {
00319                     // fake acl header
00320                     aclpkt->payload[0] = dataRead + 2; // len - hdr
00321                     aclpkt->payload[1] = 0;
00322                     aclpkt->payload[2] = 2;
00323                     aclpkt->payload[3] = 0;
00324                     
00325                     read[0]++;
00326                     read[1]++;
00327                     // Now send the pkt (stack, con_handle, length, pkt with payload)
00328                     //printf("Trying to send a pkt!\n"); // 
00329                     retval = bt_hci_send_acl_pkt(stack, con_handle, HCI_PB_FIRST_FRAGMENT, HCI_BC_UNICAST, dataRead+2+HCI_ACL_DATA_PKT_HDR, aclpkt);
00330                     if (retval!=0)
00331                         printf("Error in send pkt: %ld\n", retval);
00332                     
00333                     if (read[0]==10) {
00334                         retval = myftime(&times[1]);
00335                         if (retval!=0)
00336                             printf("Error reading time: %ld\n", retval);
00337                         
00338                         // For double:
00339                         //timediff = 10*181/(times[1].time - times[0].time + (double)(times[1].millitm - times[0].millitm)/1000);
00340                         
00341                         // For milliseconds (therefore data * 1000!)
00342                         timediff = (long) 10*183*1000 / ((times[1].time - times[0].time)*1000 + times[1].millitm - times[0].millitm);
00343                         times[0] = times[1];
00344                         history[histcounter++%HIST_SIZE]=timediff;
00345                         
00346                         timediff = 0;
00347                         for (counter=0; counter<HIST_SIZE; counter++)
00348                             timediff+=history[counter];
00349     
00350                         timediff = timediff / HIST_SIZE;
00351                         
00352                         myTime = bt_hci_read_clock( stack, BT_HCI_SYNC, 0, 0, NULL, NULL);
00353                         // retval = bt_hci_read_clock( stack, BT_HCI_SYNC, 1, con_handle, &slaveTime, 0);
00354                         // _bt_hci_debug_uart = 1;
00355                         retval = bt_hci_read_clock_offset( stack, BT_HCI_SYNC, con_handle);
00356                         // _bt_hci_debug_uart = 0;
00357                         if (retval < 16484 )
00358                             slaveTime = myTime + retval;
00359                         else
00360                             slaveTime = myTime + retval - 32768;
00361                         printf("%.6lu %.6lu %.6lu \r", myTime, slaveTime, retval);
00362                        // printf("%.6lu %.6lu %.6lu - Datarate: %.6ld byte/s, packets send: %.6ld - time: %ld\r", myTime, slaveTime, retval, timediff, read[1], times[0].time);
00363                         read[0]=0;
00364                     }
00365 
00366                 }
00367                 // now that we have the connection, let's disconnect again!
00368                 printf("Now we disconnect again!\n");
00369                 retval = bt_hci_disconnect(stack, BT_HCI_SYNC, con_handle, BT_HCI_DISCONNECT_USER_ENDED);
00370                 printf("Disconnect: %ld\n", retval);
00371             }
00372         }
00373     }
00374     
00375     printf("Done. Entering endless loop...\n");
00376     while (1) {
00377 
00378     }
00379     return 0;
00380 }

Generated on Wed Apr 29 11:12:28 2009 for BTnut System Software by doxygen 1.5.1