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