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.16 2006/10/27 14:53:52 yuecelm Exp $
00033  * 
00034  */
00035 
00072 #ifdef __BTN_UNIX__
00073 #include <dev/unix_devs.h>
00074 #include <unistd.h>
00075 #endif
00076 
00077 #ifdef __linux__
00078 #include <sys/timeb.h>
00079 #else
00080 struct timeb {
00081     long time;
00082     long millitm;
00083 };
00084 #endif
00085 
00086 #include <string.h>
00087 #include <io.h>
00088 #include <stdlib.h>
00089 #include <dev/debug.h>
00090 #include <sys/timer.h>
00091 #include <sys/event.h>
00092 #include <dev/uartavr.h>
00093 #include <dev/usartavr.h>
00094 #include <bt/bt_hci_cmds.h>
00095 #include <hardware/btn-hardware.h>
00096 #include <sys/types.h>
00097 #include <led/btn-led.h>
00098 #include <debug/toolbox.h>
00099 
00104 #define HCI_MAX_ACL_DATA_PKT    0x08
00105 
00106 #define HCI_MAX_SCO_DATA_PKT    0x01
00107 
00108 #define HCI_PACKET_TYPE BT_HCI_PACKET_TYPE_DM3
00109 
00110 // Average of HIST_SIZE measurements will be printed.
00111 #define HIST_SIZE   100
00112 
00113 //Global variables on the heap
00114 struct btstack *stack;
00115 struct bt_hci_inquiry_result inqres[5];
00116 struct bt_hci_pkt_acl *aclpkt;
00117 
00118 bt_hci_con_handle_t THE_handle;
00119 HANDLE table_changed_event;
00120 
00121 
00122 void con_table_cb(u_char type, u_char reason, bt_hci_con_handle_t con_handle, void* cb_arg)
00123 { 
00124     printf("\nconnection table changed!\n");
00125     switch (type) {
00126         case BT_HCI_MY_ROLE_MASTER:
00127             printf("CB: My role switched to master (%d)\n",con_handle);
00128             break;
00129         case BT_HCI_MY_ROLE_SLAVE:
00130             printf("CB: My role switched to slave (%d)\n",con_handle);
00131             break;
00132         case BT_HCI_CONNECTION:
00133             printf("CB: Connection opened (%d)\n",con_handle);
00134             THE_handle = con_handle;
00135             NutEventPostAsync(&table_changed_event);
00136             break;
00137         case BT_HCI_DISCONNECTION:
00138             printf("CB: Disconnected (%d)\n",con_handle);
00139             break;
00140         default:
00141             printf("Illegal type entered! (%d)\n",type);
00142     }
00143 }
00144 
00145 int myftime( struct timeb *pt){
00146 
00147 #ifdef __AVR_ATmega128__
00148     pt->time = NutGetSeconds();
00149     pt->millitm = NutGetMillis() % 1000;
00150     return 0;
00151 #endif
00152 
00153 #ifdef __APPLE__
00154     pt->time = time( NULL );
00155     pt->millitm = 0;
00156     return 0;
00157 #endif
00158 
00159 #ifdef __linux__
00160     return ftime( pt );
00161 #endif
00162 
00163 }
00164 
00165 
00166 int main(void)
00167 {
00168     long retval;
00169     long read[3];
00170     struct timeb times[2];
00171     long timediff; 
00172     u_short history[HIST_SIZE];
00173     u_short counter;
00174     long histcounter;
00175     
00176     // serial baud rate
00177     u_long baud = 57600;
00178     char name[64];
00179     bt_addr_t addr;
00180     u_char i, nr_devices, dataRead;
00181     bt_hci_con_handle_t con_handle;
00182 
00183     // hardware init
00184     btn_hardware_init();
00185     btn_led_init(1);
00186     
00187     // init app uart
00188     NutRegisterDevice(&APP_UART, 0, 0);
00189     freopen(APP_UART.dev_name, "r+", stdout);
00190     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00191     
00192     // Debug-Output
00193     printf("Main initialization about to start...\n");
00194     
00195     // bluetooth module on (takes a while)
00196     btn_hardware_bt_on();
00197 
00198     // Start the stack and let the initializaiton begin
00199     stack = bt_hci_init(&BT_UART);
00200     
00201     // add connection handling to allow role change
00202     bt_hci_register_con_table_cb(stack, &con_table_cb, NULL);
00203     
00204     // reserve data acl pkt
00205     aclpkt =(struct bt_hci_pkt_acl *) malloc( 200 );
00206     
00207     // From now on the stack should be working...
00208     
00209     strcpy(name, "BT-Streamer");
00210     retval = bt_hci_write_local_name(stack, BT_HCI_SYNC, (u_char*) name);
00211     printf("Setting the btname: %ld\n", retval);
00212     
00213     retval = bt_hci_read_local_name(stack, BT_HCI_SYNC, (u_char*) name, 64);
00214     printf("Getting the btname: %ld ('%s')\n", retval, name);
00215     
00216     bt_hci_get_local_bt_addr(stack, addr);
00217     printf("Getting the local address bt_addr: "ADDR_FMT"\n", ADDR(addr));
00218     
00219     retval = bt_hci_read_connection_accept_timeout(stack, BT_HCI_SYNC);
00220     printf("read_connection_accept_timeout: (0x%lX * 0.625 msec)\n", retval);
00221     
00222     retval = bt_hci_read_page_timeout(stack, BT_HCI_SYNC);
00223     printf("read_page_timeout: (0x%lX * 0.625 msec)\n", retval);
00224     
00225     retval = bt_hci_read_scan_enable(stack, BT_HCI_SYNC);
00226     switch (retval) {
00227         case BT_HCI_SCAN_MODE_OFF:
00228             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_OFF)\n", retval);
00229             break;
00230         case BT_HCI_SCAN_MODE_INQUIRY:
00231             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_INQUIRY)\n", retval);
00232             break;
00233         case BT_HCI_SCAN_MODE_PAGE:
00234             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_PAGE)\n", retval);
00235             break;
00236         case BT_HCI_SCAN_MODE_INQUIRY_PAGE:     
00237             printf("read_scan_enable: %ld (BT_HCI_SCAN_MODE_INQUIRY_PAGE)\n", retval);
00238             break;
00239         default:
00240             printf("read_scan_enable: %ld (error)\n", retval);
00241     }
00242     
00243     //cod = bt_hci_read_local_cod(stack, BT_HCI_SYNC);
00244     //printf("Reading local COD: 0x%lX\n",cod);
00245     
00246     //retval = bt_hci_write_local_cod(stack, BT_HCI_SYNC, cod);
00247     //printf("Writing local COD: %ld, 0x%lX\n",retval,cod);
00248     
00249     //retval = bt_hci_write_default_link_policy_settings(stack, BT_HCI_SYNC, BT_HCI_LINK_POLICY_ROLE_SWITCH);
00250     //printf("Change default link policy: %ld\n", retval);
00251     
00252     printf("Starting an inquiry inside the application (may take some time...):\n");
00253     // duration to wait for devices, max. number of devies to find
00254     retval = bt_hci_inquiry(stack, BT_HCI_SYNC, 0x08, 0x5, inqres);
00255     printf("Inquiry: %ld\n", retval);
00256     if (retval<0) retval=0;
00257     
00258     nr_devices = retval;
00259     for (i=0; i<nr_devices; i++) {
00260         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);
00261         printf("Now we try to get the name of this device... (may take a moment)\n");
00262         // Set default as 0-string
00263         name[0]='\0';
00264         retval = bt_hci_remote_name_request(stack, inqres[i].bdaddr, inqres[i].clock_offset, inqres[i].page_scan_rep_mode, name, 64);
00265         printf("Remote name request: '%s', Ret.Value: %ld Clock Offset: %d\n", name, retval, inqres[i].clock_offset);
00266         if (strncmp(name, "BT-Receiver", 11)==0) {
00267             printf("Ok, we found a device that is capable to receive streamed data.\n");
00268             printf("Now we try to open a connection to this device...\n");
00269             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);
00270             printf("Open connection: %ld\n", retval);
00271             
00272             read[0] = 0;
00273             read[1] = 0;
00274             read[2] = 0;
00275             if (retval>=0) {
00276                 printf("Connection accepted!\n");
00277                 // hooray, a connection exists, now let's do some mischief with it!
00278                 con_handle = retval;
00279                 
00280                 retval = bt_hci_write_link_policy_settings(stack, BT_HCI_SYNC, con_handle, BT_HCI_LINK_POLICY_ROLE_SWITCH);
00281                 printf("Set link policy parameters: %ld\n", retval);
00282 
00283                 printf("Ready to send data!\n");
00284                 
00285                 //streamData = fopen("3DD-Duck_and_Run.mp3", "r");
00286                 //printf("Open: %d\n", streamData);
00287                     // Set payload and length
00288                     //strcpy(aclpkt.payload,"Hello from the bttest program!");
00289                     // fake l2cap packet (if len in 0&1 is bigger then the HCI packet, the ericcson modules chokes..
00290                 
00291                 // Set pkt. to smth ;)
00292                 for (dataRead=2; dataRead<183; dataRead++)
00293                     aclpkt->payload[dataRead] = dataRead-2;
00294                 // aclpkt->payload[dataRead] = 0;
00295                 
00296                 // Data-Payload of the packet
00297                 dataRead=181;
00298                 
00299                 // Init History
00300                 for (counter=0; counter<HIST_SIZE; counter++)
00301                     history[counter]=0;
00302                     
00303                 histcounter=0;
00304                 
00305                 // get time in secs + millis
00306                 retval = myftime(&times[0]);
00307                 if (retval!=0)
00308                     printf("Error reading time: %ld\n", retval);
00309                     
00310                 while (dataRead!=4) {
00311                     //dataRead = fread(aclpkt.payload+2, 1, 181, stdin);
00312                     //DEBUG("%d\n", dataRead);
00313                     
00314                     //for (retval=0; retval<dataRead; retval++)
00315                     //{ DEBUG("%c", aclpkt.payload[2+retval]); }
00316                     //DEBUG("\n");
00317                     
00318                     aclpkt->payload[0] = dataRead + 2; // len - hdr
00319                     aclpkt->payload[1] = 0;
00320                     
00321                     read[0]++;
00322                     read[1]++;
00323                     //aclpkt.payload[2] = 'a';
00324                     //aclpkt.payload[3] = 'b';
00325                     //aclpkt.payload[4] = 'c';
00326                     // Now send the pkt (stack, con_handle, length, pkt with payload)
00327                     //printf("Trying to send a pkt!\n"); // 
00328                     retval = bt_hci_send_acl_pkt(stack, con_handle, HCI_PB_FIRST_FRAGMENT, HCI_BC_UNICAST, dataRead+2+HCI_ACL_DATA_PKT_HDR, aclpkt);
00329                     if (retval!=0)
00330                         printf("Error in send pkt: %ld\n", retval);
00331                     
00332                     if (read[0]==10) {
00333                         retval = myftime(&times[1]);
00334                         if (retval!=0)
00335                             printf("Error reading time: %ld\n", retval);
00336                         
00337                         // For double:
00338                         //timediff = 10*181/(times[1].time - times[0].time + (double)(times[1].millitm - times[0].millitm)/1000);
00339                         
00340                         // For milliseconds (therefore data * 1000!)
00341                         timediff = (long) 10*183*1000 / ((times[1].time - times[0].time)*1000 + times[1].millitm - times[0].millitm);
00342                         times[0] = times[1];
00343                         history[histcounter++%HIST_SIZE]=timediff;
00344                         
00345                         timediff = 0;
00346                         for (counter=0; counter<HIST_SIZE; counter++)
00347                             timediff+=history[counter];
00348     
00349                         timediff = timediff / HIST_SIZE;
00350                         printf("Datarate: %.6ld byte/s, packets send: %.6ld - time: %ld\r", timediff, read[1], times[0].time);
00351                         read[0]=0;
00352                     }
00353 
00354                 }
00355                 // now that we have the connection, let's disconnect again!
00356                 printf("Now we disconnect again!\n");
00357                 retval = bt_hci_disconnect(stack, BT_HCI_SYNC, con_handle, BT_HCI_DISCONNECT_USER_ENDED);
00358                 printf("Disconnect: %ld\n", retval);
00359             }
00360         }
00361     }
00362     
00363     printf("Done. Entering endless loop...\n");
00364     while (1) {
00365 
00366     }
00367     return 0;
00368 }

Generated on Tue Jan 23 21:12:24 2007 for BTnut System Software by doxygen 1.4.7