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