1cee62800SMatthias Ringwald /* 2cee62800SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3cee62800SMatthias Ringwald * 4cee62800SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5cee62800SMatthias Ringwald * modification, are permitted provided that the following conditions 6cee62800SMatthias Ringwald * are met: 7cee62800SMatthias Ringwald * 8cee62800SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9cee62800SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10cee62800SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11cee62800SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12cee62800SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13cee62800SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14cee62800SMatthias Ringwald * contributors may be used to endorse or promote products derived 15cee62800SMatthias Ringwald * from this software without specific prior written permission. 16cee62800SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17cee62800SMatthias Ringwald * personal benefit and not for any commercial purpose or for 18cee62800SMatthias Ringwald * monetary gain. 19cee62800SMatthias Ringwald * 20cee62800SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21cee62800SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22cee62800SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23cee62800SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24cee62800SMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25cee62800SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26cee62800SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27cee62800SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28cee62800SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29cee62800SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30cee62800SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31cee62800SMatthias Ringwald * SUCH DAMAGE. 32cee62800SMatthias Ringwald * 33cee62800SMatthias Ringwald * Please inquire about commercial licensing options at 34cee62800SMatthias Ringwald * [email protected] 35cee62800SMatthias Ringwald * 36cee62800SMatthias Ringwald */ 37cee62800SMatthias Ringwald 38*e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "spp_streamer_client.c" 3915de8206SMilanka Ringwald 4015de8206SMilanka Ringwald /* 4115de8206SMilanka Ringwald * spp_streamer_client.c 4215de8206SMilanka Ringwald */ 4315de8206SMilanka Ringwald 44cee62800SMatthias Ringwald // ***************************************************************************** 45cee62800SMatthias Ringwald /* EXAMPLE_START(spp_streamer_client): Client for SPP Streamer 46cee62800SMatthias Ringwald * 4758d7a529SMilanka Ringwald * @text Note: The SPP Streamer Client scans for and connects to SPP Streamer, 4858d7a529SMilanka Ringwald * and measures the throughput. 49cee62800SMatthias Ringwald */ 50cee62800SMatthias Ringwald // ***************************************************************************** 51cee62800SMatthias Ringwald 52cee62800SMatthias Ringwald #include <stdint.h> 53cee62800SMatthias Ringwald #include <stdio.h> 54cee62800SMatthias Ringwald #include <stdlib.h> 55cee62800SMatthias Ringwald #include <string.h> 56cee62800SMatthias Ringwald #include <inttypes.h> 57cee62800SMatthias Ringwald 58cee62800SMatthias Ringwald #include "btstack.h" 59cee62800SMatthias Ringwald 60cee62800SMatthias Ringwald #define RFCOMM_SERVER_CHANNEL 1 61cee62800SMatthias Ringwald 6283c12399SMatthias Ringwald #define NUM_ROWS 25 6383c12399SMatthias Ringwald #define NUM_COLS 40 6483c12399SMatthias Ringwald 65cee62800SMatthias Ringwald #define TEST_COD 0x1234 66cee62800SMatthias Ringwald 6783c12399SMatthias Ringwald #define TEST_MODE_SEND 1 6883c12399SMatthias Ringwald #define TEST_MODE_RECEIVE 2 6983c12399SMatthias Ringwald #define TEST_MODE_DUPLEX 3 7083c12399SMatthias Ringwald 7183c12399SMatthias Ringwald // configure test mode: send only, receive only, full duplex 7283c12399SMatthias Ringwald #define TEST_MODE TEST_MODE_SEND 7383c12399SMatthias Ringwald 74cee62800SMatthias Ringwald typedef enum { 75cee62800SMatthias Ringwald // SPP 76cee62800SMatthias Ringwald W4_PEER_COD, 77cee62800SMatthias Ringwald W4_SCAN_COMPLETE, 78cee62800SMatthias Ringwald W4_SDP_RESULT, 79cee62800SMatthias Ringwald W4_SDP_COMPLETE, 80cee62800SMatthias Ringwald W4_RFCOMM_CHANNEL, 81cee62800SMatthias Ringwald SENDING, 82cee62800SMatthias Ringwald DONE 83cee62800SMatthias Ringwald } state_t; 84cee62800SMatthias Ringwald 8583c12399SMatthias Ringwald static uint8_t test_data[NUM_ROWS * NUM_COLS]; 8683c12399SMatthias Ringwald static uint16_t spp_test_data_len; 8783c12399SMatthias Ringwald 88cee62800SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration; 89cee62800SMatthias Ringwald 90cee62800SMatthias Ringwald static bd_addr_t peer_addr; 91080ca4eeSMatthias Ringwald static state_t state; 92cee62800SMatthias Ringwald 93cee62800SMatthias Ringwald // SPP 94cee62800SMatthias Ringwald static uint16_t rfcomm_mtu; 95cee62800SMatthias Ringwald static uint16_t rfcomm_cid = 0; 96cee62800SMatthias Ringwald // static uint32_t data_to_send = DATA_VOLUME; 97cee62800SMatthias Ringwald 988cef84f3SMatthias Ringwald /** 998cef84f3SMatthias Ringwald * RFCOMM can make use for ERTM. Due to the need to re-transmit packets, 1008cef84f3SMatthias Ringwald * a large buffer is needed to still get high throughput 1018cef84f3SMatthias Ringwald */ 102278494d6SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE_FOR_RFCOMM 1038cef84f3SMatthias Ringwald static uint8_t ertm_buffer[20000]; 1048cef84f3SMatthias Ringwald static l2cap_ertm_config_t ertm_config = { 1058cef84f3SMatthias Ringwald 0, // ertm mandatory 1068cef84f3SMatthias Ringwald 8, // max transmit 1078cef84f3SMatthias Ringwald 2000, 1088cef84f3SMatthias Ringwald 12000, 1098cef84f3SMatthias Ringwald 1000, // l2cap ertm mtu 1108cef84f3SMatthias Ringwald 8, 1118cef84f3SMatthias Ringwald 8, 1128cef84f3SMatthias Ringwald 0, // No FCS 1138cef84f3SMatthias Ringwald }; 1148cef84f3SMatthias Ringwald static int ertm_buffer_in_use; 1158cef84f3SMatthias Ringwald static void rfcomm_ertm_request_handler(rfcomm_ertm_request_t * ertm_request){ 1168cef84f3SMatthias Ringwald printf("ERTM Buffer requested, buffer in use %u\n", ertm_buffer_in_use); 1178cef84f3SMatthias Ringwald if (ertm_buffer_in_use) return; 1188cef84f3SMatthias Ringwald ertm_buffer_in_use = 1; 1198cef84f3SMatthias Ringwald ertm_request->ertm_config = &ertm_config; 1208cef84f3SMatthias Ringwald ertm_request->ertm_buffer = ertm_buffer; 1218cef84f3SMatthias Ringwald ertm_request->ertm_buffer_size = sizeof(ertm_buffer); 1228cef84f3SMatthias Ringwald } 1238cef84f3SMatthias Ringwald static void rfcomm_ertm_released_handler(uint16_t ertm_id){ 1248cef84f3SMatthias Ringwald printf("ERTM Buffer released, buffer in use %u, ertm_id %x\n", ertm_buffer_in_use, ertm_id); 1258cef84f3SMatthias Ringwald ertm_buffer_in_use = 0; 1268cef84f3SMatthias Ringwald } 1278cef84f3SMatthias Ringwald #endif 128cee62800SMatthias Ringwald 129cee62800SMatthias Ringwald /** 130cee62800SMatthias Ringwald * Find remote peer by COD 131cee62800SMatthias Ringwald */ 132cee62800SMatthias Ringwald #define INQUIRY_INTERVAL 5 133cee62800SMatthias Ringwald static void start_scan(void){ 134cee62800SMatthias Ringwald printf("Starting inquiry scan..\n"); 135cee62800SMatthias Ringwald state = W4_PEER_COD; 136287c758dSMatthias Ringwald gap_inquiry_start(INQUIRY_INTERVAL); 137cee62800SMatthias Ringwald } 138cee62800SMatthias Ringwald static void stop_scan(void){ 139cee62800SMatthias Ringwald printf("Stopping inquiry scan..\n"); 140cee62800SMatthias Ringwald state = W4_SCAN_COMPLETE; 141287c758dSMatthias Ringwald gap_inquiry_stop(); 142cee62800SMatthias Ringwald } 143cee62800SMatthias Ringwald /* 144cee62800SMatthias Ringwald * @section Track throughput 145cee62800SMatthias Ringwald * @text We calculate the throughput by setting a start time and measuring the amount of 146cee62800SMatthias Ringwald * data sent. After a configurable REPORT_INTERVAL_MS, we print the throughput in kB/s 147cee62800SMatthias Ringwald * and reset the counter and start time. 148cee62800SMatthias Ringwald */ 149cee62800SMatthias Ringwald 150cee62800SMatthias Ringwald /* LISTING_START(tracking): Tracking throughput */ 151cee62800SMatthias Ringwald #define REPORT_INTERVAL_MS 3000 152cee62800SMatthias Ringwald static uint32_t test_data_transferred; 153cee62800SMatthias Ringwald static uint32_t test_data_start; 154cee62800SMatthias Ringwald 155cee62800SMatthias Ringwald static void test_reset(void){ 156cee62800SMatthias Ringwald test_data_start = btstack_run_loop_get_time_ms(); 157cee62800SMatthias Ringwald test_data_transferred = 0; 158cee62800SMatthias Ringwald } 159cee62800SMatthias Ringwald 160cee62800SMatthias Ringwald static void test_track_transferred(int bytes_sent){ 161cee62800SMatthias Ringwald test_data_transferred += bytes_sent; 162cee62800SMatthias Ringwald // evaluate 163cee62800SMatthias Ringwald uint32_t now = btstack_run_loop_get_time_ms(); 164cee62800SMatthias Ringwald uint32_t time_passed = now - test_data_start; 165cee62800SMatthias Ringwald if (time_passed < REPORT_INTERVAL_MS) return; 166cee62800SMatthias Ringwald // print speed 167cee62800SMatthias Ringwald int bytes_per_second = test_data_transferred * 1000 / time_passed; 168cee62800SMatthias Ringwald printf("%u bytes -> %u.%03u kB/s\n", (int) test_data_transferred, (int) bytes_per_second / 1000, bytes_per_second % 1000); 169cee62800SMatthias Ringwald 170cee62800SMatthias Ringwald // restart 171cee62800SMatthias Ringwald test_data_start = now; 172cee62800SMatthias Ringwald test_data_transferred = 0; 173cee62800SMatthias Ringwald } 174cee62800SMatthias Ringwald /* LISTING_END(tracking): Tracking throughput */ 175cee62800SMatthias Ringwald 17683c12399SMatthias Ringwald #if (TEST_MODE & TEST_MODE_SEND) 17783c12399SMatthias Ringwald static void spp_create_test_data(void){ 17883c12399SMatthias Ringwald int x,y; 17983c12399SMatthias Ringwald for (y=0;y<NUM_ROWS;y++){ 18083c12399SMatthias Ringwald for (x=0;x<NUM_COLS-2;x++){ 18183c12399SMatthias Ringwald test_data[y*NUM_COLS+x] = '0' + (x % 10); 18283c12399SMatthias Ringwald } 18383c12399SMatthias Ringwald test_data[y*NUM_COLS+NUM_COLS-2] = '\n'; 18483c12399SMatthias Ringwald test_data[y*NUM_COLS+NUM_COLS-1] = '\r'; 18583c12399SMatthias Ringwald } 18683c12399SMatthias Ringwald } 18783c12399SMatthias Ringwald static void spp_send_packet(void){ 18883c12399SMatthias Ringwald rfcomm_send(rfcomm_cid, (uint8_t*) test_data, spp_test_data_len); 18983c12399SMatthias Ringwald test_track_transferred(spp_test_data_len); 19083c12399SMatthias Ringwald rfcomm_request_can_send_now_event(rfcomm_cid); 19183c12399SMatthias Ringwald } 19283c12399SMatthias Ringwald #endif 19383c12399SMatthias Ringwald 194cee62800SMatthias Ringwald /* 195cee62800SMatthias Ringwald * @section Packet Handler 196cee62800SMatthias Ringwald * 197cee62800SMatthias Ringwald * @text The packet handler of the combined example is just the combination of the individual packet handlers. 198cee62800SMatthias Ringwald */ 199cee62800SMatthias Ringwald 200cee62800SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 201cee62800SMatthias Ringwald UNUSED(channel); 202cee62800SMatthias Ringwald 203cee62800SMatthias Ringwald bd_addr_t event_addr; 204cee62800SMatthias Ringwald uint8_t rfcomm_channel_nr; 205cee62800SMatthias Ringwald uint32_t class_of_device; 206cee62800SMatthias Ringwald 207cee62800SMatthias Ringwald switch (packet_type) { 208cee62800SMatthias Ringwald case HCI_EVENT_PACKET: 209cee62800SMatthias Ringwald switch (hci_event_packet_get_type(packet)) { 210cee62800SMatthias Ringwald 211cee62800SMatthias Ringwald case BTSTACK_EVENT_STATE: 212cee62800SMatthias Ringwald if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return; 213cee62800SMatthias Ringwald start_scan(); 214cee62800SMatthias Ringwald break; 215cee62800SMatthias Ringwald 216cee62800SMatthias Ringwald case GAP_EVENT_INQUIRY_RESULT: 2177c03fe59SMatthias Ringwald if (state != W4_PEER_COD) break; 218cee62800SMatthias Ringwald class_of_device = gap_event_inquiry_result_get_class_of_device(packet); 219cee62800SMatthias Ringwald gap_event_inquiry_result_get_bd_addr(packet, event_addr); 220cee62800SMatthias Ringwald if (class_of_device == TEST_COD){ 221cee62800SMatthias Ringwald memcpy(peer_addr, event_addr, 6); 222cee62800SMatthias Ringwald printf("Peer found: %s\n", bd_addr_to_str(peer_addr)); 223cee62800SMatthias Ringwald stop_scan(); 224cee62800SMatthias Ringwald } else { 225cee62800SMatthias Ringwald printf("Device found: %s with COD: 0x%06x\n", bd_addr_to_str(event_addr), (int) class_of_device); 226cee62800SMatthias Ringwald } 227cee62800SMatthias Ringwald break; 228cee62800SMatthias Ringwald 229287c758dSMatthias Ringwald case GAP_EVENT_INQUIRY_COMPLETE: 2307c03fe59SMatthias Ringwald switch (state){ 2317c03fe59SMatthias Ringwald case W4_PEER_COD: 232cee62800SMatthias Ringwald printf("Inquiry complete\n"); 233cee62800SMatthias Ringwald printf("Peer not found, starting scan again\n"); 234cee62800SMatthias Ringwald start_scan(); 235cee62800SMatthias Ringwald break; 2367c03fe59SMatthias Ringwald case W4_SCAN_COMPLETE: 2377c03fe59SMatthias Ringwald printf("Start to connect\n"); 2387c03fe59SMatthias Ringwald state = W4_RFCOMM_CHANNEL; 2397c03fe59SMatthias Ringwald rfcomm_create_channel(packet_handler, peer_addr, RFCOMM_SERVER_CHANNEL, NULL); 2407c03fe59SMatthias Ringwald break; 2417c03fe59SMatthias Ringwald default: 2427c03fe59SMatthias Ringwald break; 2437c03fe59SMatthias Ringwald } 2447c03fe59SMatthias Ringwald if (state == W4_PEER_COD){ 2457c03fe59SMatthias Ringwald } 2467c03fe59SMatthias Ringwald break; 247cee62800SMatthias Ringwald 24883c12399SMatthias Ringwald case HCI_EVENT_PIN_CODE_REQUEST: 24983c12399SMatthias Ringwald // inform about pin code request 25083c12399SMatthias Ringwald printf("Pin code request - using '0000'\n"); 25183c12399SMatthias Ringwald hci_event_pin_code_request_get_bd_addr(packet, event_addr); 25283c12399SMatthias Ringwald gap_pin_code_response(event_addr, "0000"); 25383c12399SMatthias Ringwald break; 25483c12399SMatthias Ringwald 25583c12399SMatthias Ringwald case HCI_EVENT_USER_CONFIRMATION_REQUEST: 25683c12399SMatthias Ringwald // inform about user confirmation request 25783c12399SMatthias Ringwald printf("SSP User Confirmation Request with numeric value '%06"PRIu32"'\n", little_endian_read_32(packet, 8)); 25883c12399SMatthias Ringwald printf("SSP User Confirmation Auto accept\n"); 25983c12399SMatthias Ringwald break; 26083c12399SMatthias Ringwald 26183c12399SMatthias Ringwald case RFCOMM_EVENT_INCOMING_CONNECTION: 26283c12399SMatthias Ringwald // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) 26383c12399SMatthias Ringwald rfcomm_event_incoming_connection_get_bd_addr(packet, event_addr); 26483c12399SMatthias Ringwald rfcomm_channel_nr = rfcomm_event_incoming_connection_get_server_channel(packet); 26583c12399SMatthias Ringwald rfcomm_cid = rfcomm_event_incoming_connection_get_rfcomm_cid(packet); 26683c12399SMatthias Ringwald printf("RFCOMM channel %u requested for %s\n", rfcomm_channel_nr, bd_addr_to_str(event_addr)); 26783c12399SMatthias Ringwald rfcomm_accept_connection(rfcomm_cid); 26883c12399SMatthias Ringwald break; 26983c12399SMatthias Ringwald 27083c12399SMatthias Ringwald case RFCOMM_EVENT_CHANNEL_OPENED: 27183c12399SMatthias Ringwald // data: event(8), len(8), status (8), address (48), server channel(8), rfcomm_cid(16), max frame size(16) 27283c12399SMatthias Ringwald if (rfcomm_event_channel_opened_get_status(packet)) { 27383c12399SMatthias Ringwald printf("RFCOMM channel open failed, status %u\n", rfcomm_event_channel_opened_get_status(packet)); 27483c12399SMatthias Ringwald } else { 27583c12399SMatthias Ringwald rfcomm_cid = rfcomm_event_channel_opened_get_rfcomm_cid(packet); 27683c12399SMatthias Ringwald rfcomm_mtu = rfcomm_event_channel_opened_get_max_frame_size(packet); 27783c12399SMatthias Ringwald printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_cid, rfcomm_mtu); 27883c12399SMatthias Ringwald test_reset(); 27983c12399SMatthias Ringwald 28083c12399SMatthias Ringwald // disable page/inquiry scan to get max performance 28183c12399SMatthias Ringwald gap_discoverable_control(0); 28283c12399SMatthias Ringwald gap_connectable_control(0); 28383c12399SMatthias Ringwald 28483c12399SMatthias Ringwald #if (TEST_MODE & TEST_MODE_SEND) 28583c12399SMatthias Ringwald // configure test data 28683c12399SMatthias Ringwald spp_test_data_len = rfcomm_mtu; 28783c12399SMatthias Ringwald if (spp_test_data_len > sizeof(test_data)){ 28883c12399SMatthias Ringwald spp_test_data_len = sizeof(test_data); 28983c12399SMatthias Ringwald } 29083c12399SMatthias Ringwald spp_create_test_data(); 29183c12399SMatthias Ringwald 29283c12399SMatthias Ringwald // start sending 29383c12399SMatthias Ringwald rfcomm_request_can_send_now_event(rfcomm_cid); 29483c12399SMatthias Ringwald #endif 29583c12399SMatthias Ringwald } 29683c12399SMatthias Ringwald break; 29783c12399SMatthias Ringwald 29883c12399SMatthias Ringwald #if (TEST_MODE & TEST_MODE_SEND) 29983c12399SMatthias Ringwald case RFCOMM_EVENT_CAN_SEND_NOW: 30083c12399SMatthias Ringwald spp_send_packet(); 30183c12399SMatthias Ringwald break; 30283c12399SMatthias Ringwald #endif 30383c12399SMatthias Ringwald 30483c12399SMatthias Ringwald case RFCOMM_EVENT_CHANNEL_CLOSED: 30583c12399SMatthias Ringwald printf("RFCOMM channel closed\n"); 30683c12399SMatthias Ringwald rfcomm_cid = 0; 30783c12399SMatthias Ringwald 30883c12399SMatthias Ringwald // re-enable page/inquiry scan again 30983c12399SMatthias Ringwald gap_discoverable_control(1); 31083c12399SMatthias Ringwald gap_connectable_control(1); 31183c12399SMatthias Ringwald break; 31283c12399SMatthias Ringwald 31383c12399SMatthias Ringwald 31483c12399SMatthias Ringwald 315cee62800SMatthias Ringwald default: 316cee62800SMatthias Ringwald break; 317cee62800SMatthias Ringwald } 318cee62800SMatthias Ringwald break; 319cee62800SMatthias Ringwald 320cee62800SMatthias Ringwald case RFCOMM_DATA_PACKET: 321cee62800SMatthias Ringwald test_track_transferred(size); 3227c03fe59SMatthias Ringwald 323cee62800SMatthias Ringwald #if 0 324cee62800SMatthias Ringwald printf("RCV: '"); 325cee62800SMatthias Ringwald for (i=0;i<size;i++){ 326cee62800SMatthias Ringwald putchar(packet[i]); 327cee62800SMatthias Ringwald } 328cee62800SMatthias Ringwald printf("'\n"); 329cee62800SMatthias Ringwald #endif 330cee62800SMatthias Ringwald break; 331cee62800SMatthias Ringwald 332cee62800SMatthias Ringwald default: 333cee62800SMatthias Ringwald break; 334cee62800SMatthias Ringwald } 335cee62800SMatthias Ringwald } 336cee62800SMatthias Ringwald 337cee62800SMatthias Ringwald /* 338cee62800SMatthias Ringwald * @section Main Application Setup 339cee62800SMatthias Ringwald * 340cee62800SMatthias Ringwald * @text As with the packet and the heartbeat handlers, the combined app setup contains the code from the individual example setups. 341cee62800SMatthias Ringwald */ 342cee62800SMatthias Ringwald 343cee62800SMatthias Ringwald 344cee62800SMatthias Ringwald /* LISTING_START(MainConfiguration): Init L2CAP RFCOMM SDO SM ATT Server and start heartbeat timer */ 345cee62800SMatthias Ringwald int btstack_main(int argc, const char * argv[]); 346cee62800SMatthias Ringwald int btstack_main(int argc, const char * argv[]){ 347cee62800SMatthias Ringwald UNUSED(argc); 348cee62800SMatthias Ringwald (void)argv; 349cee62800SMatthias Ringwald 350cee62800SMatthias Ringwald l2cap_init(); 351cee62800SMatthias Ringwald 352cee62800SMatthias Ringwald rfcomm_init(); 353cee62800SMatthias Ringwald rfcomm_register_service(packet_handler, RFCOMM_SERVER_CHANNEL, 0xffff); 354cee62800SMatthias Ringwald 355278494d6SMatthias Ringwald #ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE_FOR_RFCOMM 3568cef84f3SMatthias Ringwald // setup ERTM management 3578cef84f3SMatthias Ringwald rfcomm_enable_l2cap_ertm(&rfcomm_ertm_request_handler, &rfcomm_ertm_released_handler); 3588cef84f3SMatthias Ringwald #endif 3598cef84f3SMatthias Ringwald 360a4fe6467SMatthias Ringwald // register for HCI events 361a4fe6467SMatthias Ringwald hci_event_callback_registration.callback = &packet_handler; 362a4fe6467SMatthias Ringwald hci_add_event_handler(&hci_event_callback_registration); 363a4fe6467SMatthias Ringwald 364cee62800SMatthias Ringwald // init SDP 365cee62800SMatthias Ringwald gap_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO); 366cee62800SMatthias Ringwald 367cee62800SMatthias Ringwald // turn on! 368cee62800SMatthias Ringwald hci_power_control(HCI_POWER_ON); 369cee62800SMatthias Ringwald 370cee62800SMatthias Ringwald return 0; 371cee62800SMatthias Ringwald } 372cee62800SMatthias Ringwald /* LISTING_END */ 373cee62800SMatthias Ringwald /* EXAMPLE_END */ 374