xref: /freebsd-14.2/libexec/rc/rc.d/bluetooth (revision d0b2dbfa)
1*0696600cSBjoern A. Zeeb#!/bin/sh
2*0696600cSBjoern A. Zeeb#
3*0696600cSBjoern A. Zeeb# Copyright (c) 2005 Maksim Yevmenkin <[email protected]>
4*0696600cSBjoern A. Zeeb# All rights reserved.
5*0696600cSBjoern A. Zeeb#
6*0696600cSBjoern A. Zeeb# Redistribution and use in source and binary forms, with or without
7*0696600cSBjoern A. Zeeb# modification, are permitted provided that the following conditions
8*0696600cSBjoern A. Zeeb# are met:
9*0696600cSBjoern A. Zeeb# 1. Redistributions of source code must retain the above copyright
10*0696600cSBjoern A. Zeeb#    notice, this list of conditions and the following disclaimer.
11*0696600cSBjoern A. Zeeb# 2. Redistributions in binary form must reproduce the above copyright
12*0696600cSBjoern A. Zeeb#    notice, this list of conditions and the following disclaimer in the
13*0696600cSBjoern A. Zeeb#    documentation and/or other materials provided with the distribution.
14*0696600cSBjoern A. Zeeb#
15*0696600cSBjoern A. Zeeb# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*0696600cSBjoern A. Zeeb# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*0696600cSBjoern A. Zeeb# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*0696600cSBjoern A. Zeeb# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*0696600cSBjoern A. Zeeb# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*0696600cSBjoern A. Zeeb# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*0696600cSBjoern A. Zeeb# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*0696600cSBjoern A. Zeeb# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*0696600cSBjoern A. Zeeb# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*0696600cSBjoern A. Zeeb# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*0696600cSBjoern A. Zeeb# SUCH DAMAGE.
26*0696600cSBjoern A. Zeeb#
27*0696600cSBjoern A. Zeeb
28*0696600cSBjoern A. Zeeb# PROVIDE: bluetooth
29*0696600cSBjoern A. Zeeb# REQUIRE: DAEMON
30*0696600cSBjoern A. Zeeb# KEYWORD: nojail nostart
31*0696600cSBjoern A. Zeeb
32*0696600cSBjoern A. Zeeb. /etc/rc.subr
33*0696600cSBjoern A. Zeeb
34*0696600cSBjoern A. Zeebname="bluetooth"
35*0696600cSBjoern A. Zeebdesc="Bluetooth setup script"
36*0696600cSBjoern A. Zeebrcvar=
37*0696600cSBjoern A. Zeebstart_cmd="bluetooth_start"
38*0696600cSBjoern A. Zeebstop_cmd="bluetooth_stop"
39*0696600cSBjoern A. Zeebrequired_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket"
40*0696600cSBjoern A. Zeeb
41*0696600cSBjoern A. Zeeb##############################################################################
42*0696600cSBjoern A. Zeeb# Read and parse Bluetooth device configuration file
43*0696600cSBjoern A. Zeeb##############################################################################
44*0696600cSBjoern A. Zeeb
45*0696600cSBjoern A. Zeebbluetooth_read_conf()
46*0696600cSBjoern A. Zeeb{
47*0696600cSBjoern A. Zeeb	local _err _file _line _namespace
48*0696600cSBjoern A. Zeeb
49*0696600cSBjoern A. Zeeb	_file=$1
50*0696600cSBjoern A. Zeeb	_namespace=$2
51*0696600cSBjoern A. Zeeb	_err=0
52*0696600cSBjoern A. Zeeb
53*0696600cSBjoern A. Zeeb	if [ ! -e $_file ]; then
54*0696600cSBjoern A. Zeeb		return 0
55*0696600cSBjoern A. Zeeb	fi
56*0696600cSBjoern A. Zeeb
57*0696600cSBjoern A. Zeeb	if [ ! -f $_file -o ! -r $_file ]; then
58*0696600cSBjoern A. Zeeb		err 1 "Bluetooth configuration file $_file is not a file or not readable"
59*0696600cSBjoern A. Zeeb	fi
60*0696600cSBjoern A. Zeeb
61*0696600cSBjoern A. Zeeb	while read _line
62*0696600cSBjoern A. Zeeb	do
63*0696600cSBjoern A. Zeeb		case "$_line" in
64*0696600cSBjoern A. Zeeb		\#*)
65*0696600cSBjoern A. Zeeb			continue
66*0696600cSBjoern A. Zeeb			;;
67*0696600cSBjoern A. Zeeb
68*0696600cSBjoern A. Zeeb		*)
69*0696600cSBjoern A. Zeeb			if [ -z "$_line" ]; then
70*0696600cSBjoern A. Zeeb				continue;
71*0696600cSBjoern A. Zeeb			fi
72*0696600cSBjoern A. Zeeb
73*0696600cSBjoern A. Zeeb
74*0696600cSBjoern A. Zeeb			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
75*0696600cSBjoern A. Zeeb				eval "${_namespace}${_line}"
76*0696600cSBjoern A. Zeeb			else
77*0696600cSBjoern A. Zeeb				warn "Unable to parse line \"$_line\" in $_file"
78*0696600cSBjoern A. Zeeb				_err=1
79*0696600cSBjoern A. Zeeb			fi
80*0696600cSBjoern A. Zeeb			;;
81*0696600cSBjoern A. Zeeb		esac
82*0696600cSBjoern A. Zeeb	done < $_file
83*0696600cSBjoern A. Zeeb
84*0696600cSBjoern A. Zeeb	return $_err
85*0696600cSBjoern A. Zeeb}
86*0696600cSBjoern A. Zeeb
87*0696600cSBjoern A. Zeeb##############################################################################
88*0696600cSBjoern A. Zeeb# Setup Bluetooth stack. Create and connect nodes
89*0696600cSBjoern A. Zeeb##############################################################################
90*0696600cSBjoern A. Zeeb
91*0696600cSBjoern A. Zeebbluetooth_setup_stack()
92*0696600cSBjoern A. Zeeb{
93*0696600cSBjoern A. Zeeb	dev=$1
94*0696600cSBjoern A. Zeeb	shift
95*0696600cSBjoern A. Zeeb	hook=$1
96*0696600cSBjoern A. Zeeb	shift
97*0696600cSBjoern A. Zeeb
98*0696600cSBjoern A. Zeeb	# Setup HCI
99*0696600cSBjoern A. Zeeb	ngctl mkpeer ${dev}: hci ${hook} drv \
100*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
101*0696600cSBjoern A. Zeeb
102*0696600cSBjoern A. Zeeb	ngctl name ${dev}:${hook} ${dev}hci \
103*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
104*0696600cSBjoern A. Zeeb
105*0696600cSBjoern A. Zeeb	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
106*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
107*0696600cSBjoern A. Zeeb
108*0696600cSBjoern A. Zeeb	# Setup L2CAP
109*0696600cSBjoern A. Zeeb	ngctl mkpeer ${dev}hci: l2cap acl hci \
110*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
111*0696600cSBjoern A. Zeeb
112*0696600cSBjoern A. Zeeb	ngctl name ${dev}hci:acl ${dev}l2cap \
113*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
114*0696600cSBjoern A. Zeeb
115*0696600cSBjoern A. Zeeb	ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
116*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
117*0696600cSBjoern A. Zeeb
118*0696600cSBjoern A. Zeeb	# Connect HCI node to the Bluetooth sockets layer
119*0696600cSBjoern A. Zeeb	ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
120*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
121*0696600cSBjoern A. Zeeb
122*0696600cSBjoern A. Zeeb	# Connect L2CAP node to Bluetooth sockets layer
123*0696600cSBjoern A. Zeeb	ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
124*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
125*0696600cSBjoern A. Zeeb
126*0696600cSBjoern A. Zeeb	ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
127*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
128*0696600cSBjoern A. Zeeb
129*0696600cSBjoern A. Zeeb	# Initilalize HCI node
130*0696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci reset \
131*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
132*0696600cSBjoern A. Zeeb
133*0696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_bd_addr \
134*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
135*0696600cSBjoern A. Zeeb
136*0696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_local_supported_features \
137*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
138*0696600cSBjoern A. Zeeb
139*0696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_buffer_size \
140*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
141*0696600cSBjoern A. Zeeb
142*0696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_discoverable; then
143*0696600cSBjoern A. Zeeb		if checkyesno bluetooth_device_connectable; then
144*0696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 3 \
145*0696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
146*0696600cSBjoern A. Zeeb		else
147*0696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 1 \
148*0696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
149*0696600cSBjoern A. Zeeb		fi
150*0696600cSBjoern A. Zeeb	else
151*0696600cSBjoern A. Zeeb		if checkyesno bluetooth_device_connectable; then
152*0696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 2 \
153*0696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
154*0696600cSBjoern A. Zeeb		else
155*0696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 0 \
156*0696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
157*0696600cSBjoern A. Zeeb		fi
158*0696600cSBjoern A. Zeeb	fi
159*0696600cSBjoern A. Zeeb
160*0696600cSBjoern A. Zeeb
161*0696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
162*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
163*0696600cSBjoern A. Zeeb
164*0696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_authentication_enable; then
165*0696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
166*0696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
167*0696600cSBjoern A. Zeeb	else
168*0696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
169*0696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
170*0696600cSBjoern A. Zeeb	fi
171*0696600cSBjoern A. Zeeb
172*0696600cSBjoern A. Zeeb	case "${bluetooth_device_encryption_mode}" in
173*0696600cSBjoern A. Zeeb	[Nn][Oo][Nn][Ee]|0)
174*0696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
175*0696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
176*0696600cSBjoern A. Zeeb		;;
177*0696600cSBjoern A. Zeeb
178*0696600cSBjoern A. Zeeb	[Pp][2][Pp]|1)
179*0696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
180*0696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
181*0696600cSBjoern A. Zeeb		;;
182*0696600cSBjoern A. Zeeb
183*0696600cSBjoern A. Zeeb	[Al][Ll][Ll]|2)
184*0696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
185*0696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
186*0696600cSBjoern A. Zeeb		;;
187*0696600cSBjoern A. Zeeb
188*0696600cSBjoern A. Zeeb	*)
189*0696600cSBjoern A. Zeeb		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
190*0696600cSBjoern A. Zeeb		return 1
191*0696600cSBjoern A. Zeeb		;;
192*0696600cSBjoern A. Zeeb	esac
193*0696600cSBjoern A. Zeeb
194*0696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_role_switch; then
195*0696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
196*0696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
197*0696600cSBjoern A. Zeeb	else
198*0696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
199*0696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
200*0696600cSBjoern A. Zeeb	fi
201*0696600cSBjoern A. Zeeb
202*0696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
203*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
204*0696600cSBjoern A. Zeeb
205*0696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci initialize \
206*0696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
207*0696600cSBjoern A. Zeeb
208*0696600cSBjoern A. Zeeb	return 0
209*0696600cSBjoern A. Zeeb}
210*0696600cSBjoern A. Zeeb
211*0696600cSBjoern A. Zeeb##############################################################################
212*0696600cSBjoern A. Zeeb# Shutdown Bluetooth stack. Destroy all nodes
213*0696600cSBjoern A. Zeeb##############################################################################
214*0696600cSBjoern A. Zeeb
215*0696600cSBjoern A. Zeebbluetooth_shutdown_stack()
216*0696600cSBjoern A. Zeeb{
217*0696600cSBjoern A. Zeeb	dev=$1
218*0696600cSBjoern A. Zeeb
219*0696600cSBjoern A. Zeeb	ngctl shutdown ${dev}hci: > /dev/null 2>&1
220*0696600cSBjoern A. Zeeb	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
221*0696600cSBjoern A. Zeeb
222*0696600cSBjoern A. Zeeb	return 0
223*0696600cSBjoern A. Zeeb}
224*0696600cSBjoern A. Zeeb
225*0696600cSBjoern A. Zeeb##############################################################################
226*0696600cSBjoern A. Zeeb# bluetooth_start()
227*0696600cSBjoern A. Zeeb##############################################################################
228*0696600cSBjoern A. Zeeb
229*0696600cSBjoern A. Zeebbluetooth_start()
230*0696600cSBjoern A. Zeeb{
231*0696600cSBjoern A. Zeeb	local _file
232*0696600cSBjoern A. Zeeb
233*0696600cSBjoern A. Zeeb	dev=$1
234*0696600cSBjoern A. Zeeb
235*0696600cSBjoern A. Zeeb	# Try to figure out device type by looking at device name
236*0696600cSBjoern A. Zeeb	case "${dev}" in
237*0696600cSBjoern A. Zeeb	# USB Bluetooth adapters
238*0696600cSBjoern A. Zeeb	ubt*)
239*0696600cSBjoern A. Zeeb		hook="hook"
240*0696600cSBjoern A. Zeeb
241*0696600cSBjoern A. Zeeb		# Obtain unit number from device.
242*0696600cSBjoern A. Zeeb		unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
243*0696600cSBjoern A. Zeeb		if [ -z "${unit}" ]; then
244*0696600cSBjoern A. Zeeb			err 1 "Unable to get ubt unit number: ${dev}"
245*0696600cSBjoern A. Zeeb		fi
246*0696600cSBjoern A. Zeeb		;;
247*0696600cSBjoern A. Zeeb
248*0696600cSBjoern A. Zeeb	# Unknown
249*0696600cSBjoern A. Zeeb	*)
250*0696600cSBjoern A. Zeeb		err 1 "Unsupported device: ${dev}"
251*0696600cSBjoern A. Zeeb		;;
252*0696600cSBjoern A. Zeeb	esac
253*0696600cSBjoern A. Zeeb
254*0696600cSBjoern A. Zeeb	# Be backward compatible and setup reasonable defaults
255*0696600cSBjoern A. Zeeb	bluetooth_device_authentication_enable="0"
256*0696600cSBjoern A. Zeeb	bluetooth_device_class="ff:01:0c"
257*0696600cSBjoern A. Zeeb	bluetooth_device_connectable="1"
258*0696600cSBjoern A. Zeeb	bluetooth_device_discoverable="0"
259*0696600cSBjoern A. Zeeb	bluetooth_device_encryption_mode="0"
260*0696600cSBjoern A. Zeeb	bluetooth_device_hci_debug_level="3"
261*0696600cSBjoern A. Zeeb	bluetooth_device_l2cap_debug_level="3"
262*0696600cSBjoern A. Zeeb	bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
263*0696600cSBjoern A. Zeeb	bluetooth_device_role_switch="1"
264*0696600cSBjoern A. Zeeb
265*0696600cSBjoern A. Zeeb	# Load default device configuration parameters
266*0696600cSBjoern A. Zeeb	_file="/etc/defaults/bluetooth.device.conf"
267*0696600cSBjoern A. Zeeb
268*0696600cSBjoern A. Zeeb	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
269*0696600cSBjoern A. Zeeb		err 1 "Unable to read default Bluetooth configuration from $_file"
270*0696600cSBjoern A. Zeeb	fi
271*0696600cSBjoern A. Zeeb
272*0696600cSBjoern A. Zeeb	# Load device specific overrides
273*0696600cSBjoern A. Zeeb	_file="/etc/bluetooth/$dev.conf"
274*0696600cSBjoern A. Zeeb
275*0696600cSBjoern A. Zeeb	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
276*0696600cSBjoern A. Zeeb		err 1 "Unable to read Bluetooth device configuration from $_file"
277*0696600cSBjoern A. Zeeb	fi
278*0696600cSBjoern A. Zeeb
279*0696600cSBjoern A. Zeeb	# Setup stack
280*0696600cSBjoern A. Zeeb	if ! bluetooth_setup_stack ${dev} ${hook} ; then
281*0696600cSBjoern A. Zeeb		bluetooth_shutdown_stack $dev
282*0696600cSBjoern A. Zeeb		err 1 "Unable to setup Bluetooth stack for device ${dev}"
283*0696600cSBjoern A. Zeeb	fi
284*0696600cSBjoern A. Zeeb
285*0696600cSBjoern A. Zeeb	return 0
286*0696600cSBjoern A. Zeeb}
287*0696600cSBjoern A. Zeeb
288*0696600cSBjoern A. Zeeb##############################################################################
289*0696600cSBjoern A. Zeeb# bluetooth_stop()
290*0696600cSBjoern A. Zeeb##############################################################################
291*0696600cSBjoern A. Zeeb
292*0696600cSBjoern A. Zeebbluetooth_stop()
293*0696600cSBjoern A. Zeeb{
294*0696600cSBjoern A. Zeeb	dev=$1
295*0696600cSBjoern A. Zeeb
296*0696600cSBjoern A. Zeeb	# Try to figure out device type by looking at device name
297*0696600cSBjoern A. Zeeb	case "${dev}" in
298*0696600cSBjoern A. Zeeb	# USB Bluetooth adapters
299*0696600cSBjoern A. Zeeb	ubt*)
300*0696600cSBjoern A. Zeeb		;;
301*0696600cSBjoern A. Zeeb
302*0696600cSBjoern A. Zeeb	# Unknown
303*0696600cSBjoern A. Zeeb	*)
304*0696600cSBjoern A. Zeeb		err 1 "Unsupported device: ${dev}"
305*0696600cSBjoern A. Zeeb		;;
306*0696600cSBjoern A. Zeeb	esac
307*0696600cSBjoern A. Zeeb
308*0696600cSBjoern A. Zeeb	bluetooth_shutdown_stack ${dev}
309*0696600cSBjoern A. Zeeb
310*0696600cSBjoern A. Zeeb	return 0
311*0696600cSBjoern A. Zeeb}
312*0696600cSBjoern A. Zeeb
313*0696600cSBjoern A. Zeeb##############################################################################
314*0696600cSBjoern A. Zeeb# Start here
315*0696600cSBjoern A. Zeeb##############################################################################
316*0696600cSBjoern A. Zeeb
317*0696600cSBjoern A. Zeebload_rc_config $name
318*0696600cSBjoern A. Zeebhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
319*0696600cSBjoern A. Zeeb
320*0696600cSBjoern A. Zeebrun_rc_command $*
321*0696600cSBjoern A. Zeeb
322