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$
28152286Semax
29152286Semax# PROVIDE: bluetooth
30152286Semax# REQUIRE: DAEMON
31152286Semax# KEYWORD: nojail nostart
32152286Semax
33152286Semax. /etc/rc.subr
34152286Semax
35152286Semaxname="bluetooth"
36298514Slmedesc="Bluetooth setup script"
37152286Semaxrcvar=
38152286Semaxstart_cmd="bluetooth_start"
39152286Semaxstop_cmd="bluetooth_stop"
40165683Syarrequired_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket"
41152286Semax
42152286Semax##############################################################################
43152286Semax# Read and parse Bluetooth device configuration file
44152286Semax##############################################################################
45152286Semax
46152286Semaxbluetooth_read_conf()
47152286Semax{
48165664Syar	local _err _file _line _namespace
49165664Syar
50152286Semax	_file=$1
51152286Semax	_namespace=$2
52152286Semax	_err=0
53152286Semax
54152286Semax	if [ ! -e $_file ]; then
55152286Semax		return 0
56152286Semax	fi
57152286Semax
58152286Semax	if [ ! -f $_file -o ! -r $_file ]; then
59152286Semax		err 1 "Bluetooth configuration file $_file is not a file or not readable"
60152286Semax	fi
61152286Semax
62152286Semax	while read _line
63152286Semax	do
64152286Semax		case "$_line" in
65152286Semax		\#*)
66152286Semax			continue
67152286Semax			;;
68152286Semax
69152286Semax		*)
70152286Semax			if [ -z "$_line" ]; then
71152286Semax				continue;
72152286Semax			fi
73152286Semax
74152286Semax
75152286Semax			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
76152286Semax				eval "${_namespace}${_line}"
77152286Semax			else
78152286Semax				warn "Unable to parse line \"$_line\" in $_file"
79152286Semax				_err=1
80152286Semax			fi
81152286Semax			;;
82152286Semax		esac
83152286Semax	done < $_file
84152286Semax
85152286Semax	return $_err
86152286Semax}
87152286Semax
88152286Semax##############################################################################
89152286Semax# Setup Bluetooth stack. Create and connect nodes
90152286Semax##############################################################################
91152286Semax
92152286Semaxbluetooth_setup_stack()
93152286Semax{
94152286Semax	dev=$1
95152286Semax	shift
96152286Semax	hook=$1
97152286Semax	shift
98152286Semax
99208060Sdougb	# Setup HCI
100152286Semax	ngctl mkpeer ${dev}: hci ${hook} drv \
101152286Semax		> /dev/null 2>&1 || return 1
102152286Semax
103152286Semax	ngctl name ${dev}:${hook} ${dev}hci \
104152286Semax		> /dev/null 2>&1 || return 1
105152286Semax
106152286Semax	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
107152286Semax		> /dev/null 2>&1 || return 1
108152286Semax
109152286Semax	# Setup L2CAP
110152286Semax	ngctl mkpeer ${dev}hci: l2cap acl hci \
111152286Semax		> /dev/null 2>&1 || return 1
112152286Semax
113152286Semax	ngctl name ${dev}hci:acl ${dev}l2cap \
114152286Semax		> /dev/null 2>&1 || return 1
115152286Semax
116152286Semax	ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
117152286Semax		> /dev/null 2>&1 || return 1
118152286Semax
119152286Semax	# Connect HCI node to the Bluetooth sockets layer
120152286Semax	ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
121152286Semax		> /dev/null 2>&1 || return 1
122152286Semax
123152286Semax	# Connect L2CAP node to Bluetooth sockets layer
124152286Semax	ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
125152286Semax		> /dev/null 2>&1 || return 1
126152286Semax
127152286Semax	ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
128152286Semax		> /dev/null 2>&1 || return 1
129152286Semax
130152286Semax	# Initilalize HCI node
131152286Semax	${hccontrol} -n ${dev}hci reset \
132152286Semax		> /dev/null 2>&1 || return 1
133152286Semax
134152286Semax	${hccontrol} -n ${dev}hci read_bd_addr \
135152286Semax		> /dev/null 2>&1 || return 1
136152286Semax
137152286Semax	${hccontrol} -n ${dev}hci read_local_supported_features \
138152286Semax		> /dev/null 2>&1 || return 1
139152286Semax
140152286Semax	${hccontrol} -n ${dev}hci read_buffer_size \
141152286Semax		> /dev/null 2>&1 || return 1
142152286Semax
143152286Semax	if checkyesno bluetooth_device_discoverable; then
144152286Semax		if checkyesno bluetooth_device_connectable; then
145152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 3 \
146152286Semax				> /dev/null 2>&1 || return 1
147152286Semax		else
148152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 1 \
149152286Semax				> /dev/null 2>&1 || return 1
150152286Semax		fi
151152286Semax	else
152152286Semax		if checkyesno bluetooth_device_connectable; then
153152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 2 \
154152286Semax				> /dev/null 2>&1 || return 1
155152286Semax		else
156152286Semax			${hccontrol} -n ${dev}hci write_scan_enable 0 \
157152286Semax				> /dev/null 2>&1 || return 1
158152286Semax		fi
159152286Semax	fi
160152286Semax
161152286Semax
162152286Semax	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
163152286Semax		> /dev/null 2>&1 || return 1
164152286Semax
165152286Semax	if checkyesno bluetooth_device_authentication_enable; then
166152286Semax		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
167152286Semax			> /dev/null 2>&1 || return 1
168152286Semax	else
169152286Semax		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
170152286Semax			> /dev/null 2>&1 || return 1
171152286Semax	fi
172152286Semax
173152286Semax	case "${bluetooth_device_encryption_mode}" in
174152286Semax	[Nn][Oo][Nn][Ee]|0)
175152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
176152286Semax			> /dev/null 2>&1 || return 1
177152286Semax		;;
178152286Semax
179152286Semax	[Pp][2][Pp]|1)
180152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
181152286Semax			> /dev/null 2>&1 || return 1
182152286Semax		;;
183152286Semax
184152286Semax	[Al][Ll][Ll]|2)
185152286Semax		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
186152286Semax			> /dev/null 2>&1 || return 1
187152286Semax		;;
188152286Semax
189152286Semax	*)
190152286Semax		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
191152286Semax		return 1
192152286Semax		;;
193152286Semax	esac
194152286Semax
195152286Semax	if checkyesno bluetooth_device_role_switch; then
196152286Semax		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
197152286Semax			> /dev/null 2>&1 || return 1
198152286Semax	else
199152286Semax		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
200152286Semax			> /dev/null 2>&1 || return 1
201152286Semax	fi
202152286Semax
203152286Semax	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
204152286Semax		> /dev/null 2>&1 || return 1
205152286Semax
206152286Semax	${hccontrol} -n ${dev}hci initialize \
207152286Semax		> /dev/null 2>&1 || return 1
208152286Semax
209152286Semax	return 0
210152286Semax}
211152286Semax
212152286Semax##############################################################################
213152286Semax# Shutdown Bluetooth stack. Destroy all nodes
214152286Semax##############################################################################
215152286Semax
216152286Semaxbluetooth_shutdown_stack()
217152286Semax{
218152286Semax	dev=$1
219152286Semax
220152286Semax	ngctl shutdown ${dev}hci: > /dev/null 2>&1
221152286Semax	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
222152286Semax
223152286Semax	return 0
224152286Semax}
225152286Semax
226152286Semax##############################################################################
227152286Semax# bluetooth_start()
228152286Semax##############################################################################
229152286Semax
230152286Semaxbluetooth_start()
231152286Semax{
232165664Syar	local _file
233165664Syar
234152286Semax	dev=$1
235152286Semax
236152286Semax	# Try to figure out device type by looking at device name
237152286Semax	case "${dev}" in
238180618Smarcel	# uartX - serial/UART Bluetooth device
239180618Smarcel	uart*)
240165683Syar		load_kld ng_h4 || return 1
241152286Semax
242152286Semax		hook="hook"
243152286Semax
244152286Semax		# Obtain unit number from device.
245180618Smarcel		unit=`expr ${dev} : 'uart\([0-9]\{1,\}\)'`
246152286Semax		if [ -z "${unit}" ]; then
247180618Smarcel			err 1 "Unable to get uart unit number: ${dev}"
248152286Semax		fi
249152286Semax
250180618Smarcel		${hcseriald} -f /dev/cuau${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
286208060Sdougb	# 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
316208060Sdougb
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
330180618Smarcel	# uartX - serial/UART Bluetooth device
331180618Smarcel	uart*)
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