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