1 /*
2  * bluetooth.c
3  */
4 
5 /*-
6  * SPDX-License-Identifier: BSD-2-Clause
7  *
8  * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: ng_bluetooth.c,v 1.3 2003/04/26 22:37:31 max Exp $
33  * $FreeBSD$
34  */
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/sysctl.h>
42 
43 #include <netgraph/bluetooth/include/ng_bluetooth.h>
44 
45 /*
46  * Bluetooth stack sysctl globals
47  */
48 
49 static u_int32_t	bluetooth_hci_command_timeout_value  = 5;   /* sec */
50 static u_int32_t	bluetooth_hci_connect_timeout_value  = 60;  /* sec */
51 static u_int32_t	bluetooth_hci_max_neighbor_age_value = 600; /* sec */
52 static u_int32_t	bluetooth_l2cap_rtx_timeout_value    = 60;  /* sec */
53 static u_int32_t	bluetooth_l2cap_ertx_timeout_value   = 300; /* sec */
54 static u_int32_t	bluetooth_sco_rtx_timeout_value      = 60;  /* sec */
55 
56 /*
57  * Define sysctl tree that shared by other parts of Bluetooth stack
58  */
59 
60 SYSCTL_NODE(_net, OID_AUTO, bluetooth, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
61     "Bluetooth family");
62 SYSCTL_INT(_net_bluetooth, OID_AUTO, version,
63 	CTLFLAG_RD, SYSCTL_NULL_INT_PTR, NG_BLUETOOTH_VERSION, "Version of the stack");
64 
65 /*
66  * HCI
67  */
68 
69 SYSCTL_NODE(_net_bluetooth, OID_AUTO, hci, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
70     "Bluetooth HCI family");
71 
72 static int
73 bluetooth_set_hci_command_timeout_value(SYSCTL_HANDLER_ARGS)
74 {
75 	u_int32_t	value;
76 	int		error;
77 
78 	value = bluetooth_hci_command_timeout_value;
79 	error = sysctl_handle_int(oidp, &value, 0, req);
80 	if (error == 0 && req->newptr != NULL) {
81 		if (value > 0)
82 			bluetooth_hci_command_timeout_value = value;
83 		else
84 			error = EINVAL;
85 	}
86 
87 	return (error);
88 } /* bluetooth_set_hci_command_timeout_value */
89 
90 SYSCTL_PROC(_net_bluetooth_hci, OID_AUTO, command_timeout,
91 	CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
92 	&bluetooth_hci_command_timeout_value, 5,
93 	bluetooth_set_hci_command_timeout_value,
94 	"I", "HCI command timeout (sec)");
95 
96 static int
97 bluetooth_set_hci_connect_timeout_value(SYSCTL_HANDLER_ARGS)
98 {
99 	u_int32_t	value;
100 	int		error;
101 
102 	value = bluetooth_hci_connect_timeout_value;
103 	error = sysctl_handle_int(oidp, &value, 0, req);
104 	if (error == 0 && req->newptr != NULL) {
105 		if (0 < value && value <= bluetooth_l2cap_rtx_timeout_value)
106 			bluetooth_hci_connect_timeout_value = value;
107 		else
108 			error = EINVAL;
109 	}
110 
111 	return (error);
112 } /* bluetooth_set_hci_connect_timeout_value */
113 
114 SYSCTL_PROC(_net_bluetooth_hci, OID_AUTO, connection_timeout,
115 	CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
116 	&bluetooth_hci_connect_timeout_value, 60,
117 	bluetooth_set_hci_connect_timeout_value,
118 	"I", "HCI connect timeout (sec)");
119 
120 SYSCTL_UINT(_net_bluetooth_hci, OID_AUTO, max_neighbor_age, CTLFLAG_RW,
121 	&bluetooth_hci_max_neighbor_age_value, 600,
122 	"Maximal HCI neighbor cache entry age (sec)");
123 
124 /*
125  * L2CAP
126  */
127 
128 SYSCTL_NODE(_net_bluetooth, OID_AUTO, l2cap, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
129     "Bluetooth L2CAP family");
130 
131 static int
132 bluetooth_set_l2cap_rtx_timeout_value(SYSCTL_HANDLER_ARGS)
133 {
134 	u_int32_t	value;
135 	int		error;
136 
137 	value = bluetooth_l2cap_rtx_timeout_value;
138 	error = sysctl_handle_int(oidp, &value, 0, req);
139 	if (error == 0 && req->newptr != NULL) {
140 		if (bluetooth_hci_connect_timeout_value <= value &&
141 		    value <= bluetooth_l2cap_ertx_timeout_value)
142 			bluetooth_l2cap_rtx_timeout_value = value;
143 		else
144 			error = EINVAL;
145 	}
146 
147 	return (error);
148 } /* bluetooth_set_l2cap_rtx_timeout_value */
149 
150 SYSCTL_PROC(_net_bluetooth_l2cap, OID_AUTO, rtx_timeout,
151 	CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
152 	&bluetooth_l2cap_rtx_timeout_value, 60,
153 	bluetooth_set_l2cap_rtx_timeout_value,
154 	"I", "L2CAP RTX timeout (sec)");
155 
156 static int
157 bluetooth_set_l2cap_ertx_timeout_value(SYSCTL_HANDLER_ARGS)
158 {
159 	u_int32_t	value;
160 	int		error;
161 
162 	value = bluetooth_l2cap_ertx_timeout_value;
163 	error = sysctl_handle_int(oidp, &value, 0, req);
164 	if (error == 0 && req->newptr != NULL) {
165 		if (value >= bluetooth_l2cap_rtx_timeout_value)
166 			bluetooth_l2cap_ertx_timeout_value = value;
167 		else
168 			error = EINVAL;
169 	}
170 
171 	return (error);
172 } /* bluetooth_set_l2cap_ertx_timeout_value */
173 
174 SYSCTL_PROC(_net_bluetooth_l2cap, OID_AUTO, ertx_timeout,
175 	CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
176 	&bluetooth_l2cap_ertx_timeout_value, 300,
177 	bluetooth_set_l2cap_ertx_timeout_value,
178 	"I", "L2CAP ERTX timeout (sec)");
179 
180 /*
181  * Return various sysctl values
182  */
183 
184 u_int32_t
185 bluetooth_hci_command_timeout(void)
186 {
187 	return (bluetooth_hci_command_timeout_value * hz);
188 } /* bluetooth_hci_command_timeout */
189 
190 u_int32_t
191 bluetooth_hci_connect_timeout(void)
192 {
193 	return (bluetooth_hci_connect_timeout_value * hz);
194 } /* bluetooth_hci_connect_timeout */
195 
196 u_int32_t
197 bluetooth_hci_max_neighbor_age(void)
198 {
199 	return (bluetooth_hci_max_neighbor_age_value);
200 } /* bluetooth_hci_max_neighbor_age */
201 
202 u_int32_t
203 bluetooth_l2cap_rtx_timeout(void)
204 {
205 	return (bluetooth_l2cap_rtx_timeout_value * hz);
206 } /* bluetooth_l2cap_rtx_timeout */
207 
208 u_int32_t
209 bluetooth_l2cap_ertx_timeout(void)
210 {
211 	return (bluetooth_l2cap_ertx_timeout_value * hz);
212 } /* bluetooth_l2cap_ertx_timeout */
213 
214 u_int32_t
215 bluetooth_sco_rtx_timeout(void)
216 {
217 	return (bluetooth_sco_rtx_timeout_value * hz);
218 } /* bluetooth_sco_rtx_timeout */
219 
220 /*
221  * RFCOMM
222  */
223 
224 SYSCTL_NODE(_net_bluetooth, OID_AUTO, rfcomm, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
225     "Bluetooth RFCOMM family");
226 
227 /*
228  * SCO
229  */
230 
231 SYSCTL_NODE(_net_bluetooth, OID_AUTO, sco, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
232     "Bluetooth SCO family");
233 
234 static int
235 bluetooth_set_sco_rtx_timeout_value(SYSCTL_HANDLER_ARGS)
236 {
237 	u_int32_t	value;
238 	int		error;
239 
240 	value = bluetooth_sco_rtx_timeout_value;
241 	error = sysctl_handle_int(oidp, &value, 0, req);
242 	if (error == 0 && req->newptr != NULL) {
243 		if (bluetooth_hci_connect_timeout_value <= value)
244 			bluetooth_sco_rtx_timeout_value = value;
245 		else
246 			error = EINVAL;
247 	}
248 
249 	return (error);
250 } /* bluetooth_set_sco_rtx_timeout_value */
251 
252 SYSCTL_PROC(_net_bluetooth_sco, OID_AUTO, rtx_timeout,
253 	CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
254 	&bluetooth_sco_rtx_timeout_value, 60,
255 	bluetooth_set_sco_rtx_timeout_value,
256 	"I", "SCO RTX timeout (sec)");
257 
258 /*
259  * Handle loading and unloading for this code.
260  */
261 
262 static int
263 bluetooth_modevent(module_t mod, int event, void *data)
264 {
265 	int	error = 0;
266 
267 	switch (event) {
268 	case MOD_LOAD:
269 		break;
270 
271 	case MOD_UNLOAD:
272 		break;
273 
274 	default:
275 		error = EOPNOTSUPP;
276 		break;
277 	}
278 
279 	return (error);
280 } /* bluetooth_modevent */
281 
282 /*
283  * Module
284  */
285 
286 static moduledata_t	bluetooth_mod = {
287 	"ng_bluetooth",
288 	bluetooth_modevent,
289 	NULL
290 };
291 
292 DECLARE_MODULE(ng_bluetooth, bluetooth_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
293 MODULE_VERSION(ng_bluetooth, NG_BLUETOOTH_VERSION);
294