• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #include <getopt.h>
20 #include <signal.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 
24 #include "btcore/include/bdaddr.h"
25 #include "btcore/include/property.h"
26 #include "osi/include/osi.h"
27 #include "test/suite/support/callbacks.h"
28 #include "test/suite/support/hal.h"
29 
30 static const bt_uuid_t HFP_UUID = {{ 0x00, 0x00, 0x11, 0x1E, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }};
31 static const bt_uuid_t HFP_AG_UUID = {{ 0x00, 0x00, 0x11, 0x1F, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }};
32 
33 const bt_interface_t *bt_interface;
34 
35 bt_bdaddr_t bt_remote_bdaddr;
36 
37 static int f_verbose;
38 static bool discover = false;
39 static bool discoverable = false;
40 static bool bond = false;
41 static bool up = false;
42 static bool get_name = false;
43 static bool set_name = false;
44 static bool sco_listen = false;
45 static bool sco_connect = false;
46 
47 static int timeout_in_sec = 30;
48 static char *bd_name;
49 
50 static struct option long_options[] = {
51   {"bdaddr", required_argument, 0, 0 },
52   {"discover", no_argument, 0, 0 },
53   {"discoverable", no_argument, 0, 0 },
54   {"time", required_argument, 0, 0 },
55   {"bond", no_argument, 0, 0 },
56   {"up", no_argument, 0, 0 },
57   {"verbose", no_argument, 0, 0 },
58   {"get_name", no_argument, 0, 0 },
59   {"set_name", required_argument, 0, 0 },
60   {"sco_listen", no_argument, 0, 0 },
61   {"sco_connect", no_argument, 0, 0 },
62   {0, 0, 0, 0 }
63 };
64 
65 static void usage(const char *name);
66 static bool parse_args(int argc, char **argv);
67 static void sig_handler(int signo);
68 
69 bt_property_t *adapter_get_property(bt_property_type_t type);
70 
main(int argc,char ** argv)71 int main(int argc, char **argv) {
72   if (!parse_args(argc, argv)) {
73     usage(argv[0]);
74   }
75 
76   if (bond && discoverable) {
77     fprintf(stderr, "Can only select either bond or discoverable, not both\n");
78     usage(argv[0]);
79   }
80 
81   if (sco_listen && sco_connect) {
82     fprintf(stderr, "Can only select either sco_listen or sco_connect, not both\n");
83     usage(argv[0]);
84   }
85 
86   if (!bond && !discover && !discoverable && !up && !get_name && !set_name && !sco_listen && !sco_connect) {
87     fprintf(stderr, "Must specify one command\n");
88     usage(argv[0]);
89   }
90 
91   if (signal(SIGINT, sig_handler) == SIG_ERR) {
92     fprintf(stderr, "Will be unable to catch signals\n");
93   }
94 
95   fprintf(stdout, "Bringing up bluetooth adapter\n");
96   if (!hal_open(callbacks_get_adapter_struct())) {
97     fprintf(stderr, "Unable to open Bluetooth HAL.\n");
98     return 1;
99   }
100 
101   if (discover) {
102     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
103     fprintf(stdout, "BT adapter is up\n");
104 
105     fprintf(stdout, "Starting to start discovery\n");
106     CALL_AND_WAIT(bt_interface->start_discovery(), discovery_state_changed);
107     fprintf(stdout, "Started discovery for %d seconds\n", timeout_in_sec);
108 
109     sleep(timeout_in_sec);
110 
111     fprintf(stdout, "Starting to cancel discovery\n");
112     CALL_AND_WAIT(bt_interface->cancel_discovery(), discovery_state_changed);
113     fprintf(stdout, "Cancelled discovery after %d seconds\n", timeout_in_sec);
114   }
115 
116   if (discoverable) {
117     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
118     fprintf(stdout, "BT adapter is up\n");
119 
120     bt_property_t *property = property_new_scan_mode(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
121 
122     int rc = bt_interface->set_adapter_property(property);
123     fprintf(stdout, "Set rc:%d device as discoverable for %d seconds\n", rc, timeout_in_sec);
124 
125     sleep(timeout_in_sec);
126 
127     property_free(property);
128   }
129 
130    if (bond) {
131     if (bdaddr_is_empty(&bt_remote_bdaddr)) {
132       fprintf(stderr, "Must specify a remote device address [ --bdaddr=xx:yy:zz:aa:bb:cc ]\n");
133       exit(1);
134     }
135 
136     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
137     fprintf(stdout, "BT adapter is up\n");
138 
139     int rc = bt_interface->create_bond(&bt_remote_bdaddr, 0 /* UNKNOWN; Currently not documented :( */);
140     fprintf(stdout, "Started bonding:%d for %d seconds\n", rc, timeout_in_sec);
141 
142     sleep(timeout_in_sec);
143   }
144 
145   if (up) {
146     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
147     fprintf(stdout, "BT adapter is up\n");
148 
149     fprintf(stdout, "Waiting for %d seconds\n", timeout_in_sec);
150     sleep(timeout_in_sec);
151   }
152 
153   if (get_name) {
154     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
155     fprintf(stdout, "BT adapter is up\n");
156     int error;
157     CALL_AND_WAIT(error = bt_interface->get_adapter_property(BT_PROPERTY_BDNAME), adapter_properties);
158     if (error != BT_STATUS_SUCCESS) {
159       fprintf(stderr, "Unable to get adapter property\n");
160       exit(1);
161     }
162     bt_property_t *property = adapter_get_property(BT_PROPERTY_BDNAME);
163     const bt_bdname_t *name = property_as_name(property);
164     if (name)
165       printf("Queried bluetooth device name:%s\n", name->name);
166     else
167       printf("No name\n");
168   }
169 
170   if (set_name) {
171     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
172     fprintf(stdout, "BT adapter is up\n");
173 
174     bt_property_t *property = property_new_name(bd_name);
175     printf("Setting bluetooth device name to:%s\n", bd_name);
176     int error;
177     CALL_AND_WAIT(error = bt_interface->set_adapter_property(property), adapter_properties);
178     if (error != BT_STATUS_SUCCESS) {
179       fprintf(stderr, "Unable to set adapter property\n");
180       exit(1);
181     }
182     CALL_AND_WAIT(error = bt_interface->get_adapter_property(BT_PROPERTY_BDNAME), adapter_properties);
183     if (error != BT_STATUS_SUCCESS) {
184       fprintf(stderr, "Unable to get adapter property\n");
185       exit(1);
186     }
187     property_free(property);
188     sleep(timeout_in_sec);
189   }
190 
191   const int app_uid = 0;
192 
193   if (sco_listen) {
194     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
195     fprintf(stdout, "BT adapter is up\n");
196 
197     bt_property_t *property = property_new_scan_mode(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
198     CALL_AND_WAIT(bt_interface->set_adapter_property(property), adapter_properties);
199     property_free(property);
200 
201     const btsock_interface_t *sock = bt_interface->get_profile_interface(BT_PROFILE_SOCKETS_ID);
202 
203     int rfcomm_fd = INVALID_FD;
204     int error = sock->listen(BTSOCK_RFCOMM, "meow", (const uint8_t *)&HFP_AG_UUID, 0, &rfcomm_fd, 0, app_uid);
205     if (error != BT_STATUS_SUCCESS) {
206       fprintf(stderr, "Unable to listen for incoming RFCOMM socket: %d\n", error);
207       exit(1);
208     }
209 
210     int sock_fd = INVALID_FD;
211     error = sock->listen(BTSOCK_SCO, NULL, NULL, 5, &sock_fd, 0, app_uid);
212     if (error != BT_STATUS_SUCCESS) {
213       fprintf(stderr, "Unable to listen for incoming SCO sockets: %d\n", error);
214       exit(1);
215     }
216     fprintf(stdout, "Waiting for incoming SCO connections...\n");
217     sleep(timeout_in_sec);
218   }
219 
220   if (sco_connect) {
221     if (bdaddr_is_empty(&bt_remote_bdaddr)) {
222       fprintf(stderr, "Must specify a remote device address [ --bdaddr=xx:yy:zz:aa:bb:cc ]\n");
223       exit(1);
224     }
225 
226     CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
227     fprintf(stdout, "BT adapter is up\n");
228 
229     const btsock_interface_t *sock = bt_interface->get_profile_interface(BT_PROFILE_SOCKETS_ID);
230 
231     int rfcomm_fd = INVALID_FD;
232     int error = sock->connect(&bt_remote_bdaddr, BTSOCK_RFCOMM, (const uint8_t *)&HFP_AG_UUID, 0, &rfcomm_fd, 0, app_uid);
233     if (error != BT_STATUS_SUCCESS) {
234       fprintf(stderr, "Unable to connect to RFCOMM socket: %d.\n", error);
235       exit(1);
236     }
237 
238     WAIT(acl_state_changed);
239 
240     fprintf(stdout, "Establishing SCO connection...\n");
241 
242     int sock_fd = INVALID_FD;
243     error = sock->connect(&bt_remote_bdaddr, BTSOCK_SCO, NULL, 5, &sock_fd, 0, app_uid);
244     if (error != BT_STATUS_SUCCESS) {
245       fprintf(stderr, "Unable to connect to SCO socket: %d.\n", error);
246       exit(1);
247     }
248     sleep(timeout_in_sec);
249   }
250 
251   CALL_AND_WAIT(bt_interface->disable(), adapter_state_changed);
252   fprintf(stdout, "BT adapter is down\n");
253 }
254 
sig_handler(int signo)255 static void sig_handler(int signo) {
256   if (signo == SIGINT) {
257     fprintf(stderr, "Received SIGINT\n");
258     CALL_AND_WAIT(bt_interface->disable(), adapter_state_changed);
259     fprintf(stderr, "BT adapter is down\n");
260     exit(1);
261   }
262 }
263 
usage(const char * name)264 static void usage(const char *name) {
265   fprintf(stderr, "Usage: %s [--bond|--discover|--discoverable|--up|--sco_listen|--sco_connect] [--bdaddr=<bdaddr>] [--time=<time_in_sec>] --verbose\n", name);
266   fprintf(stderr, "     bond: Discover actively advertising devices\n");
267   fprintf(stderr, "     discover: Discover actively advertising devices\n");
268   fprintf(stderr, "     discoverable: Set into a connectable and discoverable mode\n");
269   fprintf(stderr, "     up: Only bring up stack\n");
270   fprintf(stderr, "     sco_listen: Listen for incoming SCO connections\n");
271   fprintf(stderr, "     sco_connect: Establish a SCO connection with another device\n");
272   fprintf(stderr, "     time: Time to hold in the specified mode\n");
273   exit(1);
274 }
275 
parse_args(int argc,char ** argv)276 static bool parse_args(int argc, char **argv) {
277   while (1) {
278     int option_index = 0;
279     int c = getopt_long_only(argc, argv, "", long_options, &option_index);
280     if (c != 0)
281       break;
282 
283     switch (c) {
284       case 0:
285         if (option_index == 0) {
286           if (!string_to_bdaddr(optarg, &bt_remote_bdaddr)) {
287             return false;
288           }
289         }
290         if (option_index == 1) {
291           discover = true;
292         }
293         if (option_index == 2) {
294           discoverable = true;
295         }
296         if (option_index == 3) {
297           timeout_in_sec = atoi(optarg);
298         }
299         if (option_index == 4) {
300           bond  = true;
301         }
302         if (option_index == 5) {
303           up = true;
304         }
305         if (option_index == 6) {
306           f_verbose++;
307         }
308         if (option_index == 7) {
309           get_name = true;
310         }
311         if (option_index == 8) {
312           bd_name = (char *)optarg;
313           set_name = true;
314         }
315         if (option_index == 9) {
316           sco_listen = true;
317         }
318         if (option_index == 10) {
319           sco_connect = true;
320         }
321         break;
322 
323       default:
324         fprintf(stderr, "?? getopt returned character code 0%o ??\n", c);
325     }
326   }
327 
328   if (optind < argc) {
329     fprintf(stderr, "non-option ARGV-elements: ");
330     while (optind < argc)
331       fprintf(stderr, "%s ", argv[optind++]);
332     fprintf(stderr, "\n");
333     return false;
334   }
335   return true;
336 }
337