xref: /freebsd/libexec/rc/rc.d/bluetooth (revision f7c32ed617858bcd22f8d1b03199099d50125721)
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# $FreeBSD$
28
29# PROVIDE: bluetooth
30# REQUIRE: DAEMON
31# KEYWORD: nojail nostart
32
33. /etc/rc.subr
34
35name="bluetooth"
36desc="Bluetooth setup script"
37rcvar=
38start_cmd="bluetooth_start"
39stop_cmd="bluetooth_stop"
40required_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket"
41
42##############################################################################
43# Read and parse Bluetooth device configuration file
44##############################################################################
45
46bluetooth_read_conf()
47{
48	local _err _file _line _namespace
49
50	_file=$1
51	_namespace=$2
52	_err=0
53
54	if [ ! -e $_file ]; then
55		return 0
56	fi
57
58	if [ ! -f $_file -o ! -r $_file ]; then
59		err 1 "Bluetooth configuration file $_file is not a file or not readable"
60	fi
61
62	while read _line
63	do
64		case "$_line" in
65		\#*)
66			continue
67			;;
68
69		*)
70			if [ -z "$_line" ]; then
71				continue;
72			fi
73
74
75			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
76				eval "${_namespace}${_line}"
77			else
78				warn "Unable to parse line \"$_line\" in $_file"
79				_err=1
80			fi
81			;;
82		esac
83	done < $_file
84
85	return $_err
86}
87
88##############################################################################
89# Setup Bluetooth stack. Create and connect nodes
90##############################################################################
91
92bluetooth_setup_stack()
93{
94	dev=$1
95	shift
96	hook=$1
97	shift
98
99	# Setup HCI
100	ngctl mkpeer ${dev}: hci ${hook} drv \
101		> /dev/null 2>&1 || return 1
102
103	ngctl name ${dev}:${hook} ${dev}hci \
104		> /dev/null 2>&1 || return 1
105
106	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
107		> /dev/null 2>&1 || return 1
108
109	# Setup L2CAP
110	ngctl mkpeer ${dev}hci: l2cap acl hci \
111		> /dev/null 2>&1 || return 1
112
113	ngctl name ${dev}hci:acl ${dev}l2cap \
114		> /dev/null 2>&1 || return 1
115
116	ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
117		> /dev/null 2>&1 || return 1
118
119	# Connect HCI node to the Bluetooth sockets layer
120	ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
121		> /dev/null 2>&1 || return 1
122
123	# Connect L2CAP node to Bluetooth sockets layer
124	ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
125		> /dev/null 2>&1 || return 1
126
127	ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
128		> /dev/null 2>&1 || return 1
129
130	# Initilalize HCI node
131	${hccontrol} -n ${dev}hci reset \
132		> /dev/null 2>&1 || return 1
133
134	${hccontrol} -n ${dev}hci read_bd_addr \
135		> /dev/null 2>&1 || return 1
136
137	${hccontrol} -n ${dev}hci read_local_supported_features \
138		> /dev/null 2>&1 || return 1
139
140	${hccontrol} -n ${dev}hci read_buffer_size \
141		> /dev/null 2>&1 || return 1
142
143	if checkyesno bluetooth_device_discoverable; then
144		if checkyesno bluetooth_device_connectable; then
145			${hccontrol} -n ${dev}hci write_scan_enable 3 \
146				> /dev/null 2>&1 || return 1
147		else
148			${hccontrol} -n ${dev}hci write_scan_enable 1 \
149				> /dev/null 2>&1 || return 1
150		fi
151	else
152		if checkyesno bluetooth_device_connectable; then
153			${hccontrol} -n ${dev}hci write_scan_enable 2 \
154				> /dev/null 2>&1 || return 1
155		else
156			${hccontrol} -n ${dev}hci write_scan_enable 0 \
157				> /dev/null 2>&1 || return 1
158		fi
159	fi
160
161
162	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
163		> /dev/null 2>&1 || return 1
164
165	if checkyesno bluetooth_device_authentication_enable; then
166		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
167			> /dev/null 2>&1 || return 1
168	else
169		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
170			> /dev/null 2>&1 || return 1
171	fi
172
173	case "${bluetooth_device_encryption_mode}" in
174	[Nn][Oo][Nn][Ee]|0)
175		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
176			> /dev/null 2>&1 || return 1
177		;;
178
179	[Pp][2][Pp]|1)
180		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
181			> /dev/null 2>&1 || return 1
182		;;
183
184	[Al][Ll][Ll]|2)
185		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
186			> /dev/null 2>&1 || return 1
187		;;
188
189	*)
190		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
191		return 1
192		;;
193	esac
194
195	if checkyesno bluetooth_device_role_switch; then
196		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
197			> /dev/null 2>&1 || return 1
198	else
199		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
200			> /dev/null 2>&1 || return 1
201	fi
202
203	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
204		> /dev/null 2>&1 || return 1
205
206	${hccontrol} -n ${dev}hci initialize \
207		> /dev/null 2>&1 || return 1
208
209	return 0
210}
211
212##############################################################################
213# Shutdown Bluetooth stack. Destroy all nodes
214##############################################################################
215
216bluetooth_shutdown_stack()
217{
218	dev=$1
219
220	ngctl shutdown ${dev}hci: > /dev/null 2>&1
221	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
222
223	return 0
224}
225
226##############################################################################
227# bluetooth_start()
228##############################################################################
229
230bluetooth_start()
231{
232	local _file
233
234	dev=$1
235
236	# Try to figure out device type by looking at device name
237	case "${dev}" in
238	# USB Bluetooth adapters
239	ubt*)
240		hook="hook"
241
242		# Obtain unit number from device.
243		unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
244		if [ -z "${unit}" ]; then
245			err 1 "Unable to get ubt unit number: ${dev}"
246		fi
247		;;
248
249	# Unknown
250	*)
251		err 1 "Unsupported device: ${dev}"
252		;;
253	esac
254
255	# Be backward compatible and setup reasonable defaults
256	bluetooth_device_authentication_enable="0"
257	bluetooth_device_class="ff:01:0c"
258	bluetooth_device_connectable="1"
259	bluetooth_device_discoverable="0"
260	bluetooth_device_encryption_mode="0"
261	bluetooth_device_hci_debug_level="3"
262	bluetooth_device_l2cap_debug_level="3"
263	bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
264	bluetooth_device_role_switch="1"
265
266	# Load default device configuration parameters
267	_file="/etc/defaults/bluetooth.device.conf"
268
269	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
270		err 1 "Unable to read default Bluetooth configuration from $_file"
271	fi
272
273	# Load device specific overrides
274	_file="/etc/bluetooth/$dev.conf"
275
276	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
277		err 1 "Unable to read Bluetooth device configuration from $_file"
278	fi
279
280	# Setup stack
281	if ! bluetooth_setup_stack ${dev} ${hook} ; then
282		bluetooth_shutdown_stack $dev
283		err 1 "Unable to setup Bluetooth stack for device ${dev}"
284	fi
285
286	return 0
287}
288
289##############################################################################
290# bluetooth_stop()
291##############################################################################
292
293bluetooth_stop()
294{
295	dev=$1
296
297	# Try to figure out device type by looking at device name
298	case "${dev}" in
299	# USB Bluetooth adapters
300	ubt*)
301		;;
302
303	# Unknown
304	*)
305		err 1 "Unsupported device: ${dev}"
306		;;
307	esac
308
309	bluetooth_shutdown_stack ${dev}
310
311	return 0
312}
313
314##############################################################################
315# Start here
316##############################################################################
317
318load_rc_config $name
319hccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
320
321run_rc_command $*
322
323