bluetooth revision 165683
1152286Semax#!/bin/sh
2152286Semax#
3152286Semax# Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
4152286Semax# All rights reserved.
5152286Semax#
6152286Semax# Redistribution and use in source and binary forms, with or without
7152286Semax# modification, are permitted provided that the following conditions
8152286Semax# are met:
9152286Semax# 1. Redistributions of source code must retain the above copyright
10152286Semax#    notice, this list of conditions and the following disclaimer.
11152286Semax# 2. Redistributions in binary form must reproduce the above copyright
12152286Semax#    notice, this list of conditions and the following disclaimer in the
13152286Semax#    documentation and/or other materials provided with the distribution.
14152286Semax#
15152286Semax# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16152286Semax# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17152286Semax# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18152286Semax# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19152286Semax# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20152286Semax# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21152286Semax# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22152286Semax# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23152286Semax# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24152286Semax# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25152286Semax# SUCH DAMAGE.
26152286Semax#
27152286Semax# $FreeBSD: head/etc/rc.d/bluetooth 165683 2006-12-31 10:37:18Z yar $
28152286Semax
29152286Semax# PROVIDE: bluetooth
30152286Semax# REQUIRE: DAEMON
31152286Semax# KEYWORD: nojail nostart
32152286Semax
33152286Semax. /etc/rc.subr
34152286Semax
35152286Semaxname="bluetooth"
36152286Semaxrcvar=
37152286Semaxstart_cmd="bluetooth_start"
38152286Semaxstop_cmd="bluetooth_stop"
39165683Syarrequired_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket"
40152286Semax
41152286Semax##############################################################################
42152286Semax# Read and parse Bluetooth device configuration file
43152286Semax##############################################################################
44152286Semax
45152286Semaxbluetooth_read_conf()
46152286Semax{
47165664Syar	local _err _file _line _namespace
48165664Syar
49152286Semax	_file=$1
50152286Semax	_namespace=$2
51152286Semax	_err=0
52152286Semax
53152286Semax	if [ ! -e $_file ]; then
54152286Semax		return 0
55152286Semax	fi
56152286Semax
57152286Semax	if [ ! -f $_file -o ! -r $_file ]; then
58152286Semax		err 1 "Bluetooth configuration file $_file is not a file or not readable"
59152286Semax	fi
60152286Semax
61152286Semax	while read _line
62152286Semax	do
63152286Semax		case "$_line" in
64152286Semax		\#*)
65152286Semax			continue
66152286Semax			;;
67152286Semax
68152286Semax		*)
69152286Semax			if [ -z "$_line" ]; then
70152286Semax				continue;
71152286Semax			fi
72152286Semax
73152286Semax
74152286Semax			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
75152286Semax				eval "${_namespace}${_line}"
76152286Semax			else
77152286Semax				warn "Unable to parse line \"$_line\" in $_file"
78152286Semax				_err=1
79152286Semax			fi
80152286Semax			;;
81152286Semax		esac
82152286Semax	done < $_file
83152286Semax
84152286Semax	return $_err
85152286Semax}
86152286Semax
87152286Semax##############################################################################
88152286Semax# Setup Bluetooth stack. Create and connect nodes
89152286Semax##############################################################################
90152286Semax
91152286Semaxbluetooth_setup_stack()
92152286Semax{
93152286Semax	dev=$1
94152286Semax	shift
95152286Semax	hook=$1
96152286Semax	shift
97152286Semax
98152286Semax	# Setup HCI 
99152286Semax	ngctl mkpeer ${dev}: hci ${hook} drv \
100152286Semax		> /dev/null 2>&1 || return 1
101152286Semax
102152286Semax	ngctl name ${dev}:${hook} ${dev}hci \
103152286Semax		> /dev/null 2>&1 || return 1
104152286Semax
105152286Semax	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
106152286Semax		> /dev/null 2>&1 || return 1
107152286Semax
108152286Semax	# Setup L2CAP
109152286Semax	ngctl mkpeer ${dev}hci: l2cap acl hci \
110152286Semax		> /dev/null 2>&1 || return 1
111152286Semax
112152286Semax	ngctl name ${dev}hci:acl ${dev}l2cap \
113152286Semax		> /dev/null 2>&1 || return 1
114152286Semax
115152286Semax	ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
116152286Semax		> /dev/null 2>&1 || return 1
117152286Semax
118152286Semax	# Connect HCI node to the Bluetooth sockets layer
119152286Semax	ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
120152286Semax		> /dev/null 2>&1 || return 1
121152286Semax
122152286Semax	# Connect L2CAP node to Bluetooth sockets layer
123152286Semax	ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
124152286Semax		> /dev/null 2>&1 || return 1
125152286Semax
126152286Semax	ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
127152286Semax		> /dev/null 2>&1 || return 1
128152286Semax
129152286Semax	# Initilalize HCI node
130152286Semax	${hccontrol} -n ${dev}hci reset \
131152286Semax		> /dev/null 2>&1 || return 1
132152286Semax
133152286Semax	${hccontrol} -n ${dev}hci read_bd_addr \
134152286Semax		> /dev/null 2>&1 || return 1
135152286Semax
136152286Semax	${hccontrol} -n ${dev}hci read_local_supported_features \
137152286Semax		> /dev/null 2>&1 || return 1
138152286Semax
139152286Semax	${hccontrol} -n ${dev}hci read_buffer_size \
140152286Semax		> /dev/null 2>&1 || return 1
141152286Semax
142152286Semax	if checkyesno bluetooth_device_discoverable; then
143152286Semax		if checkyesno bluetooth_device_connectable; then
144152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 3 \
145152286Semax				> /dev/null 2>&1 || return 1
146152286Semax		else
147152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 1 \
148152286Semax				> /dev/null 2>&1 || return 1
149152286Semax		fi
150152286Semax	else
151152286Semax		if checkyesno bluetooth_device_connectable; then
152152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 2 \
153152286Semax				> /dev/null 2>&1 || return 1
154152286Semax		else
155152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 0 \
156152286Semax				> /dev/null 2>&1 || return 1
157152286Semax		fi
158152286Semax	fi
159152286Semax
160152286Semax
161152286Semax	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
162152286Semax		> /dev/null 2>&1 || return 1
163152286Semax
164152286Semax	if checkyesno bluetooth_device_authentication_enable; then
165152286Semax		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
166152286Semax			> /dev/null 2>&1 || return 1
167152286Semax	else
168152286Semax		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
169152286Semax			> /dev/null 2>&1 || return 1
170152286Semax	fi
171152286Semax
172152286Semax	case "${bluetooth_device_encryption_mode}" in
173152286Semax	[Nn][Oo][Nn][Ee]|0)
174152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
175152286Semax			> /dev/null 2>&1 || return 1
176152286Semax		;;
177152286Semax
178152286Semax	[Pp][2][Pp]|1)
179152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
180152286Semax			> /dev/null 2>&1 || return 1
181152286Semax		;;
182152286Semax
183152286Semax	[Al][Ll][Ll]|2)
184152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
185152286Semax			> /dev/null 2>&1 || return 1
186152286Semax		;;
187152286Semax
188152286Semax	*)
189152286Semax		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
190152286Semax		return 1
191152286Semax		;;
192152286Semax	esac
193152286Semax
194152286Semax	if checkyesno bluetooth_device_role_switch; then
195152286Semax		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
196152286Semax			> /dev/null 2>&1 || return 1
197152286Semax	else
198152286Semax		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
199152286Semax			> /dev/null 2>&1 || return 1
200152286Semax	fi
201152286Semax
202152286Semax	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
203152286Semax		> /dev/null 2>&1 || return 1
204152286Semax
205152286Semax	${hccontrol} -n ${dev}hci initialize \
206152286Semax		> /dev/null 2>&1 || return 1
207152286Semax
208152286Semax	return 0
209152286Semax}
210152286Semax
211152286Semax##############################################################################
212152286Semax# Shutdown Bluetooth stack. Destroy all nodes
213152286Semax##############################################################################
214152286Semax
215152286Semaxbluetooth_shutdown_stack()
216152286Semax{
217152286Semax	dev=$1
218152286Semax
219152286Semax	ngctl shutdown ${dev}hci: > /dev/null 2>&1
220152286Semax	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
221152286Semax
222152286Semax	return 0
223152286Semax}
224152286Semax
225152286Semax##############################################################################
226152286Semax# bluetooth_start()
227152286Semax##############################################################################
228152286Semax
229152286Semaxbluetooth_start()
230152286Semax{
231165664Syar	local _file
232165664Syar
233152286Semax	dev=$1
234152286Semax
235152286Semax	# Try to figure out device type by looking at device name
236152286Semax	case "${dev}" in
237152286Semax	# sioX - serial/UART Bluetooth device
238152286Semax	sio*)
239165683Syar		load_kld ng_h4 || return 1
240152286Semax
241152286Semax		hook="hook"
242152286Semax
243152286Semax		# Obtain unit number from device.
244152286Semax		unit=`expr ${dev} : 'sio\([0-9]\{1,\}\)'`
245152286Semax		if [ -z "${unit}" ]; then
246152286Semax			err 1 "Unable to get sio unit number: ${dev}"
247152286Semax		fi
248152286Semax
249152286Semax		${hcseriald} -f /dev/cuad${unit} -n ${dev}
250152286Semax		sleep 1 # wait a little bit
251152286Semax
252152286Semax		if [ ! -f "/var/run/hcseriald.${dev}.pid" ]; then
253152286Semax			err 1 "Unable to start hcseriald on ${dev}"
254152286Semax		fi
255152286Semax		;;
256152286Semax
257152286Semax	# 3Com Bluetooth Adapter 3CRWB60-A
258152286Semax	btccc*)
259152286Semax		hook="hook"
260152286Semax
261152286Semax		# Obtain unit number from device.
262152286Semax		unit=`expr ${dev} : 'btccc\([0-9]\{1,\}\)'`
263152286Semax		if [ -z "${unit}" ]; then
264152286Semax			err 1 "Unable to get bt3c unit number: ${dev}"
265152286Semax		fi
266152286Semax		;;
267152286Semax
268152286Semax	# USB Bluetooth adapters
269152286Semax	ubt*)
270152286Semax		hook="hook"
271152286Semax
272152286Semax		# Obtain unit number from device.
273152286Semax		unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
274152286Semax		if [ -z "${unit}" ]; then
275152286Semax			err 1 "Unable to get ubt unit number: ${dev}"
276152286Semax		fi
277152286Semax		;;
278152286Semax
279152286Semax	# Unknown
280152286Semax	*)
281152286Semax		err 1 "Unsupported device: ${dev}"
282152286Semax		;;
283152286Semax	esac
284152286Semax
285152286Semax	# Be backward compatible and setup reasonable defaults 
286152286Semax	bluetooth_device_authentication_enable="0"
287152286Semax	bluetooth_device_class="ff:01:0c"
288152286Semax	bluetooth_device_connectable="1"
289152286Semax	bluetooth_device_discoverable="1"
290152286Semax	bluetooth_device_encryption_mode="0"
291152286Semax	bluetooth_device_hci_debug_level="3"
292152286Semax	bluetooth_device_l2cap_debug_level="3"
293152286Semax	bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
294152286Semax	bluetooth_device_role_switch="1"
295152286Semax
296152286Semax	# Load default device configuration parameters
297152286Semax	_file="/etc/defaults/bluetooth.device.conf"
298152286Semax
299152286Semax	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
300152286Semax		err 1 "Unable to read default Bluetooth configuration from $_file"
301152286Semax	fi
302152286Semax
303152286Semax	# Load device specific overrides
304152286Semax	_file="/etc/bluetooth/$dev.conf"
305152286Semax
306152286Semax	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
307152286Semax		err 1 "Unable to read Bluetooth device configuration from $_file"
308152286Semax	fi
309152286Semax
310152286Semax	# Setup stack
311152286Semax	if ! bluetooth_setup_stack ${dev} ${hook} ; then
312152286Semax		bluetooth_shutdown_stack $dev
313152286Semax		err 1 "Unable to setup Bluetooth stack for device ${dev}"
314152286Semax	fi
315152286Semax		
316152286Semax	return 0
317152286Semax}
318152286Semax
319152286Semax##############################################################################
320152286Semax# bluetooth_stop()
321152286Semax##############################################################################
322152286Semax
323152286Semaxbluetooth_stop()
324152286Semax{
325152286Semax	dev=$1
326152286Semax
327152286Semax	# Try to figure out device type by looking at device name
328152286Semax	case "${dev}" in
329152286Semax	# sioX - serial/UART Bluetooth device
330152286Semax	sio*)
331152286Semax		if [ -f "/var/run/hcseriald.${dev}.pid" ]; then
332152286Semax			kill `cat /var/run/hcseriald.${dev}.pid`
333152286Semax			sleep 1 # wait a little bit
334152286Semax		fi
335152286Semax		;;
336152286Semax
337152286Semax	# 3Com Bluetooth Adapter 3CRWB60-A
338152286Semax	btccc*)
339152286Semax		;;
340152286Semax
341152286Semax	# USB Bluetooth adapters
342152286Semax	ubt*)
343152286Semax		;;
344152286Semax
345152286Semax	# Unknown
346152286Semax	*)
347152286Semax		err 1 "Unsupported device: ${dev}"
348152286Semax		;;
349152286Semax	esac
350152286Semax
351152286Semax	bluetooth_shutdown_stack ${dev}
352152286Semax
353152286Semax	return 0
354152286Semax}
355152286Semax
356152286Semax##############################################################################
357152286Semax# Start here
358152286Semax##############################################################################
359152286Semax
360152286Semaxload_rc_config $name
361152286Semaxhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
362152286Semaxhcseriald="${bluetooth_hcseriald:-/usr/sbin/hcseriald}"
363152286Semax
364152286Semaxrun_rc_command $*
365152286Semax
366