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(×[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(×[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 }