xref: /freebsd-src/usr.sbin/bluetooth/hccontrol/node.c (revision fdbf7cab91ae9ae7ca87bd47acb7400813bd7160)
11de7b4b8SPedro F. Giffuni /*-
2878ed226SJulian Elischer  * node.c
3878ed226SJulian Elischer  *
44d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni  *
6878ed226SJulian Elischer  * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7878ed226SJulian Elischer  * All rights reserved.
8878ed226SJulian Elischer  *
9878ed226SJulian Elischer  * Redistribution and use in source and binary forms, with or without
10878ed226SJulian Elischer  * modification, are permitted provided that the following conditions
11878ed226SJulian Elischer  * are met:
12878ed226SJulian Elischer  * 1. Redistributions of source code must retain the above copyright
13878ed226SJulian Elischer  *    notice, this list of conditions and the following disclaimer.
14878ed226SJulian Elischer  * 2. Redistributions in binary form must reproduce the above copyright
15878ed226SJulian Elischer  *    notice, this list of conditions and the following disclaimer in the
16878ed226SJulian Elischer  *    documentation and/or other materials provided with the distribution.
17878ed226SJulian Elischer  *
18878ed226SJulian Elischer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19878ed226SJulian Elischer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20878ed226SJulian Elischer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21878ed226SJulian Elischer  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22878ed226SJulian Elischer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23878ed226SJulian Elischer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24878ed226SJulian Elischer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25878ed226SJulian Elischer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26878ed226SJulian Elischer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27878ed226SJulian Elischer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28878ed226SJulian Elischer  * SUCH DAMAGE.
29878ed226SJulian Elischer  *
300986ab12SMaksim Yevmenkin  * $Id: node.c,v 1.6 2003/07/22 21:14:02 max Exp $
31878ed226SJulian Elischer  */
32878ed226SJulian Elischer 
33878ed226SJulian Elischer #include <sys/ioctl.h>
34*fdbf7cabSElyes Haouas #include <sys/param.h>
358d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
360986ab12SMaksim Yevmenkin #include <bluetooth.h>
37878ed226SJulian Elischer #include <errno.h>
38fc5806edSMarkus Brueffer #include <netgraph/ng_message.h>
39878ed226SJulian Elischer #include <stdio.h>
40878ed226SJulian Elischer #include <stdlib.h>
41878ed226SJulian Elischer #include <string.h>
42fc5806edSMarkus Brueffer #include <unistd.h>
4384662d68STakanori Watanabe #include <uuid.h>
44878ed226SJulian Elischer #include "hccontrol.h"
45878ed226SJulian Elischer 
46878ed226SJulian Elischer /* Send Read_Node_State command to the node */
47878ed226SJulian Elischer static int
hci_read_node_state(int s,int argc,char ** argv)48878ed226SJulian Elischer hci_read_node_state(int s, int argc, char **argv)
49878ed226SJulian Elischer {
50878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_state	r;
51878ed226SJulian Elischer 
52878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
53878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STATE, &r, sizeof(r)) < 0)
54878ed226SJulian Elischer 		return (ERROR);
55878ed226SJulian Elischer 
561a63eb31SJulian Elischer 	fprintf(stdout, "State: %#x\n", r.state);
57878ed226SJulian Elischer 
58878ed226SJulian Elischer 	return (OK);
59878ed226SJulian Elischer } /* hci_read_node_state */
60878ed226SJulian Elischer 
61878ed226SJulian Elischer /* Send Intitialize command to the node */
62878ed226SJulian Elischer static int
hci_node_initialize(int s,int argc,char ** argv)63878ed226SJulian Elischer hci_node_initialize(int s, int argc, char **argv)
64878ed226SJulian Elischer {
651a63eb31SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_INIT) < 0)
66878ed226SJulian Elischer 		return (ERROR);
67878ed226SJulian Elischer 
68878ed226SJulian Elischer 	return (OK);
69878ed226SJulian Elischer } /* hci_node_initialize */
70878ed226SJulian Elischer 
71878ed226SJulian Elischer /* Send Read_Debug_Level command to the node */
72878ed226SJulian Elischer static int
hci_read_debug_level(int s,int argc,char ** argv)73878ed226SJulian Elischer hci_read_debug_level(int s, int argc, char **argv)
74878ed226SJulian Elischer {
75878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_debug	r;
76878ed226SJulian Elischer 
77878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
78878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_DEBUG, &r, sizeof(r)) < 0)
79878ed226SJulian Elischer 		return (ERROR);
80878ed226SJulian Elischer 
811a63eb31SJulian Elischer 	fprintf(stdout, "Debug level: %d\n", r.debug);
82878ed226SJulian Elischer 
83878ed226SJulian Elischer 	return (OK);
84878ed226SJulian Elischer } /* hci_read_debug_level */
85878ed226SJulian Elischer 
86878ed226SJulian Elischer /* Send Write_Debug_Level command to the node */
87878ed226SJulian Elischer static int
hci_write_debug_level(int s,int argc,char ** argv)88878ed226SJulian Elischer hci_write_debug_level(int s, int argc, char **argv)
89878ed226SJulian Elischer {
90878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_debug	r;
91878ed226SJulian Elischer 
92878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
93878ed226SJulian Elischer 	switch (argc) {
94878ed226SJulian Elischer 	case 1:
95878ed226SJulian Elischer 		r.debug = atoi(argv[0]);
96878ed226SJulian Elischer 		break;
97878ed226SJulian Elischer 
98878ed226SJulian Elischer 	default:
99878ed226SJulian Elischer 		return (USAGE);
100878ed226SJulian Elischer 	}
101878ed226SJulian Elischer 
102878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_SET_DEBUG, &r, sizeof(r)) < 0)
103878ed226SJulian Elischer 		return (ERROR);
104878ed226SJulian Elischer 
105878ed226SJulian Elischer 	return (OK);
106878ed226SJulian Elischer } /* hci_write_debug_level */
107878ed226SJulian Elischer 
108878ed226SJulian Elischer /* Send Read_Node_Buffer_Size command to the node */
109878ed226SJulian Elischer static int
hci_read_node_buffer_size(int s,int argc,char ** argv)110878ed226SJulian Elischer hci_read_node_buffer_size(int s, int argc, char **argv)
111878ed226SJulian Elischer {
112878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_buffer	r;
113878ed226SJulian Elischer 
114878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
115878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BUFFER, &r, sizeof(r)) < 0)
116878ed226SJulian Elischer 		return (ERROR);
117878ed226SJulian Elischer 
118878ed226SJulian Elischer 	fprintf(stdout, "Number of free command buffers: %d\n",
119878ed226SJulian Elischer 		r.buffer.cmd_free);
120878ed226SJulian Elischer 	fprintf(stdout, "Max. ACL packet size: %d\n",
121878ed226SJulian Elischer 		r.buffer.acl_size);
122878ed226SJulian Elischer 	fprintf(stdout, "Numbef of free ACL buffers: %d\n",
123878ed226SJulian Elischer 		r.buffer.acl_free);
124878ed226SJulian Elischer 	fprintf(stdout, "Total number of ACL buffers: %d\n",
125878ed226SJulian Elischer 		r.buffer.acl_pkts);
126878ed226SJulian Elischer 	fprintf(stdout, "Max. SCO packet size: %d\n",
127878ed226SJulian Elischer 		r.buffer.sco_size);
128878ed226SJulian Elischer 	fprintf(stdout, "Numbef of free SCO buffers: %d\n",
129878ed226SJulian Elischer 		r.buffer.sco_free);
130878ed226SJulian Elischer 	fprintf(stdout, "Total number of SCO buffers: %d\n",
131878ed226SJulian Elischer 		r.buffer.sco_pkts);
132878ed226SJulian Elischer 
133878ed226SJulian Elischer 	return (OK);
134878ed226SJulian Elischer } /* hci_read_node_buffer_size */
135878ed226SJulian Elischer 
136878ed226SJulian Elischer /* Send Read_Node_BD_ADDR command to the node */
137878ed226SJulian Elischer static int
hci_read_node_bd_addr(int s,int argc,char ** argv)138878ed226SJulian Elischer hci_read_node_bd_addr(int s, int argc, char **argv)
139878ed226SJulian Elischer {
140878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_bdaddr	r;
141878ed226SJulian Elischer 
142878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
143878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &r, sizeof(r)) < 0)
144878ed226SJulian Elischer 		return (ERROR);
145878ed226SJulian Elischer 
1460986ab12SMaksim Yevmenkin 	fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&r.bdaddr, NULL));
147878ed226SJulian Elischer 
148878ed226SJulian Elischer 	return (OK);
149878ed226SJulian Elischer } /* hci_read_node_bd_addr */
150878ed226SJulian Elischer 
151878ed226SJulian Elischer /* Send Read_Node_Features command to the node */
152878ed226SJulian Elischer static int
hci_read_node_features(int s,int argc,char ** argv)153878ed226SJulian Elischer hci_read_node_features(int s, int argc, char **argv)
154878ed226SJulian Elischer {
155878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_features	r;
156878ed226SJulian Elischer 	int						n;
1576f80a2c8SHans Petter Selasky 	char						buffer[2048];
158878ed226SJulian Elischer 
159878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
160878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_FEATURES, &r, sizeof(r)) < 0)
161878ed226SJulian Elischer 		return (ERROR);
162878ed226SJulian Elischer 
1631a63eb31SJulian Elischer 	fprintf(stdout, "Features: ");
164*fdbf7cabSElyes Haouas 	for (n = 0; n < nitems(r.features); n++)
165878ed226SJulian Elischer 		fprintf(stdout, "%#02x ", r.features[n]);
166878ed226SJulian Elischer 	fprintf(stdout, "\n%s\n", hci_features2str(r.features,
167878ed226SJulian Elischer 		buffer, sizeof(buffer)));
168878ed226SJulian Elischer 
169878ed226SJulian Elischer 	return (OK);
170878ed226SJulian Elischer } /* hci_read_node_features */
171878ed226SJulian Elischer 
172878ed226SJulian Elischer /* Send Read_Node_Stat command to the node */
173878ed226SJulian Elischer static int
hci_read_node_stat(int s,int argc,char ** argv)174878ed226SJulian Elischer hci_read_node_stat(int s, int argc, char **argv)
175878ed226SJulian Elischer {
176878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_stat	r;
177878ed226SJulian Elischer 
178878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
179878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STAT, &r, sizeof(r)) < 0)
180878ed226SJulian Elischer 		return (ERROR);
181878ed226SJulian Elischer 
182878ed226SJulian Elischer 	fprintf(stdout, "Commands sent: %d\n", r.stat.cmd_sent);
183878ed226SJulian Elischer 	fprintf(stdout, "Events received: %d\n", r.stat.evnt_recv);
184878ed226SJulian Elischer 	fprintf(stdout, "ACL packets received: %d\n", r.stat.acl_recv);
185878ed226SJulian Elischer 	fprintf(stdout, "ACL packets sent: %d\n", r.stat.acl_sent);
186878ed226SJulian Elischer 	fprintf(stdout, "SCO packets received: %d\n", r.stat.sco_recv);
187878ed226SJulian Elischer 	fprintf(stdout, "SCO packets sent: %d\n", r.stat.sco_sent);
188878ed226SJulian Elischer 	fprintf(stdout, "Bytes received: %d\n", r.stat.bytes_recv);
189878ed226SJulian Elischer 	fprintf(stdout, "Bytes sent: %d\n", r.stat.bytes_sent);
190878ed226SJulian Elischer 
191878ed226SJulian Elischer 	return (OK);
192878ed226SJulian Elischer } /* hci_read_node_stat */
193878ed226SJulian Elischer 
194878ed226SJulian Elischer /* Send Reset_Node_Stat command to the node */
195878ed226SJulian Elischer static int
hci_reset_node_stat(int s,int argc,char ** argv)196878ed226SJulian Elischer hci_reset_node_stat(int s, int argc, char **argv)
197878ed226SJulian Elischer {
1981a63eb31SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_RESET_STAT) < 0)
199878ed226SJulian Elischer 		return (ERROR);
200878ed226SJulian Elischer 
201878ed226SJulian Elischer 	return (OK);
202878ed226SJulian Elischer } /* hci_reset_node_stat */
203878ed226SJulian Elischer 
204878ed226SJulian Elischer /* Send Flush_Neighbor_Cache command to the node */
205878ed226SJulian Elischer static int
hci_flush_neighbor_cache(int s,int argc,char ** argv)206878ed226SJulian Elischer hci_flush_neighbor_cache(int s, int argc, char **argv)
207878ed226SJulian Elischer {
2081a63eb31SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE) < 0)
209878ed226SJulian Elischer 		return (ERROR);
210878ed226SJulian Elischer 
211878ed226SJulian Elischer 	return (OK);
212878ed226SJulian Elischer } /* hci_flush_neighbor_cache */
213878ed226SJulian Elischer 
214878ed226SJulian Elischer /* Send Read_Neighbor_Cache command to the node */
215878ed226SJulian Elischer static int
hci_read_neighbor_cache(int s,int argc,char ** argv)216878ed226SJulian Elischer hci_read_neighbor_cache(int s, int argc, char **argv)
217878ed226SJulian Elischer {
218878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_neighbor_cache	r;
219878ed226SJulian Elischer 	int						n, error = OK;
2204aa92fe2STakanori Watanabe 	const char  *addrtype2str[] = {"B", "P", "R", "E"};
221878ed226SJulian Elischer 
222878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
223878ed226SJulian Elischer 	r.num_entries = NG_HCI_MAX_NEIGHBOR_NUM;
224878ed226SJulian Elischer 	r.entries = calloc(NG_HCI_MAX_NEIGHBOR_NUM,
225878ed226SJulian Elischer 				sizeof(ng_hci_node_neighbor_cache_entry_ep));
226878ed226SJulian Elischer 	if (r.entries == NULL) {
227878ed226SJulian Elischer 		errno = ENOMEM;
228878ed226SJulian Elischer 		return (ERROR);
229878ed226SJulian Elischer 	}
230878ed226SJulian Elischer 
231878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE, &r,
232878ed226SJulian Elischer 			sizeof(r)) < 0) {
233878ed226SJulian Elischer 		error = ERROR;
234878ed226SJulian Elischer 		goto out;
235878ed226SJulian Elischer 	}
236878ed226SJulian Elischer 
237878ed226SJulian Elischer 	fprintf(stdout,
2384aa92fe2STakanori Watanabe "T " \
239878ed226SJulian Elischer "BD_ADDR           " \
240878ed226SJulian Elischer "Features                " \
241878ed226SJulian Elischer "Clock offset " \
242878ed226SJulian Elischer "Page scan " \
243878ed226SJulian Elischer "Rep. scan\n");
244878ed226SJulian Elischer 
245878ed226SJulian Elischer 	for (n = 0; n < r.num_entries; n++) {
2464aa92fe2STakanori Watanabe 	        uint8_t addrtype = r.entries[n].addrtype;
247*fdbf7cabSElyes Haouas 		if(addrtype >= nitems(addrtype2str))
248*fdbf7cabSElyes Haouas 			addrtype = nitems(addrtype2str) - 1;
249878ed226SJulian Elischer 		fprintf(stdout,
2504aa92fe2STakanori Watanabe "%1s %-17.17s " \
251878ed226SJulian Elischer "%02x %02x %02x %02x %02x %02x %02x %02x " \
252878ed226SJulian Elischer "%#12x " \
253878ed226SJulian Elischer "%#9x " \
254878ed226SJulian Elischer "%#9x\n",
2554aa92fe2STakanori Watanabe 			addrtype2str[addrtype],
2560986ab12SMaksim Yevmenkin 			hci_bdaddr2str(&r.entries[n].bdaddr),
257878ed226SJulian Elischer 			r.entries[n].features[0], r.entries[n].features[1],
258878ed226SJulian Elischer 			r.entries[n].features[2], r.entries[n].features[3],
259878ed226SJulian Elischer 			r.entries[n].features[4], r.entries[n].features[5],
260878ed226SJulian Elischer 			r.entries[n].features[6], r.entries[n].features[7],
261878ed226SJulian Elischer 			r.entries[n].clock_offset, r.entries[n].page_scan_mode,
262878ed226SJulian Elischer 			r.entries[n].page_scan_rep_mode);
2639287f06dSTakanori Watanabe 		print_adv_data(r.entries[n].extinq_size,
2649287f06dSTakanori Watanabe 			r.entries[n].extinq_data);
2654aa92fe2STakanori Watanabe 		fprintf(stdout,"\n");
266878ed226SJulian Elischer 	}
267878ed226SJulian Elischer out:
268878ed226SJulian Elischer 	free(r.entries);
269878ed226SJulian Elischer 
270878ed226SJulian Elischer 	return (error);
271878ed226SJulian Elischer } /* hci_read_neightbor_cache */
272878ed226SJulian Elischer 
273878ed226SJulian Elischer /* Send Read_Connection_List command to the node */
274878ed226SJulian Elischer static int
hci_read_connection_list(int s,int argc,char ** argv)275878ed226SJulian Elischer hci_read_connection_list(int s, int argc, char **argv)
276878ed226SJulian Elischer {
277878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_con_list	r;
278878ed226SJulian Elischer 	int					n, error = OK;
279878ed226SJulian Elischer 
280878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
281878ed226SJulian Elischer 	r.num_connections = NG_HCI_MAX_CON_NUM;
282878ed226SJulian Elischer 	r.connections = calloc(NG_HCI_MAX_CON_NUM, sizeof(ng_hci_node_con_ep));
283878ed226SJulian Elischer 	if (r.connections == NULL) {
284878ed226SJulian Elischer 		errno = ENOMEM;
285878ed226SJulian Elischer 		return (ERROR);
286878ed226SJulian Elischer 	}
287878ed226SJulian Elischer 
288878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_CON_LIST, &r, sizeof(r)) < 0) {
289878ed226SJulian Elischer 		error = ERROR;
290878ed226SJulian Elischer 		goto out;
291878ed226SJulian Elischer 	}
292878ed226SJulian Elischer 
293878ed226SJulian Elischer 	fprintf(stdout,
294878ed226SJulian Elischer "Remote BD_ADDR    " \
295878ed226SJulian Elischer "Handle " \
296878ed226SJulian Elischer "Type " \
297878ed226SJulian Elischer "Mode " \
298878ed226SJulian Elischer "Role " \
299878ed226SJulian Elischer "Encrypt " \
300878ed226SJulian Elischer "Pending " \
301878ed226SJulian Elischer "Queue " \
302878ed226SJulian Elischer "State\n");
303878ed226SJulian Elischer 
304878ed226SJulian Elischer 	for (n = 0; n < r.num_connections; n++) {
305878ed226SJulian Elischer 		fprintf(stdout,
3060986ab12SMaksim Yevmenkin "%-17.17s " \
307878ed226SJulian Elischer "%6d " \
308878ed226SJulian Elischer "%4.4s " \
309878ed226SJulian Elischer "%4d " \
310878ed226SJulian Elischer "%4.4s " \
311878ed226SJulian Elischer "%7.7s " \
312878ed226SJulian Elischer "%7d " \
313878ed226SJulian Elischer "%5d " \
314878ed226SJulian Elischer "%s\n",
3150986ab12SMaksim Yevmenkin 			hci_bdaddr2str(&r.connections[n].bdaddr),
316878ed226SJulian Elischer 			r.connections[n].con_handle,
317878ed226SJulian Elischer 			(r.connections[n].link_type == NG_HCI_LINK_ACL)?
318878ed226SJulian Elischer 				"ACL" : "SCO",
319878ed226SJulian Elischer 			r.connections[n].mode,
320878ed226SJulian Elischer 			(r.connections[n].role == NG_HCI_ROLE_MASTER)?
321878ed226SJulian Elischer 				"MAST" : "SLAV",
322878ed226SJulian Elischer 			hci_encrypt2str(r.connections[n].encryption_mode, 1),
323878ed226SJulian Elischer 			r.connections[n].pending,
324878ed226SJulian Elischer 			r.connections[n].queue_len,
325878ed226SJulian Elischer 			hci_con_state2str(r.connections[n].state));
326878ed226SJulian Elischer 	}
327878ed226SJulian Elischer out:
328878ed226SJulian Elischer 	free(r.connections);
329878ed226SJulian Elischer 
330878ed226SJulian Elischer 	return (error);
331878ed226SJulian Elischer } /* hci_read_connection_list */
332878ed226SJulian Elischer 
3331a63eb31SJulian Elischer /* Send Read_Node_Link_Policy_Settings_Mask command to the node */
334878ed226SJulian Elischer int
hci_read_node_link_policy_settings_mask(int s,int argc,char ** argv)3351a63eb31SJulian Elischer hci_read_node_link_policy_settings_mask(int s, int argc, char **argv)
336878ed226SJulian Elischer {
337878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_link_policy_mask	r;
338878ed226SJulian Elischer 
339878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
340878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK, &r, sizeof(r)) < 0)
341878ed226SJulian Elischer 		return (ERROR);
342878ed226SJulian Elischer 
3431a63eb31SJulian Elischer 	fprintf(stdout, "Link Policy Settings mask: %#04x\n", r.policy_mask);
344878ed226SJulian Elischer 
345878ed226SJulian Elischer 	return (OK);
3461a63eb31SJulian Elischer } /* hci_read_node_link_policy_settings_mask */
347878ed226SJulian Elischer 
3481a63eb31SJulian Elischer /* Send Write_Node_Link_Policy_Settings_Mask command to the node */
349878ed226SJulian Elischer int
hci_write_node_link_policy_settings_mask(int s,int argc,char ** argv)3501a63eb31SJulian Elischer hci_write_node_link_policy_settings_mask(int s, int argc, char **argv)
351878ed226SJulian Elischer {
352878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_link_policy_mask	r;
353878ed226SJulian Elischer 	int							m;
354878ed226SJulian Elischer 
355878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
356878ed226SJulian Elischer 
357878ed226SJulian Elischer 	switch (argc) {
358878ed226SJulian Elischer 	case 1:
359878ed226SJulian Elischer 		if (sscanf(argv[0], "%x", &m) != 1)
360878ed226SJulian Elischer 			return (USAGE);
361878ed226SJulian Elischer 
362878ed226SJulian Elischer 		r.policy_mask = (m & 0xffff);
363878ed226SJulian Elischer 		break;
364878ed226SJulian Elischer 
365878ed226SJulian Elischer 	default:
366878ed226SJulian Elischer 		return (USAGE);
367878ed226SJulian Elischer 	}
368878ed226SJulian Elischer 
369878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK, &r, sizeof(r)) < 0)
370878ed226SJulian Elischer 		return (ERROR);
371878ed226SJulian Elischer 
372878ed226SJulian Elischer 	return (OK);
3731a63eb31SJulian Elischer } /* hci_write_node_link_policy_settings_mask */
374878ed226SJulian Elischer 
3751a63eb31SJulian Elischer /* Send Read_Node_Packet_Mask command to the node */
376878ed226SJulian Elischer int
hci_read_node_packet_mask(int s,int argc,char ** argv)3771a63eb31SJulian Elischer hci_read_node_packet_mask(int s, int argc, char **argv)
378878ed226SJulian Elischer {
379878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_packet_mask	r;
380878ed226SJulian Elischer 
381878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
382878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_PACKET_MASK, &r, sizeof(r)) < 0)
383878ed226SJulian Elischer 		return (ERROR);
384878ed226SJulian Elischer 
3851a63eb31SJulian Elischer 	fprintf(stdout, "Packet mask: %#04x\n", r.packet_mask);
386878ed226SJulian Elischer 
387878ed226SJulian Elischer 	return (OK);
3881a63eb31SJulian Elischer } /* hci_read_node_packet_mask */
389878ed226SJulian Elischer 
3901a63eb31SJulian Elischer /* Send Write_Node_Packet_Mask command to the node */
391878ed226SJulian Elischer int
hci_write_node_packet_mask(int s,int argc,char ** argv)3921a63eb31SJulian Elischer hci_write_node_packet_mask(int s, int argc, char **argv)
393878ed226SJulian Elischer {
394878ed226SJulian Elischer 	struct ng_btsocket_hci_raw_node_packet_mask	r;
395878ed226SJulian Elischer 	int						m;
396878ed226SJulian Elischer 
397878ed226SJulian Elischer 	memset(&r, 0, sizeof(r));
398878ed226SJulian Elischer 
399878ed226SJulian Elischer 	switch (argc) {
400878ed226SJulian Elischer 	case 1:
401878ed226SJulian Elischer 		if (sscanf(argv[0], "%x", &m) != 1)
402878ed226SJulian Elischer 			return (USAGE);
403878ed226SJulian Elischer 
404878ed226SJulian Elischer 		r.packet_mask = (m & 0xffff);
405878ed226SJulian Elischer 		break;
406878ed226SJulian Elischer 
407878ed226SJulian Elischer 	default:
408878ed226SJulian Elischer 		return (USAGE);
409878ed226SJulian Elischer 	}
410878ed226SJulian Elischer 
411878ed226SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_SET_PACKET_MASK, &r, sizeof(r)) < 0)
412878ed226SJulian Elischer 		return (ERROR);
413878ed226SJulian Elischer 
414878ed226SJulian Elischer 	return (OK);
4151a63eb31SJulian Elischer } /* hci_write_node_packet_mask */
4161a63eb31SJulian Elischer 
4171a63eb31SJulian Elischer /* Send Read_Node_Role_Switch command to the node */
4181a63eb31SJulian Elischer int
hci_read_node_role_switch(int s,int argc,char ** argv)4191a63eb31SJulian Elischer hci_read_node_role_switch(int s, int argc, char **argv)
4201a63eb31SJulian Elischer {
4211a63eb31SJulian Elischer 	struct ng_btsocket_hci_raw_node_role_switch	r;
4221a63eb31SJulian Elischer 
4231a63eb31SJulian Elischer 	memset(&r, 0, sizeof(r));
4241a63eb31SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH, &r, sizeof(r)) < 0)
4251a63eb31SJulian Elischer 		return (ERROR);
4261a63eb31SJulian Elischer 
4271a63eb31SJulian Elischer 	fprintf(stdout, "Role switch: %d\n", r.role_switch);
4281a63eb31SJulian Elischer 
4291a63eb31SJulian Elischer 	return (OK);
4301a63eb31SJulian Elischer } /* hci_read_node_role_switch */
4311a63eb31SJulian Elischer 
4321a63eb31SJulian Elischer /* Send Write_Node_Role_Switch command to the node */
4331a63eb31SJulian Elischer int
hci_write_node_role_switch(int s,int argc,char ** argv)4341a63eb31SJulian Elischer hci_write_node_role_switch(int s, int argc, char **argv)
4351a63eb31SJulian Elischer {
4361a63eb31SJulian Elischer 	struct ng_btsocket_hci_raw_node_role_switch	r;
4371a63eb31SJulian Elischer 	int						m;
4381a63eb31SJulian Elischer 
4391a63eb31SJulian Elischer 	memset(&r, 0, sizeof(r));
4401a63eb31SJulian Elischer 
4411a63eb31SJulian Elischer 	switch (argc) {
4421a63eb31SJulian Elischer 	case 1:
4431a63eb31SJulian Elischer 		if (sscanf(argv[0], "%d", &m) != 1)
4441a63eb31SJulian Elischer 			return (USAGE);
4451a63eb31SJulian Elischer 
4461a63eb31SJulian Elischer 		r.role_switch = m? 1 : 0;
4471a63eb31SJulian Elischer 		break;
4481a63eb31SJulian Elischer 
4491a63eb31SJulian Elischer 	default:
4501a63eb31SJulian Elischer 		return (USAGE);
4511a63eb31SJulian Elischer 	}
4521a63eb31SJulian Elischer 
4531a63eb31SJulian Elischer 	if (ioctl(s, SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH, &r, sizeof(r)) < 0)
4541a63eb31SJulian Elischer 		return (ERROR);
4551a63eb31SJulian Elischer 
4561a63eb31SJulian Elischer 	return (OK);
4571a63eb31SJulian Elischer } /* hci_write_node_role_switch */
458878ed226SJulian Elischer 
459fc5806edSMarkus Brueffer /* Send Read_Node_List command to the node */
460fc5806edSMarkus Brueffer int
hci_read_node_list(int s,int argc,char ** argv)461fc5806edSMarkus Brueffer hci_read_node_list(int s, int argc, char **argv)
462fc5806edSMarkus Brueffer {
463fc5806edSMarkus Brueffer 	struct ng_btsocket_hci_raw_node_list_names	r;
464fc5806edSMarkus Brueffer 	int						i;
465fc5806edSMarkus Brueffer 
466fc5806edSMarkus Brueffer 	r.num_names = MAX_NODE_NUM;
467fc5806edSMarkus Brueffer 	r.names = (struct nodeinfo*)calloc(MAX_NODE_NUM, sizeof(struct nodeinfo));
468fc5806edSMarkus Brueffer 	if (r.names == NULL)
469fc5806edSMarkus Brueffer 		return (ERROR);
470fc5806edSMarkus Brueffer 
471fc5806edSMarkus Brueffer 	if (ioctl(s, SIOC_HCI_RAW_NODE_LIST_NAMES, &r, sizeof(r)) < 0) {
472fc5806edSMarkus Brueffer 		free(r.names);
473fc5806edSMarkus Brueffer 		return (ERROR);
474fc5806edSMarkus Brueffer 	}
475fc5806edSMarkus Brueffer 
476fc5806edSMarkus Brueffer 	fprintf(stdout, "Name            ID       Num hooks\n");
477fc5806edSMarkus Brueffer 	for (i = 0; i < r.num_names; ++i)
478fc5806edSMarkus Brueffer 		fprintf(stdout, "%-15s %08x %9d\n",
479fc5806edSMarkus Brueffer 		    r.names[i].name, r.names[i].id, r.names[i].hooks);
480fc5806edSMarkus Brueffer 
481fc5806edSMarkus Brueffer 	free(r.names);
482fc5806edSMarkus Brueffer 
483fc5806edSMarkus Brueffer 	return (OK);
484fc5806edSMarkus Brueffer } /* hci_read_node_list */
485fc5806edSMarkus Brueffer 
486878ed226SJulian Elischer struct hci_command	node_commands[] = {
487878ed226SJulian Elischer {
488878ed226SJulian Elischer "read_node_state",
4891a63eb31SJulian Elischer "Get the HCI node state",
490878ed226SJulian Elischer &hci_read_node_state
491878ed226SJulian Elischer },
492878ed226SJulian Elischer {
493878ed226SJulian Elischer "initialize",
4941a63eb31SJulian Elischer "Initialize the HCI node",
495878ed226SJulian Elischer &hci_node_initialize
496878ed226SJulian Elischer },
497878ed226SJulian Elischer {
498878ed226SJulian Elischer "read_debug_level",
4991a63eb31SJulian Elischer "Read the HCI node debug level",
500878ed226SJulian Elischer &hci_read_debug_level
501878ed226SJulian Elischer },
502878ed226SJulian Elischer {
503878ed226SJulian Elischer "write_debug_level <level>",
5041a63eb31SJulian Elischer "Write the HCI node debug level",
505878ed226SJulian Elischer &hci_write_debug_level
506878ed226SJulian Elischer },
507878ed226SJulian Elischer {
508878ed226SJulian Elischer "read_node_buffer_size",
5091a63eb31SJulian Elischer "Read the HCI node buffer information. This will return current state of the\n"\
5101a63eb31SJulian Elischer "HCI buffer for the HCI node",
511878ed226SJulian Elischer &hci_read_node_buffer_size
512878ed226SJulian Elischer },
513878ed226SJulian Elischer {
514878ed226SJulian Elischer "read_node_bd_addr",
5151a63eb31SJulian Elischer "Read the HCI node BD_ADDR. Returns device BD_ADDR as cached by the HCI node",
516878ed226SJulian Elischer &hci_read_node_bd_addr
517878ed226SJulian Elischer },
518878ed226SJulian Elischer {
519878ed226SJulian Elischer "read_node_features",
5201a63eb31SJulian Elischer "Read the HCI node features. This will return list of supported features as\n" \
5211a63eb31SJulian Elischer "cached by the HCI node",
522878ed226SJulian Elischer &hci_read_node_features
523878ed226SJulian Elischer },
524878ed226SJulian Elischer {
525878ed226SJulian Elischer "read_node_stat",
5261a63eb31SJulian Elischer "Read packets and bytes counters for the HCI node",
527878ed226SJulian Elischer &hci_read_node_stat
528878ed226SJulian Elischer },
529878ed226SJulian Elischer {
530878ed226SJulian Elischer "reset_node_stat",
5311a63eb31SJulian Elischer "Reset packets and bytes counters for the HCI node",
532878ed226SJulian Elischer &hci_reset_node_stat
533878ed226SJulian Elischer },
534878ed226SJulian Elischer {
535878ed226SJulian Elischer "flush_neighbor_cache",
5361a63eb31SJulian Elischer "Flush content of the HCI node neighbor cache",
537878ed226SJulian Elischer &hci_flush_neighbor_cache
538878ed226SJulian Elischer },
539878ed226SJulian Elischer {
540878ed226SJulian Elischer "read_neighbor_cache",
5411a63eb31SJulian Elischer "Read content of the HCI node neighbor cache",
542878ed226SJulian Elischer &hci_read_neighbor_cache
543878ed226SJulian Elischer },
544878ed226SJulian Elischer {
545878ed226SJulian Elischer "read_connection_list",
5461a63eb31SJulian Elischer "Read the baseband connection descriptors list for the HCI node",
547878ed226SJulian Elischer &hci_read_connection_list
548878ed226SJulian Elischer },
549878ed226SJulian Elischer {
550878ed226SJulian Elischer "read_node_link_policy_settings_mask",
5511a63eb31SJulian Elischer "Read the value of the Link Policy Settinngs mask for the HCI node",
5521a63eb31SJulian Elischer &hci_read_node_link_policy_settings_mask
553878ed226SJulian Elischer },
554878ed226SJulian Elischer {
555878ed226SJulian Elischer "write_node_link_policy_settings_mask <policy_mask>",
5561a63eb31SJulian Elischer "Write the value of the Link Policy Settings mask for the HCI node. By default\n" \
5571a63eb31SJulian Elischer "all supported Link Policy modes (as reported by the local device features) are\n"\
5581a63eb31SJulian Elischer "enabled. The particular Link Policy mode is enabled if local device supports\n"\
5591a63eb31SJulian Elischer "it and correspinding bit in the mask was set\n\n" \
5601a63eb31SJulian Elischer "\t<policy_mask> - xxxx; Link Policy mask\n" \
5611a63eb31SJulian Elischer "\t\t0x0000 - Disable All LM Modes\n" \
5621a63eb31SJulian Elischer "\t\t0x0001 - Enable Master Slave Switch\n" \
5631a63eb31SJulian Elischer "\t\t0x0002 - Enable Hold Mode\n" \
5641a63eb31SJulian Elischer "\t\t0x0004 - Enable Sniff Mode\n" \
5651a63eb31SJulian Elischer "\t\t0x0008 - Enable Park Mode\n",
5661a63eb31SJulian Elischer &hci_write_node_link_policy_settings_mask
567878ed226SJulian Elischer },
568878ed226SJulian Elischer {
569878ed226SJulian Elischer "read_node_packet_mask",
5701a63eb31SJulian Elischer "Read the value of the Packet mask for the HCI node",
5711a63eb31SJulian Elischer &hci_read_node_packet_mask
572878ed226SJulian Elischer },
573878ed226SJulian Elischer {
574878ed226SJulian Elischer "write_node_packet_mask <packet_mask>",
5751a63eb31SJulian Elischer "Write the value of the Packet mask for the HCI node. By default all supported\n" \
5761a63eb31SJulian Elischer "packet types (as reported by the local device features) are enabled. The\n" \
5771a63eb31SJulian Elischer "particular packet type is enabled if local device supports it and corresponding\n" \
5781a63eb31SJulian Elischer "bit in the mask was set\n\n" \
5791a63eb31SJulian Elischer "\t<packet_mask> - xxxx; packet type mask\n" \
5801a63eb31SJulian Elischer "" \
5811a63eb31SJulian Elischer "\t\tACL packets\n" \
5821a63eb31SJulian Elischer "\t\t-----------\n" \
5831a63eb31SJulian Elischer "\t\t0x0008 DM1\n" \
5841a63eb31SJulian Elischer "\t\t0x0010 DH1\n" \
5851a63eb31SJulian Elischer "\t\t0x0400 DM3\n" \
5861a63eb31SJulian Elischer "\t\t0x0800 DH3\n" \
5871a63eb31SJulian Elischer "\t\t0x4000 DM5\n" \
5881a63eb31SJulian Elischer "\t\t0x8000 DH5\n" \
5891a63eb31SJulian Elischer "\n" \
5901a63eb31SJulian Elischer "\t\tSCO packets\n" \
5911a63eb31SJulian Elischer "\t\t-----------\n" \
5921a63eb31SJulian Elischer "\t\t0x0020 HV1\n" \
5931a63eb31SJulian Elischer "\t\t0x0040 HV2\n" \
5941a63eb31SJulian Elischer "\t\t0x0080 HV3\n",
5951a63eb31SJulian Elischer &hci_write_node_packet_mask
5961a63eb31SJulian Elischer },
5971a63eb31SJulian Elischer {
5981a63eb31SJulian Elischer "read_node_role_switch",
5991a63eb31SJulian Elischer "Read the value of the Role Switch parameter for the HCI node",
6001a63eb31SJulian Elischer &hci_read_node_role_switch
6011a63eb31SJulian Elischer },
6021a63eb31SJulian Elischer {
6031a63eb31SJulian Elischer "write_node_role_switch {0|1}",
6041a63eb31SJulian Elischer "Write the value of the Role Switch parameter for the HCI node. By default,\n" \
6051a63eb31SJulian Elischer "if Role Switch is supported, local device will try to perform Role Switch\n" \
6061a63eb31SJulian Elischer "and become Master on incoming connection. Some devices do not support Role\n" \
607beb45c4fSPedro F. Giffuni "Switch and thus incoming connections from such devices will fail. Setting\n" \
6081a63eb31SJulian Elischer "this parameter to zero will prevent Role Switch and thus accepting device\n" \
6091a63eb31SJulian Elischer "will remain Slave",
6101a63eb31SJulian Elischer &hci_write_node_role_switch
611878ed226SJulian Elischer },
612878ed226SJulian Elischer {
613fc5806edSMarkus Brueffer "read_node_list",
614fc5806edSMarkus Brueffer "Get a list of HCI nodes, their Netgraph IDs and connected hooks.",
615fc5806edSMarkus Brueffer &hci_read_node_list
616fc5806edSMarkus Brueffer },
617fc5806edSMarkus Brueffer {
618878ed226SJulian Elischer NULL,
619878ed226SJulian Elischer }};
620878ed226SJulian Elischer 
621