bluetooth revision 165664
1132524Ssilby#!/bin/sh
2132524Ssilby#
3132524Ssilby# Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
4132524Ssilby# All rights reserved.
5132524Ssilby#
6132524Ssilby# Redistribution and use in source and binary forms, with or without
7132524Ssilby# modification, are permitted provided that the following conditions
8132524Ssilby# are met:
9132524Ssilby# 1. Redistributions of source code must retain the above copyright
10132524Ssilby#    notice, this list of conditions and the following disclaimer.
11132524Ssilby# 2. Redistributions in binary form must reproduce the above copyright
12132524Ssilby#    notice, this list of conditions and the following disclaimer in the
13132524Ssilby#    documentation and/or other materials provided with the distribution.
14132524Ssilby#
15132524Ssilby# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16132524Ssilby# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17132524Ssilby# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18132524Ssilby# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19132524Ssilby# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20132524Ssilby# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21132524Ssilby# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22132524Ssilby# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23132524Ssilby# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24132524Ssilby# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25132524Ssilby# SUCH DAMAGE.
26132524Ssilby#
27132524Ssilby# $FreeBSD: head/etc/rc.d/bluetooth 165664 2006-12-30 22:53:20Z yar $
28132524Ssilby
29132524Ssilby# PROVIDE: bluetooth
30132524Ssilby# REQUIRE: DAEMON
31132524Ssilby# KEYWORD: nojail nostart
32132524Ssilby
33132524Ssilby. /etc/rc.subr
34132524Ssilby
35132524Ssilbyname="bluetooth"
36132524Ssilbyrcvar=
37132524Ssilbystart_cmd="bluetooth_start"
38132524Ssilbystop_cmd="bluetooth_stop"
39132524Ssilby
40132524Ssilby##############################################################################
41132524Ssilby# Read and parse Bluetooth device configuration file
42132524Ssilby##############################################################################
43132524Ssilby
44132524Ssilbybluetooth_read_conf()
45132524Ssilby{
46132524Ssilby	local _err _file _line _namespace
47228274Seadler
48132524Ssilby	_file=$1
49132524Ssilby	_namespace=$2
50132524Ssilby	_err=0
51132524Ssilby
52132524Ssilby	if [ ! -e $_file ]; then
53132524Ssilby		return 0
54132524Ssilby	fi
55132524Ssilby
56228274Seadler	if [ ! -f $_file -o ! -r $_file ]; then
57132524Ssilby		err 1 "Bluetooth configuration file $_file is not a file or not readable"
58132524Ssilby	fi
59132524Ssilby
60132524Ssilby	while read _line
61132524Ssilby	do
62132524Ssilby		case "$_line" in
63132524Ssilby		\#*)
64132524Ssilby			continue
65132524Ssilby			;;
66132524Ssilby
67132524Ssilby		*)
68132524Ssilby			if [ -z "$_line" ]; then
69132524Ssilby				continue;
70132524Ssilby			fi
71132524Ssilby
72132524Ssilby
73132524Ssilby			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
74132524Ssilby				eval "${_namespace}${_line}"
75132524Ssilby			else
76132524Ssilby				warn "Unable to parse line \"$_line\" in $_file"
77132524Ssilby				_err=1
78132524Ssilby			fi
79132524Ssilby			;;
80132524Ssilby		esac
81132524Ssilby	done < $_file
82132524Ssilby
83132524Ssilby	return $_err
84132524Ssilby}
85132524Ssilby
86132524Ssilby##############################################################################
87132524Ssilby# Setup Bluetooth stack. Create and connect nodes
88132524Ssilby##############################################################################
89132524Ssilby
90132524Ssilbybluetooth_setup_stack()
91132524Ssilby{
92132524Ssilby	dev=$1
93132524Ssilby	shift
94132524Ssilby	hook=$1
95132524Ssilby	shift
96132524Ssilby
97132524Ssilby	# Setup HCI 
98132524Ssilby	ngctl mkpeer ${dev}: hci ${hook} drv \
99132524Ssilby		> /dev/null 2>&1 || return 1
100132524Ssilby
101132524Ssilby	ngctl name ${dev}:${hook} ${dev}hci \
102132524Ssilby		> /dev/null 2>&1 || return 1
103132524Ssilby
104132524Ssilby	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
105132524Ssilby		> /dev/null 2>&1 || return 1
106132524Ssilby
107132524Ssilby	# Setup L2CAP
108132524Ssilby	ngctl mkpeer ${dev}hci: l2cap acl hci \
109132524Ssilby		> /dev/null 2>&1 || return 1
110132524Ssilby
111132524Ssilby	ngctl name ${dev}hci:acl ${dev}l2cap \
112132524Ssilby		> /dev/null 2>&1 || return 1
113132524Ssilby
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