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