xref: /btstack/platform/daemon/example/rfcomm_test.c (revision 2531c97e167e1cae4616c774a6c07906b45ebb44)
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