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