xref: /freebsd/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c (revision 390e8cc2974df1888369c06339ef8e0e92b312b6)
1 /*
2  * host_controller_baseband.c
3  *
4  * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
15  *
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
26  * SUCH DAMAGE.
27  *
28  * $Id: host_controller_baseband.c,v 1.1 2002/11/24 20:22:38 max Exp $
29  * $FreeBSD$
30  */
31 
32 #include <sys/types.h>
33 #include <sys/endian.h>
34 #include <errno.h>
35 #include <ng_hci.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include "hccontrol.h"
39 
40 /* Convert hex ASCII to int4 */
41 static int
42 hci_hexa2int4(const char *a)
43 {
44 	if ('0' <= *a && *a <= '9')
45 		return (*a - '0');
46 
47 	if ('A' <= *a && *a <= 'F')
48 		return (*a - 'A' + 0xa);
49 
50 	if ('a' <= *a && *a <= 'f')
51 		return (*a - 'a' + 0xa);
52 
53 	return (-1);
54 }
55 
56 /* Convert hex ASCII to int8 */
57 static int
58 hci_hexa2int8(const char *a)
59 {
60 	int	hi = hci_hexa2int4(a);
61 	int	lo = hci_hexa2int4(a + 1);
62 
63 	if (hi < 0 || lo < 0)
64 		return (-1);
65 
66 	return ((hi << 4) | lo);
67 }
68 
69 /* Convert ascii hex string to the u_int8_t[] */
70 static int
71 hci_hexstring2array(char const *s, u_int8_t *a, int asize)
72 {
73 	int	i, l, b;
74 
75 	l = strlen(s) / 2;
76 	if (l > asize)
77 		l = asize;
78 
79 	for (i = 0; i < l; i++) {
80 		b = hci_hexa2int8(s + i * 2);
81 		if (b < 0)
82 			return (-1);
83 
84 		a[i] = (b & 0xff);
85 	}
86 
87 	return (0);
88 }
89 
90 /* Send RESET to the unit */
91 static int
92 hci_reset(int s, int argc, char **argv)
93 {
94 	ng_hci_status_rp	rp;
95 	int			n;
96 
97 	n = sizeof(rp);
98 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
99 			NG_HCI_OCF_RESET), (char *) &rp, &n) == ERROR)
100 		return (ERROR);
101 
102 	if (rp.status != 0x00) {
103 		fprintf(stdout, "Status: %s [%#02x]\n",
104 			hci_status2str(rp.status), rp.status);
105 		return (FAILED);
106 	}
107 
108 	return (OK);
109 } /* hci_reset */
110 
111 /* Send Read_PIN_Type command to the unit */
112 static int
113 hci_read_pin_type(int s, int argc, char **argv)
114 {
115 	ng_hci_read_pin_type_rp	rp;
116 	int			n;
117 
118 	n = sizeof(rp);
119 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
120 			NG_HCI_OCF_READ_PIN_TYPE),
121 			(char *) &rp, &n) == ERROR)
122 		return (ERROR);
123 
124 	if (rp.status != 0x00) {
125 		fprintf(stdout, "Status: %s [%#02x]\n",
126 			hci_status2str(rp.status), rp.status);
127 		return (FAILED);
128 	}
129 
130 	fprintf(stdout, "PIN type: %s [%#02x]\n",
131 			hci_pin2str(rp.pin_type), rp.pin_type);
132 
133 	return (OK);
134 } /* hci_read_pin_type */
135 
136 /* Send Write_PIN_Type command to the unit */
137 static int
138 hci_write_pin_type(int s, int argc, char **argv)
139 {
140 	ng_hci_write_pin_type_cp	cp;
141 	ng_hci_write_pin_type_rp	rp;
142 	int				n;
143 
144 	/* parse command parameters */
145 	switch (argc) {
146 	case 1:
147 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 1)
148 			return (USAGE);
149 
150 		cp.pin_type = (u_int8_t) n;
151 		break;
152 
153 	default:
154 		return (USAGE);
155 	}
156 
157 	/* send command */
158 	n = sizeof(rp);
159 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
160 			NG_HCI_OCF_WRITE_PIN_TYPE),
161 			(char const *) &cp, sizeof(cp),
162 			(char *) &rp , &n) ==  ERROR)
163 		return (ERROR);
164 
165 	if (rp.status != 0x00) {
166 		fprintf(stdout, "Status: %s [%#02x]\n",
167 			hci_status2str(rp.status), rp.status);
168 		return (FAILED);
169 	}
170 
171 	return (OK);
172 } /* hci_write_pin_type */
173 
174 /* Send Read_Stored_Link_Key command to the unit */
175 static int
176 hci_read_stored_link_key(int s, int argc, char **argv)
177 {
178 	struct {
179 		ng_hci_cmd_pkt_t			hdr;
180 		ng_hci_read_stored_link_key_cp		cp;
181 	} __attribute__ ((packed))			cmd;
182 
183 	struct {
184 		ng_hci_event_pkt_t			hdr;
185 		union {
186 			ng_hci_command_compl_ep		cc;
187 			ng_hci_return_link_keys_ep	key;
188 			u_int8_t			b[NG_HCI_EVENT_PKT_SIZE];
189 		}					ep;
190 	} __attribute__ ((packed))			event;
191 
192 	int						n,a0,a1,a2,a3,a4,a5;
193 
194 	/* Send command */
195 	memset(&cmd, 0, sizeof(cmd));
196 	cmd.hdr.type = NG_HCI_CMD_PKT;
197 	cmd.hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
198 				NG_HCI_OCF_READ_STORED_LINK_KEY));
199 	cmd.hdr.length = sizeof(cmd.cp);
200 
201 	switch (argc) {
202 	case 1:
203 		/* parse BD_ADDR */
204 		if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", &a5, &a4, &a3, &a2,
205 				&a1, &a0) != 6)
206 			return (USAGE);
207 
208 		cmd.cp.bdaddr.b[0] = (a0 & 0xff);
209 		cmd.cp.bdaddr.b[1] = (a1 & 0xff);
210 		cmd.cp.bdaddr.b[2] = (a2 & 0xff);
211 		cmd.cp.bdaddr.b[3] = (a3 & 0xff);
212 		cmd.cp.bdaddr.b[4] = (a4 & 0xff);
213 		cmd.cp.bdaddr.b[5] = (a5 & 0xff);
214 		break;
215 
216 	default:
217 		cmd.cp.read_all = 1;
218 		break;
219 	}
220 
221 	if (hci_send(s, (char const *) &cmd, sizeof(cmd)) != OK)
222 		return (ERROR);
223 
224 	/* Receive events */
225 again:
226 	memset(&event, 0, sizeof(event));
227 	n = sizeof(event);
228 	if (hci_recv(s, (char *) &event, &n) != OK)
229 		return (ERROR);
230 
231 	if (n <= sizeof(event.hdr)) {
232 		errno = EMSGSIZE;
233 		return (ERROR);
234 	}
235 
236 	if (event.hdr.type != NG_HCI_EVENT_PKT) {
237 		errno = EIO;
238 		return (ERROR);
239 	}
240 
241 	/* Parse event */
242 	switch (event.hdr.event) {
243 	case NG_HCI_EVENT_COMMAND_COMPL: {
244 		ng_hci_read_stored_link_key_rp	*rp = NULL;
245 
246 		if (event.ep.cc.opcode == 0x0000 ||
247 		    event.ep.cc.opcode != cmd.hdr.opcode)
248 			goto again;
249 
250 		rp = (ng_hci_read_stored_link_key_rp *)(event.ep.b +
251 				sizeof(event.ep.cc));
252 
253 		fprintf(stdout, "Complete: Status: %s [%#x]\n",
254 				hci_status2str(rp->status), rp->status);
255 		fprintf(stdout, "Maximum Number of keys: %d\n",
256 				le16toh(rp->max_num_keys));
257 		fprintf(stdout, "Number of keys read: %d\n",
258 				le16toh(rp->num_keys_read));
259 		} break;
260 
261 	case NG_HCI_EVENT_RETURN_LINK_KEYS: {
262 		struct _key {
263 			bdaddr_t	bdaddr;
264 			u_int8_t	key[NG_HCI_KEY_SIZE];
265 		} __attribute__ ((packed))	*k = NULL;
266 
267 		fprintf(stdout, "Event: Number of keys: %d\n",
268 			event.ep.key.num_keys);
269 
270 		k = (struct _key *)(event.ep.b + sizeof(event.ep.key));
271 		for (n = 0; n < event.ep.key.num_keys; n++) {
272 			fprintf(stdout, "\t%d: %02x:%02x:%02x:%02x:%02x:%02x ",
273 				n + 1,
274 				k->bdaddr.b[5], k->bdaddr.b[4], k->bdaddr.b[3],
275 				k->bdaddr.b[2], k->bdaddr.b[1], k->bdaddr.b[0]);
276 
277 			for (a0 = 0; a0 < sizeof(k->key); a0++)
278 				fprintf(stdout, "%02x", k->key[a0]);
279 			fprintf(stdout, "\n");
280 
281 			k ++;
282 		}
283 
284 		goto again;
285 
286 		} break;
287 
288 	default:
289 		goto again;
290 	}
291 
292 	return (OK);
293 } /* hci_read_store_link_key */
294 
295 /* Send Write_Stored_Link_Key command to the unit */
296 static int
297 hci_write_stored_link_key(int s, int argc, char **argv)
298 {
299 	struct {
300 		ng_hci_write_stored_link_key_cp	p;
301 		bdaddr_t			bdaddr;
302 		u_int8_t			key[NG_HCI_KEY_SIZE];
303 	}					cp;
304 	ng_hci_write_stored_link_key_rp		rp;
305 	int32_t					n, a0, a1, a2, a3, a4, a5;
306 
307 	memset(&cp, 0, sizeof(cp));
308 
309 	switch (argc) {
310 	case 2:
311 		cp.p.num_keys_write = 1;
312 
313 		/* parse BD_ADDR */
314 		if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
315 				&a5, &a4, &a3, &a2, &a1, &a0) != 6)
316 			return (USAGE);
317 
318 		cp.bdaddr.b[0] = (a0 & 0xff);
319 		cp.bdaddr.b[1] = (a1 & 0xff);
320 		cp.bdaddr.b[2] = (a2 & 0xff);
321 		cp.bdaddr.b[3] = (a3 & 0xff);
322 		cp.bdaddr.b[4] = (a4 & 0xff);
323 		cp.bdaddr.b[5] = (a5 & 0xff);
324 
325 		/* parse key */
326 		if (hci_hexstring2array(argv[1], cp.key, sizeof(cp.key)) < 0)
327 			return (USAGE);
328 		break;
329 
330 	default:
331 		return (USAGE);
332 	}
333 
334 	/* send command */
335 	n = sizeof(rp);
336 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
337 			NG_HCI_OCF_WRITE_STORED_LINK_KEY),
338 			(char const *) &cp, sizeof(cp),
339 			(char *) &rp, &n) == ERROR)
340 		return (ERROR);
341 
342 	if (rp.status != 0x00) {
343 		fprintf(stdout, "Status: %s [%#02x]\n",
344 			hci_status2str(rp.status), rp.status);
345 		return (FAILED);
346 	}
347 
348 	fprintf(stdout, "Number of keys written: %d\n", rp.num_keys_written);
349 
350 	return (OK);
351 } /* hci_write_stored_link_key */
352 
353 
354 /* Send Delete_Stored_Link_Key command to the unit */
355 static int
356 hci_delete_stored_link_key(int s, int argc, char **argv)
357 {
358 	ng_hci_delete_stored_link_key_cp	cp;
359 	ng_hci_delete_stored_link_key_rp	rp;
360 	int32_t					n, a0, a1, a2, a3, a4, a5;
361 
362 	memset(&cp, 0, sizeof(cp));
363 
364 	switch (argc) {
365 	case 1:
366 		/* parse BD_ADDR */
367 		if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
368 				&a5, &a4, &a3, &a2, &a1, &a0) != 6)
369 			return (USAGE);
370 
371 		cp.bdaddr.b[0] = (a0 & 0xff);
372 		cp.bdaddr.b[1] = (a1 & 0xff);
373 		cp.bdaddr.b[2] = (a2 & 0xff);
374 		cp.bdaddr.b[3] = (a3 & 0xff);
375 		cp.bdaddr.b[4] = (a4 & 0xff);
376 		cp.bdaddr.b[5] = (a5 & 0xff);
377 		break;
378 
379 	default:
380 		cp.delete_all = 1;
381 		break;
382 	}
383 
384 	/* send command */
385 	n = sizeof(cp);
386 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
387 			NG_HCI_OCF_DELETE_STORED_LINK_KEY),
388 			(char const *) &cp, sizeof(cp),
389 			(char *) &rp, &n) == ERROR)
390 		return (ERROR);
391 
392 	if (rp.status != 0x00) {
393 		fprintf(stdout, "Status: %s [%#02x]\n",
394 			hci_status2str(rp.status), rp.status);
395 		return (FAILED);
396 	}
397 
398 	fprintf(stdout, "Number of keys deleted: %d\n", rp.num_keys_deleted);
399 
400 	return (OK);
401 } /* hci_delete_stored_link_key */
402 
403 /* Send Change_Local_Name command to the unit */
404 static int
405 hci_change_local_name(int s, int argc, char **argv)
406 {
407 	ng_hci_change_local_name_cp	cp;
408 	ng_hci_change_local_name_rp	rp;
409 	int				n;
410 
411 	/* parse command parameters */
412 	switch (argc) {
413 	case 1:
414 		snprintf(cp.name, sizeof(cp.name), "%s", argv[0]);
415 		break;
416 
417 	default:
418 		return (USAGE);
419 	}
420 
421 	/* send command */
422 	n = sizeof(rp);
423 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
424 			NG_HCI_OCF_CHANGE_LOCAL_NAME),
425 			(char const *) &cp, sizeof(cp),
426 			(char *) &rp, &n) == ERROR)
427 		return (ERROR);
428 
429 	if (rp.status != 0x00) {
430 		fprintf(stdout, "Status: %s [%#02x]\n",
431 			hci_status2str(rp.status), rp.status);
432 		return (FAILED);
433 	}
434 
435 	return (OK);
436 } /* hci_change_local_name */
437 
438 /* Send Read_Local_Name command to the unit */
439 static int
440 hci_read_local_name(int s, int argc, char **argv)
441 {
442 	ng_hci_read_local_name_rp	rp;
443 	int				n;
444 
445 	n = sizeof(rp);
446 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
447 			NG_HCI_OCF_READ_LOCAL_NAME),
448 			(char *) &rp, &n) == ERROR)
449 		return (ERROR);
450 
451 	if (rp.status != 0x00) {
452 		fprintf(stdout, "Status: %s [%#02x]\n",
453 			hci_status2str(rp.status), rp.status);
454 		return (FAILED);
455 	}
456 
457 	fprintf(stdout, "Local name: %s\n", rp.name);
458 
459 	return (OK);
460 } /* hci_read_local_name */
461 
462 /* Send Read_Connection_Accept_Timeout to the unit */
463 static int
464 hci_read_connection_accept_timeout(int s, int argc, char **argv)
465 {
466 	ng_hci_read_con_accept_timo_rp	rp;
467 	int				n;
468 
469 	n = sizeof(rp);
470 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
471 			NG_HCI_OCF_READ_CON_ACCEPT_TIMO),
472 			(char *) &rp, &n) == ERROR)
473 		return (ERROR);
474 
475 	if (rp.status != 0x00) {
476 		fprintf(stdout, "Status: %s [%#02x]\n",
477 			hci_status2str(rp.status), rp.status);
478 		return (FAILED);
479 	}
480 
481 	rp.timeout = le16toh(rp.timeout);
482 	fprintf(stdout, "Connection accept timeout: %.2f msec [%d slots]\n",
483 			rp.timeout * 0.625, rp.timeout);
484 
485 	return (OK);
486 } /* hci_read_connection_accept_timeout */
487 
488 /* Send Write_Connection_Accept_Timeout to the unit */
489 static int
490 hci_write_connection_accept_timeout(int s, int argc, char **argv)
491 {
492 	ng_hci_write_con_accept_timo_cp	cp;
493 	ng_hci_write_con_accept_timo_rp	rp;
494 	int				n;
495 
496 	/* parse command parameters */
497 	switch (argc) {
498 	case 1:
499 		if (sscanf(argv[0], "%d", &n) != 1 || n < 1 || n > 0xb540)
500 			return (USAGE);
501 
502 		cp.timeout = (u_int16_t) n;
503 		cp.timeout = htole16(cp.timeout);
504 		break;
505 
506 	default:
507 		return (USAGE);
508 	}
509 
510 	/* send command */
511 	n = sizeof(rp);
512 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
513 			NG_HCI_OCF_WRITE_CON_ACCEPT_TIMO),
514 			(char const *) &cp, sizeof(cp),
515 			(char *) &rp, &n) == ERROR)
516 		return (ERROR);
517 
518 	if (rp.status != 0x00) {
519 		fprintf(stdout, "Status: %s [%#02x]\n",
520 			hci_status2str(rp.status), rp.status);
521 		return (FAILED);
522 	}
523 
524 	return (OK);
525 } /* hci_write_connection_accept_timeout */
526 
527 /* Send Read_Page_Timeout command to the unit */
528 static int
529 hci_read_page_timeout(int s, int argc, char **argv)
530 {
531 	ng_hci_read_page_timo_rp	rp;
532 	int				n;
533 
534 	n = sizeof(rp);
535 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
536 			NG_HCI_OCF_READ_PAGE_TIMO),
537 			(char *) &rp, &n) == ERROR)
538 		return (ERROR);
539 
540 	if (rp.status != 0x00) {
541 		fprintf(stdout, "Status: %s [%#02x]\n",
542 			hci_status2str(rp.status), rp.status);
543 		return (FAILED);
544 	}
545 
546 	rp.timeout = le16toh(rp.timeout);
547 	fprintf(stdout, "Page timeout: %.2f msec [%d slots]\n",
548 		rp.timeout * 0.625, rp.timeout);
549 
550 	return (OK);
551 } /* hci_read_page_timeoout */
552 
553 /* Send Write_Page_Timeout command to the unit */
554 static int
555 hci_write_page_timeout(int s, int argc, char **argv)
556 {
557 	ng_hci_write_page_timo_cp	cp;
558 	ng_hci_write_page_timo_rp	rp;
559 	int				n;
560 
561 	/* parse command parameters */
562 	switch (argc) {
563 	case 1:
564 		if (sscanf(argv[0], "%d", &n) != 1 || n < 1 || n > 0xffff)
565 			return (USAGE);
566 
567 		cp.timeout = (u_int16_t) n;
568 		cp.timeout = htole16(cp.timeout);
569 		break;
570 
571 	default:
572 		return (USAGE);
573 	}
574 
575 	/* send command */
576 	n = sizeof(rp);
577 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
578 			NG_HCI_OCF_WRITE_PAGE_TIMO),
579 			(char const *) &cp, sizeof(cp),
580 			(char *) &rp, &n) == ERROR)
581 		return (ERROR);
582 
583 	if (rp.status != 0x00) {
584 		fprintf(stdout, "Status: %s [%#02x]\n",
585 			hci_status2str(rp.status), rp.status);
586 		return (FAILED);
587 	}
588 
589 	return (OK);
590 } /* hci_write_page_timeout */
591 
592 /* Send Read_Scan_Enable command to the unit */
593 static int
594 hci_read_scan_enable(int s, int argc, char **argv)
595 {
596 	ng_hci_read_scan_enable_rp	rp;
597 	int				n;
598 
599 	n = sizeof(rp);
600 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
601 			NG_HCI_OCF_READ_SCAN_ENABLE),
602 			(char *) &rp, &n) == ERROR)
603 		return (ERROR);
604 
605 	if (rp.status != 0x00) {
606 		fprintf(stdout, "Status: %s [%#02x]\n",
607 			hci_status2str(rp.status), rp.status);
608 		return (FAILED);
609 	}
610 
611 	fprintf(stdout, "Scan enable: %s [%#02x]\n",
612 		hci_scan2str(rp.scan_enable), rp.scan_enable);
613 
614 	return (OK);
615 } /* hci_read_scan_enable */
616 
617 /* Send Write_Scan_Enable command to the unit */
618 static int
619 hci_write_scan_enable(int s, int argc, char **argv)
620 {
621 	ng_hci_write_scan_enable_cp	cp;
622 	ng_hci_write_scan_enable_rp	rp;
623 	int				n;
624 
625 	/* parse command parameters */
626 	switch (argc) {
627 	case 1:
628 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 3)
629 			return (USAGE);
630 
631 		cp.scan_enable = (u_int8_t) n;
632 		break;
633 
634 	default:
635 		return (USAGE);
636 	}
637 
638 	n = sizeof(rp);
639 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
640 			NG_HCI_OCF_WRITE_SCAN_ENABLE),
641 			(char const *) &cp, sizeof(cp),
642 			(char *) &rp, &n) == ERROR)
643 		return (ERROR);
644 
645 	if (rp.status != 0x00) {
646 		fprintf(stdout, "Status: %s [%#02x]\n",
647 			hci_status2str(rp.status), rp.status);
648 		return (FAILED);
649 	}
650 
651 	return (OK);
652 } /* hci_write_scan_enable */
653 
654 /* Send Read_Page_Scan_Activity command to the unit */
655 static int
656 hci_read_page_scan_activity(int s, int argc, char **argv)
657 {
658 	ng_hci_read_page_scan_activity_rp	rp;
659 	int					n;
660 
661 	n = sizeof(rp);
662 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
663 			NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY),
664 			(char *) &rp, &n) == ERROR)
665 		return (ERROR);
666 
667 	if (rp.status != 0x00) {
668 		fprintf(stdout, "Status: %s [%#02x]\n",
669 			hci_status2str(rp.status), rp.status);
670 		return (FAILED);
671 	}
672 
673 	rp.page_scan_interval = le16toh(rp.page_scan_interval);
674 	rp.page_scan_window = le16toh(rp.page_scan_window);
675 
676 	fprintf(stdout, "Page Scan Interval: %.2f msec [%d slots]\n",
677 		rp.page_scan_interval * 0.625, rp.page_scan_interval);
678 	fprintf(stdout, "Page Scan Window: %.2f msec [%d slots]\n",
679 		rp.page_scan_window * 0.625, rp.page_scan_window);
680 
681 	return (OK);
682 } /* hci_read_page_scan_activity */
683 
684 /* Send Write_Page_Scan_Activity command to the unit */
685 static int
686 hci_write_page_scan_activity(int s, int argc, char **argv)
687 {
688 	ng_hci_write_page_scan_activity_cp	cp;
689 	ng_hci_write_page_scan_activity_rp	rp;
690 	int					n;
691 
692 	/* parse command parameters */
693 	switch (argc) {
694 	case 2:
695 		/* page scan interval */
696 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0x12 || n > 0x1000)
697 			return (USAGE);
698 
699 		cp.page_scan_interval = (u_int16_t) n;
700 
701 		/* page scan window */
702 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0x12 || n > 0x1000)
703 			return (USAGE);
704 
705 		cp.page_scan_window = (u_int16_t) n;
706 
707 		if (cp.page_scan_window > cp.page_scan_interval)
708 			return (USAGE);
709 
710 		cp.page_scan_interval = htole16(cp.page_scan_interval);
711 		cp.page_scan_window = htole16(cp.page_scan_window);
712 		break;
713 
714 	default:
715 		return (USAGE);
716 	}
717 
718 	/* send command */
719 	n = sizeof(rp);
720 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
721 			NG_HCI_OCF_WRITE_PAGE_SCAN_ACTIVITY),
722 			(char const *) &cp, sizeof(cp),
723 			(char *) &rp, &n) == ERROR)
724 		return (ERROR);
725 
726 	if (rp.status != 0x00) {
727 		fprintf(stdout, "Status: %s [%#02x]\n",
728 			hci_status2str(rp.status), rp.status);
729 		return (FAILED);
730 	}
731 
732 	return (OK);
733 } /* hci_write_page_scan_activity */
734 
735 /* Send Read_Inquiry_Scan_Activity command to the unit */
736 static int
737 hci_read_inquiry_scan_activity(int s, int argc, char **argv)
738 {
739 	ng_hci_read_inquiry_scan_activity_rp	rp;
740 	int					n;
741 
742 	n = sizeof(rp);
743 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
744 			NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY),
745 			(char *) &rp, &n) == ERROR)
746 		return (ERROR);
747 
748 	if (rp.status != 0x00) {
749 		fprintf(stdout, "Status: %s [%#02x]\n",
750 			hci_status2str(rp.status), rp.status);
751 		return (FAILED);
752 	}
753 
754 	rp.inquiry_scan_interval = le16toh(rp.inquiry_scan_interval);
755 	rp.inquiry_scan_window = le16toh(rp.inquiry_scan_window);
756 
757 	fprintf(stdout, "Inquiry Scan Interval: %.2f msec [%d slots]\n",
758 		rp.inquiry_scan_interval * 0.625, rp.inquiry_scan_interval);
759 	fprintf(stdout, "Inquiry Scan Window: %.2f msec [%d slots]\n",
760 		rp.inquiry_scan_window * 0.625, rp.inquiry_scan_interval);
761 
762 	return (OK);
763 } /* hci_read_inquiry_scan_activity */
764 
765 /* Send Write_Inquiry_Scan_Activity command to the unit */
766 static int
767 hci_write_inquiry_scan_activity(int s, int argc, char **argv)
768 {
769 	ng_hci_write_inquiry_scan_activity_cp	cp;
770 	ng_hci_write_inquiry_scan_activity_rp	rp;
771 	int					n;
772 
773 	/* parse command parameters */
774 	switch (argc) {
775 	case 2:
776 		/* inquiry scan interval */
777 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0x12 || n > 0x1000)
778 			return (USAGE);
779 
780 		cp.inquiry_scan_interval = (u_int16_t) n;
781 
782 		/* inquiry scan window */
783 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0x12 || n > 0x1000)
784 			return (USAGE);
785 
786 		cp.inquiry_scan_window = (u_int16_t) n;
787 
788 		if (cp.inquiry_scan_window > cp.inquiry_scan_interval)
789 			return (USAGE);
790 
791 		cp.inquiry_scan_interval =
792 			htole16(cp.inquiry_scan_interval);
793 		cp.inquiry_scan_window = htole16(cp.inquiry_scan_window);
794 		break;
795 
796 	default:
797 		return (USAGE);
798 	}
799 
800 	/* send command */
801 	n = sizeof(rp);
802 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
803 			NG_HCI_OCF_WRITE_INQUIRY_SCAN_ACTIVITY),
804 			(char const *) &cp, sizeof(cp),
805 			(char *) &rp, &n) == ERROR)
806 		return (ERROR);
807 
808 	if (rp.status != 0x00) {
809 		fprintf(stdout, "Status: %s [%#02x]\n",
810 			hci_status2str(rp.status), rp.status);
811 		return (FAILED);
812 	}
813 
814 	return (OK);
815 } /* hci_write_inquiry_scan_activity */
816 
817 /* Send Read_Authentication_Enable command to the unit */
818 static int
819 hci_read_authentication_enable(int s, int argc, char **argv)
820 {
821 	ng_hci_read_auth_enable_rp	rp;
822 	int				n;
823 
824 	n = sizeof(rp);
825 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
826 			NG_HCI_OCF_READ_AUTH_ENABLE),
827 			(char *) &rp, &n) == ERROR)
828 		return (ERROR);
829 
830 	if (rp.status != 0x00) {
831 		fprintf(stdout, "Status: %s [%#02x]\n",
832 			hci_status2str(rp.status), rp.status);
833 		return (FAILED);
834 	}
835 
836 	fprintf(stdout, "Authentication Enable: %s [%d]\n",
837 		rp.auth_enable? "Enabled" : "Disabled", rp.auth_enable);
838 
839 	return (OK);
840 } /* hci_read_authentication_enable */
841 
842 /* Send Write_Authentication_Enable command to the unit */
843 static int
844 hci_write_authentication_enable(int s, int argc, char **argv)
845 {
846 	ng_hci_write_auth_enable_cp	cp;
847 	ng_hci_write_auth_enable_rp	rp;
848 	int				n;
849 
850 	/* parse command parameters */
851 	switch (argc) {
852 	case 1:
853 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 1)
854 			return (USAGE);
855 
856 		cp.auth_enable = (u_int8_t) n;
857 		break;
858 
859 	default:
860 		return (USAGE);
861 	}
862 
863 	/* send command */
864 	n = sizeof(rp);
865 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
866 			NG_HCI_OCF_WRITE_AUTH_ENABLE),
867 			(char const *) &cp, sizeof(cp),
868 			(char *) &rp, &n) == ERROR)
869 		return (ERROR);
870 
871 	if (rp.status != 0x00) {
872 		fprintf(stdout, "Status: %s [%#02x]\n",
873 			hci_status2str(rp.status), rp.status);
874 		return (FAILED);
875 	}
876 
877 	return (OK);
878 } /* hci_write_authentication_enable */
879 
880 /* Send Read_Encryption_Mode command to the unit */
881 static int
882 hci_read_encryption_mode(int s, int argc, char **argv)
883 {
884 	ng_hci_read_encryption_mode_rp	rp;
885 	int				n;
886 
887 	n = sizeof(rp);
888 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
889 			NG_HCI_OCF_READ_ENCRYPTION_MODE),
890 			(char *) &rp, &n) == ERROR)
891 		return (ERROR);
892 
893 	if (rp.status != 0x00) {
894 		fprintf(stdout, "Status: %s [%#02x]\n",
895 			hci_status2str(rp.status), rp.status);
896 		return (FAILED);
897 	}
898 
899 	fprintf(stdout, "Encryption mode: %s [%#02x]\n",
900 		hci_encrypt2str(rp.encryption_mode, 0), rp.encryption_mode);
901 
902 	return (OK);
903 } /* hci_read_encryption_mode */
904 
905 /* Send Write_Encryption_Mode command to the unit */
906 static int
907 hci_write_encryption_mode(int s, int argc, char **argv)
908 {
909 	ng_hci_write_encryption_mode_cp	cp;
910 	ng_hci_write_encryption_mode_rp	rp;
911 	int				n;
912 
913 	/* parse command parameters */
914 	switch (argc) {
915 	case 1:
916 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 2)
917 			return (USAGE);
918 
919 		cp.encryption_mode = (u_int8_t) n;
920 		break;
921 
922 	default:
923 		return (USAGE);
924 	}
925 
926 	/* send command */
927 	n = sizeof(rp);
928 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
929 			NG_HCI_OCF_WRITE_ENCRYPTION_MODE),
930 			(char const *) &cp, sizeof(cp),
931 			(char *) &rp, &n) == ERROR)
932 		return (ERROR);
933 
934 	if (rp.status != 0x00) {
935 		fprintf(stdout, "Status: %s [%#02x]\n",
936 			hci_status2str(rp.status), rp.status);
937 		return (FAILED);
938 	}
939 
940 	return (OK);
941 } /* hci_write_encryption_mode */
942 
943 /* Send Read_Class_Of_Device command to the unit */
944 static int
945 hci_read_class_of_device(int s, int argc, char **argv)
946 {
947 	ng_hci_read_unit_class_rp	rp;
948 	int				n;
949 
950 	n = sizeof(rp);
951 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
952 			NG_HCI_OCF_READ_UNIT_CLASS),
953 			(char *) &rp, &n) == ERROR)
954 		return (ERROR);
955 
956 	if (rp.status != 0x00) {
957 		fprintf(stdout, "Status: %s [%#02x]\n",
958 			hci_status2str(rp.status), rp.status);
959 		return (FAILED);
960 	}
961 
962 	fprintf(stdout, "Class: %02x:%02x:%02x\n",
963 		rp.uclass[2], rp.uclass[1], rp.uclass[0]);
964 
965 	return (0);
966 } /* hci_read_class_of_device */
967 
968 /* Send Write_Class_Of_Device command to the unit */
969 static int
970 hci_write_class_of_device(int s, int argc, char **argv)
971 {
972 	ng_hci_write_unit_class_cp	cp;
973 	ng_hci_write_unit_class_rp	rp;
974 	int				n0, n1, n2;
975 
976 	/* parse command parameters */
977 	switch (argc) {
978 	case 1:
979 		if (sscanf(argv[0], "%x:%x:%x", &n2, &n1, &n0) != 3)
980 			return (USAGE);
981 
982 		cp.uclass[0] = (n0 & 0xff);
983 		cp.uclass[1] = (n1 & 0xff);
984 		cp.uclass[2] = (n2 & 0xff);
985 		break;
986 
987 	default:
988 		return (USAGE);
989 	}
990 
991 	/* send command */
992 	n0 = sizeof(rp);
993 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
994 			NG_HCI_OCF_WRITE_UNIT_CLASS),
995 			(char const *) &cp, sizeof(cp),
996 			(char *) &rp, &n0) == ERROR)
997 		return (ERROR);
998 
999 	if (rp.status != 0x00) {
1000 		fprintf(stdout, "Status: %s [%#02x]\n",
1001 			hci_status2str(rp.status), rp.status);
1002 		return (FAILED);
1003 	}
1004 
1005 	return (OK);
1006 } /* hci_write_class_of_device */
1007 
1008 /* Send Read_Voice_Settings command to the unit */
1009 static int
1010 hci_read_voice_settings(int s, int argc, char **argv)
1011 {
1012 	ng_hci_read_voice_settings_rp	rp;
1013 	int				n,
1014 					input_coding,
1015 					input_data_format,
1016 					input_sample_size;
1017 
1018 	n = sizeof(rp);
1019 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1020 			NG_HCI_OCF_READ_VOICE_SETTINGS),
1021 			(char *) &rp, &n) == ERROR)
1022 		return (ERROR);
1023 
1024 	if (rp.status != 0x00) {
1025 		fprintf(stdout, "Status: %s [%#02x]\n",
1026 			hci_status2str(rp.status), rp.status);
1027 		return (FAILED);
1028 	}
1029 
1030 	rp.settings = le16toh(rp.settings);
1031 
1032 	input_coding      = (rp.settings & 0x0300) >> 8;
1033 	input_data_format = (rp.settings & 0x00c0) >> 6;
1034 	input_sample_size = (rp.settings & 0x0020) >> 5;
1035 
1036 	fprintf(stdout, "Voice settings: %#04x\n", rp.settings);
1037 	fprintf(stdout, "Input coding: %s [%d]\n",
1038 		hci_coding2str(input_coding), input_coding);
1039 	fprintf(stdout, "Input data format: %s [%d]\n",
1040 		hci_vdata2str(input_data_format), input_data_format);
1041 
1042 	if (input_coding == 0x00) /* Only for Linear PCM */
1043 		fprintf(stdout, "Input sample size: %d bit [%d]\n",
1044 			input_sample_size? 16 : 8, input_sample_size);
1045 
1046 	return (OK);
1047 } /* hci_read_voice_settings */
1048 
1049 /* Send Write_Voice_Settings command to the unit */
1050 static int
1051 hci_write_voice_settings(int s, int argc, char **argv)
1052 {
1053 	ng_hci_write_voice_settings_cp	cp;
1054 	ng_hci_write_voice_settings_rp	rp;
1055 	int				n;
1056 
1057 	/* parse command parameters */
1058 	switch (argc) {
1059 	case 1:
1060 		if (sscanf(argv[0], "%x", &n) != 1)
1061 			return (USAGE);
1062 
1063 		cp.settings = (u_int16_t) n;
1064 		cp.settings = htole16(cp.settings);
1065 		break;
1066 
1067 	default:
1068 		return (USAGE);
1069 	}
1070 
1071 	/* send command */
1072 	n = sizeof(rp);
1073 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1074 			NG_HCI_OCF_WRITE_VOICE_SETTINGS),
1075 			(char const *) &cp, sizeof(cp),
1076 			(char *) &rp, &n) == ERROR)
1077 		return (ERROR);
1078 
1079 	if (rp.status != 0x00) {
1080 		fprintf(stdout, "Status: %s [%#02x]\n",
1081 			hci_status2str(rp.status), rp.status);
1082 		return (FAILED);
1083 	}
1084 
1085 	return (OK);
1086 } /* hci_write_voice_settings */
1087 
1088 /* Send Read_Number_Broadcast_Restransmissions */
1089 static int
1090 hci_read_number_broadcast_retransmissions(int s, int argc, char **argv)
1091 {
1092 	ng_hci_read_num_broadcast_retrans_rp	rp;
1093 	int					n;
1094 
1095 	n = sizeof(rp);
1096 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1097 			NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS),
1098 			(char *) &rp, &n) == ERROR)
1099 		return (ERROR);
1100 
1101 	if (rp.status != 0x00) {
1102 		fprintf(stdout, "Status: %s [%#02x]\n",
1103 			hci_status2str(rp.status), rp.status);
1104 		return (FAILED);
1105 	}
1106 
1107 	fprintf(stdout, "Number of broadcast retransmissions: %d\n",
1108 		rp.counter);
1109 
1110 	return (OK);
1111 } /* hci_read_number_broadcast_retransmissions */
1112 
1113 /* Send Write_Number_Broadcast_Restransmissions */
1114 static int
1115 hci_write_number_broadcast_retransmissions(int s, int argc, char **argv)
1116 {
1117 	ng_hci_write_num_broadcast_retrans_cp	cp;
1118 	ng_hci_write_num_broadcast_retrans_rp	rp;
1119 	int					n;
1120 
1121 	/* parse command parameters */
1122 	switch (argc) {
1123 	case 1:
1124 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 0xff)
1125 			return (USAGE);
1126 
1127 		cp.counter = (u_int8_t) n;
1128 		break;
1129 
1130 	default:
1131 		return (USAGE);
1132 	}
1133 
1134 	/* send command */
1135 	n = sizeof(rp);
1136 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1137 			NG_HCI_OCF_WRITE_NUM_BROADCAST_RETRANS),
1138 			(char const *) &cp, sizeof(cp),
1139 			(char *) &rp, &n) == ERROR)
1140 		return (ERROR);
1141 
1142 	if (rp.status != 0x00) {
1143 		fprintf(stdout, "Status: %s [%#02x]\n",
1144 			hci_status2str(rp.status), rp.status);
1145 		return (FAILED);
1146 	}
1147 
1148 	return (OK);
1149 } /* hci_write_number_broadcast_retransmissions */
1150 
1151 /* Send Read_Hold_Mode_Activity command to the unit */
1152 static int
1153 hci_read_hold_mode_activity(int s, int argc, char **argv)
1154 {
1155 	ng_hci_read_hold_mode_activity_rp	rp;
1156 	int					n;
1157 	char					buffer[1024];
1158 
1159 	n = sizeof(rp);
1160 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1161 			NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY),
1162 			(char *) &rp, &n) == ERROR)
1163 		return (ERROR);
1164 
1165 	if (rp.status != 0x00) {
1166 		fprintf(stdout, "Status: %s [%#02x]\n",
1167 			hci_status2str(rp.status), rp.status);
1168 		return (FAILED);
1169 	}
1170 
1171 	fprintf(stdout, "Hold Mode Activities: %#02x\n", rp.hold_mode_activity);
1172 	if (rp.hold_mode_activity == 0)
1173 		fprintf(stdout, "Maintain current Power State");
1174 	else
1175 		fprintf(stdout, "%s", hci_hmode2str(rp.hold_mode_activity,
1176 				buffer, sizeof(buffer)));
1177 
1178 	fprintf(stdout, "\n");
1179 
1180 	return (OK);
1181 } /* hci_read_hold_mode_activity */
1182 
1183 /* Send Write_Hold_Mode_Activity command to the unit */
1184 static int
1185 hci_write_hold_mode_activity(int s, int argc, char **argv)
1186 {
1187 	ng_hci_write_hold_mode_activity_cp	cp;
1188 	ng_hci_write_hold_mode_activity_rp	rp;
1189 	int					n;
1190 
1191 	/* parse command parameters */
1192 	switch (argc) {
1193 	case 1:
1194 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 4)
1195 			return (USAGE);
1196 
1197 		cp.hold_mode_activity = (u_int8_t) n;
1198 		break;
1199 
1200 	default:
1201 		return (USAGE);
1202 	}
1203 
1204 	/* send command */
1205 	n = sizeof(rp);
1206 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1207 			NG_HCI_OCF_WRITE_HOLD_MODE_ACTIVITY),
1208 			(char const *) &cp, sizeof(cp),
1209 			(char *) &rp, &n) == ERROR)
1210 		return (ERROR);
1211 
1212 	if (rp.status != 0x00) {
1213 		fprintf(stdout, "Status: %s [%#02x]\n",
1214 			hci_status2str(rp.status), rp.status);
1215 		return (FAILED);
1216 	}
1217 
1218 	return (OK);
1219 } /* hci_write_hold_mode_activity */
1220 
1221 /* Send Read_SCO_Flow_Control_Enable command to the unit */
1222 static int
1223 hci_read_sco_flow_control_enable(int s, int argc, char **argv)
1224 {
1225 	ng_hci_read_sco_flow_control_rp	rp;
1226 	int				n;
1227 
1228 	n = sizeof(rp);
1229 	if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1230 			NG_HCI_OCF_READ_SCO_FLOW_CONTROL),
1231 			(char *) &rp, &n) == ERROR)
1232 		return (ERROR);
1233 
1234 	if (rp.status != 0x00) {
1235 		fprintf(stdout, "Status: %s [%#02x]\n",
1236 			hci_status2str(rp.status), rp.status);
1237 		return (FAILED);
1238 	}
1239 
1240 	fprintf(stdout, "SCO flow control %s [%d]\n",
1241 		rp.flow_control? "enabled" : "disabled", rp.flow_control);
1242 
1243 	return (OK);
1244 } /* hci_read_sco_flow_control_enable */
1245 
1246 /* Send Write_SCO_Flow_Control_Enable command to the unit */
1247 static int
1248 hci_write_sco_flow_control_enable(int s, int argc, char **argv)
1249 {
1250 	ng_hci_write_sco_flow_control_cp	cp;
1251 	ng_hci_write_sco_flow_control_rp	rp;
1252 	int					n;
1253 
1254 	/* parse command parameters */
1255 	switch (argc) {
1256 	case 1:
1257 		if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 1)
1258 			return (USAGE);
1259 
1260 		cp.flow_control = (u_int8_t) n;
1261 		break;
1262 
1263 	default:
1264 		return (USAGE);
1265 	}
1266 
1267 	/* send command */
1268 	n = sizeof(rp);
1269 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1270 			NG_HCI_OCF_WRITE_SCO_FLOW_CONTROL),
1271 			(char const *) &cp, sizeof(cp),
1272 			(char *) &rp, &n) == ERROR)
1273 		return (ERROR);
1274 
1275 	if (rp.status != 0x00) {
1276 		fprintf(stdout, "Status: %s [%#02x]\n",
1277 			hci_status2str(rp.status), rp.status);
1278 		return (FAILED);
1279 	}
1280 
1281 	return (OK);
1282 } /* hci_write_sco_flow_control_enable */
1283 
1284 /* Send Read_Link_Supervision_Timeout command to the unit */
1285 static int
1286 hci_read_link_supervision_timeout(int s, int argc, char **argv)
1287 {
1288 	ng_hci_read_link_supervision_timo_cp	cp;
1289 	ng_hci_read_link_supervision_timo_rp	rp;
1290 	int					n;
1291 
1292 	switch (argc) {
1293 	case 1:
1294 		/* connection handle */
1295 		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
1296 			return (USAGE);
1297 
1298 		cp.con_handle = (u_int16_t) (n & 0x0fff);
1299 		cp.con_handle = htole16(cp.con_handle);
1300 		break;
1301 
1302 	default:
1303 		return (USAGE);
1304 	}
1305 
1306 	/* send command */
1307 	n = sizeof(rp);
1308 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1309 			NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO),
1310 			(char const *) &cp, sizeof(cp),
1311 			(char *) &rp, &n) == ERROR)
1312 		return (ERROR);
1313 
1314 	if (rp.status != 0x00) {
1315 		fprintf(stdout, "Status: %s [%#02x]\n",
1316 			hci_status2str(rp.status), rp.status);
1317 		return (FAILED);
1318 	}
1319 
1320 	rp.timeout = le16toh(rp.timeout);
1321 
1322 	fprintf(stdout, "Connection handle: %d\n", le16toh(rp.con_handle));
1323 	fprintf(stdout, "Link supervision timeout: %.2f msec [%d slots]\n",
1324 		rp.timeout * 0.625, rp.timeout);
1325 
1326 	return (OK);
1327 } /* hci_read_link_supervision_timeout */
1328 
1329 /* Send Write_Link_Supervision_Timeout command to the unit */
1330 static int
1331 hci_write_link_supervision_timeout(int s, int argc, char **argv)
1332 {
1333 	ng_hci_write_link_supervision_timo_cp	cp;
1334 	ng_hci_write_link_supervision_timo_rp	rp;
1335 	int					n;
1336 
1337 	switch (argc) {
1338 	case 2:
1339 		/* connection handle */
1340 		if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff)
1341 			return (USAGE);
1342 
1343 		cp.con_handle = (u_int16_t) (n & 0x0fff);
1344 		cp.con_handle = htole16(cp.con_handle);
1345 
1346 		/* link supervision timeout */
1347 		if (sscanf(argv[1], "%d", &n) != 1 || n < 0 || n > 0xeff)
1348 			return (USAGE);
1349 
1350 		cp.timeout = (u_int16_t) (n & 0x0fff);
1351 		cp.timeout = htole16(cp.timeout);
1352 		break;
1353 
1354 	default:
1355 		return (USAGE);
1356 	}
1357 
1358 	/* send command */
1359 	n = sizeof(rp);
1360 	if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
1361 			NG_HCI_OCF_WRITE_LINK_SUPERVISION_TIMO),
1362 			(char const *) &cp, sizeof(cp),
1363 			(char *) &rp, &n) == ERROR)
1364 		return (ERROR);
1365 
1366 	if (rp.status != 0x00) {
1367 		fprintf(stdout, "Status: %s [%#02x]\n",
1368 			hci_status2str(rp.status), rp.status);
1369 		return (FAILED);
1370 	}
1371 
1372 	return (OK);
1373 } /* hci_write_link_supervision_timeout */
1374 
1375 struct hci_command	host_controller_baseband_commands[] = {
1376 {
1377 "reset",
1378 "\nThe Reset command will reset the Host Controller and the Link Manager.\n" \
1379 "After the reset is completed, the current operational state will be lost,\n" \
1380 "the Bluetooth unit will enter standby mode and the Host Controller will\n" \
1381 "automatically revert to the default values for the parameters for which\n" \
1382 "default values are defined in the specification.",
1383 &hci_reset
1384 },
1385 {
1386 "read_pin_type",
1387 "\nThe Read_PIN_Type command is used for the Host to read whether the Link\n" \
1388 "Manager assumes that the Host supports variable PIN codes only a fixed PIN\n" \
1389 "code.",
1390 &hci_read_pin_type
1391 },
1392 {
1393 "write_pin_type <pin_type>",
1394 "\nThe Write_PIN_Type command is used for the Host to write to the Host\n" \
1395 "Controller whether the Host supports variable PIN codes or only a fixed PIN\n"\
1396 "code.\n\n" \
1397 "\t<pin_type> - dd; 0 - Variable; 1 - Fixed",
1398 &hci_write_pin_type
1399 },
1400 {
1401 "read_stored_link_key [<bdaddr>]",
1402 "\nThe Read_Stored_Link_Key command provides the ability to read one or\n" \
1403 "more link keys stored in the Bluetooth Host Controller. The Bluetooth Host\n" \
1404 "Controller can store a limited number of link keys for other Bluetooth\n" \
1405 "devices.\n\n" \
1406 "\t<bdaddr> - xx:xx:xx:xx:xx:xx BD_ADDR",
1407 &hci_read_stored_link_key
1408 },
1409 {
1410 "write_stored_link_key <bdaddr> <key>",
1411 "\nThe Write_Stored_Link_Key command provides the ability to write one\n" \
1412 "or more link keys to be stored in the Bluetooth Host Controller. The\n" \
1413 "Bluetooth Host Controller can store a limited number of link keys for other\n"\
1414 "Bluetooth devices. If no additional space is available in the Bluetooth\n"\
1415 "Host Controller then no additional link keys will be stored.\n\n" \
1416 "\t<bdaddr> - xx:xx:xx:xx:xx:xx BD_ADDR\n" \
1417 "\t<key>    - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx up to 16 bytes link key",
1418 &hci_write_stored_link_key
1419 },
1420 {
1421 "delete_stored_link_key [<bdaddr>]",
1422 "\nThe Delete_Stored_Link_Key command provides the ability to remove one\n" \
1423 "or more of the link keys stored in the Bluetooth Host Controller. The\n" \
1424 "Bluetooth Host Controller can store a limited number of link keys for other\n"\
1425 "Bluetooth devices.\n\n" \
1426 "\t<bdaddr> - xx:xx:xx:xx:xx:xx BD_ADDR",
1427 &hci_delete_stored_link_key
1428 },
1429 {
1430 "change_local_name <name>",
1431 "\nThe Change_Local_Name command provides the ability to modify the user\n" \
1432 "friendly name for the Bluetooth unit.\n\n" \
1433 "\t<name> - string",
1434 &hci_change_local_name
1435 },
1436 {
1437 "read_local_name",
1438 "\nThe Read_Local_Name command provides the ability to read the\n" \
1439 "stored user-friendly name for the Bluetooth unit.",
1440 &hci_read_local_name
1441 },
1442 {
1443 "read_connection_accept_timeout",
1444 "\nThis command will read the value for the Connection_Accept_Timeout\n" \
1445 "configuration parameter. The Connection_Accept_Timeout configuration\n" \
1446 "parameter allows the Bluetooth hardware to automatically deny a\n" \
1447 "connection request after a specified time period has occurred and\n" \
1448 "the new connection is not accepted. Connection Accept Timeout\n" \
1449 "measured in Number of Baseband slots.",
1450 &hci_read_connection_accept_timeout
1451 },
1452 {
1453 "write_connection_accept_timeout <timeout>",
1454 "\nThis command will write the value for the Connection_Accept_Timeout\n" \
1455 "configuration parameter.\n\n" \
1456 "\t<timeout> - dddd; measured in number of baseband slots.",
1457 &hci_write_connection_accept_timeout
1458 },
1459 {
1460 "read_page_timeout",
1461 "\nThis command will read the value for the Page_Timeout configuration\n" \
1462 "parameter. The Page_Timeout configuration parameter defines the\n" \
1463 "maximum time the local Link Manager will wait for a baseband page\n" \
1464 "response from the remote unit at a locally initiated connection\n" \
1465 "attempt. Page Timeout measured in Number of Baseband slots.",
1466 &hci_read_page_timeout
1467 },
1468 {
1469 "write_page_timeout <timeout>",
1470 "\nThis command will write the value for the Page_Timeout configuration\n" \
1471 "parameter.\n\n" \
1472 "\t<timeout> - dddd; measured in number of baseband slots.",
1473 &hci_write_page_timeout
1474 },
1475 {
1476 "read_scan_enable",
1477 "\nThis command will read the value for the Scan_Enable parameter. The\n" \
1478 "Scan_Enable parameter controls whether or not the Bluetooth uint\n" \
1479 "will periodically scan for page attempts and/or inquiry requests\n" \
1480 "from other Bluetooth unit.\n\n" \
1481 "\t0x00 - No Scans enabled.\n" \
1482 "\t0x01 - Inquiry Scan enabled. Page Scan disabled.\n" \
1483 "\t0x02 - Inquiry Scan disabled. Page Scan enabled.\n" \
1484 "\t0x03 - Inquiry Scan enabled. Page Scan enabled.",
1485 &hci_read_scan_enable
1486 },
1487 {
1488 "write_scan_enable <scan_enable>",
1489 "\nThis command will write the value for the Scan_Enable parameter.\n" \
1490 "The Scan_Enable parameter controls whether or not the Bluetooth\n" \
1491 "unit will periodically scan for page attempts and/or inquiry\n" \
1492 "requests from other Bluetooth unit.\n\n" \
1493 "\t<scan_enable> - dd;\n" \
1494 "\t0 - No Scans enabled.\n" \
1495 "\t1 - Inquiry Scan enabled. Page Scan disabled.\n" \
1496 "\t2 - Inquiry Scan disabled. Page Scan enabled.\n" \
1497 "\t3 - Inquiry Scan enabled. Page Scan enabled.",
1498 &hci_write_scan_enable
1499 },
1500 {
1501 "read_page_scan_activity",
1502 "\nThis command will read the value for Page_Scan_Activity configuration\n" \
1503 "parameters. The Page_Scan_Interval configuration parameter defines the\n" \
1504 "amount of time between consecutive page scans. This time interval is \n" \
1505 "defined from when the Host Controller started its last page scan until\n" \
1506 "it begins the next page scan. The Page_Scan_Window configuration parameter\n" \
1507 "defines the amount of time for the duration of the page scan. The\n" \
1508 "Page_Scan_Window can only be less than or equal to the Page_Scan_Interval.",
1509 &hci_read_page_scan_activity
1510 },
1511 {
1512 "write_page_scan_activity interval(dddd) window(dddd)",
1513 "\nThis command will write the value for Page_Scan_Activity configuration\n" \
1514 "parameter. The Page_Scan_Interval configuration parameter defines the\n" \
1515 "amount of time between consecutive page scans. This is defined as the time\n" \
1516 "interval from when the Host Controller started its last page scan until it\n" \
1517 "begins the next page scan. The Page_Scan_Window configuration parameter\n" \
1518 "defines the amount of time for the duration of the page scan. \n" \
1519 "The Page_Scan_Window can only be less than or equal to the Page_Scan_Interval.\n\n" \
1520 "\t<interval> - Range: 0x0012 -� 0x100, Time = N * 0.625 msec\n" \
1521 "\t<window>   - Range: 0x0012 -� 0x100, Time = N * 0.625 msen",
1522 &hci_write_page_scan_activity
1523 },
1524 {
1525 "read_inquiry_scan_activity",
1526 "\nThis command will read the value for Inquiry_Scan_Activity configuration\n" \
1527 "parameter. The Inquiry_Scan_Interval configuration parameter defines the\n" \
1528 "amount of time between consecutive inquiry scans. This is defined as the\n" \
1529 "time interval from when the Host Controller started its last inquiry scan\n" \
1530 "until it begins the next inquiry scan.",
1531 &hci_read_inquiry_scan_activity
1532 },
1533 {
1534 "write_inquiry_scan_activity interval(dddd) window(dddd)",
1535 "\nThis command will write the value for Inquiry_Scan_Activity configuration\n"\
1536 "parameter. The Inquiry_Scan_Interval configuration parameter defines the\n" \
1537 "amount of time between consecutive inquiry scans. This is defined as the\n" \
1538 "time interval from when the Host Controller started its last inquiry scan\n" \
1539 "until it begins the next inquiry scan. The Inquiry_Scan_Window configuration\n" \
1540 "parameter defines the amount of time for the duration of the inquiry scan.\n" \
1541 "The Inquiry_Scan_Window can only be less than or equal to the Inquiry_Scan_Interval.\n\n" \
1542 "\t<interval> - Range: 0x0012 -� 0x100, Time = N * 0.625 msec\n" \
1543 "\t<window>   - Range: 0x0012 -� 0x100, Time = N * 0.625 msen",
1544 &hci_write_inquiry_scan_activity
1545 },
1546 {
1547 "read_authentication_enable",
1548 "\nThis command will read the value for the Authentication_Enable parameter.\n"\
1549 "The Authentication_Enable parameter controls if the local unit requires\n"\
1550 "to authenticate the remote unit at connection setup (between the\n" \
1551 "Create_Connection command or acceptance of an incoming ACL connection\n"\
1552 "and the corresponding Connection Complete event). At connection setup, only\n"\
1553 "the unit(s) with the Authentication_Enable parameter enabled will try to\n"\
1554 "authenticate the other unit.",
1555 &hci_read_authentication_enable
1556 },
1557 {
1558 "write_authentication_enable enable(0|1)",
1559 "\nThis command will write the value for the Authentication_Enable parameter.\n"\
1560 "The Authentication_Enable parameter controls if the local unit requires to\n"\
1561 "authenticate the remote unit at connection setup (between the\n" \
1562 "Create_Connection command or acceptance of an incoming ACL connection\n" \
1563 "and the corresponding Connection Complete event). At connection setup, only\n"\
1564 "the unit(s) with the Authentication_Enable parameter enabled will try to\n"\
1565 "authenticate the other unit.",
1566 &hci_write_authentication_enable
1567 },
1568 {
1569 "read_encryption_mode",
1570 "\nThis command will read the value for the Encryption_Mode parameter. The\n" \
1571 "Encryption_Mode parameter controls if the local unit requires encryption\n" \
1572 "to the remote unit at connection setup (between the Create_Connection\n" \
1573 "command or acceptance of an incoming ACL connection and the corresponding\n" \
1574 "Connection Complete event). At connection setup, only the unit(s) with\n" \
1575 "the Authentication_Enable parameter enabled and Encryption_Mode parameter\n" \
1576 "enabled will try to encrypt the connection to the other unit.\n\n" \
1577 "\t<encryption_mode>:\n" \
1578 "\t0x00 - Encryption disabled.\n" \
1579 "\t0x01 - Encryption only for point-to-point packets.\n" \
1580 "\t0x02 - Encryption for both point-to-point and broadcast packets.",
1581 &hci_read_encryption_mode
1582 },
1583 {
1584 "write_encryption_mode mode(0|1|2)",
1585 "\tThis command will write the value for the Encryption_Mode parameter.\n" \
1586 "The Encryption_Mode parameter controls if the local unit requires\n" \
1587 "encryption to the remote unit at connection setup (between the\n" \
1588 "Create_Connection command or acceptance of an incoming ACL connection\n" \
1589 "and the corresponding Connection Complete event). At connection setup,\n" \
1590 "only the unit(s) with the Authentication_Enable parameter enabled and\n" \
1591 "Encryption_Mode parameter enabled will try to encrypt the connection to\n" \
1592 "the other unit.\n\n" \
1593 "\t<encryption_mode> (dd)\n" \
1594 "\t0 - Encryption disabled.\n" \
1595 "\t1 - Encryption only for point-to-point packets.\n" \
1596 "\t2 - Encryption for both point-to-point and broadcast packets.",
1597 &hci_write_encryption_mode
1598 },
1599 {
1600 "read_class_of_device",
1601 "\nThis command will read the value for the Class_of_Device parameter.\n" \
1602 "The Class_of_Device parameter is used to indicate the capabilities of\n" \
1603 "the local unit to other units.",
1604 &hci_read_class_of_device
1605 },
1606 {
1607 "write_class_of_device class(xx:xx:xx)",
1608 "\nThis command will write the value for the Class_of_Device parameter.\n" \
1609 "The Class_of_Device parameter is used to indicate the capabilities of \n" \
1610 "the local unit to other units.\n\n" \
1611 "\t<class> (xx:xx:xx) - class of device",
1612 &hci_write_class_of_device
1613 },
1614 {
1615 "read_voice_settings",
1616 "\nThis command will read the values for the Voice_Setting parameter.\n" \
1617 "The Voice_Setting parameter controls all the various settings for voice\n" \
1618 "connections. These settings apply to all voice connections, and cannot be\n" \
1619 "set for individual voice connections. The Voice_Setting parameter controls\n" \
1620 "the configuration for voice connections: Input Coding, Air coding format,\n" \
1621 "input data format, Input sample size, and linear PCM parameter.",
1622 &hci_read_voice_settings
1623 },
1624 {
1625 "write_voice_settings settings(xxxx)",
1626 "\nThis command will write the values for the Voice_Setting parameter.\n" \
1627 "The Voice_Setting parameter controls all the various settings for voice\n" \
1628 "connections. These settings apply to all voice connections, and cannot be\n" \
1629 "set for individual voice connections. The Voice_Setting parameter controls\n" \
1630 "the configuration for voice connections: Input Coding, Air coding format,\n" \
1631 "input data format, Input sample size, and linear PCM parameter.\n\n" \
1632 "\t<voice_settings> (xxxx) - voice settings",
1633 &hci_write_voice_settings
1634 },
1635 {
1636 "read_number_broadcast_retransmissions",
1637 "\nThis command will read the unit's parameter value for the Number of\n" \
1638 "Broadcast Retransmissions. Broadcast packets are not acknowledged and are\n" \
1639 "unreliable.",
1640 &hci_read_number_broadcast_retransmissions
1641 },
1642 {
1643 "write_number_broadcast_retransmissions count(dd)",
1644 "\nThis command will write the unit's parameter value for the Number of\n" \
1645 "Broadcast Retransmissions. Broadcast packets are not acknowledged and are\n" \
1646 "unreliable.\n\n" \
1647 "\t<count> (dd) - number of broadcast retransimissions",
1648 &hci_write_number_broadcast_retransmissions
1649 },
1650 {
1651 "read_hold_mode_activity",
1652 "\nThis command will read the value for the Hold_Mode_Activity parameter.\n" \
1653 "The Hold_Mode_Activity value is used to determine what activities should\n" \
1654 "be suspended when the unit is in hold mode.",
1655 &hci_read_hold_mode_activity
1656 },
1657 {
1658 "write_hold_mode_activity settings(0|1|2|4)",
1659 "\nThis command will write the value for the Hold_Mode_Activity parameter.\n" \
1660 "The Hold_Mode_Activity value is used to determine what activities should\n" \
1661 "be suspended when the unit is in hold mode.\n\n" \
1662 "\t<settings> (dd) - bit mask:\n" \
1663 "\t0 - Maintain current Power State. Default\n" \
1664 "\t1 - Suspend Page Scan.\n" \
1665 "\t2 - Suspend Inquiry Scan.\n" \
1666 "\t4 - Suspend Periodic Inquiries.",
1667 &hci_write_hold_mode_activity
1668 },
1669 {
1670 "read_sco_flow_control_enable",
1671 "\nThe Read_SCO_Flow_Control_Enable command provides the ability to read\n" \
1672 "the SCO_Flow_Control_Enable setting. By using this setting, the Host can\n" \
1673 "decide if the Host Controller will send Number Of Completed Packets events\n" \
1674 "for SCO Connection Handles. This setting allows the Host to enable and\n" \
1675 "disable SCO flow control.",
1676 &hci_read_sco_flow_control_enable
1677 },
1678 {
1679 "write_sco_flow_control_enable enable(0|1)",
1680 "\nThe Write_SCO_Flow_Control_Enable command provides the ability to write\n" \
1681 "the SCO_Flow_Control_Enable setting. By using this setting, the Host can\n" \
1682 "decide if the Host Controller will send Number Of Completed Packets events\n" \
1683 "for SCO Connection Handles. This setting allows the Host to enable and\n" \
1684 "disable SCO flow control. The SCO_Flow_Control_Enable setting can only be\n" \
1685 "changed if no connections exist.",
1686 &hci_write_sco_flow_control_enable
1687 },
1688 {
1689 "read_link_supervision_timeout <connection_handle>",
1690 "\nThis command will read the value for the Link_Supervision_Timeout\n" \
1691 "parameter for the device. The Link_Supervision_Timeout parameter is used\n" \
1692 "by the master or slave Bluetooth device to monitor link loss. If, for any\n" \
1693 "reason, no Baseband packets are received from that Connection Handle for a\n" \
1694 "duration longer than the Link_Supervision_Timeout, the connection is\n"
1695 "disconnected.\n\n" \
1696 "\t<connection_handle> - dddd; connection handle\n",
1697 &hci_read_link_supervision_timeout
1698 },
1699 {
1700 "write_link_supervision_timeout <connection_handle> <timeout>",
1701 "\nThis command will write the value for the Link_Supervision_Timeout\n" \
1702 "parameter for the device. The Link_Supervision_Timeout parameter is used\n" \
1703 "by the master or slave Bluetooth device to monitor link loss. If, for any\n" \
1704 "reason, no Baseband packets are received from that connection handle for a\n" \
1705 "duration longer than the Link_Supervision_Timeout, the connection is\n" \
1706 "disconnected.\n\n" \
1707 "\t<connection_handle> - dddd; connection handle\n" \
1708 "\t<timeout>           - dddd; timeout measured in number of baseband slots\n",
1709 &hci_write_link_supervision_timeout
1710 },
1711 { NULL, }
1712 };
1713 
1714