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