4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * $Id: node.c,v 1.6 2003/07/22 21:14:02 max Exp $
34 #include <sys/ioctl.h>
35 #define L2CAP_SOCKET_CHECKED
36 #include <bluetooth.h>
38 #include <netgraph/ng_message.h>
43 #include "hccontrol.h"
45 /* Send Read_Node_State command to the node */
47 hci_read_node_state(int s, int argc, char **argv)
49 struct ng_btsocket_hci_raw_node_state r;
51 memset(&r, 0, sizeof(r));
52 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STATE, &r, sizeof(r)) < 0)
55 fprintf(stdout, "State: %#x\n", r.state);
58 } /* hci_read_node_state */
60 /* Send Intitialize command to the node */
62 hci_node_initialize(int s, int argc, char **argv)
64 if (ioctl(s, SIOC_HCI_RAW_NODE_INIT) < 0)
68 } /* hci_node_initialize */
70 /* Send Read_Debug_Level command to the node */
72 hci_read_debug_level(int s, int argc, char **argv)
74 struct ng_btsocket_hci_raw_node_debug r;
76 memset(&r, 0, sizeof(r));
77 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_DEBUG, &r, sizeof(r)) < 0)
80 fprintf(stdout, "Debug level: %d\n", r.debug);
83 } /* hci_read_debug_level */
85 /* Send Write_Debug_Level command to the node */
87 hci_write_debug_level(int s, int argc, char **argv)
89 struct ng_btsocket_hci_raw_node_debug r;
91 memset(&r, 0, sizeof(r));
94 r.debug = atoi(argv[0]);
101 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_DEBUG, &r, sizeof(r)) < 0)
105 } /* hci_write_debug_level */
107 /* Send Read_Node_Buffer_Size command to the node */
109 hci_read_node_buffer_size(int s, int argc, char **argv)
111 struct ng_btsocket_hci_raw_node_buffer r;
113 memset(&r, 0, sizeof(r));
114 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BUFFER, &r, sizeof(r)) < 0)
117 fprintf(stdout, "Number of free command buffers: %d\n",
119 fprintf(stdout, "Max. ACL packet size: %d\n",
121 fprintf(stdout, "Numbef of free ACL buffers: %d\n",
123 fprintf(stdout, "Total number of ACL buffers: %d\n",
125 fprintf(stdout, "Max. SCO packet size: %d\n",
127 fprintf(stdout, "Numbef of free SCO buffers: %d\n",
129 fprintf(stdout, "Total number of SCO buffers: %d\n",
133 } /* hci_read_node_buffer_size */
135 /* Send Read_Node_BD_ADDR command to the node */
137 hci_read_node_bd_addr(int s, int argc, char **argv)
139 struct ng_btsocket_hci_raw_node_bdaddr r;
141 memset(&r, 0, sizeof(r));
142 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &r, sizeof(r)) < 0)
145 fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&r.bdaddr, NULL));
148 } /* hci_read_node_bd_addr */
150 /* Send Read_Node_Features command to the node */
152 hci_read_node_features(int s, int argc, char **argv)
154 struct ng_btsocket_hci_raw_node_features r;
158 memset(&r, 0, sizeof(r));
159 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_FEATURES, &r, sizeof(r)) < 0)
162 fprintf(stdout, "Features: ");
163 for (n = 0; n < sizeof(r.features)/sizeof(r.features[0]); n++)
164 fprintf(stdout, "%#02x ", r.features[n]);
165 fprintf(stdout, "\n%s\n", hci_features2str(r.features,
166 buffer, sizeof(buffer)));
169 } /* hci_read_node_features */
171 /* Send Read_Node_Stat command to the node */
173 hci_read_node_stat(int s, int argc, char **argv)
175 struct ng_btsocket_hci_raw_node_stat r;
177 memset(&r, 0, sizeof(r));
178 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STAT, &r, sizeof(r)) < 0)
181 fprintf(stdout, "Commands sent: %d\n", r.stat.cmd_sent);
182 fprintf(stdout, "Events received: %d\n", r.stat.evnt_recv);
183 fprintf(stdout, "ACL packets received: %d\n", r.stat.acl_recv);
184 fprintf(stdout, "ACL packets sent: %d\n", r.stat.acl_sent);
185 fprintf(stdout, "SCO packets received: %d\n", r.stat.sco_recv);
186 fprintf(stdout, "SCO packets sent: %d\n", r.stat.sco_sent);
187 fprintf(stdout, "Bytes received: %d\n", r.stat.bytes_recv);
188 fprintf(stdout, "Bytes sent: %d\n", r.stat.bytes_sent);
191 } /* hci_read_node_stat */
193 /* Send Reset_Node_Stat command to the node */
195 hci_reset_node_stat(int s, int argc, char **argv)
197 if (ioctl(s, SIOC_HCI_RAW_NODE_RESET_STAT) < 0)
201 } /* hci_reset_node_stat */
203 /* Send Flush_Neighbor_Cache command to the node */
205 hci_flush_neighbor_cache(int s, int argc, char **argv)
207 if (ioctl(s, SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE) < 0)
211 } /* hci_flush_neighbor_cache */
213 #define MIN(a,b) (((a)>(b)) ? (b) :(a) )
215 static int hci_dump_adv(uint8_t *data, int length)
236 printf("NDflag:%x\n", *data);
239 printf("LocalName:");
240 for(i = 0; i < MIN(length,elemlen); i++){
246 printf("Type%d:", type);
247 for(i=0; i < MIN(length,elemlen); i++){
248 printf("%02x ",data[i]);
259 /* Send Read_Neighbor_Cache command to the node */
261 hci_read_neighbor_cache(int s, int argc, char **argv)
263 struct ng_btsocket_hci_raw_node_neighbor_cache r;
265 const char *addrtype2str[] = {"B", "P", "R", "E"};
267 memset(&r, 0, sizeof(r));
268 r.num_entries = NG_HCI_MAX_NEIGHBOR_NUM;
269 r.entries = calloc(NG_HCI_MAX_NEIGHBOR_NUM,
270 sizeof(ng_hci_node_neighbor_cache_entry_ep));
271 if (r.entries == NULL) {
276 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE, &r,
290 for (n = 0; n < r.num_entries; n++) {
291 uint8_t addrtype = r.entries[n].addrtype;
292 if(addrtype >= sizeof(addrtype2str)/sizeof(addrtype2str[0]))
293 addrtype = sizeof(addrtype2str)/sizeof(addrtype2str[0]) - 1;
296 "%02x %02x %02x %02x %02x %02x %02x %02x " \
300 addrtype2str[addrtype],
301 hci_bdaddr2str(&r.entries[n].bdaddr),
302 r.entries[n].features[0], r.entries[n].features[1],
303 r.entries[n].features[2], r.entries[n].features[3],
304 r.entries[n].features[4], r.entries[n].features[5],
305 r.entries[n].features[6], r.entries[n].features[7],
306 r.entries[n].clock_offset, r.entries[n].page_scan_mode,
307 r.entries[n].page_scan_rep_mode);
308 hci_dump_adv(r.entries[n].extinq_data,
309 r.entries[n].extinq_size);
310 fprintf(stdout,"\n");
316 } /* hci_read_neightbor_cache */
318 /* Send Read_Connection_List command to the node */
320 hci_read_connection_list(int s, int argc, char **argv)
322 struct ng_btsocket_hci_raw_con_list r;
325 memset(&r, 0, sizeof(r));
326 r.num_connections = NG_HCI_MAX_CON_NUM;
327 r.connections = calloc(NG_HCI_MAX_CON_NUM, sizeof(ng_hci_node_con_ep));
328 if (r.connections == NULL) {
333 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_CON_LIST, &r, sizeof(r)) < 0) {
349 for (n = 0; n < r.num_connections; n++) {
360 hci_bdaddr2str(&r.connections[n].bdaddr),
361 r.connections[n].con_handle,
362 (r.connections[n].link_type == NG_HCI_LINK_ACL)?
364 r.connections[n].mode,
365 (r.connections[n].role == NG_HCI_ROLE_MASTER)?
367 hci_encrypt2str(r.connections[n].encryption_mode, 1),
368 r.connections[n].pending,
369 r.connections[n].queue_len,
370 hci_con_state2str(r.connections[n].state));
376 } /* hci_read_connection_list */
378 /* Send Read_Node_Link_Policy_Settings_Mask command to the node */
380 hci_read_node_link_policy_settings_mask(int s, int argc, char **argv)
382 struct ng_btsocket_hci_raw_node_link_policy_mask r;
384 memset(&r, 0, sizeof(r));
385 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK, &r, sizeof(r)) < 0)
388 fprintf(stdout, "Link Policy Settings mask: %#04x\n", r.policy_mask);
391 } /* hci_read_node_link_policy_settings_mask */
393 /* Send Write_Node_Link_Policy_Settings_Mask command to the node */
395 hci_write_node_link_policy_settings_mask(int s, int argc, char **argv)
397 struct ng_btsocket_hci_raw_node_link_policy_mask r;
400 memset(&r, 0, sizeof(r));
404 if (sscanf(argv[0], "%x", &m) != 1)
407 r.policy_mask = (m & 0xffff);
414 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK, &r, sizeof(r)) < 0)
418 } /* hci_write_node_link_policy_settings_mask */
420 /* Send Read_Node_Packet_Mask command to the node */
422 hci_read_node_packet_mask(int s, int argc, char **argv)
424 struct ng_btsocket_hci_raw_node_packet_mask r;
426 memset(&r, 0, sizeof(r));
427 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_PACKET_MASK, &r, sizeof(r)) < 0)
430 fprintf(stdout, "Packet mask: %#04x\n", r.packet_mask);
433 } /* hci_read_node_packet_mask */
435 /* Send Write_Node_Packet_Mask command to the node */
437 hci_write_node_packet_mask(int s, int argc, char **argv)
439 struct ng_btsocket_hci_raw_node_packet_mask r;
442 memset(&r, 0, sizeof(r));
446 if (sscanf(argv[0], "%x", &m) != 1)
449 r.packet_mask = (m & 0xffff);
456 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_PACKET_MASK, &r, sizeof(r)) < 0)
460 } /* hci_write_node_packet_mask */
462 /* Send Read_Node_Role_Switch command to the node */
464 hci_read_node_role_switch(int s, int argc, char **argv)
466 struct ng_btsocket_hci_raw_node_role_switch r;
468 memset(&r, 0, sizeof(r));
469 if (ioctl(s, SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH, &r, sizeof(r)) < 0)
472 fprintf(stdout, "Role switch: %d\n", r.role_switch);
475 } /* hci_read_node_role_switch */
477 /* Send Write_Node_Role_Switch command to the node */
479 hci_write_node_role_switch(int s, int argc, char **argv)
481 struct ng_btsocket_hci_raw_node_role_switch r;
484 memset(&r, 0, sizeof(r));
488 if (sscanf(argv[0], "%d", &m) != 1)
491 r.role_switch = m? 1 : 0;
498 if (ioctl(s, SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH, &r, sizeof(r)) < 0)
502 } /* hci_write_node_role_switch */
504 /* Send Read_Node_List command to the node */
506 hci_read_node_list(int s, int argc, char **argv)
508 struct ng_btsocket_hci_raw_node_list_names r;
511 r.num_names = MAX_NODE_NUM;
512 r.names = (struct nodeinfo*)calloc(MAX_NODE_NUM, sizeof(struct nodeinfo));
516 if (ioctl(s, SIOC_HCI_RAW_NODE_LIST_NAMES, &r, sizeof(r)) < 0) {
521 fprintf(stdout, "Name ID Num hooks\n");
522 for (i = 0; i < r.num_names; ++i)
523 fprintf(stdout, "%-15s %08x %9d\n",
524 r.names[i].name, r.names[i].id, r.names[i].hooks);
529 } /* hci_read_node_list */
531 struct hci_command node_commands[] = {
534 "Get the HCI node state",
539 "Initialize the HCI node",
544 "Read the HCI node debug level",
545 &hci_read_debug_level
548 "write_debug_level <level>",
549 "Write the HCI node debug level",
550 &hci_write_debug_level
553 "read_node_buffer_size",
554 "Read the HCI node buffer information. This will return current state of the\n"\
555 "HCI buffer for the HCI node",
556 &hci_read_node_buffer_size
560 "Read the HCI node BD_ADDR. Returns device BD_ADDR as cached by the HCI node",
561 &hci_read_node_bd_addr
564 "read_node_features",
565 "Read the HCI node features. This will return list of supported features as\n" \
566 "cached by the HCI node",
567 &hci_read_node_features
571 "Read packets and bytes counters for the HCI node",
576 "Reset packets and bytes counters for the HCI node",
580 "flush_neighbor_cache",
581 "Flush content of the HCI node neighbor cache",
582 &hci_flush_neighbor_cache
585 "read_neighbor_cache",
586 "Read content of the HCI node neighbor cache",
587 &hci_read_neighbor_cache
590 "read_connection_list",
591 "Read the baseband connection descriptors list for the HCI node",
592 &hci_read_connection_list
595 "read_node_link_policy_settings_mask",
596 "Read the value of the Link Policy Settinngs mask for the HCI node",
597 &hci_read_node_link_policy_settings_mask
600 "write_node_link_policy_settings_mask <policy_mask>",
601 "Write the value of the Link Policy Settings mask for the HCI node. By default\n" \
602 "all supported Link Policy modes (as reported by the local device features) are\n"\
603 "enabled. The particular Link Policy mode is enabled if local device supports\n"\
604 "it and correspinding bit in the mask was set\n\n" \
605 "\t<policy_mask> - xxxx; Link Policy mask\n" \
606 "\t\t0x0000 - Disable All LM Modes\n" \
607 "\t\t0x0001 - Enable Master Slave Switch\n" \
608 "\t\t0x0002 - Enable Hold Mode\n" \
609 "\t\t0x0004 - Enable Sniff Mode\n" \
610 "\t\t0x0008 - Enable Park Mode\n",
611 &hci_write_node_link_policy_settings_mask
614 "read_node_packet_mask",
615 "Read the value of the Packet mask for the HCI node",
616 &hci_read_node_packet_mask
619 "write_node_packet_mask <packet_mask>",
620 "Write the value of the Packet mask for the HCI node. By default all supported\n" \
621 "packet types (as reported by the local device features) are enabled. The\n" \
622 "particular packet type is enabled if local device supports it and corresponding\n" \
623 "bit in the mask was set\n\n" \
624 "\t<packet_mask> - xxxx; packet type mask\n" \
626 "\t\tACL packets\n" \
627 "\t\t-----------\n" \
635 "\t\tSCO packets\n" \
636 "\t\t-----------\n" \
640 &hci_write_node_packet_mask
643 "read_node_role_switch",
644 "Read the value of the Role Switch parameter for the HCI node",
645 &hci_read_node_role_switch
648 "write_node_role_switch {0|1}",
649 "Write the value of the Role Switch parameter for the HCI node. By default,\n" \
650 "if Role Switch is supported, local device will try to perform Role Switch\n" \
651 "and become Master on incoming connection. Some devices do not support Role\n" \
652 "Switch and thus incoming connections from such devices will fail. Setting\n" \
653 "this parameter to zero will prevent Role Switch and thus accepting device\n" \
655 &hci_write_node_role_switch
659 "Get a list of HCI nodes, their Netgraph IDs and connected hooks.",