1bcff2d91STakanori Watanabe /* 2bcff2d91STakanori Watanabe * le.c 3bcff2d91STakanori Watanabe * 4bcff2d91STakanori Watanabe * Copyright (c) 2015 Takanori Watanabe <takawata@freebsd.org> 5bcff2d91STakanori Watanabe * All rights reserved. 6bcff2d91STakanori Watanabe * 7bcff2d91STakanori Watanabe * Redistribution and use in source and binary forms, with or without 8bcff2d91STakanori Watanabe * modification, are permitted provided that the following conditions 9bcff2d91STakanori Watanabe * are met: 10bcff2d91STakanori Watanabe * 1. Redistributions of source code must retain the above copyright 11bcff2d91STakanori Watanabe * notice, this list of conditions and the following disclaimer. 12bcff2d91STakanori Watanabe * 2. Redistributions in binary form must reproduce the above copyright 13bcff2d91STakanori Watanabe * notice, this list of conditions and the following disclaimer in the 14bcff2d91STakanori Watanabe * documentation and/or other materials provided with the distribution. 15bcff2d91STakanori Watanabe * 16bcff2d91STakanori Watanabe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17bcff2d91STakanori Watanabe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18bcff2d91STakanori Watanabe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19bcff2d91STakanori Watanabe * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20bcff2d91STakanori Watanabe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21bcff2d91STakanori Watanabe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22bcff2d91STakanori Watanabe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23bcff2d91STakanori Watanabe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24bcff2d91STakanori Watanabe * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25bcff2d91STakanori Watanabe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26bcff2d91STakanori Watanabe * SUCH DAMAGE. 27bcff2d91STakanori Watanabe * 28bcff2d91STakanori Watanabe * $Id: hccontrol.c,v 1.5 2003/09/05 00:38:24 max Exp $ 29bcff2d91STakanori Watanabe * $FreeBSD$ 30bcff2d91STakanori Watanabe */ 31bcff2d91STakanori Watanabe 32bcff2d91STakanori Watanabe #include <sys/types.h> 33bcff2d91STakanori Watanabe #include <sys/ioctl.h> 34bcff2d91STakanori Watanabe #include <sys/sysctl.h> 35bcff2d91STakanori Watanabe #include <sys/select.h> 36bcff2d91STakanori Watanabe #include <assert.h> 378907f744SAlan Somers #include <bitstring.h> 38bcff2d91STakanori Watanabe #include <err.h> 39bcff2d91STakanori Watanabe #include <errno.h> 40bcff2d91STakanori Watanabe #include <netgraph/ng_message.h> 41bcff2d91STakanori Watanabe #include <errno.h> 42bcff2d91STakanori Watanabe #include <stdio.h> 43bcff2d91STakanori Watanabe #include <stdlib.h> 44bcff2d91STakanori Watanabe #include <string.h> 45bcff2d91STakanori Watanabe #include <unistd.h> 464cae2db2STakanori Watanabe #include <stdint.h> 47bcff2d91STakanori Watanabe #define L2CAP_SOCKET_CHECKED 48bcff2d91STakanori Watanabe #include <bluetooth.h> 49bcff2d91STakanori Watanabe #include "hccontrol.h" 509c3471faSMarcelo Araujo 51bcff2d91STakanori Watanabe static int le_set_scan_param(int s, int argc, char *argv[]); 52bcff2d91STakanori Watanabe static int le_set_scan_enable(int s, int argc, char *argv[]); 53bcff2d91STakanori Watanabe static int parse_param(int argc, char *argv[], char *buf, int *len); 54bcff2d91STakanori Watanabe static int le_set_scan_response(int s, int argc, char *argv[]); 55*21eefd31SHans Petter Selasky static int le_read_supported_states(int s, int argc, char *argv[]); 56bcff2d91STakanori Watanabe static int le_read_local_supported_features(int s, int argc ,char *argv[]); 57bcff2d91STakanori Watanabe static int set_le_event_mask(int s, uint64_t mask); 58bcff2d91STakanori Watanabe static int set_event_mask(int s, uint64_t mask); 59bcff2d91STakanori Watanabe static int le_enable(int s, int argc, char *argv[]); 60bcff2d91STakanori Watanabe 619c3471faSMarcelo Araujo static int 629c3471faSMarcelo Araujo le_set_scan_param(int s, int argc, char *argv[]) 63bcff2d91STakanori Watanabe { 64bcff2d91STakanori Watanabe int type; 65bcff2d91STakanori Watanabe int interval; 66bcff2d91STakanori Watanabe int window; 67bcff2d91STakanori Watanabe int adrtype; 68bcff2d91STakanori Watanabe int policy; 699c3471faSMarcelo Araujo int e, n; 70bcff2d91STakanori Watanabe 71bcff2d91STakanori Watanabe ng_hci_le_set_scan_parameters_cp cp; 72bcff2d91STakanori Watanabe ng_hci_le_set_scan_parameters_rp rp; 73bcff2d91STakanori Watanabe 749c3471faSMarcelo Araujo if (argc != 5) 75bcff2d91STakanori Watanabe return USAGE; 76bcff2d91STakanori Watanabe 779c3471faSMarcelo Araujo if (strcmp(argv[0], "active") == 0) 78bcff2d91STakanori Watanabe type = 1; 799c3471faSMarcelo Araujo else if (strcmp(argv[0], "passive") == 0) 80bcff2d91STakanori Watanabe type = 0; 819c3471faSMarcelo Araujo else 82bcff2d91STakanori Watanabe return USAGE; 83bcff2d91STakanori Watanabe 84bcff2d91STakanori Watanabe interval = (int)(atof(argv[1])/0.625); 85bcff2d91STakanori Watanabe interval = (interval < 4)? 4: interval; 86bcff2d91STakanori Watanabe window = (int)(atof(argv[2])/0.625); 87bcff2d91STakanori Watanabe window = (window < 4) ? 4 : interval; 88bcff2d91STakanori Watanabe 899c3471faSMarcelo Araujo if (strcmp(argv[3], "public") == 0) 90bcff2d91STakanori Watanabe adrtype = 0; 9105e526fbSTakanori Watanabe else if (strcmp(argv[3], "random") == 0) 92bcff2d91STakanori Watanabe adrtype = 1; 939c3471faSMarcelo Araujo else 94bcff2d91STakanori Watanabe return USAGE; 95bcff2d91STakanori Watanabe 969c3471faSMarcelo Araujo if (strcmp(argv[4], "all") == 0) 97bcff2d91STakanori Watanabe policy = 0; 989c3471faSMarcelo Araujo else if (strcmp(argv[4], "whitelist") == 0) 99bcff2d91STakanori Watanabe policy = 1; 1009c3471faSMarcelo Araujo else 101bcff2d91STakanori Watanabe return USAGE; 102bcff2d91STakanori Watanabe 103bcff2d91STakanori Watanabe cp.le_scan_type = type; 104bcff2d91STakanori Watanabe cp.le_scan_interval = interval; 105bcff2d91STakanori Watanabe cp.own_address_type = adrtype; 106bcff2d91STakanori Watanabe cp.le_scan_window = window; 107bcff2d91STakanori Watanabe cp.scanning_filter_policy = policy; 108bcff2d91STakanori Watanabe n = sizeof(rp); 109bcff2d91STakanori Watanabe e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 110bcff2d91STakanori Watanabe NG_HCI_OCF_LE_SET_SCAN_PARAMETERS), 111bcff2d91STakanori Watanabe (void *)&cp, sizeof(cp), (void *)&rp, &n); 112bcff2d91STakanori Watanabe 113bcff2d91STakanori Watanabe return 0; 114bcff2d91STakanori Watanabe } 115bcff2d91STakanori Watanabe 1169c3471faSMarcelo Araujo static int 1179c3471faSMarcelo Araujo le_set_scan_enable(int s, int argc, char *argv[]) 118bcff2d91STakanori Watanabe { 119bcff2d91STakanori Watanabe ng_hci_le_set_scan_enable_cp cp; 120bcff2d91STakanori Watanabe ng_hci_le_set_scan_enable_rp rp; 121bcff2d91STakanori Watanabe int e, n, enable = 0; 122bcff2d91STakanori Watanabe 123bcff2d91STakanori Watanabe if (argc != 1) 124bcff2d91STakanori Watanabe return USAGE; 125bcff2d91STakanori Watanabe 1269c3471faSMarcelo Araujo if (strcmp(argv[0], "enable") == 0) 127bcff2d91STakanori Watanabe enable = 1; 1289c3471faSMarcelo Araujo else if (strcmp(argv[0], "disable") != 0) 129bcff2d91STakanori Watanabe return USAGE; 1309c3471faSMarcelo Araujo 131bcff2d91STakanori Watanabe n = sizeof(rp); 132bcff2d91STakanori Watanabe cp.le_scan_enable = enable; 133bcff2d91STakanori Watanabe cp.filter_duplicates = 0; 134bcff2d91STakanori Watanabe e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 135bcff2d91STakanori Watanabe NG_HCI_OCF_LE_SET_SCAN_ENABLE), 136bcff2d91STakanori Watanabe (void *)&cp, sizeof(cp), (void *)&rp, &n); 137bcff2d91STakanori Watanabe 1389c3471faSMarcelo Araujo if (e != 0 || rp.status != 0) 139bcff2d91STakanori Watanabe return ERROR; 140bcff2d91STakanori Watanabe 1419c3471faSMarcelo Araujo return OK; 142bcff2d91STakanori Watanabe } 1439c3471faSMarcelo Araujo 1449c3471faSMarcelo Araujo static int 1459c3471faSMarcelo Araujo parse_param(int argc, char *argv[], char *buf, int *len) 146bcff2d91STakanori Watanabe { 147bcff2d91STakanori Watanabe char *buflast = buf + (*len); 148bcff2d91STakanori Watanabe char *curbuf = buf; 149bcff2d91STakanori Watanabe char *token,*lenpos; 150bcff2d91STakanori Watanabe int ch; 151bcff2d91STakanori Watanabe int datalen; 152bcff2d91STakanori Watanabe uint16_t value; 153bcff2d91STakanori Watanabe optreset = 1; 154bcff2d91STakanori Watanabe optind = 0; 155bcff2d91STakanori Watanabe while ((ch = getopt(argc, argv , "n:f:u:")) != -1) { 156bcff2d91STakanori Watanabe switch(ch){ 157bcff2d91STakanori Watanabe case 'n': 158bcff2d91STakanori Watanabe datalen = strlen(optarg); 1599c3471faSMarcelo Araujo if ((curbuf + datalen + 2) >= buflast) 160bcff2d91STakanori Watanabe goto done; 161bcff2d91STakanori Watanabe curbuf[0] = datalen + 1; 162bcff2d91STakanori Watanabe curbuf[1] = 8; 163bcff2d91STakanori Watanabe curbuf += 2; 164bcff2d91STakanori Watanabe memcpy(curbuf, optarg, datalen); 165bcff2d91STakanori Watanabe curbuf += datalen; 166bcff2d91STakanori Watanabe break; 167bcff2d91STakanori Watanabe case 'f': 1689c3471faSMarcelo Araujo if (curbuf+3 > buflast) 169bcff2d91STakanori Watanabe goto done; 170bcff2d91STakanori Watanabe curbuf[0] = 2; 171bcff2d91STakanori Watanabe curbuf[1] = 1; 172bcff2d91STakanori Watanabe curbuf[2] = atoi(optarg); 173bcff2d91STakanori Watanabe curbuf += 3; 174bcff2d91STakanori Watanabe break; 175bcff2d91STakanori Watanabe case 'u': 176bcff2d91STakanori Watanabe lenpos = buf; 177bcff2d91STakanori Watanabe if ((buf+2) >= buflast) 178bcff2d91STakanori Watanabe goto done; 179bcff2d91STakanori Watanabe curbuf[1] = 2; 180bcff2d91STakanori Watanabe *lenpos = 1; 181bcff2d91STakanori Watanabe curbuf += 2; 182bcff2d91STakanori Watanabe while ((token = strsep(&optarg, ",")) != NULL) { 183bcff2d91STakanori Watanabe value = strtol(token, NULL, 16); 184bcff2d91STakanori Watanabe if ((curbuf+2) >= buflast) 185bcff2d91STakanori Watanabe break; 186bcff2d91STakanori Watanabe curbuf[0] = value &0xff; 187bcff2d91STakanori Watanabe curbuf[1] = (value>>8)&0xff; 188bcff2d91STakanori Watanabe curbuf += 2; 189bcff2d91STakanori Watanabe } 190bcff2d91STakanori Watanabe 191bcff2d91STakanori Watanabe } 192bcff2d91STakanori Watanabe } 193bcff2d91STakanori Watanabe done: 194bcff2d91STakanori Watanabe *len = curbuf - buf; 195bcff2d91STakanori Watanabe 196bcff2d91STakanori Watanabe return OK; 197bcff2d91STakanori Watanabe } 198bcff2d91STakanori Watanabe 1999c3471faSMarcelo Araujo static int 2009c3471faSMarcelo Araujo le_set_scan_response(int s, int argc, char *argv[]) 201bcff2d91STakanori Watanabe { 202bcff2d91STakanori Watanabe ng_hci_le_set_scan_response_data_cp cp; 203bcff2d91STakanori Watanabe ng_hci_le_set_scan_response_data_rp rp; 204bcff2d91STakanori Watanabe int n; 205bcff2d91STakanori Watanabe int e; 206bcff2d91STakanori Watanabe int len; 207bcff2d91STakanori Watanabe char buf[NG_HCI_ADVERTISING_DATA_SIZE]; 2089c3471faSMarcelo Araujo 209bcff2d91STakanori Watanabe len = sizeof(buf); 210bcff2d91STakanori Watanabe parse_param(argc, argv, buf, &len); 211bcff2d91STakanori Watanabe memset(cp.scan_response_data, 0, sizeof(cp.scan_response_data)); 212bcff2d91STakanori Watanabe cp.scan_response_data_length = len; 213bcff2d91STakanori Watanabe memcpy(cp.scan_response_data, buf, len); 214bcff2d91STakanori Watanabe n = sizeof(rp); 215bcff2d91STakanori Watanabe e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 216bcff2d91STakanori Watanabe NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA), 217bcff2d91STakanori Watanabe (void *)&cp, sizeof(cp), (void *)&rp, &n); 218bcff2d91STakanori Watanabe 2199c3471faSMarcelo Araujo printf("SET SCAN RESPONSE %d %d %d\n", e, rp.status, n); 220bcff2d91STakanori Watanabe 221bcff2d91STakanori Watanabe return OK; 222bcff2d91STakanori Watanabe } 223bcff2d91STakanori Watanabe 2249c3471faSMarcelo Araujo static int 2259c3471faSMarcelo Araujo le_read_local_supported_features(int s, int argc ,char *argv[]) 226bcff2d91STakanori Watanabe { 227bcff2d91STakanori Watanabe ng_hci_le_read_local_supported_features_rp rp; 228bcff2d91STakanori Watanabe int n = sizeof(rp); 2299c3471faSMarcelo Araujo 230ea011491SHans Petter Selasky union { 231ea011491SHans Petter Selasky uint64_t raw; 232ea011491SHans Petter Selasky uint8_t octets[8]; 233ea011491SHans Petter Selasky } le_features; 234ea011491SHans Petter Selasky 235ea011491SHans Petter Selasky char buffer[2048]; 236ea011491SHans Petter Selasky 237ea011491SHans Petter Selasky if (hci_simple_request(s, 238bcff2d91STakanori Watanabe NG_HCI_OPCODE(NG_HCI_OGF_LE, 239bcff2d91STakanori Watanabe NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES), 240ea011491SHans Petter Selasky (void *)&rp, &n) == ERROR) 241ea011491SHans Petter Selasky return (ERROR); 2429c3471faSMarcelo Araujo 243ea011491SHans Petter Selasky if (rp.status != 0x00) { 244ea011491SHans Petter Selasky fprintf(stdout, "Status: %s [%#02x]\n", 245ea011491SHans Petter Selasky hci_status2str(rp.status), rp.status); 246ea011491SHans Petter Selasky return (FAILED); 247ea011491SHans Petter Selasky } 248bcff2d91STakanori Watanabe 249ea011491SHans Petter Selasky le_features.raw = rp.le_features; 250ea011491SHans Petter Selasky 251ea011491SHans Petter Selasky fprintf(stdout, "LE Features: "); 252ea011491SHans Petter Selasky for(int i = 0; i < 8; i++) 253ea011491SHans Petter Selasky fprintf(stdout, " %#02x", le_features.octets[i]); 254ea011491SHans Petter Selasky fprintf(stdout, "\n%s\n", hci_le_features2str(le_features.octets, 255ea011491SHans Petter Selasky buffer, sizeof(buffer))); 256ea011491SHans Petter Selasky fprintf(stdout, "\n"); 257ea011491SHans Petter Selasky 258ea011491SHans Petter Selasky return OK; 259bcff2d91STakanori Watanabe } 2609c3471faSMarcelo Araujo 2619c3471faSMarcelo Araujo static int 262*21eefd31SHans Petter Selasky le_read_supported_states(int s, int argc, char *argv[]) 263bcff2d91STakanori Watanabe { 264*21eefd31SHans Petter Selasky ng_hci_le_read_supported_states_rp rp; 265bcff2d91STakanori Watanabe int n = sizeof(rp); 2669c3471faSMarcelo Araujo 267*21eefd31SHans Petter Selasky if (hci_simple_request(s, NG_HCI_OPCODE( 2689c3471faSMarcelo Araujo NG_HCI_OGF_LE, 269*21eefd31SHans Petter Selasky NG_HCI_OCF_LE_READ_SUPPORTED_STATES), 270*21eefd31SHans Petter Selasky (void *)&rp, &n) == ERROR) 271*21eefd31SHans Petter Selasky return (ERROR); 2729c3471faSMarcelo Araujo 273*21eefd31SHans Petter Selasky if (rp.status != 0x00) { 274*21eefd31SHans Petter Selasky fprintf(stdout, "Status: %s [%#02x]\n", 275*21eefd31SHans Petter Selasky hci_status2str(rp.status), rp.status); 276*21eefd31SHans Petter Selasky return (FAILED); 277*21eefd31SHans Petter Selasky } 278bcff2d91STakanori Watanabe 279*21eefd31SHans Petter Selasky fprintf(stdout, "LE States: %jx\n", rp.le_states); 280*21eefd31SHans Petter Selasky 281*21eefd31SHans Petter Selasky return (OK); 282bcff2d91STakanori Watanabe } 283bcff2d91STakanori Watanabe 2849c3471faSMarcelo Araujo static int 2859c3471faSMarcelo Araujo set_le_event_mask(int s, uint64_t mask) 286bcff2d91STakanori Watanabe { 287bcff2d91STakanori Watanabe ng_hci_le_set_event_mask_cp semc; 288bcff2d91STakanori Watanabe ng_hci_le_set_event_mask_rp rp; 289bcff2d91STakanori Watanabe int i, n ,e; 290bcff2d91STakanori Watanabe 291bcff2d91STakanori Watanabe n = sizeof(rp); 292bcff2d91STakanori Watanabe 293bcff2d91STakanori Watanabe for (i=0; i < NG_HCI_LE_EVENT_MASK_SIZE; i++) { 294bcff2d91STakanori Watanabe semc.event_mask[i] = mask&0xff; 295bcff2d91STakanori Watanabe mask >>= 8; 296bcff2d91STakanori Watanabe } 2979c3471faSMarcelo Araujo e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 2989c3471faSMarcelo Araujo NG_HCI_OCF_LE_SET_EVENT_MASK), 2999c3471faSMarcelo Araujo (void *)&semc, sizeof(semc), (void *)&rp, &n); 300bcff2d91STakanori Watanabe 301bcff2d91STakanori Watanabe return 0; 302bcff2d91STakanori Watanabe } 303bcff2d91STakanori Watanabe 3049c3471faSMarcelo Araujo static int 3059c3471faSMarcelo Araujo set_event_mask(int s, uint64_t mask) 306bcff2d91STakanori Watanabe { 307bcff2d91STakanori Watanabe ng_hci_set_event_mask_cp semc; 308bcff2d91STakanori Watanabe ng_hci_set_event_mask_rp rp; 309bcff2d91STakanori Watanabe int i, n, e; 310bcff2d91STakanori Watanabe 311bcff2d91STakanori Watanabe n = sizeof(rp); 312bcff2d91STakanori Watanabe 313bcff2d91STakanori Watanabe for (i=0; i < NG_HCI_EVENT_MASK_SIZE; i++) { 314bcff2d91STakanori Watanabe semc.event_mask[i] = mask&0xff; 315bcff2d91STakanori Watanabe mask >>= 8; 316bcff2d91STakanori Watanabe } 3179c3471faSMarcelo Araujo e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, 3189c3471faSMarcelo Araujo NG_HCI_OCF_SET_EVENT_MASK), 3199c3471faSMarcelo Araujo (void *)&semc, sizeof(semc), (void *)&rp, &n); 320bcff2d91STakanori Watanabe 321bcff2d91STakanori Watanabe return 0; 322bcff2d91STakanori Watanabe } 323bcff2d91STakanori Watanabe 3249c3471faSMarcelo Araujo static 3259c3471faSMarcelo Araujo int le_enable(int s, int argc, char *argv[]) 326bcff2d91STakanori Watanabe { 3279c3471faSMarcelo Araujo if (argc != 1) 328bcff2d91STakanori Watanabe return USAGE; 329bcff2d91STakanori Watanabe 330bcff2d91STakanori Watanabe if (strcasecmp(argv[0], "enable") == 0) { 331bcff2d91STakanori Watanabe set_event_mask(s, NG_HCI_EVENT_MASK_DEFAULT | 332bcff2d91STakanori Watanabe NG_HCI_EVENT_MASK_LE); 333bcff2d91STakanori Watanabe set_le_event_mask(s, NG_HCI_LE_EVENT_MASK_ALL); 334b4b880cbSEd Maste } else if (strcasecmp(argv[0], "disable") == 0) 335bcff2d91STakanori Watanabe set_event_mask(s, NG_HCI_EVENT_MASK_DEFAULT); 3369c3471faSMarcelo Araujo else 337bcff2d91STakanori Watanabe return USAGE; 338bcff2d91STakanori Watanabe 339bcff2d91STakanori Watanabe return OK; 340bcff2d91STakanori Watanabe } 341bcff2d91STakanori Watanabe 342bcff2d91STakanori Watanabe struct hci_command le_commands[] = { 343bcff2d91STakanori Watanabe { 344bcff2d91STakanori Watanabe "le_enable", 345bcff2d91STakanori Watanabe "le_enable [enable|disable] \n" 346bcff2d91STakanori Watanabe "Enable LE event ", 347bcff2d91STakanori Watanabe &le_enable, 348bcff2d91STakanori Watanabe }, 349bcff2d91STakanori Watanabe { 350bcff2d91STakanori Watanabe "le_read_local_supported_features", 351bcff2d91STakanori Watanabe "le_read_local_supported_features\n" 352bcff2d91STakanori Watanabe "read local supported features mask", 353bcff2d91STakanori Watanabe &le_read_local_supported_features, 354bcff2d91STakanori Watanabe }, 355bcff2d91STakanori Watanabe { 356*21eefd31SHans Petter Selasky "le_read_supported_states", 357*21eefd31SHans Petter Selasky "le_read_supported_states\n" 358bcff2d91STakanori Watanabe "read supported status" 359bcff2d91STakanori Watanabe , 360*21eefd31SHans Petter Selasky &le_read_supported_states, 361bcff2d91STakanori Watanabe }, 362bcff2d91STakanori Watanabe { 363bcff2d91STakanori Watanabe "le_set_scan_response", 364bcff2d91STakanori Watanabe "le_set_scan_response -n $name -f $flag -u $uuid16,$uuid16 \n" 365bcff2d91STakanori Watanabe "set LE scan response data" 366bcff2d91STakanori Watanabe , 367bcff2d91STakanori Watanabe &le_set_scan_response, 368bcff2d91STakanori Watanabe }, 369bcff2d91STakanori Watanabe { 370bcff2d91STakanori Watanabe "le_set_scan_enable", 371bcff2d91STakanori Watanabe "le_set_scan_enable [enable|disable] \n" 372bcff2d91STakanori Watanabe "enable or disable LE device scan", 373bcff2d91STakanori Watanabe &le_set_scan_enable 374bcff2d91STakanori Watanabe }, 375bcff2d91STakanori Watanabe { 376bcff2d91STakanori Watanabe "le_set_scan_param", 377bcff2d91STakanori Watanabe "le_set_scan_param [active|passive] interval(ms) window(ms) [public|random] [all|whitelist] \n" 378bcff2d91STakanori Watanabe "set LE device scan parameter", 379bcff2d91STakanori Watanabe &le_set_scan_param 380bcff2d91STakanori Watanabe }, 381bcff2d91STakanori Watanabe }; 382