Home | History | Annotate | Download | only in bdtool
      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