Sat Aug 27 22:22:01 2011 UTC ()
static + __dead


(joerg)
diff -r1.24 -r1.25 src/usr.sbin/btconfig/btconfig.c

cvs diff -r1.24 -r1.25 src/usr.sbin/btconfig/btconfig.c (switch to unified diff)

--- src/usr.sbin/btconfig/btconfig.c 2010/11/28 20:37:24 1.24
+++ src/usr.sbin/btconfig/btconfig.c 2011/08/27 22:22:01 1.25
@@ -1,1111 +1,1110 @@ @@ -1,1111 +1,1110 @@
1/* $NetBSD: btconfig.c,v 1.24 2010/11/28 20:37:24 plunky Exp $ */ 1/* $NetBSD: btconfig.c,v 1.25 2011/08/27 22:22:01 joerg Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2006 Itronix Inc. 4 * Copyright (c) 2006 Itronix Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Iain Hibbert for Itronix Inc. 7 * Written by Iain Hibbert for Itronix Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of Itronix Inc. may not be used to endorse 17 * 3. The name of Itronix Inc. may not be used to endorse
18 * or promote products derived from this software without specific 18 * or promote products derived from this software without specific
19 * prior written permission. 19 * prior written permission.
20 * 20 *
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN 28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE. 31 * POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35__COPYRIGHT("@(#) Copyright (c) 2006 Itronix, Inc. All rights reserved."); 35__COPYRIGHT("@(#) Copyright (c) 2006 Itronix, Inc. All rights reserved.");
36__RCSID("$NetBSD: btconfig.c,v 1.24 2010/11/28 20:37:24 plunky Exp $"); 36__RCSID("$NetBSD: btconfig.c,v 1.25 2011/08/27 22:22:01 joerg Exp $");
37 37
38#include <sys/ioctl.h> 38#include <sys/ioctl.h>
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/socket.h> 40#include <sys/socket.h>
41 41
42#include <bluetooth.h> 42#include <bluetooth.h>
43#include <err.h> 43#include <err.h>
44#include <errno.h> 44#include <errno.h>
45#include <stdio.h> 45#include <stdio.h>
46#include <stdlib.h> 46#include <stdlib.h>
47#include <string.h> 47#include <string.h>
48#include <time.h> 48#include <time.h>
49#include <unistd.h> 49#include <unistd.h>
50#include <util.h> 50#include <util.h>
51 51
52int main(int, char *[]); 52__dead static void badarg(const char *);
53void badarg(const char *); 53__dead static void badparam(const char *);
54void badparam(const char *); 54__dead static void badval(const char *, const char *);
55void badval(const char *, const char *); 55__dead static void usage(void);
56void usage(void); 56static int set_unit(unsigned long);
57int set_unit(unsigned long); 57static void config_unit(void);
58void config_unit(void); 58static void print_val(const char *, const char **, int);
59void print_val(const char *, const char **, int); 59static void print_info(int);
60void print_info(int); 60static void print_stats(void);
61void print_stats(void); 61static void print_class(const char *, uint8_t *);
62void print_class(const char *, uint8_t *); 62static void print_class0(void);
63void print_class0(void); 63static void print_voice(int);
64void print_voice(int); 64static void tag(const char *);
65void tag(const char *); 65static void print_features0(uint8_t *);
66void print_features0(uint8_t *); 66static void print_features1(uint8_t *);
67void print_features1(uint8_t *); 67static void print_result(int, struct bt_devinquiry *);
68void print_result(int, struct bt_devinquiry *); 68static void do_inquiry(void);
69void do_inquiry(void); 69
70 70static void hci_req(uint16_t, uint8_t , void *, size_t, void *, size_t);
71void hci_req(uint16_t, uint8_t , void *, size_t, void *, size_t); 71static void save_value(uint16_t, void *, size_t);
72void save_value(uint16_t, void *, size_t); 72static void load_value(uint16_t, void *, size_t);
73void load_value(uint16_t, void *, size_t); 
74 73
75#define MAX_STR_SIZE 0xff 74#define MAX_STR_SIZE 0xff
76 75
77/* print width */ 76/* print width */
78int width = 0; 77static int width = 0;
79#define MAX_WIDTH 70 78#define MAX_WIDTH 70
80 79
81/* global variables */ 80/* global variables */
82int hci; 81static int hci;
83struct btreq btr; 82static struct btreq btr;
84 83
85/* command line flags */ 84/* command line flags */
86int verbose = 0; /* more info */ 85static int verbose = 0; /* more info */
87int lflag = 0; /* list devices */ 86static int lflag = 0; /* list devices */
88int sflag = 0; /* get/zero stats */ 87static int sflag = 0; /* get/zero stats */
89 88
90/* device up/down (flag) */ 89/* device up/down (flag) */
91int opt_enable = 0; 90static int opt_enable = 0;
92int opt_reset = 0; 91static int opt_reset = 0;
93#define FLAGS_FMT "\20" \ 92#define FLAGS_FMT "\20" \
94 "\001UP" \ 93 "\001UP" \
95 "\002RUNNING" \ 94 "\002RUNNING" \
96 "\003XMIT_CMD" \ 95 "\003XMIT_CMD" \
97 "\004XMIT_ACL" \ 96 "\004XMIT_ACL" \
98 "\005XMIT_SCO" \ 97 "\005XMIT_SCO" \
99 "\006INIT_BDADDR" \ 98 "\006INIT_BDADDR" \
100 "\007INIT_BUFFER_SIZE" \ 99 "\007INIT_BUFFER_SIZE" \
101 "\010INIT_FEATURES" \ 100 "\010INIT_FEATURES" \
102 "\011POWER_UP_NOOP" \ 101 "\011POWER_UP_NOOP" \
103 "\012INIT_COMMANDS" \ 102 "\012INIT_COMMANDS" \
104 "\013MASTER" \ 103 "\013MASTER" \
105 "" 104 ""
106 105
107/* authorisation (flag) */ 106/* authorisation (flag) */
108int opt_auth = 0; 107static int opt_auth = 0;
109 108
110/* encryption (flag) */ 109/* encryption (flag) */
111int opt_encrypt = 0; 110static int opt_encrypt = 0;
112 111
113/* scan enable options (flags) */ 112/* scan enable options (flags) */
114int opt_pscan = 0; 113static int opt_pscan = 0;
115int opt_iscan = 0; 114static int opt_iscan = 0;
116 115
117/* master role option */ 116/* master role option */
118int opt_master = 0; 117static int opt_master = 0;
119 118
120/* link policy options (flags) */ 119/* link policy options (flags) */
121int opt_switch = 0; 120static int opt_switch = 0;
122int opt_hold = 0; 121static int opt_hold = 0;
123int opt_sniff = 0; 122static int opt_sniff = 0;
124int opt_park = 0; 123static int opt_park = 0;
125 124
126/* class of device (hex value) */ 125/* class of device (hex value) */
127int opt_class = 0; 126static int opt_class = 0;
128uint32_t class; 127static uint32_t class;
129 128
130/* packet type mask (hex value) */ 129/* packet type mask (hex value) */
131int opt_ptype = 0; 130static int opt_ptype = 0;
132uint32_t ptype; 131static uint32_t ptype;
133 132
134/* unit name (string) */ 133/* unit name (string) */
135int opt_name = 0; 134static int opt_name = 0;
136char name[MAX_STR_SIZE]; 135static char name[MAX_STR_SIZE];
137 136
138/* pin type */ 137/* pin type */
139int opt_pin = 0; 138static int opt_pin = 0;
140 139
141/* Inquiry */ 140/* Inquiry */
142int opt_rssi = 0; /* inquiry_with_rssi (obsolete flag) */ 141static int opt_rssi = 0; /* inquiry_with_rssi (obsolete flag) */
143int opt_imode = 0; /* inquiry mode */ 142static int opt_imode = 0; /* inquiry mode */
144int opt_inquiry = 0; 143static int opt_inquiry = 0;
145#define INQUIRY_LENGTH 10 /* seconds */ 144#define INQUIRY_LENGTH 10 /* seconds */
146#define INQUIRY_MAX_RESPONSES 10 145#define INQUIRY_MAX_RESPONSES 10
147const char *imodes[] = { "std", "rssi", "ext", NULL }; 146static const char *imodes[] = { "std", "rssi", "ext", NULL };
148 147
149/* Voice Settings */ 148/* Voice Settings */
150int opt_voice = 0; 149static int opt_voice = 0;
151uint32_t voice; 150static uint32_t voice;
152 151
153/* Page Timeout */ 152/* Page Timeout */
154int opt_pto = 0; 153static int opt_pto = 0;
155uint32_t pto; 154static uint32_t pto;
156 155
157/* set SCO mtu */ 156/* set SCO mtu */
158int opt_scomtu; 157static int opt_scomtu;
159uint32_t scomtu; 158static uint32_t scomtu;
160 159
161struct parameter { 160static struct parameter {
162 const char *name; 161 const char *name;
163 enum { P_SET, P_CLR, P_STR, P_HEX, P_NUM, P_VAL } type; 162 enum { P_SET, P_CLR, P_STR, P_HEX, P_NUM, P_VAL } type;
164 int *opt; 163 int *opt;
165 void *val; 164 void *val;
166} parameters[] = { 165} parameters[] = {
167 { "up", P_SET, &opt_enable, NULL }, 166 { "up", P_SET, &opt_enable, NULL },
168 { "enable", P_SET, &opt_enable, NULL }, 167 { "enable", P_SET, &opt_enable, NULL },
169 { "down", P_CLR, &opt_enable, NULL }, 168 { "down", P_CLR, &opt_enable, NULL },
170 { "disable", P_CLR, &opt_enable, NULL }, 169 { "disable", P_CLR, &opt_enable, NULL },
171 { "name", P_STR, &opt_name, name }, 170 { "name", P_STR, &opt_name, name },
172 { "pscan", P_SET, &opt_pscan, NULL }, 171 { "pscan", P_SET, &opt_pscan, NULL },
173 { "-pscan", P_CLR, &opt_pscan, NULL }, 172 { "-pscan", P_CLR, &opt_pscan, NULL },
174 { "iscan", P_SET, &opt_iscan, NULL }, 173 { "iscan", P_SET, &opt_iscan, NULL },
175 { "-iscan", P_CLR, &opt_iscan, NULL }, 174 { "-iscan", P_CLR, &opt_iscan, NULL },
176 { "master", P_SET, &opt_master, NULL }, 175 { "master", P_SET, &opt_master, NULL },
177 { "-master", P_CLR, &opt_master, NULL }, 176 { "-master", P_CLR, &opt_master, NULL },
178 { "switch", P_SET, &opt_switch, NULL }, 177 { "switch", P_SET, &opt_switch, NULL },
179 { "-switch", P_CLR, &opt_switch, NULL }, 178 { "-switch", P_CLR, &opt_switch, NULL },
180 { "hold", P_SET, &opt_hold, NULL }, 179 { "hold", P_SET, &opt_hold, NULL },
181 { "-hold", P_CLR, &opt_hold, NULL }, 180 { "-hold", P_CLR, &opt_hold, NULL },
182 { "sniff", P_SET, &opt_sniff, NULL }, 181 { "sniff", P_SET, &opt_sniff, NULL },
183 { "-sniff", P_CLR, &opt_sniff, NULL }, 182 { "-sniff", P_CLR, &opt_sniff, NULL },
184 { "park", P_SET, &opt_park, NULL }, 183 { "park", P_SET, &opt_park, NULL },
185 { "-park", P_CLR, &opt_park, NULL }, 184 { "-park", P_CLR, &opt_park, NULL },
186 { "auth", P_SET, &opt_auth, NULL }, 185 { "auth", P_SET, &opt_auth, NULL },
187 { "-auth", P_CLR, &opt_auth, NULL }, 186 { "-auth", P_CLR, &opt_auth, NULL },
188 { "encrypt", P_SET, &opt_encrypt, NULL }, 187 { "encrypt", P_SET, &opt_encrypt, NULL },
189 { "-encrypt", P_CLR, &opt_encrypt, NULL }, 188 { "-encrypt", P_CLR, &opt_encrypt, NULL },
190 { "ptype", P_HEX, &opt_ptype, &ptype }, 189 { "ptype", P_HEX, &opt_ptype, &ptype },
191 { "class", P_HEX, &opt_class, &class }, 190 { "class", P_HEX, &opt_class, &class },
192 { "fixed", P_SET, &opt_pin, NULL }, 191 { "fixed", P_SET, &opt_pin, NULL },
193 { "variable", P_CLR, &opt_pin, NULL }, 192 { "variable", P_CLR, &opt_pin, NULL },
194 { "inq", P_SET, &opt_inquiry, NULL }, 193 { "inq", P_SET, &opt_inquiry, NULL },
195 { "inquiry", P_SET, &opt_inquiry, NULL }, 194 { "inquiry", P_SET, &opt_inquiry, NULL },
196 { "imode", P_VAL, &opt_imode, imodes }, 195 { "imode", P_VAL, &opt_imode, imodes },
197 { "rssi", P_SET, &opt_rssi, NULL }, 196 { "rssi", P_SET, &opt_rssi, NULL },
198 { "-rssi", P_CLR, &opt_rssi, NULL }, 197 { "-rssi", P_CLR, &opt_rssi, NULL },
199 { "reset", P_SET, &opt_reset, NULL }, 198 { "reset", P_SET, &opt_reset, NULL },
200 { "voice", P_HEX, &opt_voice, &voice }, 199 { "voice", P_HEX, &opt_voice, &voice },
201 { "pto", P_NUM, &opt_pto, &pto }, 200 { "pto", P_NUM, &opt_pto, &pto },
202 { "scomtu", P_NUM, &opt_scomtu, &scomtu }, 201 { "scomtu", P_NUM, &opt_scomtu, &scomtu },
203 { NULL, 0, NULL, NULL } 202 { NULL, 0, NULL, NULL }
204}; 203};
205 204
206int 205int
207main(int ac, char *av[]) 206main(int ac, char *av[])
208{ 207{
209 int ch; 208 int ch;
210 struct parameter *p; 209 struct parameter *p;
211 210
212 while ((ch = getopt(ac, av, "hlsvz")) != -1) { 211 while ((ch = getopt(ac, av, "hlsvz")) != -1) {
213 switch(ch) { 212 switch(ch) {
214 case 'l': 213 case 'l':
215 lflag = 1; 214 lflag = 1;
216 break; 215 break;
217 216
218 case 's': 217 case 's':
219 sflag = 1; 218 sflag = 1;
220 break; 219 break;
221 220
222 case 'v': 221 case 'v':
223 verbose++; 222 verbose++;
224 break; 223 break;
225 224
226 case 'z': 225 case 'z':
227 sflag = 2; 226 sflag = 2;
228 break; 227 break;
229 228
230 case 'h': 229 case 'h':
231 default: 230 default:
232 usage(); 231 usage();
233 } 232 }
234 } 233 }
235 av += optind; 234 av += optind;
236 ac -= optind; 235 ac -= optind;
237 236
238 if (lflag && sflag) 237 if (lflag && sflag)
239 usage(); 238 usage();
240 239
241 hci = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 240 hci = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
242 if (hci == -1) 241 if (hci == -1)
243 err(EXIT_FAILURE, "socket"); 242 err(EXIT_FAILURE, "socket");
244 243
245 if (ac == 0) { 244 if (ac == 0) {
246 verbose++; 245 verbose++;
247 246
248 memset(&btr, 0, sizeof(btr)); 247 memset(&btr, 0, sizeof(btr));
249 while (set_unit(SIOCNBTINFO) != -1) { 248 while (set_unit(SIOCNBTINFO) != -1) {
250 print_info(verbose); 249 print_info(verbose);
251 print_stats(); 250 print_stats();
252 } 251 }
253 252
254 tag(NULL); 253 tag(NULL);
255 } else { 254 } else {
256 strlcpy(btr.btr_name, *av, HCI_DEVNAME_SIZE); 255 strlcpy(btr.btr_name, *av, HCI_DEVNAME_SIZE);
257 av++, ac--; 256 av++, ac--;
258 257
259 if (set_unit(SIOCGBTINFO) < 0) 258 if (set_unit(SIOCGBTINFO) < 0)
260 err(EXIT_FAILURE, "%s", btr.btr_name); 259 err(EXIT_FAILURE, "%s", btr.btr_name);
261 260
262 if (ac == 0) 261 if (ac == 0)
263 verbose += 2; 262 verbose += 2;
264 263
265 while (ac > 0) { 264 while (ac > 0) {
266 for (p = parameters ; ; p++) { 265 for (p = parameters ; ; p++) {
267 if (p->name == NULL) 266 if (p->name == NULL)
268 badparam(*av); 267 badparam(*av);
269 268
270 if (strcmp(*av, p->name) == 0) 269 if (strcmp(*av, p->name) == 0)
271 break; 270 break;
272 } 271 }
273 272
274 switch(p->type) { 273 switch(p->type) {
275 case P_SET: 274 case P_SET:
276 *(p->opt) = 1; 275 *(p->opt) = 1;
277 break; 276 break;
278 277
279 case P_CLR: 278 case P_CLR:
280 *(p->opt) = -1; 279 *(p->opt) = -1;
281 break; 280 break;
282 281
283 case P_STR: 282 case P_STR:
284 if (--ac < 1) badarg(p->name); 283 if (--ac < 1) badarg(p->name);
285 strlcpy((char *)(p->val), *++av, MAX_STR_SIZE); 284 strlcpy((char *)(p->val), *++av, MAX_STR_SIZE);
286 *(p->opt) = 1; 285 *(p->opt) = 1;
287 break; 286 break;
288 287
289 case P_HEX: 288 case P_HEX:
290 if (--ac < 1) badarg(p->name); 289 if (--ac < 1) badarg(p->name);
291 *(uint32_t *)(p->val) = strtoul(*++av, NULL, 16); 290 *(uint32_t *)(p->val) = strtoul(*++av, NULL, 16);
292 *(p->opt) = 1; 291 *(p->opt) = 1;
293 break; 292 break;
294 293
295 case P_NUM: 294 case P_NUM:
296 if (--ac < 1) badarg(p->name); 295 if (--ac < 1) badarg(p->name);
297 *(uint32_t *)(p->val) = strtoul(*++av, NULL, 10); 296 *(uint32_t *)(p->val) = strtoul(*++av, NULL, 10);
298 *(p->opt) = 1; 297 *(p->opt) = 1;
299 break; 298 break;
300 299
301 case P_VAL: 300 case P_VAL:
302 if (--ac < 1) badarg(p->name); 301 if (--ac < 1) badarg(p->name);
303 ++av; 302 ++av;
304 ch = 0; 303 ch = 0;
305 do { 304 do {
306 if (((char **)(p->val))[ch] == NULL) 305 if (((char **)(p->val))[ch] == NULL)
307 badval(p->name, *av); 306 badval(p->name, *av);
308 } while (strcmp(((char **)(p->val))[ch++], *av)); 307 } while (strcmp(((char **)(p->val))[ch++], *av));
309 *(p->opt) = ch; 308 *(p->opt) = ch;
310 break; 309 break;
311 } 310 }
312 311
313 av++, ac--; 312 av++, ac--;
314 } 313 }
315 314
316 config_unit(); 315 config_unit();
317 print_info(verbose); 316 print_info(verbose);
318 print_stats(); 317 print_stats();
319 do_inquiry(); 318 do_inquiry();
320 } 319 }
321 320
322 close(hci); 321 close(hci);
323 return EXIT_SUCCESS; 322 return EXIT_SUCCESS;
324} 323}
325 324
326void 325static void
327badparam(const char *param) 326badparam(const char *param)
328{ 327{
329 328
330 fprintf(stderr, "unknown parameter '%s'\n", param); 329 fprintf(stderr, "unknown parameter '%s'\n", param);
331 exit(EXIT_FAILURE); 330 exit(EXIT_FAILURE);
332} 331}
333 332
334void 333static void
335badarg(const char *param) 334badarg(const char *param)
336{ 335{
337 336
338 fprintf(stderr, "parameter '%s' needs argument\n", param); 337 fprintf(stderr, "parameter '%s' needs argument\n", param);
339 exit(EXIT_FAILURE); 338 exit(EXIT_FAILURE);
340} 339}
341 340
342void 341static void
343badval(const char *param, const char *value) 342badval(const char *param, const char *value)
344{ 343{
345 344
346 fprintf(stderr, "bad value '%s' for parameter '%s'\n", value, param); 345 fprintf(stderr, "bad value '%s' for parameter '%s'\n", value, param);
347 exit(EXIT_FAILURE); 346 exit(EXIT_FAILURE);
348} 347}
349 348
350void 349static void
351usage(void) 350usage(void)
352{ 351{
353 352
354 fprintf(stderr, "usage: %s [-svz] [device [parameters]]\n", getprogname()); 353 fprintf(stderr, "usage: %s [-svz] [device [parameters]]\n", getprogname());
355 fprintf(stderr, " %s -l\n", getprogname()); 354 fprintf(stderr, " %s -l\n", getprogname());
356 exit(EXIT_FAILURE); 355 exit(EXIT_FAILURE);
357} 356}
358 357
359/* 358/*
360 * pretty printing feature 359 * pretty printing feature
361 */ 360 */
362void 361static void
363tag(const char *f) 362tag(const char *f)
364{ 363{
365 364
366 if (f == NULL) { 365 if (f == NULL) {
367 if (width > 0) 366 if (width > 0)
368 printf("\n"); 367 printf("\n");
369 368
370 width = 0; 369 width = 0;
371 } else { 370 } else {
372 width += printf("%*s%s", 371 width += printf("%*s%s",
373 (width == 0 ? (lflag ? 0 : 8) : 1), 372 (width == 0 ? (lflag ? 0 : 8) : 1),
374 "", f); 373 "", f);
375 374
376 if (width > MAX_WIDTH) { 375 if (width > MAX_WIDTH) {
377 printf("\n"); 376 printf("\n");
378 width = 0; 377 width = 0;
379 } 378 }
380 } 379 }
381} 380}
382 381
383/* 382/*
384 * basic HCI request wrapper with error check 383 * basic HCI request wrapper with error check
385 */ 384 */
386void 385static void
387hci_req(uint16_t opcode, uint8_t event, void *cbuf, size_t clen, 386hci_req(uint16_t opcode, uint8_t event, void *cbuf, size_t clen,
388 void *rbuf, size_t rlen) 387 void *rbuf, size_t rlen)
389{ 388{
390 struct bt_devreq req; 389 struct bt_devreq req;
391 390
392 req.opcode = opcode; 391 req.opcode = opcode;
393 req.event = event; 392 req.event = event;
394 req.cparam = cbuf; 393 req.cparam = cbuf;
395 req.clen = clen; 394 req.clen = clen;
396 req.rparam = rbuf; 395 req.rparam = rbuf;
397 req.rlen = rlen; 396 req.rlen = rlen;
398 397
399 if (bt_devreq(hci, &req, 10) == -1) 398 if (bt_devreq(hci, &req, 10) == -1)
400 err(EXIT_FAILURE, "cmd (%02x|%03x)", 399 err(EXIT_FAILURE, "cmd (%02x|%03x)",
401 HCI_OGF(opcode), HCI_OCF(opcode)); 400 HCI_OGF(opcode), HCI_OCF(opcode));
402 401
403 if (event == 0 && rlen > 0 && ((uint8_t *)rbuf)[0] != 0) 402 if (event == 0 && rlen > 0 && ((uint8_t *)rbuf)[0] != 0)
404 errx(EXIT_FAILURE, "cmd (%02x|%03x): status 0x%02x", 403 errx(EXIT_FAILURE, "cmd (%02x|%03x): status 0x%02x",
405 HCI_OGF(opcode), HCI_OCF(opcode), ((uint8_t *)rbuf)[0]); 404 HCI_OGF(opcode), HCI_OCF(opcode), ((uint8_t *)rbuf)[0]);
406} 405}
407 406
408/* 407/*
409 * write value to device with opcode. 408 * write value to device with opcode.
410 * provide a small response buffer so that the status can be checked 409 * provide a small response buffer so that the status can be checked
411 */ 410 */
412void 411static void
413save_value(uint16_t opcode, void *cbuf, size_t clen) 412save_value(uint16_t opcode, void *cbuf, size_t clen)
414{ 413{
415 uint8_t buf[1]; 414 uint8_t buf[1];
416 415
417 hci_req(opcode, 0, cbuf, clen, buf, sizeof(buf)); 416 hci_req(opcode, 0, cbuf, clen, buf, sizeof(buf));
418} 417}
419 418
420/* 419/*
421 * read value from device with opcode. 420 * read value from device with opcode.
422 * use our own buffer and only return the value from the response packet 421 * use our own buffer and only return the value from the response packet
423 */ 422 */
424void 423static void
425load_value(uint16_t opcode, void *rbuf, size_t rlen) 424load_value(uint16_t opcode, void *rbuf, size_t rlen)
426{ 425{
427 uint8_t buf[UINT8_MAX]; 426 uint8_t buf[UINT8_MAX];
428 427
429 hci_req(opcode, 0, NULL, 0, buf, sizeof(buf)); 428 hci_req(opcode, 0, NULL, 0, buf, sizeof(buf));
430 memcpy(rbuf, buf + 1, rlen); 429 memcpy(rbuf, buf + 1, rlen);
431} 430}
432 431
433int 432static int
434set_unit(unsigned long cmd) 433set_unit(unsigned long cmd)
435{ 434{
436 435
437 if (ioctl(hci, cmd, &btr) == -1) 436 if (ioctl(hci, cmd, &btr) == -1)
438 return -1; 437 return -1;
439 438
440 if (btr.btr_flags & BTF_UP) { 439 if (btr.btr_flags & BTF_UP) {
441 struct sockaddr_bt sa; 440 struct sockaddr_bt sa;
442 441
443 sa.bt_len = sizeof(sa); 442 sa.bt_len = sizeof(sa);
444 sa.bt_family = AF_BLUETOOTH; 443 sa.bt_family = AF_BLUETOOTH;
445 bdaddr_copy(&sa.bt_bdaddr, &btr.btr_bdaddr); 444 bdaddr_copy(&sa.bt_bdaddr, &btr.btr_bdaddr);
446 445
447 if (bind(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0) 446 if (bind(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0)
448 err(EXIT_FAILURE, "bind"); 447 err(EXIT_FAILURE, "bind");
449 448
450 if (connect(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0) 449 if (connect(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0)
451 err(EXIT_FAILURE, "connect"); 450 err(EXIT_FAILURE, "connect");
452 } 451 }
453 452
454 return 0; 453 return 0;
455} 454}
456 455
457/* 456/*
458 * apply configuration parameters to unit 457 * apply configuration parameters to unit
459 */ 458 */
460void 459static void
461config_unit(void) 460config_unit(void)
462{ 461{
463 462
464 if (opt_enable) { 463 if (opt_enable) {
465 if (opt_enable > 0) 464 if (opt_enable > 0)
466 btr.btr_flags |= BTF_UP; 465 btr.btr_flags |= BTF_UP;
467 else 466 else
468 btr.btr_flags &= ~BTF_UP; 467 btr.btr_flags &= ~BTF_UP;
469 468
470 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0) 469 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0)
471 err(EXIT_FAILURE, "SIOCSBTFLAGS"); 470 err(EXIT_FAILURE, "SIOCSBTFLAGS");
472 471
473 if (set_unit(SIOCGBTINFO) < 0) 472 if (set_unit(SIOCGBTINFO) < 0)
474 err(EXIT_FAILURE, "%s", btr.btr_name); 473 err(EXIT_FAILURE, "%s", btr.btr_name);
475 } 474 }
476 475
477 if (opt_reset) { 476 if (opt_reset) {
478 static const struct timespec ts = { 0, 100000000 }; /* 100ms */ 477 static const struct timespec ts = { 0, 100000000 }; /* 100ms */
479 478
480 btr.btr_flags |= BTF_INIT; 479 btr.btr_flags |= BTF_INIT;
481 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0) 480 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0)
482 err(EXIT_FAILURE, "SIOCSBTFLAGS"); 481 err(EXIT_FAILURE, "SIOCSBTFLAGS");
483 482
484 hci_req(HCI_CMD_RESET, 0, NULL, 0, NULL, 0); 483 hci_req(HCI_CMD_RESET, 0, NULL, 0, NULL, 0);
485 484
486 do { 485 do {
487 nanosleep(&ts, NULL); 486 nanosleep(&ts, NULL);
488 if (ioctl(hci, SIOCGBTINFO, &btr) < 0) 487 if (ioctl(hci, SIOCGBTINFO, &btr) < 0)
489 err(EXIT_FAILURE, "%s", btr.btr_name); 488 err(EXIT_FAILURE, "%s", btr.btr_name);
490 } while ((btr.btr_flags & BTF_INIT) != 0); 489 } while ((btr.btr_flags & BTF_INIT) != 0);
491 } 490 }
492 491
493 if (opt_master) { 492 if (opt_master) {
494 if (opt_master > 0) 493 if (opt_master > 0)
495 btr.btr_flags |= BTF_MASTER; 494 btr.btr_flags |= BTF_MASTER;
496 else 495 else
497 btr.btr_flags &= ~BTF_MASTER; 496 btr.btr_flags &= ~BTF_MASTER;
498 497
499 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0) 498 if (ioctl(hci, SIOCSBTFLAGS, &btr) < 0)
500 err(EXIT_FAILURE, "SIOCSBTFLAGS"); 499 err(EXIT_FAILURE, "SIOCSBTFLAGS");
501 } 500 }
502 501
503 if (opt_switch || opt_hold || opt_sniff || opt_park) { 502 if (opt_switch || opt_hold || opt_sniff || opt_park) {
504 uint16_t val = btr.btr_link_policy; 503 uint16_t val = btr.btr_link_policy;
505 504
506 if (opt_switch > 0) val |= HCI_LINK_POLICY_ENABLE_ROLE_SWITCH; 505 if (opt_switch > 0) val |= HCI_LINK_POLICY_ENABLE_ROLE_SWITCH;
507 if (opt_switch < 0) val &= ~HCI_LINK_POLICY_ENABLE_ROLE_SWITCH; 506 if (opt_switch < 0) val &= ~HCI_LINK_POLICY_ENABLE_ROLE_SWITCH;
508 if (opt_hold > 0) val |= HCI_LINK_POLICY_ENABLE_HOLD_MODE; 507 if (opt_hold > 0) val |= HCI_LINK_POLICY_ENABLE_HOLD_MODE;
509 if (opt_hold < 0) val &= ~HCI_LINK_POLICY_ENABLE_HOLD_MODE; 508 if (opt_hold < 0) val &= ~HCI_LINK_POLICY_ENABLE_HOLD_MODE;
510 if (opt_sniff > 0) val |= HCI_LINK_POLICY_ENABLE_SNIFF_MODE; 509 if (opt_sniff > 0) val |= HCI_LINK_POLICY_ENABLE_SNIFF_MODE;
511 if (opt_sniff < 0) val &= ~HCI_LINK_POLICY_ENABLE_SNIFF_MODE; 510 if (opt_sniff < 0) val &= ~HCI_LINK_POLICY_ENABLE_SNIFF_MODE;
512 if (opt_park > 0) val |= HCI_LINK_POLICY_ENABLE_PARK_MODE; 511 if (opt_park > 0) val |= HCI_LINK_POLICY_ENABLE_PARK_MODE;
513 if (opt_park < 0) val &= ~HCI_LINK_POLICY_ENABLE_PARK_MODE; 512 if (opt_park < 0) val &= ~HCI_LINK_POLICY_ENABLE_PARK_MODE;
514 513
515 btr.btr_link_policy = val; 514 btr.btr_link_policy = val;
516 if (ioctl(hci, SIOCSBTPOLICY, &btr) < 0) 515 if (ioctl(hci, SIOCSBTPOLICY, &btr) < 0)
517 err(EXIT_FAILURE, "SIOCSBTPOLICY"); 516 err(EXIT_FAILURE, "SIOCSBTPOLICY");
518 } 517 }
519 518
520 if (opt_ptype) { 519 if (opt_ptype) {
521 btr.btr_packet_type = ptype; 520 btr.btr_packet_type = ptype;
522 if (ioctl(hci, SIOCSBTPTYPE, &btr) < 0) 521 if (ioctl(hci, SIOCSBTPTYPE, &btr) < 0)
523 err(EXIT_FAILURE, "SIOCSBTPTYPE"); 522 err(EXIT_FAILURE, "SIOCSBTPTYPE");
524 } 523 }
525 524
526 if (opt_pscan || opt_iscan) { 525 if (opt_pscan || opt_iscan) {
527 uint8_t val; 526 uint8_t val;
528 527
529 load_value(HCI_CMD_READ_SCAN_ENABLE, &val, sizeof(val)); 528 load_value(HCI_CMD_READ_SCAN_ENABLE, &val, sizeof(val));
530 if (opt_pscan > 0) val |= HCI_PAGE_SCAN_ENABLE; 529 if (opt_pscan > 0) val |= HCI_PAGE_SCAN_ENABLE;
531 if (opt_pscan < 0) val &= ~HCI_PAGE_SCAN_ENABLE; 530 if (opt_pscan < 0) val &= ~HCI_PAGE_SCAN_ENABLE;
532 if (opt_iscan > 0) val |= HCI_INQUIRY_SCAN_ENABLE; 531 if (opt_iscan > 0) val |= HCI_INQUIRY_SCAN_ENABLE;
533 if (opt_iscan < 0) val &= ~HCI_INQUIRY_SCAN_ENABLE; 532 if (opt_iscan < 0) val &= ~HCI_INQUIRY_SCAN_ENABLE;
534 save_value(HCI_CMD_WRITE_SCAN_ENABLE, &val, sizeof(val)); 533 save_value(HCI_CMD_WRITE_SCAN_ENABLE, &val, sizeof(val));
535 } 534 }
536 535
537 if (opt_auth) { 536 if (opt_auth) {
538 uint8_t val = (opt_auth > 0 ? 1 : 0); 537 uint8_t val = (opt_auth > 0 ? 1 : 0);
539 538
540 save_value(HCI_CMD_WRITE_AUTH_ENABLE, &val, sizeof(val)); 539 save_value(HCI_CMD_WRITE_AUTH_ENABLE, &val, sizeof(val));
541 } 540 }
542 541
543 if (opt_encrypt) { 542 if (opt_encrypt) {
544 uint8_t val = (opt_encrypt > 0 ? 1 : 0); 543 uint8_t val = (opt_encrypt > 0 ? 1 : 0);
545 544
546 save_value(HCI_CMD_WRITE_ENCRYPTION_MODE, &val, sizeof(val)); 545 save_value(HCI_CMD_WRITE_ENCRYPTION_MODE, &val, sizeof(val));
547 } 546 }
548 547
549 if (opt_name) 548 if (opt_name)
550 save_value(HCI_CMD_WRITE_LOCAL_NAME, name, HCI_UNIT_NAME_SIZE); 549 save_value(HCI_CMD_WRITE_LOCAL_NAME, name, HCI_UNIT_NAME_SIZE);
551 550
552 if (opt_class) { 551 if (opt_class) {
553 uint8_t val[HCI_CLASS_SIZE]; 552 uint8_t val[HCI_CLASS_SIZE];
554 553
555 val[0] = (class >> 0) & 0xff; 554 val[0] = (class >> 0) & 0xff;
556 val[1] = (class >> 8) & 0xff; 555 val[1] = (class >> 8) & 0xff;
557 val[2] = (class >> 16) & 0xff; 556 val[2] = (class >> 16) & 0xff;
558 557
559 save_value(HCI_CMD_WRITE_UNIT_CLASS, val, HCI_CLASS_SIZE); 558 save_value(HCI_CMD_WRITE_UNIT_CLASS, val, HCI_CLASS_SIZE);
560 } 559 }
561 560
562 if (opt_pin) { 561 if (opt_pin) {
563 uint8_t val; 562 uint8_t val;
564 563
565 if (opt_pin > 0) val = 1; 564 if (opt_pin > 0) val = 1;
566 else val = 0; 565 else val = 0;
567 566
568 save_value(HCI_CMD_WRITE_PIN_TYPE, &val, sizeof(val)); 567 save_value(HCI_CMD_WRITE_PIN_TYPE, &val, sizeof(val));
569 } 568 }
570 569
571 if (opt_voice) { 570 if (opt_voice) {
572 uint16_t val; 571 uint16_t val;
573 572
574 val = htole16(voice & 0x03ff); 573 val = htole16(voice & 0x03ff);
575 save_value(HCI_CMD_WRITE_VOICE_SETTING, &val, sizeof(val)); 574 save_value(HCI_CMD_WRITE_VOICE_SETTING, &val, sizeof(val));
576 } 575 }
577 576
578 if (opt_pto) { 577 if (opt_pto) {
579 uint16_t val; 578 uint16_t val;
580 579
581 val = htole16(pto * 8 / 5); 580 val = htole16(pto * 8 / 5);
582 save_value(HCI_CMD_WRITE_PAGE_TIMEOUT, &val, sizeof(val)); 581 save_value(HCI_CMD_WRITE_PAGE_TIMEOUT, &val, sizeof(val));
583 } 582 }
584 583
585 if (opt_scomtu) { 584 if (opt_scomtu) {
586 if (scomtu > 0xff) { 585 if (scomtu > 0xff) {
587 warnx("Invalid SCO mtu %d", scomtu); 586 warnx("Invalid SCO mtu %d", scomtu);
588 } else { 587 } else {
589 btr.btr_sco_mtu = scomtu; 588 btr.btr_sco_mtu = scomtu;
590 589
591 if (ioctl(hci, SIOCSBTSCOMTU, &btr) < 0) 590 if (ioctl(hci, SIOCSBTSCOMTU, &btr) < 0)
592 warn("SIOCSBTSCOMTU"); 591 warn("SIOCSBTSCOMTU");
593 } 592 }
594 } 593 }
595 594
596 if (opt_imode | opt_rssi) { 595 if (opt_imode | opt_rssi) {
597 uint8_t val = (opt_rssi > 0 ? 1 : 0); 596 uint8_t val = (opt_rssi > 0 ? 1 : 0);
598 597
599 if (opt_imode) 598 if (opt_imode)
600 val = opt_imode - 1; 599 val = opt_imode - 1;
601 600
602 save_value(HCI_CMD_WRITE_INQUIRY_MODE, &val, sizeof(val)); 601 save_value(HCI_CMD_WRITE_INQUIRY_MODE, &val, sizeof(val));
603 } 602 }
604} 603}
605 604
606/* 605/*
607 * print value from NULL terminated array given index 606 * print value from NULL terminated array given index
608 */ 607 */
609void 608static void
610print_val(const char *hdr, const char **argv, int idx) 609print_val(const char *hdr, const char **argv, int idx)
611{ 610{
612 int i = 0; 611 int i = 0;
613 612
614 while (i < idx && *argv != NULL) 613 while (i < idx && *argv != NULL)
615 i++, argv++; 614 i++, argv++;
616 615
617 printf("\t%s: %s\n", hdr, *argv == NULL ? "unknown" : *argv); 616 printf("\t%s: %s\n", hdr, *argv == NULL ? "unknown" : *argv);
618} 617}
619 618
620/* 619/*
621 * Print info for Bluetooth Device with varying verbosity levels 620 * Print info for Bluetooth Device with varying verbosity levels
622 */ 621 */
623void 622static void
624print_info(int level) 623print_info(int level)
625{ 624{
626 uint8_t version, val, buf[MAX_STR_SIZE]; 625 uint8_t version, val, buf[MAX_STR_SIZE];
627 626
628 if (lflag) { 627 if (lflag) {
629 tag(btr.btr_name); 628 tag(btr.btr_name);
630 return; 629 return;
631 } 630 }
632 631
633 if (level-- < 1) 632 if (level-- < 1)
634 return; 633 return;
635 634
636 snprintb((char *)buf, MAX_STR_SIZE, FLAGS_FMT, btr.btr_flags); 635 snprintb((char *)buf, MAX_STR_SIZE, FLAGS_FMT, btr.btr_flags);
637 636
638 printf("%s: bdaddr %s flags %s\n", btr.btr_name, 637 printf("%s: bdaddr %s flags %s\n", btr.btr_name,
639 bt_ntoa(&btr.btr_bdaddr, NULL), buf); 638 bt_ntoa(&btr.btr_bdaddr, NULL), buf);
640 639
641 if (level-- < 1) 640 if (level-- < 1)
642 return; 641 return;
643 642
644 printf("\tnum_cmd = %d\n" 643 printf("\tnum_cmd = %d\n"
645 "\tnum_acl = %d (max %d), acl_mtu = %d\n" 644 "\tnum_acl = %d (max %d), acl_mtu = %d\n"
646 "\tnum_sco = %d (max %d), sco_mtu = %d\n", 645 "\tnum_sco = %d (max %d), sco_mtu = %d\n",
647 btr.btr_num_cmd, 646 btr.btr_num_cmd,
648 btr.btr_num_acl, btr.btr_max_acl, btr.btr_acl_mtu, 647 btr.btr_num_acl, btr.btr_max_acl, btr.btr_acl_mtu,
649 btr.btr_num_sco, btr.btr_max_sco, btr.btr_sco_mtu); 648 btr.btr_num_sco, btr.btr_max_sco, btr.btr_sco_mtu);
650 649
651 if (level-- < 1 || (btr.btr_flags & BTF_UP) == 0) 650 if (level-- < 1 || (btr.btr_flags & BTF_UP) == 0)
652 return; 651 return;
653 652
654 load_value(HCI_CMD_READ_LOCAL_VER, &version, sizeof(version)); 653 load_value(HCI_CMD_READ_LOCAL_VER, &version, sizeof(version));
655 printf("\tHCI version: "); 654 printf("\tHCI version: ");
656 switch(version) { 655 switch(version) {
657 case HCI_SPEC_V10: printf("1.0b\n"); break; 656 case HCI_SPEC_V10: printf("1.0b\n"); break;
658 case HCI_SPEC_V11: printf("1.1\n"); break; 657 case HCI_SPEC_V11: printf("1.1\n"); break;
659 case HCI_SPEC_V12: printf("1.2\n"); break; 658 case HCI_SPEC_V12: printf("1.2\n"); break;
660 case HCI_SPEC_V20: printf("2.0 + EDR\n"); break; 659 case HCI_SPEC_V20: printf("2.0 + EDR\n"); break;
661 case HCI_SPEC_V21: printf("2.1 + EDR\n"); break; 660 case HCI_SPEC_V21: printf("2.1 + EDR\n"); break;
662 case HCI_SPEC_V30: printf("3.0 + HS\n"); break; 661 case HCI_SPEC_V30: printf("3.0 + HS\n"); break;
663 default: printf("unknown\n"); break; 662 default: printf("unknown\n"); break;
664 } 663 }
665 664
666 load_value(HCI_CMD_READ_UNIT_CLASS, buf, HCI_CLASS_SIZE); 665 load_value(HCI_CMD_READ_UNIT_CLASS, buf, HCI_CLASS_SIZE);
667 print_class("\tclass:", buf); 666 print_class("\tclass:", buf);
668 667
669 load_value(HCI_CMD_READ_LOCAL_NAME, buf, HCI_UNIT_NAME_SIZE); 668 load_value(HCI_CMD_READ_LOCAL_NAME, buf, HCI_UNIT_NAME_SIZE);
670 printf("\tname: \"%s\"\n", buf); 669 printf("\tname: \"%s\"\n", buf);
671 670
672 load_value(HCI_CMD_READ_VOICE_SETTING, buf, sizeof(uint16_t)); 671 load_value(HCI_CMD_READ_VOICE_SETTING, buf, sizeof(uint16_t));
673 voice = (buf[1] << 8) | buf[0]; 672 voice = (buf[1] << 8) | buf[0];
674 print_voice(level); 673 print_voice(level);
675 674
676 load_value(HCI_CMD_READ_PIN_TYPE, &val, sizeof(val)); 675 load_value(HCI_CMD_READ_PIN_TYPE, &val, sizeof(val));
677 printf("\tpin: %s\n", val ? "fixed" : "variable"); 676 printf("\tpin: %s\n", val ? "fixed" : "variable");
678 677
679 val = 0; 678 val = 0;
680 if (version >= HCI_SPEC_V12) 679 if (version >= HCI_SPEC_V12)
681 load_value(HCI_CMD_READ_INQUIRY_MODE, &val, sizeof(val)); 680 load_value(HCI_CMD_READ_INQUIRY_MODE, &val, sizeof(val));
682 681
683 print_val("inquiry mode", imodes, val); 682 print_val("inquiry mode", imodes, val);
684 683
685 width = printf("\toptions:"); 684 width = printf("\toptions:");
686 685
687 load_value(HCI_CMD_READ_SCAN_ENABLE, &val, sizeof(val)); 686 load_value(HCI_CMD_READ_SCAN_ENABLE, &val, sizeof(val));
688 if (val & HCI_INQUIRY_SCAN_ENABLE) tag("iscan"); 687 if (val & HCI_INQUIRY_SCAN_ENABLE) tag("iscan");
689 else if (level > 0) tag("-iscan"); 688 else if (level > 0) tag("-iscan");
690 689
691 if (val & HCI_PAGE_SCAN_ENABLE) tag("pscan"); 690 if (val & HCI_PAGE_SCAN_ENABLE) tag("pscan");
692 else if (level > 0) tag("-pscan"); 691 else if (level > 0) tag("-pscan");
693 692
694 load_value(HCI_CMD_READ_AUTH_ENABLE, &val, sizeof(val)); 693 load_value(HCI_CMD_READ_AUTH_ENABLE, &val, sizeof(val));
695 if (val) tag("auth"); 694 if (val) tag("auth");
696 else if (level > 0) tag("-auth"); 695 else if (level > 0) tag("-auth");
697 696
698 load_value(HCI_CMD_READ_ENCRYPTION_MODE, &val, sizeof(val)); 697 load_value(HCI_CMD_READ_ENCRYPTION_MODE, &val, sizeof(val));
699 if (val) tag("encrypt"); 698 if (val) tag("encrypt");
700 else if (level > 0) tag("-encrypt"); 699 else if (level > 0) tag("-encrypt");
701 700
702 val = btr.btr_link_policy; 701 val = btr.btr_link_policy;
703 if (val & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH) tag("switch"); 702 if (val & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH) tag("switch");
704 else if (level > 0) tag("-switch"); 703 else if (level > 0) tag("-switch");
705 if (val & HCI_LINK_POLICY_ENABLE_HOLD_MODE) tag("hold"); 704 if (val & HCI_LINK_POLICY_ENABLE_HOLD_MODE) tag("hold");
706 else if (level > 0) tag("-hold"); 705 else if (level > 0) tag("-hold");
707 if (val & HCI_LINK_POLICY_ENABLE_SNIFF_MODE) tag("sniff"); 706 if (val & HCI_LINK_POLICY_ENABLE_SNIFF_MODE) tag("sniff");
708 else if (level > 0) tag("-sniff"); 707 else if (level > 0) tag("-sniff");
709 if (val & HCI_LINK_POLICY_ENABLE_PARK_MODE) tag("park"); 708 if (val & HCI_LINK_POLICY_ENABLE_PARK_MODE) tag("park");
710 else if (level > 0) tag("-park"); 709 else if (level > 0) tag("-park");
711 710
712 tag(NULL); 711 tag(NULL);
713 712
714 if (level-- < 1) 713 if (level-- < 1)
715 return; 714 return;
716 715
717 ptype = btr.btr_packet_type; 716 ptype = btr.btr_packet_type;
718 width = printf("\tptype: [0x%04x]", ptype); 717 width = printf("\tptype: [0x%04x]", ptype);
719 if (ptype & HCI_PKT_DM1) tag("DM1"); 718 if (ptype & HCI_PKT_DM1) tag("DM1");
720 if (ptype & HCI_PKT_DH1) tag("DH1"); 719 if (ptype & HCI_PKT_DH1) tag("DH1");
721 if (ptype & HCI_PKT_DM3) tag("DM3"); 720 if (ptype & HCI_PKT_DM3) tag("DM3");
722 if (ptype & HCI_PKT_DH3) tag("DH3"); 721 if (ptype & HCI_PKT_DH3) tag("DH3");
723 if (ptype & HCI_PKT_DM5) tag("DM5"); 722 if (ptype & HCI_PKT_DM5) tag("DM5");
724 if (ptype & HCI_PKT_DH5) tag("DH5"); 723 if (ptype & HCI_PKT_DH5) tag("DH5");
725 if ((ptype & HCI_PKT_2MBPS_DH1) == 0) tag("2-DH1"); 724 if ((ptype & HCI_PKT_2MBPS_DH1) == 0) tag("2-DH1");
726 if ((ptype & HCI_PKT_3MBPS_DH1) == 0) tag("3-DH1"); 725 if ((ptype & HCI_PKT_3MBPS_DH1) == 0) tag("3-DH1");
727 if ((ptype & HCI_PKT_2MBPS_DH3) == 0) tag("2-DH3"); 726 if ((ptype & HCI_PKT_2MBPS_DH3) == 0) tag("2-DH3");
728 if ((ptype & HCI_PKT_3MBPS_DH3) == 0) tag("3-DH3"); 727 if ((ptype & HCI_PKT_3MBPS_DH3) == 0) tag("3-DH3");
729 if ((ptype & HCI_PKT_2MBPS_DH5) == 0) tag("2-DH5"); 728 if ((ptype & HCI_PKT_2MBPS_DH5) == 0) tag("2-DH5");
730 if ((ptype & HCI_PKT_3MBPS_DH5) == 0) tag("3-DH5"); 729 if ((ptype & HCI_PKT_3MBPS_DH5) == 0) tag("3-DH5");
731 tag(NULL); 730 tag(NULL);
732 731
733 load_value(HCI_CMD_READ_PAGE_TIMEOUT, buf, sizeof(uint16_t)); 732 load_value(HCI_CMD_READ_PAGE_TIMEOUT, buf, sizeof(uint16_t));
734 printf("\tpage timeout: %d ms\n", le16dec(buf) * 5 / 8); 733 printf("\tpage timeout: %d ms\n", le16dec(buf) * 5 / 8);
735 734
736 if (level-- < 1) 735 if (level-- < 1)
737 return; 736 return;
738 737
739 if (ioctl(hci, SIOCGBTFEAT, &btr) < 0) 738 if (ioctl(hci, SIOCGBTFEAT, &btr) < 0)
740 err(EXIT_FAILURE, "SIOCGBTFEAT"); 739 err(EXIT_FAILURE, "SIOCGBTFEAT");
741 740
742 width = printf("\tfeatures:"); 741 width = printf("\tfeatures:");
743 print_features0(btr.btr_features0); 742 print_features0(btr.btr_features0);
744 print_features1(btr.btr_features1); 743 print_features1(btr.btr_features1);
745 tag(NULL); 744 tag(NULL);
746} 745}
747 746
748void 747static void
749print_stats(void) 748print_stats(void)
750{ 749{
751 750
752 if (sflag == 0) 751 if (sflag == 0)
753 return; 752 return;
754 753
755 if (sflag == 1) { 754 if (sflag == 1) {
756 if (ioctl(hci, SIOCGBTSTATS, &btr) < 0) 755 if (ioctl(hci, SIOCGBTSTATS, &btr) < 0)
757 err(EXIT_FAILURE, "SIOCGBTSTATS"); 756 err(EXIT_FAILURE, "SIOCGBTSTATS");
758 } else { 757 } else {
759 if (ioctl(hci, SIOCZBTSTATS, &btr) < 0) 758 if (ioctl(hci, SIOCZBTSTATS, &btr) < 0)
760 err(EXIT_FAILURE, "SIOCZBTSTATS"); 759 err(EXIT_FAILURE, "SIOCZBTSTATS");
761 } 760 }
762 761
763 printf( "\tTotal bytes sent %d, recieved %d\n" 762 printf( "\tTotal bytes sent %d, recieved %d\n"
764 "\tCommands sent %d, Events received %d\n" 763 "\tCommands sent %d, Events received %d\n"
765 "\tACL data packets sent %d, received %d\n" 764 "\tACL data packets sent %d, received %d\n"
766 "\tSCO data packets sent %d, received %d\n" 765 "\tSCO data packets sent %d, received %d\n"
767 "\tInput errors %d, Output errors %d\n", 766 "\tInput errors %d, Output errors %d\n",
768 btr.btr_stats.byte_tx, btr.btr_stats.byte_rx, 767 btr.btr_stats.byte_tx, btr.btr_stats.byte_rx,
769 btr.btr_stats.cmd_tx, btr.btr_stats.evt_rx, 768 btr.btr_stats.cmd_tx, btr.btr_stats.evt_rx,
770 btr.btr_stats.acl_tx, btr.btr_stats.acl_rx, 769 btr.btr_stats.acl_tx, btr.btr_stats.acl_rx,
771 btr.btr_stats.sco_tx, btr.btr_stats.sco_rx, 770 btr.btr_stats.sco_tx, btr.btr_stats.sco_rx,
772 btr.btr_stats.err_rx, btr.btr_stats.err_tx); 771 btr.btr_stats.err_rx, btr.btr_stats.err_tx);
773} 772}
774 773
775void 774static void
776print_features0(uint8_t *f) 775print_features0(uint8_t *f)
777{ 776{
778 777
779 /* ------------------- byte 0 --------------------*/ 778 /* ------------------- byte 0 --------------------*/
780 if (*f & HCI_LMP_3SLOT) tag("<3 slot>"); 779 if (*f & HCI_LMP_3SLOT) tag("<3 slot>");
781 if (*f & HCI_LMP_5SLOT) tag("<5 slot>"); 780 if (*f & HCI_LMP_5SLOT) tag("<5 slot>");
782 if (*f & HCI_LMP_ENCRYPTION) tag("<encryption>"); 781 if (*f & HCI_LMP_ENCRYPTION) tag("<encryption>");
783 if (*f & HCI_LMP_SLOT_OFFSET) tag("<slot offset>"); 782 if (*f & HCI_LMP_SLOT_OFFSET) tag("<slot offset>");
784 if (*f & HCI_LMP_TIMIACCURACY) tag("<timing accuracy>"); 783 if (*f & HCI_LMP_TIMIACCURACY) tag("<timing accuracy>");
785 if (*f & HCI_LMP_ROLE_SWITCH) tag("<role switch>"); 784 if (*f & HCI_LMP_ROLE_SWITCH) tag("<role switch>");
786 if (*f & HCI_LMP_HOLD_MODE) tag("<hold mode>"); 785 if (*f & HCI_LMP_HOLD_MODE) tag("<hold mode>");
787 if (*f & HCI_LMP_SNIFF_MODE) tag("<sniff mode>"); 786 if (*f & HCI_LMP_SNIFF_MODE) tag("<sniff mode>");
788 f++; 787 f++;
789 788
790 /* ------------------- byte 1 --------------------*/ 789 /* ------------------- byte 1 --------------------*/
791 if (*f & HCI_LMP_PARK_MODE) tag("<park mode>"); 790 if (*f & HCI_LMP_PARK_MODE) tag("<park mode>");
792 if (*f & HCI_LMP_RSSI) tag("<RSSI>"); 791 if (*f & HCI_LMP_RSSI) tag("<RSSI>");
793 if (*f & HCI_LMP_CHANNEL_QUALITY) tag("<channel quality>"); 792 if (*f & HCI_LMP_CHANNEL_QUALITY) tag("<channel quality>");
794 if (*f & HCI_LMP_SCO_LINK) tag("<SCO link>"); 793 if (*f & HCI_LMP_SCO_LINK) tag("<SCO link>");
795 if (*f & HCI_LMP_HV2_PKT) tag("<HV2>"); 794 if (*f & HCI_LMP_HV2_PKT) tag("<HV2>");
796 if (*f & HCI_LMP_HV3_PKT) tag("<HV3>"); 795 if (*f & HCI_LMP_HV3_PKT) tag("<HV3>");
797 if (*f & HCI_LMP_ULAW_LOG) tag("<u-Law log>"); 796 if (*f & HCI_LMP_ULAW_LOG) tag("<u-Law log>");
798 if (*f & HCI_LMP_ALAW_LOG) tag("<A-Law log>"); 797 if (*f & HCI_LMP_ALAW_LOG) tag("<A-Law log>");
799 f++; 798 f++;
800 799
801 /* ------------------- byte 1 --------------------*/ 800 /* ------------------- byte 1 --------------------*/
802 if (*f & HCI_LMP_CVSD) tag("<CVSD data>"); 801 if (*f & HCI_LMP_CVSD) tag("<CVSD data>");
803 if (*f & HCI_LMP_PAGISCHEME) tag("<paging parameter>"); 802 if (*f & HCI_LMP_PAGISCHEME) tag("<paging parameter>");
804 if (*f & HCI_LMP_POWER_CONTROL) tag("<power control>"); 803 if (*f & HCI_LMP_POWER_CONTROL) tag("<power control>");
805 if (*f & HCI_LMP_TRANSPARENT_SCO) tag("<transparent SCO>"); 804 if (*f & HCI_LMP_TRANSPARENT_SCO) tag("<transparent SCO>");
806 if (*f & HCI_LMP_FLOW_CONTROL_LAG0) tag("<flow control lag 0>"); 805 if (*f & HCI_LMP_FLOW_CONTROL_LAG0) tag("<flow control lag 0>");
807 if (*f & HCI_LMP_FLOW_CONTROL_LAG1) tag("<flow control lag 1>"); 806 if (*f & HCI_LMP_FLOW_CONTROL_LAG1) tag("<flow control lag 1>");
808 if (*f & HCI_LMP_FLOW_CONTROL_LAG2) tag("<flow control lag 2>"); 807 if (*f & HCI_LMP_FLOW_CONTROL_LAG2) tag("<flow control lag 2>");
809 if (*f & HCI_LMP_BC_ENCRYPTION) tag("<broadcast encryption>"); 808 if (*f & HCI_LMP_BC_ENCRYPTION) tag("<broadcast encryption>");
810 f++; 809 f++;
811 810
812 /* ------------------- byte 3 --------------------*/ 811 /* ------------------- byte 3 --------------------*/
813 if (*f & HCI_LMP_EDR_ACL_2MBPS) tag("<EDR ACL 2Mbps>"); 812 if (*f & HCI_LMP_EDR_ACL_2MBPS) tag("<EDR ACL 2Mbps>");
814 if (*f & HCI_LMP_EDR_ACL_3MBPS) tag("<EDR ACL 3Mbps>"); 813 if (*f & HCI_LMP_EDR_ACL_3MBPS) tag("<EDR ACL 3Mbps>");
815 if (*f & HCI_LMP_ENHANCED_ISCAN) tag("<enhanced inquiry scan>"); 814 if (*f & HCI_LMP_ENHANCED_ISCAN) tag("<enhanced inquiry scan>");
816 if (*f & HCI_LMP_INTERLACED_ISCAN) tag("<interlaced inquiry scan>"); 815 if (*f & HCI_LMP_INTERLACED_ISCAN) tag("<interlaced inquiry scan>");
817 if (*f & HCI_LMP_INTERLACED_PSCAN) tag("<interlaced page scan>"); 816 if (*f & HCI_LMP_INTERLACED_PSCAN) tag("<interlaced page scan>");
818 if (*f & HCI_LMP_RSSI_INQUIRY) tag("<RSSI with inquiry result>"); 817 if (*f & HCI_LMP_RSSI_INQUIRY) tag("<RSSI with inquiry result>");
819 if (*f & HCI_LMP_EV3_PKT) tag("<EV3 packets>"); 818 if (*f & HCI_LMP_EV3_PKT) tag("<EV3 packets>");
820 f++; 819 f++;
821 820
822 /* ------------------- byte 4 --------------------*/ 821 /* ------------------- byte 4 --------------------*/
823 if (*f & HCI_LMP_EV4_PKT) tag("<EV4 packets>"); 822 if (*f & HCI_LMP_EV4_PKT) tag("<EV4 packets>");
824 if (*f & HCI_LMP_EV5_PKT) tag("<EV5 packets>"); 823 if (*f & HCI_LMP_EV5_PKT) tag("<EV5 packets>");
825 if (*f & HCI_LMP_AFH_CAPABLE_SLAVE) tag("<AFH capable slave>"); 824 if (*f & HCI_LMP_AFH_CAPABLE_SLAVE) tag("<AFH capable slave>");
826 if (*f & HCI_LMP_AFH_CLASS_SLAVE) tag("<AFH class slave>"); 825 if (*f & HCI_LMP_AFH_CLASS_SLAVE) tag("<AFH class slave>");
827 if (*f & HCI_LMP_3SLOT_EDR_ACL) tag("<3 slot EDR ACL>"); 826 if (*f & HCI_LMP_3SLOT_EDR_ACL) tag("<3 slot EDR ACL>");
828 f++; 827 f++;
829 828
830 /* ------------------- byte 5 --------------------*/ 829 /* ------------------- byte 5 --------------------*/
831 if (*f & HCI_LMP_5SLOT_EDR_ACL) tag("<5 slot EDR ACL>"); 830 if (*f & HCI_LMP_5SLOT_EDR_ACL) tag("<5 slot EDR ACL>");
832 if (*f & HCI_LMP_SNIFF_SUBRATING) tag("<sniff subrating>"); 831 if (*f & HCI_LMP_SNIFF_SUBRATING) tag("<sniff subrating>");
833 if (*f & HCI_LMP_PAUSE_ENCRYPTION) tag("<pause encryption>"); 832 if (*f & HCI_LMP_PAUSE_ENCRYPTION) tag("<pause encryption>");
834 if (*f & HCI_LMP_AFH_CAPABLE_MASTER)tag("<AFH capable master>"); 833 if (*f & HCI_LMP_AFH_CAPABLE_MASTER)tag("<AFH capable master>");
835 if (*f & HCI_LMP_AFH_CLASS_MASTER) tag("<AFH class master>"); 834 if (*f & HCI_LMP_AFH_CLASS_MASTER) tag("<AFH class master>");
836 if (*f & HCI_LMP_EDR_eSCO_2MBPS) tag("<EDR eSCO 2Mbps>"); 835 if (*f & HCI_LMP_EDR_eSCO_2MBPS) tag("<EDR eSCO 2Mbps>");
837 if (*f & HCI_LMP_EDR_eSCO_3MBPS) tag("<EDR eSCO 3Mbps>"); 836 if (*f & HCI_LMP_EDR_eSCO_3MBPS) tag("<EDR eSCO 3Mbps>");
838 if (*f & HCI_LMP_3SLOT_EDR_eSCO) tag("<3 slot EDR eSCO>"); 837 if (*f & HCI_LMP_3SLOT_EDR_eSCO) tag("<3 slot EDR eSCO>");
839 f++; 838 f++;
840 839
841 /* ------------------- byte 6 --------------------*/ 840 /* ------------------- byte 6 --------------------*/
842 if (*f & HCI_LMP_EXTENDED_INQUIRY) tag("<extended inquiry>"); 841 if (*f & HCI_LMP_EXTENDED_INQUIRY) tag("<extended inquiry>");
843 if (*f & HCI_LMP_SIMPLE_PAIRING) tag("<secure simple pairing>"); 842 if (*f & HCI_LMP_SIMPLE_PAIRING) tag("<secure simple pairing>");
844 if (*f & HCI_LMP_ENCAPSULATED_PDU) tag("<encapsulated PDU>"); 843 if (*f & HCI_LMP_ENCAPSULATED_PDU) tag("<encapsulated PDU>");
845 if (*f & HCI_LMP_ERRDATA_REPORTING) tag("<errdata reporting>"); 844 if (*f & HCI_LMP_ERRDATA_REPORTING) tag("<errdata reporting>");
846 if (*f & HCI_LMP_NOFLUSH_PB_FLAG) tag("<no flush PB flag>"); 845 if (*f & HCI_LMP_NOFLUSH_PB_FLAG) tag("<no flush PB flag>");
847 f++; 846 f++;
848 847
849 /* ------------------- byte 7 --------------------*/ 848 /* ------------------- byte 7 --------------------*/
850 if (*f & HCI_LMP_LINK_SUPERVISION_TO)tag("<link supervision timeout changed>"); 849 if (*f & HCI_LMP_LINK_SUPERVISION_TO)tag("<link supervision timeout changed>");
851 if (*f & HCI_LMP_INQ_RSP_TX_POWER) tag("<inquiry rsp TX power level>"); 850 if (*f & HCI_LMP_INQ_RSP_TX_POWER) tag("<inquiry rsp TX power level>");
852 if (*f & HCI_LMP_ENHANCED_POWER_CONTROL)tag("<enhanced power control>"); 851 if (*f & HCI_LMP_ENHANCED_POWER_CONTROL)tag("<enhanced power control>");
853 if (*f & HCI_LMP_EXTENDED_FEATURES) tag("<extended features>"); 852 if (*f & HCI_LMP_EXTENDED_FEATURES) tag("<extended features>");
854} 853}
855 854
856void 855static void
857print_features1(uint8_t *f) 856print_features1(uint8_t *f)
858{ 857{
859 858
860 /* ------------------- byte 0 --------------------*/ 859 /* ------------------- byte 0 --------------------*/
861 if (*f & HCI_LMP_SSP) tag("<secure simple pairing>"); 860 if (*f & HCI_LMP_SSP) tag("<secure simple pairing>");
862} 861}
863 862
864void 863static void
865print_class(const char *str, uint8_t *uclass) 864print_class(const char *str, uint8_t *uclass)
866{ 865{
867 866
868 class = (uclass[2] << 16) | (uclass[1] << 8) | uclass[0]; 867 class = (uclass[2] << 16) | (uclass[1] << 8) | uclass[0];
869 width = printf("%s [0x%06x]", str, class); 868 width = printf("%s [0x%06x]", str, class);
870 869
871 switch(__SHIFTOUT(class, __BITS(0, 1))) { 870 switch(__SHIFTOUT(class, __BITS(0, 1))) {
872 case 0: print_class0(); break; 871 case 0: print_class0(); break;
873 default: break; 872 default: break;
874 } 873 }
875 874
876 tag(NULL); 875 tag(NULL);
877} 876}
878 877
879void 878static void
880print_class0(void) 879print_class0(void)
881{ 880{
882 881
883 switch (__SHIFTOUT(class, __BITS(8, 12))) { 882 switch (__SHIFTOUT(class, __BITS(8, 12))) {
884 case 1: /* Computer */ 883 case 1: /* Computer */
885 switch (__SHIFTOUT(class, __BITS(2, 7))) { 884 switch (__SHIFTOUT(class, __BITS(2, 7))) {
886 case 1: tag("Desktop workstation"); break; 885 case 1: tag("Desktop workstation"); break;
887 case 2: tag("Server-class computer"); break; 886 case 2: tag("Server-class computer"); break;
888 case 3: tag("Laptop"); break; 887 case 3: tag("Laptop"); break;
889 case 4: tag("Handheld PC/PDA"); break; 888 case 4: tag("Handheld PC/PDA"); break;
890 case 5: tag("Palm Sized PC/PDA"); break; 889 case 5: tag("Palm Sized PC/PDA"); break;
891 case 6: tag("Wearable computer"); break; 890 case 6: tag("Wearable computer"); break;
892 default: tag("Computer"); break; 891 default: tag("Computer"); break;
893 } 892 }
894 break; 893 break;
895 894
896 case 2: /* Phone */ 895 case 2: /* Phone */
897 switch (__SHIFTOUT(class, __BITS(2, 7))) { 896 switch (__SHIFTOUT(class, __BITS(2, 7))) {
898 case 1: tag("Cellular Phone"); break; 897 case 1: tag("Cellular Phone"); break;
899 case 2: tag("Cordless Phone"); break; 898 case 2: tag("Cordless Phone"); break;
900 case 3: tag("Smart Phone"); break; 899 case 3: tag("Smart Phone"); break;
901 case 4: tag("Wired Modem/Phone Gateway"); break; 900 case 4: tag("Wired Modem/Phone Gateway"); break;
902 case 5: tag("Common ISDN"); break; 901 case 5: tag("Common ISDN"); break;
903 default:tag("Phone"); break; 902 default:tag("Phone"); break;
904 } 903 }
905 break; 904 break;
906 905
907 case 3: /* LAN */ 906 case 3: /* LAN */
908 tag("LAN"); 907 tag("LAN");
909 switch (__SHIFTOUT(class, __BITS(5, 7))) { 908 switch (__SHIFTOUT(class, __BITS(5, 7))) {
910 case 0: tag("[Fully available]"); break; 909 case 0: tag("[Fully available]"); break;
911 case 1: tag("[1-17% utilised]"); break; 910 case 1: tag("[1-17% utilised]"); break;
912 case 2: tag("[17-33% utilised]"); break; 911 case 2: tag("[17-33% utilised]"); break;
913 case 3: tag("[33-50% utilised]"); break; 912 case 3: tag("[33-50% utilised]"); break;
914 case 4: tag("[50-67% utilised]"); break; 913 case 4: tag("[50-67% utilised]"); break;
915 case 5: tag("[67-83% utilised]"); break; 914 case 5: tag("[67-83% utilised]"); break;
916 case 6: tag("[83-99% utilised]"); break; 915 case 6: tag("[83-99% utilised]"); break;
917 case 7: tag("[No service available]"); break; 916 case 7: tag("[No service available]"); break;
918 } 917 }
919 break; 918 break;
920 919
921 case 4: /* Audio/Visual */ 920 case 4: /* Audio/Visual */
922 switch (__SHIFTOUT(class, __BITS(2, 7))) { 921 switch (__SHIFTOUT(class, __BITS(2, 7))) {
923 case 1: tag("Wearable Headset"); break; 922 case 1: tag("Wearable Headset"); break;
924 case 2: tag("Hands-free Audio"); break; 923 case 2: tag("Hands-free Audio"); break;
925 case 4: tag("Microphone"); break; 924 case 4: tag("Microphone"); break;
926 case 5: tag("Loudspeaker"); break; 925 case 5: tag("Loudspeaker"); break;
927 case 6: tag("Headphones"); break; 926 case 6: tag("Headphones"); break;
928 case 7: tag("Portable Audio"); break; 927 case 7: tag("Portable Audio"); break;
929 case 8: tag("Car Audio"); break; 928 case 8: tag("Car Audio"); break;
930 case 9: tag("Set-top Box"); break; 929 case 9: tag("Set-top Box"); break;
931 case 10: tag("HiFi Audio"); break; 930 case 10: tag("HiFi Audio"); break;
932 case 11: tag("VCR"); break; 931 case 11: tag("VCR"); break;
933 case 12: tag("Video Camera"); break; 932 case 12: tag("Video Camera"); break;
934 case 13: tag("Camcorder"); break; 933 case 13: tag("Camcorder"); break;
935 case 14: tag("Video Monitor"); break; 934 case 14: tag("Video Monitor"); break;
936 case 15: tag("Video Display and Loudspeaker"); break; 935 case 15: tag("Video Display and Loudspeaker"); break;
937 case 16: tag("Video Conferencing"); break; 936 case 16: tag("Video Conferencing"); break;
938 case 18: tag("A/V [Gaming/Toy]"); break; 937 case 18: tag("A/V [Gaming/Toy]"); break;
939 default: tag("Audio/Visual"); break; 938 default: tag("Audio/Visual"); break;
940 } 939 }
941 break; 940 break;
942 941
943 case 5: /* Peripheral */ 942 case 5: /* Peripheral */
944 switch (__SHIFTOUT(class, __BITS(2, 5))) { 943 switch (__SHIFTOUT(class, __BITS(2, 5))) {
945 case 1: tag("Joystick"); break; 944 case 1: tag("Joystick"); break;
946 case 2: tag("Gamepad"); break; 945 case 2: tag("Gamepad"); break;
947 case 3: tag("Remote Control"); break; 946 case 3: tag("Remote Control"); break;
948 case 4: tag("Sensing Device"); break; 947 case 4: tag("Sensing Device"); break;
949 case 5: tag("Digitiser Tablet"); break; 948 case 5: tag("Digitiser Tablet"); break;
950 case 6: tag("Card Reader"); break; 949 case 6: tag("Card Reader"); break;
951 default: tag("Peripheral"); break; 950 default: tag("Peripheral"); break;
952 } 951 }
953 952
954 if (class & __BIT(6)) tag("Keyboard"); 953 if (class & __BIT(6)) tag("Keyboard");
955 if (class & __BIT(7)) tag("Mouse"); 954 if (class & __BIT(7)) tag("Mouse");
956 break; 955 break;
957 956
958 case 6: /* Imaging */ 957 case 6: /* Imaging */
959 if (class & __BIT(4)) tag("Display"); 958 if (class & __BIT(4)) tag("Display");
960 if (class & __BIT(5)) tag("Camera"); 959 if (class & __BIT(5)) tag("Camera");
961 if (class & __BIT(6)) tag("Scanner"); 960 if (class & __BIT(6)) tag("Scanner");
962 if (class & __BIT(7)) tag("Printer"); 961 if (class & __BIT(7)) tag("Printer");
963 if ((class & __BITS(4, 7)) == 0) tag("Imaging"); 962 if ((class & __BITS(4, 7)) == 0) tag("Imaging");
964 break; 963 break;
965 964
966 case 7: /* Wearable */ 965 case 7: /* Wearable */
967 switch (__SHIFTOUT(class, __BITS(2, 7))) { 966 switch (__SHIFTOUT(class, __BITS(2, 7))) {
968 case 1: tag("Wrist Watch"); break; 967 case 1: tag("Wrist Watch"); break;
969 case 2: tag("Pager"); break; 968 case 2: tag("Pager"); break;
970 case 3: tag("Jacket"); break; 969 case 3: tag("Jacket"); break;
971 case 4: tag("Helmet"); break; 970 case 4: tag("Helmet"); break;
972 case 5: tag("Glasses"); break; 971 case 5: tag("Glasses"); break;
973 default: tag("Wearable"); break; 972 default: tag("Wearable"); break;
974 } 973 }
975 break; 974 break;
976 975
977 case 8: /* Toy */ 976 case 8: /* Toy */
978 switch (__SHIFTOUT(class, __BITS(2, 7))) { 977 switch (__SHIFTOUT(class, __BITS(2, 7))) {
979 case 1: tag("Robot"); break; 978 case 1: tag("Robot"); break;
980 case 2: tag("Vehicle"); break; 979 case 2: tag("Vehicle"); break;
981 case 3: tag("Doll / Action Figure"); break; 980 case 3: tag("Doll / Action Figure"); break;
982 case 4: tag("Controller"); break; 981 case 4: tag("Controller"); break;
983 case 5: tag("Game"); break; 982 case 5: tag("Game"); break;
984 default: tag("Toy"); break; 983 default: tag("Toy"); break;
985 } 984 }
986 break; 985 break;
987 986
988 case 9: /* Health */ 987 case 9: /* Health */
989 switch (__SHIFTOUT(class, __BITS(2, 7))) { 988 switch (__SHIFTOUT(class, __BITS(2, 7))) {
990 case 1: tag("Blood Pressure Monitor"); break; 989 case 1: tag("Blood Pressure Monitor"); break;
991 case 2: tag("Thermometer"); break; 990 case 2: tag("Thermometer"); break;
992 case 3: tag("Weighing Scale"); break; 991 case 3: tag("Weighing Scale"); break;
993 case 4: tag("Glucose Meter"); break; 992 case 4: tag("Glucose Meter"); break;
994 case 5: tag("Pulse Oximeter"); break; 993 case 5: tag("Pulse Oximeter"); break;
995 case 6: tag("Heart/Pulse Rate Monitor"); break; 994 case 6: tag("Heart/Pulse Rate Monitor"); break;
996 case 7: tag("Health Data Display"); break; 995 case 7: tag("Health Data Display"); break;
997 default: tag("Health"); break; 996 default: tag("Health"); break;
998 } 997 }
999 break; 998 break;
1000 999
1001 default: 1000 default:
1002 break; 1001 break;
1003 } 1002 }
1004 1003
1005 if (class & __BIT(13)) tag("<Limited Discoverable>"); 1004 if (class & __BIT(13)) tag("<Limited Discoverable>");
1006 if (class & __BIT(16)) tag("<Positioning>"); 1005 if (class & __BIT(16)) tag("<Positioning>");
1007 if (class & __BIT(17)) tag("<Networking>"); 1006 if (class & __BIT(17)) tag("<Networking>");
1008 if (class & __BIT(18)) tag("<Rendering>"); 1007 if (class & __BIT(18)) tag("<Rendering>");
1009 if (class & __BIT(19)) tag("<Capturing>"); 1008 if (class & __BIT(19)) tag("<Capturing>");
1010 if (class & __BIT(20)) tag("<Object Transfer>"); 1009 if (class & __BIT(20)) tag("<Object Transfer>");
1011 if (class & __BIT(21)) tag("<Audio>"); 1010 if (class & __BIT(21)) tag("<Audio>");
1012 if (class & __BIT(22)) tag("<Telephony>"); 1011 if (class & __BIT(22)) tag("<Telephony>");
1013 if (class & __BIT(23)) tag("<Information>"); 1012 if (class & __BIT(23)) tag("<Information>");
1014} 1013}
1015 1014
1016void 1015static void
1017print_voice(int level) 1016print_voice(int level)
1018{ 1017{
1019 printf("\tvoice: [0x%4.4x]\n", voice); 1018 printf("\tvoice: [0x%4.4x]\n", voice);
1020 1019
1021 if (level == 0) 1020 if (level == 0)
1022 return; 1021 return;
1023 1022
1024 printf("\t\tInput Coding: "); 1023 printf("\t\tInput Coding: ");
1025 switch ((voice & 0x0300) >> 8) { 1024 switch ((voice & 0x0300) >> 8) {
1026 case 0x00: printf("Linear PCM [%d-bit, pos %d]", 1025 case 0x00: printf("Linear PCM [%d-bit, pos %d]",
1027 (voice & 0x0020 ? 16 : 8), 1026 (voice & 0x0020 ? 16 : 8),
1028 (voice & 0x001c) >> 2); break; 1027 (voice & 0x001c) >> 2); break;
1029 case 0x01: printf("u-Law"); break; 1028 case 0x01: printf("u-Law"); break;
1030 case 0x02: printf("A-Law"); break; 1029 case 0x02: printf("A-Law"); break;
1031 case 0x03: printf("unknown"); break; 1030 case 0x03: printf("unknown"); break;
1032 } 1031 }
1033 1032
1034 switch ((voice & 0x00c0) >> 6) { 1033 switch ((voice & 0x00c0) >> 6) {
1035 case 0x00: printf(", 1's complement"); break; 1034 case 0x00: printf(", 1's complement"); break;
1036 case 0x01: printf(", 2's complement"); break; 1035 case 0x01: printf(", 2's complement"); break;
1037 case 0x02: printf(", sign magnitude"); break; 1036 case 0x02: printf(", sign magnitude"); break;
1038 case 0x03: printf(", unsigned"); break; 1037 case 0x03: printf(", unsigned"); break;
1039 } 1038 }
1040 1039
1041 printf("\n\t\tAir Coding: "); 1040 printf("\n\t\tAir Coding: ");
1042 switch (voice & 0x0003) { 1041 switch (voice & 0x0003) {
1043 case 0x00: printf("CVSD"); break; 1042 case 0x00: printf("CVSD"); break;
1044 case 0x01: printf("u-Law"); break; 1043 case 0x01: printf("u-Law"); break;
1045 case 0x02: printf("A-Law"); break; 1044 case 0x02: printf("A-Law"); break;
1046 case 0x03: printf("Transparent"); break; 1045 case 0x03: printf("Transparent"); break;
1047 } 1046 }
1048 1047
1049 printf("\n"); 1048 printf("\n");
1050} 1049}
1051 1050
1052void 1051static void
1053print_result(int num, struct bt_devinquiry *r) 1052print_result(int num, struct bt_devinquiry *r)
1054{ 1053{
1055 hci_remote_name_req_cp ncp; 1054 hci_remote_name_req_cp ncp;
1056 hci_remote_name_req_compl_ep nep; 1055 hci_remote_name_req_compl_ep nep;
1057 struct hostent *hp; 1056 struct hostent *hp;
1058 1057
1059 printf("%3d: bdaddr %s", num, bt_ntoa(&r->bdaddr, NULL)); 1058 printf("%3d: bdaddr %s", num, bt_ntoa(&r->bdaddr, NULL));
1060 1059
1061 hp = bt_gethostbyaddr((const char *)&r->bdaddr, sizeof(bdaddr_t), AF_BLUETOOTH); 1060 hp = bt_gethostbyaddr((const char *)&r->bdaddr, sizeof(bdaddr_t), AF_BLUETOOTH);
1062 if (hp != NULL) 1061 if (hp != NULL)
1063 printf(" (%s)", hp->h_name); 1062 printf(" (%s)", hp->h_name);
1064 1063
1065 printf("\n"); 1064 printf("\n");
1066 1065
1067 memset(&ncp, 0, sizeof(ncp)); 1066 memset(&ncp, 0, sizeof(ncp));
1068 bdaddr_copy(&ncp.bdaddr, &r->bdaddr); 1067 bdaddr_copy(&ncp.bdaddr, &r->bdaddr);
1069 ncp.page_scan_rep_mode = r->pscan_rep_mode; 1068 ncp.page_scan_rep_mode = r->pscan_rep_mode;
1070 ncp.clock_offset = r->clock_offset; 1069 ncp.clock_offset = r->clock_offset;
1071 1070
1072 hci_req(HCI_CMD_REMOTE_NAME_REQ, 1071 hci_req(HCI_CMD_REMOTE_NAME_REQ,
1073 HCI_EVENT_REMOTE_NAME_REQ_COMPL, 1072 HCI_EVENT_REMOTE_NAME_REQ_COMPL,
1074 &ncp, sizeof(ncp), 1073 &ncp, sizeof(ncp),
1075 &nep, sizeof(nep)); 1074 &nep, sizeof(nep));
1076 1075
1077 printf(" : name \"%s\"\n", nep.name); 1076 printf(" : name \"%s\"\n", nep.name);
1078 print_class(" : class", r->dev_class); 1077 print_class(" : class", r->dev_class);
1079 printf(" : page scan rep mode 0x%02x\n", r->pscan_rep_mode); 1078 printf(" : page scan rep mode 0x%02x\n", r->pscan_rep_mode);
1080 printf(" : clock offset %d\n", le16toh(r->clock_offset)); 1079 printf(" : clock offset %d\n", le16toh(r->clock_offset));
1081 printf(" : rssi %d\n", r->rssi); 1080 printf(" : rssi %d\n", r->rssi);
1082 printf("\n"); 1081 printf("\n");
1083} 1082}
1084 1083
1085void 1084static void
1086do_inquiry(void) 1085do_inquiry(void)
1087{ 1086{
1088 struct bt_devinquiry *result; 1087 struct bt_devinquiry *result;
1089 int i, num; 1088 int i, num;
1090 1089
1091 if (opt_inquiry == 0) 1090 if (opt_inquiry == 0)
1092 return; 1091 return;
1093 1092
1094 printf("Device Discovery from device: %s ...", btr.btr_name); 1093 printf("Device Discovery from device: %s ...", btr.btr_name);
1095 fflush(stdout); 1094 fflush(stdout);
1096 1095
1097 num = bt_devinquiry(btr.btr_name, INQUIRY_LENGTH, 1096 num = bt_devinquiry(btr.btr_name, INQUIRY_LENGTH,
1098 INQUIRY_MAX_RESPONSES, &result); 1097 INQUIRY_MAX_RESPONSES, &result);
1099 1098
1100 if (num == -1) { 1099 if (num == -1) {
1101 printf("failed\n"); 1100 printf("failed\n");
1102 err(EXIT_FAILURE, "%s", btr.btr_name); 1101 err(EXIT_FAILURE, "%s", btr.btr_name);
1103 } 1102 }
1104 1103
1105 printf(" %d response%s\n", num, (num == 1 ? "" : "s")); 1104 printf(" %d response%s\n", num, (num == 1 ? "" : "s"));
1106 1105
1107 for (i = 0 ; i < num ; i++) 1106 for (i = 0 ; i < num ; i++)
1108 print_result(i + 1, &result[i]); 1107 print_result(i + 1, &result[i]);
1109 1108
1110 free(result); 1109 free(result);
1111} 1110}