1*2531c97eSMatthias Ringwald /* 2*2531c97eSMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 3*2531c97eSMatthias Ringwald * 4*2531c97eSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*2531c97eSMatthias Ringwald * modification, are permitted provided that the following conditions 6*2531c97eSMatthias Ringwald * are met: 7*2531c97eSMatthias Ringwald * 8*2531c97eSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*2531c97eSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*2531c97eSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*2531c97eSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*2531c97eSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*2531c97eSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*2531c97eSMatthias Ringwald * contributors may be used to endorse or promote products derived 15*2531c97eSMatthias Ringwald * from this software without specific prior written permission. 16*2531c97eSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*2531c97eSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*2531c97eSMatthias Ringwald * monetary gain. 19*2531c97eSMatthias Ringwald * 20*2531c97eSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*2531c97eSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*2531c97eSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*2531c97eSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24*2531c97eSMatthias Ringwald * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*2531c97eSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*2531c97eSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*2531c97eSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*2531c97eSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*2531c97eSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*2531c97eSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*2531c97eSMatthias Ringwald * SUCH DAMAGE. 32*2531c97eSMatthias Ringwald * 33*2531c97eSMatthias Ringwald * Please inquire about commercial licensing options at 34*2531c97eSMatthias Ringwald * [email protected] 35*2531c97eSMatthias Ringwald * 36*2531c97eSMatthias Ringwald */ 37*2531c97eSMatthias Ringwald 38*2531c97eSMatthias Ringwald /* 39*2531c97eSMatthias Ringwald * rfcomm_echo.c 40*2531c97eSMatthias Ringwald */ 41*2531c97eSMatthias Ringwald 42*2531c97eSMatthias Ringwald #include <unistd.h> 43*2531c97eSMatthias Ringwald #include <stdio.h> 44*2531c97eSMatthias Ringwald #include <stdlib.h> 45*2531c97eSMatthias Ringwald #include <strings.h> 46*2531c97eSMatthias Ringwald #include <errno.h> 47*2531c97eSMatthias Ringwald #include <string.h> 48*2531c97eSMatthias Ringwald #include <fcntl.h> 49*2531c97eSMatthias Ringwald #include <sys/types.h> 50*2531c97eSMatthias Ringwald #include <sys/stat.h> 51*2531c97eSMatthias Ringwald 52*2531c97eSMatthias Ringwald #include "btstack_client.h" 53*2531c97eSMatthias Ringwald #include "btstack_run_loop_posix.h" 54*2531c97eSMatthias Ringwald #include "classic/sdp_util.h" 55*2531c97eSMatthias Ringwald 56*2531c97eSMatthias Ringwald #define NUM_ROWS 25 57*2531c97eSMatthias Ringwald #define NUM_COLS 80 58*2531c97eSMatthias Ringwald 59*2531c97eSMatthias Ringwald // input from command line arguments 60*2531c97eSMatthias Ringwald bd_addr_t addr = { }; 61*2531c97eSMatthias Ringwald uint16_t con_handle; 62*2531c97eSMatthias Ringwald char pin[17]; 63*2531c97eSMatthias Ringwald int counter = 0; 64*2531c97eSMatthias Ringwald uint16_t rfcomm_channel_id = 0; 65*2531c97eSMatthias Ringwald uint16_t mtu = 0; 66*2531c97eSMatthias Ringwald static uint8_t spp_service_buffer[150]; 67*2531c97eSMatthias Ringwald uint8_t test_data[NUM_ROWS * NUM_COLS + 1]; 68*2531c97eSMatthias Ringwald 69*2531c97eSMatthias Ringwald void create_test_data(void){ 70*2531c97eSMatthias Ringwald int x,y; 71*2531c97eSMatthias Ringwald for (y=0;y<NUM_ROWS;y++){ 72*2531c97eSMatthias Ringwald for (x=0;x<NUM_COLS-2;x++){ 73*2531c97eSMatthias Ringwald test_data[y*NUM_COLS+x] = '0' + (x % 10); 74*2531c97eSMatthias Ringwald } 75*2531c97eSMatthias Ringwald test_data[y*NUM_COLS+NUM_COLS-2] = '\n'; 76*2531c97eSMatthias Ringwald test_data[y*NUM_COLS+NUM_COLS-1] = '\r'; 77*2531c97eSMatthias Ringwald } 78*2531c97eSMatthias Ringwald test_data[NUM_COLS*NUM_ROWS] = 0; 79*2531c97eSMatthias Ringwald } 80*2531c97eSMatthias Ringwald 81*2531c97eSMatthias Ringwald void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 82*2531c97eSMatthias Ringwald bd_addr_t event_addr; 83*2531c97eSMatthias Ringwald uint16_t rfcomm_channel_nr; 84*2531c97eSMatthias Ringwald 85*2531c97eSMatthias Ringwald switch (packet_type) { 86*2531c97eSMatthias Ringwald 87*2531c97eSMatthias Ringwald case RFCOMM_DATA_PACKET: 88*2531c97eSMatthias Ringwald printf("Received RFCOMM data on channel id %u, size %u\n", channel, size); 89*2531c97eSMatthias Ringwald printf_hexdump(packet, size); 90*2531c97eSMatthias Ringwald bt_send_rfcomm(channel, packet, size); 91*2531c97eSMatthias Ringwald break; 92*2531c97eSMatthias Ringwald 93*2531c97eSMatthias Ringwald case HCI_EVENT_PACKET: 94*2531c97eSMatthias Ringwald switch (packet[0]) { 95*2531c97eSMatthias Ringwald 96*2531c97eSMatthias Ringwald case BTSTACK_EVENT_POWERON_FAILED: 97*2531c97eSMatthias Ringwald // handle HCI init failure 98*2531c97eSMatthias Ringwald printf("HCI Init failed - make sure you have turned off Bluetooth in the System Settings\n"); 99*2531c97eSMatthias Ringwald exit(1); 100*2531c97eSMatthias Ringwald break; 101*2531c97eSMatthias Ringwald 102*2531c97eSMatthias Ringwald case BTSTACK_EVENT_STATE: 103*2531c97eSMatthias Ringwald // bt stack activated, get started 104*2531c97eSMatthias Ringwald if (packet[2] == HCI_STATE_WORKING) { 105*2531c97eSMatthias Ringwald // get persistent RFCOMM channel 106*2531c97eSMatthias Ringwald printf("HCI_STATE_WORKING\n"); 107*2531c97eSMatthias Ringwald bt_send_cmd(&rfcomm_persistent_channel_for_service_cmd, "ch.ringwald.btstack.rfcomm_test"); 108*2531c97eSMatthias Ringwald } 109*2531c97eSMatthias Ringwald break; 110*2531c97eSMatthias Ringwald 111*2531c97eSMatthias Ringwald case RFCOMM_EVENT_PERSISTENT_CHANNEL: 112*2531c97eSMatthias Ringwald rfcomm_channel_nr = packet[3]; 113*2531c97eSMatthias Ringwald printf("RFCOMM channel %u was assigned by BTdaemon\n", rfcomm_channel_nr); 114*2531c97eSMatthias Ringwald bt_send_cmd(&rfcomm_register_service_cmd, rfcomm_channel_nr, 0xffff); // reserved channel, mtu limited by l2cap 115*2531c97eSMatthias Ringwald break; 116*2531c97eSMatthias Ringwald 117*2531c97eSMatthias Ringwald case RFCOMM_EVENT_SERVICE_REGISTERED: 118*2531c97eSMatthias Ringwald printf("RFCOMM_EVENT_SERVICE_REGISTERED\n"); 119*2531c97eSMatthias Ringwald rfcomm_channel_nr = packet[3]; 120*2531c97eSMatthias Ringwald // register SDP for our SPP 121*2531c97eSMatthias Ringwald sdp_create_spp_service((uint8_t*) spp_service_buffer, 0x10001, rfcomm_channel_nr, "RFCOMM Test"); 122*2531c97eSMatthias Ringwald bt_send_cmd(&sdp_register_service_record_cmd, spp_service_buffer); 123*2531c97eSMatthias Ringwald bt_send_cmd(&btstack_set_discoverable, 1); 124*2531c97eSMatthias Ringwald break; 125*2531c97eSMatthias Ringwald 126*2531c97eSMatthias Ringwald case RFCOMM_EVENT_CREDITS: 127*2531c97eSMatthias Ringwald sprintf((char*)test_data, "\n\r\n\r-> %09u <- ", counter++); 128*2531c97eSMatthias Ringwald bt_send_rfcomm(rfcomm_channel_id, test_data, mtu); 129*2531c97eSMatthias Ringwald break; 130*2531c97eSMatthias Ringwald 131*2531c97eSMatthias Ringwald case HCI_EVENT_PIN_CODE_REQUEST: 132*2531c97eSMatthias Ringwald // inform about pin code request 133*2531c97eSMatthias Ringwald printf("Using PIN 0000\n"); 134*2531c97eSMatthias Ringwald reverse_bd_addr(&packet[2], 135*2531c97eSMatthias Ringwald event_addr); 136*2531c97eSMatthias Ringwald bt_send_cmd(&hci_pin_code_request_reply, &event_addr, 4, "0000"); 137*2531c97eSMatthias Ringwald break; 138*2531c97eSMatthias Ringwald 139*2531c97eSMatthias Ringwald case RFCOMM_EVENT_INCOMING_CONNECTION: 140*2531c97eSMatthias Ringwald // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16) 141*2531c97eSMatthias Ringwald reverse_bd_addr(&packet[2], 142*2531c97eSMatthias Ringwald event_addr); 143*2531c97eSMatthias Ringwald rfcomm_channel_nr = packet[8]; 144*2531c97eSMatthias Ringwald rfcomm_channel_id = little_endian_read_16(packet, 9); 145*2531c97eSMatthias Ringwald printf("RFCOMM channel %u requested for %s\n", rfcomm_channel_nr, bd_addr_to_str(event_addr)); 146*2531c97eSMatthias Ringwald bt_send_cmd(&rfcomm_accept_connection_cmd, rfcomm_channel_id); 147*2531c97eSMatthias Ringwald break; 148*2531c97eSMatthias Ringwald 149*2531c97eSMatthias Ringwald case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: 150*2531c97eSMatthias Ringwald // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) 151*2531c97eSMatthias Ringwald if (packet[2]) { 152*2531c97eSMatthias Ringwald printf("RFCOMM channel open failed, status %u\n", packet[2]); 153*2531c97eSMatthias Ringwald } else { 154*2531c97eSMatthias Ringwald // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16) 155*2531c97eSMatthias Ringwald rfcomm_channel_id = little_endian_read_16(packet, 12); 156*2531c97eSMatthias Ringwald mtu = little_endian_read_16(packet, 14); 157*2531c97eSMatthias Ringwald 158*2531c97eSMatthias Ringwald printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_channel_id, mtu); 159*2531c97eSMatthias Ringwald } 160*2531c97eSMatthias Ringwald break; 161*2531c97eSMatthias Ringwald 162*2531c97eSMatthias Ringwald case HCI_EVENT_DISCONNECTION_COMPLETE: 163*2531c97eSMatthias Ringwald // connection closed -> quit test app 164*2531c97eSMatthias Ringwald printf("Basebank connection closed\n"); 165*2531c97eSMatthias Ringwald break; 166*2531c97eSMatthias Ringwald 167*2531c97eSMatthias Ringwald default: 168*2531c97eSMatthias Ringwald break; 169*2531c97eSMatthias Ringwald } 170*2531c97eSMatthias Ringwald break; 171*2531c97eSMatthias Ringwald default: 172*2531c97eSMatthias Ringwald break; 173*2531c97eSMatthias Ringwald } 174*2531c97eSMatthias Ringwald } 175*2531c97eSMatthias Ringwald 176*2531c97eSMatthias Ringwald 177*2531c97eSMatthias Ringwald int main (int argc, const char * argv[]){ 178*2531c97eSMatthias Ringwald 179*2531c97eSMatthias Ringwald create_test_data(); 180*2531c97eSMatthias Ringwald printf("created test data: \n%s\n", test_data); 181*2531c97eSMatthias Ringwald 182*2531c97eSMatthias Ringwald btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 183*2531c97eSMatthias Ringwald int err = bt_open(); 184*2531c97eSMatthias Ringwald if (err) { 185*2531c97eSMatthias Ringwald fprintf(stderr,"Failed to open connection to BTdaemon, err %d\n",err); 186*2531c97eSMatthias Ringwald return 1; 187*2531c97eSMatthias Ringwald } 188*2531c97eSMatthias Ringwald bt_register_packet_handler(packet_handler); 189*2531c97eSMatthias Ringwald 190*2531c97eSMatthias Ringwald bt_send_cmd(&btstack_set_power_mode, HCI_POWER_ON ); 191*2531c97eSMatthias Ringwald btstack_run_loop_execute(); 192*2531c97eSMatthias Ringwald bt_close(); 193*2531c97eSMatthias Ringwald return 0; 194*2531c97eSMatthias Ringwald } 195