bluetooth revision 152286
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 152286 2005-11-10 19:09:22Z emax $
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"
39152286Semax
40152286Semax##############################################################################
41152286Semax# Read and parse Bluetooth device configuration file
42152286Semax##############################################################################
43152286Semax
44152286Semaxbluetooth_read_conf()
45152286Semax{
46152286Semax	_file=$1
47152286Semax	_namespace=$2
48152286Semax	_err=0
49152286Semax
50152286Semax	if [ ! -e $_file ]; then
51152286Semax		return 0
52152286Semax	fi
53152286Semax
54152286Semax	if [ ! -f $_file -o ! -r $_file ]; then
55152286Semax		err 1 "Bluetooth configuration file $_file is not a file or not readable"
56152286Semax	fi
57152286Semax
58152286Semax	while read _line
59152286Semax	do
60152286Semax		case "$_line" in
61152286Semax		\#*)
62152286Semax			continue
63152286Semax			;;
64152286Semax
65152286Semax		*)
66152286Semax			if [ -z "$_line" ]; then
67152286Semax				continue;
68152286Semax			fi
69152286Semax
70152286Semax
71152286Semax			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
72152286Semax				eval "${_namespace}${_line}"
73152286Semax			else
74152286Semax				warn "Unable to parse line \"$_line\" in $_file"
75152286Semax				_err=1
76152286Semax			fi
77152286Semax			;;
78152286Semax		esac
79152286Semax	done < $_file
80152286Semax
81152286Semax	return $_err
82152286Semax}
83152286Semax
84152286Semax##############################################################################
85152286Semax# Setup Bluetooth stack. Create and connect nodes
86152286Semax##############################################################################
87152286Semax
88152286Semaxbluetooth_setup_stack()
89152286Semax{
90152286Semax	dev=$1
91152286Semax	shift
92152286Semax	hook=$1
93152286Semax	shift
94152286Semax
95152286Semax	# Setup HCI 
96152286Semax	ngctl mkpeer ${dev}: hci ${hook} drv \
97152286Semax		> /dev/null 2>&1 || return 1
98152286Semax
99152286Semax	ngctl name ${dev}:${hook} ${dev}hci \
100152286Semax		> /dev/null 2>&1 || return 1
101152286Semax
102152286Semax	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
103152286Semax		> /dev/null 2>&1 || return 1
104152286Semax
105152286Semax	# Setup L2CAP
106152286Semax	ngctl mkpeer ${dev}hci: l2cap acl hci \
107152286Semax		> /dev/null 2>&1 || return 1
108152286Semax
109152286Semax	ngctl name ${dev}hci:acl ${dev}l2cap \
110152286Semax		> /dev/null 2>&1 || return 1
111152286Semax
112152286Semax	ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
113152286Semax		> /dev/null 2>&1 || return 1
114152286Semax
115152286Semax	# Connect HCI node to the Bluetooth sockets layer
116152286Semax	ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
117152286Semax		> /dev/null 2>&1 || return 1
118152286Semax
119152286Semax	# Connect L2CAP node to Bluetooth sockets layer
120152286Semax	ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
121152286Semax		> /dev/null 2>&1 || return 1
122152286Semax
123152286Semax	ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
124152286Semax		> /dev/null 2>&1 || return 1
125152286Semax
126152286Semax	# Initilalize HCI node
127152286Semax	${hccontrol} -n ${dev}hci reset \
128152286Semax		> /dev/null 2>&1 || return 1
129152286Semax
130152286Semax	${hccontrol} -n ${dev}hci read_bd_addr \
131152286Semax		> /dev/null 2>&1 || return 1
132152286Semax
133152286Semax	${hccontrol} -n ${dev}hci read_local_supported_features \
134152286Semax		> /dev/null 2>&1 || return 1
135152286Semax
136152286Semax	${hccontrol} -n ${dev}hci read_buffer_size \
137152286Semax		> /dev/null 2>&1 || return 1
138152286Semax
139152286Semax	if checkyesno bluetooth_device_discoverable; then
140152286Semax		if checkyesno bluetooth_device_connectable; then
141152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 3 \
142152286Semax				> /dev/null 2>&1 || return 1
143152286Semax		else
144152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 1 \
145152286Semax				> /dev/null 2>&1 || return 1
146152286Semax		fi
147152286Semax	else
148152286Semax		if checkyesno bluetooth_device_connectable; then
149152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 2 \
150152286Semax				> /dev/null 2>&1 || return 1
151152286Semax		else
152152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 0 \
153152286Semax				> /dev/null 2>&1 || return 1
154152286Semax		fi
155152286Semax	fi
156152286Semax
157152286Semax
158152286Semax	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
159152286Semax		> /dev/null 2>&1 || return 1
160152286Semax
161152286Semax	if checkyesno bluetooth_device_authentication_enable; then
162152286Semax		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
163152286Semax			> /dev/null 2>&1 || return 1
164152286Semax	else
165152286Semax		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
166152286Semax			> /dev/null 2>&1 || return 1
167152286Semax	fi
168152286Semax
169152286Semax	case "${bluetooth_device_encryption_mode}" in
170152286Semax	[Nn][Oo][Nn][Ee]|0)
171152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
172152286Semax			> /dev/null 2>&1 || return 1
173152286Semax		;;
174152286Semax
175152286Semax	[Pp][2][Pp]|1)
176152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
177152286Semax			> /dev/null 2>&1 || return 1
178152286Semax		;;
179152286Semax
180152286Semax	[Al][Ll][Ll]|2)
181152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
182152286Semax			> /dev/null 2>&1 || return 1
183152286Semax		;;
184152286Semax
185152286Semax	*)
186152286Semax		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
187152286Semax		return 1
188152286Semax		;;
189152286Semax	esac
190152286Semax
191152286Semax	if checkyesno bluetooth_device_role_switch; then
192152286Semax		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
193152286Semax			> /dev/null 2>&1 || return 1
194152286Semax	else
195152286Semax		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
196152286Semax			> /dev/null 2>&1 || return 1
197152286Semax	fi
198152286Semax
199152286Semax	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
200152286Semax		> /dev/null 2>&1 || return 1
201152286Semax
202152286Semax	${hccontrol} -n ${dev}hci initialize \
203152286Semax		> /dev/null 2>&1 || return 1
204152286Semax
205152286Semax	return 0
206152286Semax}
207152286Semax
208152286Semax##############################################################################
209152286Semax# Shutdown Bluetooth stack. Destroy all nodes
210152286Semax##############################################################################
211152286Semax
212152286Semaxbluetooth_shutdown_stack()
213152286Semax{
214152286Semax	dev=$1
215152286Semax
216152286Semax	ngctl shutdown ${dev}hci: > /dev/null 2>&1
217152286Semax	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
218152286Semax
219152286Semax	return 0
220152286Semax}
221152286Semax
222152286Semax##############################################################################
223152286Semax# bluetooth_start()
224152286Semax##############################################################################
225152286Semax
226152286Semaxbluetooth_start()
227152286Semax{
228152286Semax	dev=$1
229152286Semax
230152286Semax	# Automatically load modules
231152286Semax	kldload ng_bluetooth > /dev/null 2>&1
232152286Semax	kldload ng_hci > /dev/null 2>&1
233152286Semax	kldload ng_l2cap > /dev/null 2>&1
234152286Semax	kldload ng_btsocket > /dev/null 2>&1
235152286Semax
236152286Semax	# Try to figure out device type by looking at device name
237152286Semax	case "${dev}" in
238152286Semax	# sioX - serial/UART Bluetooth device
239152286Semax	sio*)
240152286Semax		kldload ng_h4 > /dev/null 2>&1
241152286Semax
242152286Semax		hook="hook"
243152286Semax
244152286Semax		# Obtain unit number from device.
245152286Semax		unit=`expr ${dev} : 'sio\([0-9]\{1,\}\)'`
246152286Semax		if [ -z "${unit}" ]; then
247152286Semax			err 1 "Unable to get sio unit number: ${dev}"
248152286Semax		fi
249152286Semax
250152286Semax		${hcseriald} -f /dev/cuad${unit} -n ${dev}
251152286Semax		sleep 1 # wait a little bit
252152286Semax
253152286Semax		if [ ! -f "/var/run/hcseriald.${dev}.pid" ]; then
254152286Semax			err 1 "Unable to start hcseriald on ${dev}"
255152286Semax		fi
256152286Semax		;;
257152286Semax
258152286Semax	# 3Com Bluetooth Adapter 3CRWB60-A
259152286Semax	btccc*)
260152286Semax		hook="hook"
261152286Semax
262152286Semax		# Obtain unit number from device.
263152286Semax		unit=`expr ${dev} : 'btccc\([0-9]\{1,\}\)'`
264152286Semax		if [ -z "${unit}" ]; then
265152286Semax			err 1 "Unable to get bt3c unit number: ${dev}"
266152286Semax		fi
267152286Semax		;;
268152286Semax
269152286Semax	# USB Bluetooth adapters
270152286Semax	ubt*)
271152286Semax		hook="hook"
272152286Semax
273152286Semax		# Obtain unit number from device.
274152286Semax		unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
275152286Semax		if [ -z "${unit}" ]; then
276152286Semax			err 1 "Unable to get ubt unit number: ${dev}"
277152286Semax		fi
278152286Semax		;;
279152286Semax
280152286Semax	# Unknown
281152286Semax	*)
282152286Semax		err 1 "Unsupported device: ${dev}"
283152286Semax		;;
284152286Semax	esac
285152286Semax
286152286Semax	# Be backward compatible and setup reasonable defaults 
287152286Semax	bluetooth_device_authentication_enable="0"
288152286Semax	bluetooth_device_class="ff:01:0c"
289152286Semax	bluetooth_device_connectable="1"
290152286Semax	bluetooth_device_discoverable="1"
291152286Semax	bluetooth_device_encryption_mode="0"
292152286Semax	bluetooth_device_hci_debug_level="3"
293152286Semax	bluetooth_device_l2cap_debug_level="3"
294152286Semax	bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
295152286Semax	bluetooth_device_role_switch="1"
296152286Semax
297152286Semax	# Load default device configuration parameters
298152286Semax	_file="/etc/defaults/bluetooth.device.conf"
299152286Semax
300152286Semax	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
301152286Semax		err 1 "Unable to read default Bluetooth configuration from $_file"
302152286Semax	fi
303152286Semax
304152286Semax	# Load device specific overrides
305152286Semax	_file="/etc/bluetooth/$dev.conf"
306152286Semax
307152286Semax	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
308152286Semax		err 1 "Unable to read Bluetooth device configuration from $_file"
309152286Semax	fi
310152286Semax
311152286Semax	# Setup stack
312152286Semax	if ! bluetooth_setup_stack ${dev} ${hook} ; then
313152286Semax		bluetooth_shutdown_stack $dev
314152286Semax		err 1 "Unable to setup Bluetooth stack for device ${dev}"
315152286Semax	fi
316152286Semax		
317152286Semax	return 0
318152286Semax}
319152286Semax
320152286Semax##############################################################################
321152286Semax# bluetooth_stop()
322152286Semax##############################################################################
323152286Semax
324152286Semaxbluetooth_stop()
325152286Semax{
326152286Semax	dev=$1
327152286Semax
328152286Semax	# Try to figure out device type by looking at device name
329152286Semax	case "${dev}" in
330152286Semax	# sioX - serial/UART Bluetooth device
331152286Semax	sio*)
332152286Semax		if [ -f "/var/run/hcseriald.${dev}.pid" ]; then
333152286Semax			kill `cat /var/run/hcseriald.${dev}.pid`
334152286Semax			sleep 1 # wait a little bit
335152286Semax		fi
336152286Semax		;;
337152286Semax
338152286Semax	# 3Com Bluetooth Adapter 3CRWB60-A
339152286Semax	btccc*)
340152286Semax		;;
341152286Semax
342152286Semax	# USB Bluetooth adapters
343152286Semax	ubt*)
344152286Semax		;;
345152286Semax
346152286Semax	# Unknown
347152286Semax	*)
348152286Semax		err 1 "Unsupported device: ${dev}"
349152286Semax		;;
350152286Semax	esac
351152286Semax
352152286Semax	bluetooth_shutdown_stack ${dev}
353152286Semax
354152286Semax	return 0
355152286Semax}
356152286Semax
357152286Semax##############################################################################
358152286Semax# Start here
359152286Semax##############################################################################
360152286Semax
361152286Semaxload_rc_config $name
362152286Semaxhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
363152286Semaxhcseriald="${bluetooth_hcseriald:-/usr/sbin/hcseriald}"
364152286Semax
365152286Semaxrun_rc_command $*
366152286Semax
367