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