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