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/bitstring.h> 36bcff2d91STakanori Watanabe #include <sys/select.h> 37bcff2d91STakanori Watanabe #include <assert.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> 46bcff2d91STakanori Watanabe #define L2CAP_SOCKET_CHECKED 47bcff2d91STakanori Watanabe #include <bluetooth.h> 48bcff2d91STakanori Watanabe #include "hccontrol.h" 49*9c3471faSMarcelo Araujo 50bcff2d91STakanori Watanabe static int le_set_scan_param(int s, int argc, char *argv[]); 51bcff2d91STakanori Watanabe static int le_set_scan_enable(int s, int argc, char *argv[]); 52bcff2d91STakanori Watanabe static int parse_param(int argc, char *argv[], char *buf, int *len); 53bcff2d91STakanori Watanabe static int le_set_scan_response(int s, int argc, char *argv[]); 54bcff2d91STakanori Watanabe static int le_read_supported_status(int s, int argc, char *argv[]); 55bcff2d91STakanori Watanabe static int le_read_local_supported_features(int s, int argc ,char *argv[]); 56bcff2d91STakanori Watanabe static int set_le_event_mask(int s, uint64_t mask); 57bcff2d91STakanori Watanabe static int set_event_mask(int s, uint64_t mask); 58bcff2d91STakanori Watanabe static int le_enable(int s, int argc, char *argv[]); 59bcff2d91STakanori Watanabe 60*9c3471faSMarcelo Araujo static int 61*9c3471faSMarcelo Araujo le_set_scan_param(int s, int argc, char *argv[]) 62bcff2d91STakanori Watanabe { 63bcff2d91STakanori Watanabe int type; 64bcff2d91STakanori Watanabe int interval; 65bcff2d91STakanori Watanabe int window; 66bcff2d91STakanori Watanabe int adrtype; 67bcff2d91STakanori Watanabe int policy; 68*9c3471faSMarcelo Araujo int e, n; 69bcff2d91STakanori Watanabe 70bcff2d91STakanori Watanabe ng_hci_le_set_scan_parameters_cp cp; 71bcff2d91STakanori Watanabe ng_hci_le_set_scan_parameters_rp rp; 72bcff2d91STakanori Watanabe 73*9c3471faSMarcelo Araujo if (argc != 5) 74bcff2d91STakanori Watanabe return USAGE; 75bcff2d91STakanori Watanabe 76*9c3471faSMarcelo Araujo if (strcmp(argv[0], "active") == 0) 77bcff2d91STakanori Watanabe type = 1; 78*9c3471faSMarcelo Araujo else if (strcmp(argv[0], "passive") == 0) 79bcff2d91STakanori Watanabe type = 0; 80*9c3471faSMarcelo Araujo else 81bcff2d91STakanori Watanabe return USAGE; 82bcff2d91STakanori Watanabe 83bcff2d91STakanori Watanabe interval = (int)(atof(argv[1])/0.625); 84bcff2d91STakanori Watanabe interval = (interval < 4)? 4: interval; 85bcff2d91STakanori Watanabe window = (int)(atof(argv[2])/0.625); 86bcff2d91STakanori Watanabe window = (window < 4) ? 4 : interval; 87bcff2d91STakanori Watanabe 88*9c3471faSMarcelo Araujo if (strcmp(argv[3], "public") == 0) 89bcff2d91STakanori Watanabe adrtype = 0; 90*9c3471faSMarcelo Araujo else if (strcmp(argv[0], "random") == 0) 91bcff2d91STakanori Watanabe adrtype = 1; 92*9c3471faSMarcelo Araujo else 93bcff2d91STakanori Watanabe return USAGE; 94bcff2d91STakanori Watanabe 95*9c3471faSMarcelo Araujo if (strcmp(argv[4], "all") == 0) 96bcff2d91STakanori Watanabe policy = 0; 97*9c3471faSMarcelo Araujo else if (strcmp(argv[4], "whitelist") == 0) 98bcff2d91STakanori Watanabe policy = 1; 99*9c3471faSMarcelo Araujo else 100bcff2d91STakanori Watanabe return USAGE; 101bcff2d91STakanori Watanabe 102bcff2d91STakanori Watanabe cp.le_scan_type = type; 103bcff2d91STakanori Watanabe cp.le_scan_interval = interval; 104bcff2d91STakanori Watanabe cp.own_address_type = adrtype; 105bcff2d91STakanori Watanabe cp.le_scan_window = window; 106bcff2d91STakanori Watanabe cp.scanning_filter_policy = policy; 107bcff2d91STakanori Watanabe n = sizeof(rp); 108bcff2d91STakanori Watanabe e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 109bcff2d91STakanori Watanabe NG_HCI_OCF_LE_SET_SCAN_PARAMETERS), 110bcff2d91STakanori Watanabe (void *)&cp, sizeof(cp), (void *)&rp, &n); 111bcff2d91STakanori Watanabe 112bcff2d91STakanori Watanabe return 0; 113bcff2d91STakanori Watanabe } 114bcff2d91STakanori Watanabe 115*9c3471faSMarcelo Araujo static int 116*9c3471faSMarcelo Araujo le_set_scan_enable(int s, int argc, char *argv[]) 117bcff2d91STakanori Watanabe { 118bcff2d91STakanori Watanabe ng_hci_le_set_scan_enable_cp cp; 119bcff2d91STakanori Watanabe ng_hci_le_set_scan_enable_rp rp; 120bcff2d91STakanori Watanabe int e, n, enable = 0; 121bcff2d91STakanori Watanabe 122bcff2d91STakanori Watanabe if (argc != 1) 123bcff2d91STakanori Watanabe return USAGE; 124bcff2d91STakanori Watanabe 125*9c3471faSMarcelo Araujo if (strcmp(argv[0], "enable") == 0) 126bcff2d91STakanori Watanabe enable = 1; 127*9c3471faSMarcelo Araujo else if (strcmp(argv[0], "disable") != 0) 128bcff2d91STakanori Watanabe return USAGE; 129*9c3471faSMarcelo Araujo 130bcff2d91STakanori Watanabe n = sizeof(rp); 131bcff2d91STakanori Watanabe cp.le_scan_enable = enable; 132bcff2d91STakanori Watanabe cp.filter_duplicates = 0; 133bcff2d91STakanori Watanabe e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 134bcff2d91STakanori Watanabe NG_HCI_OCF_LE_SET_SCAN_ENABLE), 135bcff2d91STakanori Watanabe (void *)&cp, sizeof(cp), (void *)&rp, &n); 136bcff2d91STakanori Watanabe 137*9c3471faSMarcelo Araujo if (e != 0 || rp.status != 0) 138bcff2d91STakanori Watanabe return ERROR; 139bcff2d91STakanori Watanabe 140*9c3471faSMarcelo Araujo return OK; 141bcff2d91STakanori Watanabe } 142*9c3471faSMarcelo Araujo 143*9c3471faSMarcelo Araujo static int 144*9c3471faSMarcelo Araujo parse_param(int argc, char *argv[], char *buf, int *len) 145bcff2d91STakanori Watanabe { 146bcff2d91STakanori Watanabe char *buflast = buf + (*len); 147bcff2d91STakanori Watanabe char *curbuf = buf; 148bcff2d91STakanori Watanabe char *token,*lenpos; 149bcff2d91STakanori Watanabe int ch; 150bcff2d91STakanori Watanabe int datalen; 151bcff2d91STakanori Watanabe uint16_t value; 152bcff2d91STakanori Watanabe optreset = 1; 153bcff2d91STakanori Watanabe optind = 0; 154bcff2d91STakanori Watanabe while ((ch = getopt(argc, argv , "n:f:u:")) != -1) { 155bcff2d91STakanori Watanabe switch(ch){ 156bcff2d91STakanori Watanabe case 'n': 157bcff2d91STakanori Watanabe datalen = strlen(optarg); 158*9c3471faSMarcelo Araujo if ((curbuf + datalen + 2) >= buflast) 159bcff2d91STakanori Watanabe goto done; 160bcff2d91STakanori Watanabe curbuf[0] = datalen + 1; 161bcff2d91STakanori Watanabe curbuf[1] = 8; 162bcff2d91STakanori Watanabe curbuf += 2; 163bcff2d91STakanori Watanabe memcpy(curbuf, optarg, datalen); 164bcff2d91STakanori Watanabe curbuf += datalen; 165bcff2d91STakanori Watanabe break; 166bcff2d91STakanori Watanabe case 'f': 167*9c3471faSMarcelo Araujo if (curbuf+3 > buflast) 168bcff2d91STakanori Watanabe goto done; 169bcff2d91STakanori Watanabe curbuf[0] = 2; 170bcff2d91STakanori Watanabe curbuf[1] = 1; 171bcff2d91STakanori Watanabe curbuf[2] = atoi(optarg); 172bcff2d91STakanori Watanabe curbuf += 3; 173bcff2d91STakanori Watanabe break; 174bcff2d91STakanori Watanabe case 'u': 175bcff2d91STakanori Watanabe lenpos = buf; 176bcff2d91STakanori Watanabe if ((buf+2) >= buflast) 177bcff2d91STakanori Watanabe goto done; 178bcff2d91STakanori Watanabe curbuf[1] = 2; 179bcff2d91STakanori Watanabe *lenpos = 1; 180bcff2d91STakanori Watanabe curbuf += 2; 181bcff2d91STakanori Watanabe while ((token = strsep(&optarg, ",")) != NULL) { 182bcff2d91STakanori Watanabe value = strtol(token, NULL, 16); 183bcff2d91STakanori Watanabe if ((curbuf+2) >= buflast) 184bcff2d91STakanori Watanabe break; 185bcff2d91STakanori Watanabe curbuf[0] = value &0xff; 186bcff2d91STakanori Watanabe curbuf[1] = (value>>8)&0xff; 187bcff2d91STakanori Watanabe curbuf += 2; 188bcff2d91STakanori Watanabe } 189bcff2d91STakanori Watanabe 190bcff2d91STakanori Watanabe } 191bcff2d91STakanori Watanabe } 192bcff2d91STakanori Watanabe done: 193bcff2d91STakanori Watanabe *len = curbuf - buf; 194bcff2d91STakanori Watanabe 195bcff2d91STakanori Watanabe return OK; 196bcff2d91STakanori Watanabe } 197bcff2d91STakanori Watanabe 198*9c3471faSMarcelo Araujo static int 199*9c3471faSMarcelo Araujo le_set_scan_response(int s, int argc, char *argv[]) 200bcff2d91STakanori Watanabe { 201bcff2d91STakanori Watanabe ng_hci_le_set_scan_response_data_cp cp; 202bcff2d91STakanori Watanabe ng_hci_le_set_scan_response_data_rp rp; 203bcff2d91STakanori Watanabe int n; 204bcff2d91STakanori Watanabe int e; 205bcff2d91STakanori Watanabe int len; 206bcff2d91STakanori Watanabe char buf[NG_HCI_ADVERTISING_DATA_SIZE]; 207*9c3471faSMarcelo Araujo 208bcff2d91STakanori Watanabe len = sizeof(buf); 209bcff2d91STakanori Watanabe parse_param(argc, argv, buf, &len); 210bcff2d91STakanori Watanabe memset(cp.scan_response_data, 0, sizeof(cp.scan_response_data)); 211bcff2d91STakanori Watanabe cp.scan_response_data_length = len; 212bcff2d91STakanori Watanabe memcpy(cp.scan_response_data, buf, len); 213bcff2d91STakanori Watanabe n = sizeof(rp); 214bcff2d91STakanori Watanabe e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 215bcff2d91STakanori Watanabe NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA), 216bcff2d91STakanori Watanabe (void *)&cp, sizeof(cp), (void *)&rp, &n); 217bcff2d91STakanori Watanabe 218*9c3471faSMarcelo Araujo printf("SET SCAN RESPONSE %d %d %d\n", e, rp.status, n); 219bcff2d91STakanori Watanabe 220bcff2d91STakanori Watanabe return OK; 221bcff2d91STakanori Watanabe } 222bcff2d91STakanori Watanabe 223*9c3471faSMarcelo Araujo static int 224*9c3471faSMarcelo Araujo le_read_local_supported_features(int s, int argc ,char *argv[]) 225bcff2d91STakanori Watanabe { 226bcff2d91STakanori Watanabe ng_hci_le_read_local_supported_features_rp rp; 227bcff2d91STakanori Watanabe int e; 228bcff2d91STakanori Watanabe int n = sizeof(rp); 229*9c3471faSMarcelo Araujo 230bcff2d91STakanori Watanabe e = hci_simple_request(s, 231bcff2d91STakanori Watanabe NG_HCI_OPCODE(NG_HCI_OGF_LE, 232bcff2d91STakanori Watanabe NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES), 233bcff2d91STakanori Watanabe (void *)&rp, &n); 234*9c3471faSMarcelo Araujo 235*9c3471faSMarcelo Araujo printf("LOCAL SUPPOREDED: %d %d %lu\n", e, rp.status, 236*9c3471faSMarcelo Araujo rp.le_features); 237bcff2d91STakanori Watanabe 238bcff2d91STakanori Watanabe return 0; 239bcff2d91STakanori Watanabe } 240*9c3471faSMarcelo Araujo 241*9c3471faSMarcelo Araujo static int 242*9c3471faSMarcelo Araujo le_read_supported_status(int s, int argc, char *argv[]) 243bcff2d91STakanori Watanabe { 244bcff2d91STakanori Watanabe ng_hci_le_read_supported_status_rp rp; 245bcff2d91STakanori Watanabe int e; 246bcff2d91STakanori Watanabe int n = sizeof(rp); 247*9c3471faSMarcelo Araujo 248*9c3471faSMarcelo Araujo e = hci_simple_request(s, NG_HCI_OPCODE( 249*9c3471faSMarcelo Araujo NG_HCI_OGF_LE, 250*9c3471faSMarcelo Araujo NG_HCI_OCF_LE_READ_SUPPORTED), 251bcff2d91STakanori Watanabe (void *)&rp, &n); 252*9c3471faSMarcelo Araujo 253bcff2d91STakanori Watanabe printf("LE_STATUS: %d %d %lx\n", e, rp.status, rp.le_status); 254bcff2d91STakanori Watanabe 255bcff2d91STakanori Watanabe return 0; 256bcff2d91STakanori Watanabe } 257bcff2d91STakanori Watanabe 258*9c3471faSMarcelo Araujo static int 259*9c3471faSMarcelo Araujo set_le_event_mask(int s, uint64_t mask) 260bcff2d91STakanori Watanabe { 261bcff2d91STakanori Watanabe ng_hci_le_set_event_mask_cp semc; 262bcff2d91STakanori Watanabe ng_hci_le_set_event_mask_rp rp; 263bcff2d91STakanori Watanabe int i, n ,e; 264bcff2d91STakanori Watanabe 265bcff2d91STakanori Watanabe n = sizeof(rp); 266bcff2d91STakanori Watanabe 267bcff2d91STakanori Watanabe for (i=0; i < NG_HCI_LE_EVENT_MASK_SIZE; i++) { 268bcff2d91STakanori Watanabe semc.event_mask[i] = mask&0xff; 269bcff2d91STakanori Watanabe mask >>= 8; 270bcff2d91STakanori Watanabe } 271*9c3471faSMarcelo Araujo e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, 272*9c3471faSMarcelo Araujo NG_HCI_OCF_LE_SET_EVENT_MASK), 273*9c3471faSMarcelo Araujo (void *)&semc, sizeof(semc), (void *)&rp, &n); 274bcff2d91STakanori Watanabe 275bcff2d91STakanori Watanabe return 0; 276bcff2d91STakanori Watanabe } 277bcff2d91STakanori Watanabe 278*9c3471faSMarcelo Araujo static int 279*9c3471faSMarcelo Araujo set_event_mask(int s, uint64_t mask) 280bcff2d91STakanori Watanabe { 281bcff2d91STakanori Watanabe ng_hci_set_event_mask_cp semc; 282bcff2d91STakanori Watanabe ng_hci_set_event_mask_rp rp; 283bcff2d91STakanori Watanabe int i, n, e; 284bcff2d91STakanori Watanabe 285bcff2d91STakanori Watanabe n = sizeof(rp); 286bcff2d91STakanori Watanabe 287bcff2d91STakanori Watanabe for (i=0; i < NG_HCI_EVENT_MASK_SIZE; i++) { 288bcff2d91STakanori Watanabe semc.event_mask[i] = mask&0xff; 289bcff2d91STakanori Watanabe mask >>= 8; 290bcff2d91STakanori Watanabe } 291*9c3471faSMarcelo Araujo e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, 292*9c3471faSMarcelo Araujo NG_HCI_OCF_SET_EVENT_MASK), 293*9c3471faSMarcelo Araujo (void *)&semc, sizeof(semc), (void *)&rp, &n); 294bcff2d91STakanori Watanabe 295bcff2d91STakanori Watanabe return 0; 296bcff2d91STakanori Watanabe } 297bcff2d91STakanori Watanabe 298*9c3471faSMarcelo Araujo static 299*9c3471faSMarcelo Araujo int le_enable(int s, int argc, char *argv[]) 300bcff2d91STakanori Watanabe { 301*9c3471faSMarcelo Araujo if (argc != 1) 302bcff2d91STakanori Watanabe return USAGE; 303bcff2d91STakanori Watanabe 304bcff2d91STakanori Watanabe if (strcasecmp(argv[0], "enable") == 0) { 305bcff2d91STakanori Watanabe set_event_mask(s, NG_HCI_EVENT_MASK_DEFAULT | 306bcff2d91STakanori Watanabe NG_HCI_EVENT_MASK_LE); 307bcff2d91STakanori Watanabe set_le_event_mask(s, NG_HCI_LE_EVENT_MASK_ALL); 308*9c3471faSMarcelo Araujo } else if (strcasecmp(argv[0], "disble") == 0) 309bcff2d91STakanori Watanabe set_event_mask(s, NG_HCI_EVENT_MASK_DEFAULT); 310*9c3471faSMarcelo Araujo else 311bcff2d91STakanori Watanabe return USAGE; 312bcff2d91STakanori Watanabe 313bcff2d91STakanori Watanabe return OK; 314bcff2d91STakanori Watanabe } 315bcff2d91STakanori Watanabe 316bcff2d91STakanori Watanabe struct hci_command le_commands[] = { 317bcff2d91STakanori Watanabe { 318bcff2d91STakanori Watanabe "le_enable", 319bcff2d91STakanori Watanabe "le_enable [enable|disable] \n" 320bcff2d91STakanori Watanabe "Enable LE event ", 321bcff2d91STakanori Watanabe &le_enable, 322bcff2d91STakanori Watanabe }, 323bcff2d91STakanori Watanabe { 324bcff2d91STakanori Watanabe "le_read_local_supported_features", 325bcff2d91STakanori Watanabe "le_read_local_supported_features\n" 326bcff2d91STakanori Watanabe "read local supported features mask", 327bcff2d91STakanori Watanabe &le_read_local_supported_features, 328bcff2d91STakanori Watanabe }, 329bcff2d91STakanori Watanabe { 330bcff2d91STakanori Watanabe "le_read_supported_status", 331bcff2d91STakanori Watanabe "le_read_supported_status\n" 332bcff2d91STakanori Watanabe "read supported status" 333bcff2d91STakanori Watanabe , 334bcff2d91STakanori Watanabe &le_read_supported_status, 335bcff2d91STakanori Watanabe }, 336bcff2d91STakanori Watanabe { 337bcff2d91STakanori Watanabe "le_set_scan_response", 338bcff2d91STakanori Watanabe "le_set_scan_response -n $name -f $flag -u $uuid16,$uuid16 \n" 339bcff2d91STakanori Watanabe "set LE scan response data" 340bcff2d91STakanori Watanabe , 341bcff2d91STakanori Watanabe &le_set_scan_response, 342bcff2d91STakanori Watanabe }, 343bcff2d91STakanori Watanabe { 344bcff2d91STakanori Watanabe "le_set_scan_enable", 345bcff2d91STakanori Watanabe "le_set_scan_enable [enable|disable] \n" 346bcff2d91STakanori Watanabe "enable or disable LE device scan", 347bcff2d91STakanori Watanabe &le_set_scan_enable 348bcff2d91STakanori Watanabe }, 349bcff2d91STakanori Watanabe { 350bcff2d91STakanori Watanabe "le_set_scan_param", 351bcff2d91STakanori Watanabe "le_set_scan_param [active|passive] interval(ms) window(ms) [public|random] [all|whitelist] \n" 352bcff2d91STakanori Watanabe "set LE device scan parameter", 353bcff2d91STakanori Watanabe &le_set_scan_param 354bcff2d91STakanori Watanabe }, 355bcff2d91STakanori Watanabe }; 356