4 * Copyright (c) 2015 Takanori Watanabe <takawata@freebsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $Id: hccontrol.c,v 1.5 2003/09/05 00:38:24 max Exp $
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34 #include <sys/sysctl.h>
35 #include <sys/select.h>
37 #include <bitstring.h>
40 #include <netgraph/ng_message.h>
47 #define L2CAP_SOCKET_CHECKED
48 #include <bluetooth.h>
49 #include "hccontrol.h"
51 static int le_set_scan_param(int s, int argc, char *argv[]);
52 static int le_set_scan_enable(int s, int argc, char *argv[]);
53 static int parse_param(int argc, char *argv[], char *buf, int *len);
54 static int le_set_scan_response(int s, int argc, char *argv[]);
55 static int le_read_supported_status(int s, int argc, char *argv[]);
56 static int le_read_local_supported_features(int s, int argc ,char *argv[]);
57 static int set_le_event_mask(int s, uint64_t mask);
58 static int set_event_mask(int s, uint64_t mask);
59 static int le_enable(int s, int argc, char *argv[]);
62 le_set_scan_param(int s, int argc, char *argv[])
71 ng_hci_le_set_scan_parameters_cp cp;
72 ng_hci_le_set_scan_parameters_rp rp;
77 if (strcmp(argv[0], "active") == 0)
79 else if (strcmp(argv[0], "passive") == 0)
84 interval = (int)(atof(argv[1])/0.625);
85 interval = (interval < 4)? 4: interval;
86 window = (int)(atof(argv[2])/0.625);
87 window = (window < 4) ? 4 : interval;
89 if (strcmp(argv[3], "public") == 0)
91 else if (strcmp(argv[3], "random") == 0)
96 if (strcmp(argv[4], "all") == 0)
98 else if (strcmp(argv[4], "whitelist") == 0)
103 cp.le_scan_type = type;
104 cp.le_scan_interval = interval;
105 cp.own_address_type = adrtype;
106 cp.le_scan_window = window;
107 cp.scanning_filter_policy = policy;
109 e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE,
110 NG_HCI_OCF_LE_SET_SCAN_PARAMETERS),
111 (void *)&cp, sizeof(cp), (void *)&rp, &n);
117 le_set_scan_enable(int s, int argc, char *argv[])
119 ng_hci_le_set_scan_enable_cp cp;
120 ng_hci_le_set_scan_enable_rp rp;
121 int e, n, enable = 0;
126 if (strcmp(argv[0], "enable") == 0)
128 else if (strcmp(argv[0], "disable") != 0)
132 cp.le_scan_enable = enable;
133 cp.filter_duplicates = 0;
134 e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE,
135 NG_HCI_OCF_LE_SET_SCAN_ENABLE),
136 (void *)&cp, sizeof(cp), (void *)&rp, &n);
138 if (e != 0 || rp.status != 0)
145 parse_param(int argc, char *argv[], char *buf, int *len)
147 char *buflast = buf + (*len);
155 while ((ch = getopt(argc, argv , "n:f:u:")) != -1) {
158 datalen = strlen(optarg);
159 if ((curbuf + datalen + 2) >= buflast)
161 curbuf[0] = datalen + 1;
164 memcpy(curbuf, optarg, datalen);
168 if (curbuf+3 > buflast)
172 curbuf[2] = atoi(optarg);
177 if ((buf+2) >= buflast)
182 while ((token = strsep(&optarg, ",")) != NULL) {
183 value = strtol(token, NULL, 16);
184 if ((curbuf+2) >= buflast)
186 curbuf[0] = value &0xff;
187 curbuf[1] = (value>>8)&0xff;
200 le_set_scan_response(int s, int argc, char *argv[])
202 ng_hci_le_set_scan_response_data_cp cp;
203 ng_hci_le_set_scan_response_data_rp rp;
207 char buf[NG_HCI_ADVERTISING_DATA_SIZE];
210 parse_param(argc, argv, buf, &len);
211 memset(cp.scan_response_data, 0, sizeof(cp.scan_response_data));
212 cp.scan_response_data_length = len;
213 memcpy(cp.scan_response_data, buf, len);
215 e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE,
216 NG_HCI_OCF_LE_SET_SCAN_RESPONSE_DATA),
217 (void *)&cp, sizeof(cp), (void *)&rp, &n);
219 printf("SET SCAN RESPONSE %d %d %d\n", e, rp.status, n);
225 le_read_local_supported_features(int s, int argc ,char *argv[])
227 ng_hci_le_read_local_supported_features_rp rp;
231 e = hci_simple_request(s,
232 NG_HCI_OPCODE(NG_HCI_OGF_LE,
233 NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES),
236 printf("LOCAL SUPPORTED: %d %d %jx\n", e, rp.status,
237 (uintmax_t) rp.le_features);
243 le_read_supported_status(int s, int argc, char *argv[])
245 ng_hci_le_read_supported_status_rp rp;
249 e = hci_simple_request(s, NG_HCI_OPCODE(
251 NG_HCI_OCF_LE_READ_SUPPORTED_STATUS),
254 printf("LE_STATUS: %d %d %jx\n", e, rp.status, (uintmax_t)rp.le_status);
260 set_le_event_mask(int s, uint64_t mask)
262 ng_hci_le_set_event_mask_cp semc;
263 ng_hci_le_set_event_mask_rp rp;
268 for (i=0; i < NG_HCI_LE_EVENT_MASK_SIZE; i++) {
269 semc.event_mask[i] = mask&0xff;
272 e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE,
273 NG_HCI_OCF_LE_SET_EVENT_MASK),
274 (void *)&semc, sizeof(semc), (void *)&rp, &n);
280 set_event_mask(int s, uint64_t mask)
282 ng_hci_set_event_mask_cp semc;
283 ng_hci_set_event_mask_rp rp;
288 for (i=0; i < NG_HCI_EVENT_MASK_SIZE; i++) {
289 semc.event_mask[i] = mask&0xff;
292 e = hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
293 NG_HCI_OCF_SET_EVENT_MASK),
294 (void *)&semc, sizeof(semc), (void *)&rp, &n);
300 int le_enable(int s, int argc, char *argv[])
305 if (strcasecmp(argv[0], "enable") == 0) {
306 set_event_mask(s, NG_HCI_EVENT_MASK_DEFAULT |
307 NG_HCI_EVENT_MASK_LE);
308 set_le_event_mask(s, NG_HCI_LE_EVENT_MASK_ALL);
309 } else if (strcasecmp(argv[0], "disble") == 0)
310 set_event_mask(s, NG_HCI_EVENT_MASK_DEFAULT);
317 struct hci_command le_commands[] = {
320 "le_enable [enable|disable] \n"
325 "le_read_local_supported_features",
326 "le_read_local_supported_features\n"
327 "read local supported features mask",
328 &le_read_local_supported_features,
331 "le_read_supported_status",
332 "le_read_supported_status\n"
333 "read supported status"
335 &le_read_supported_status,
338 "le_set_scan_response",
339 "le_set_scan_response -n $name -f $flag -u $uuid16,$uuid16 \n"
340 "set LE scan response data"
342 &le_set_scan_response,
345 "le_set_scan_enable",
346 "le_set_scan_enable [enable|disable] \n"
347 "enable or disable LE device scan",
352 "le_set_scan_param [active|passive] interval(ms) window(ms) [public|random] [all|whitelist] \n"
353 "set LE device scan parameter",