bluetooth revision 180618
1101704Smjacob#!/bin/sh
2101704Smjacob#
3101704Smjacob# Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
4101704Smjacob# All rights reserved.
5101704Smjacob#
6101704Smjacob# Redistribution and use in source and binary forms, with or without
7101704Smjacob# modification, are permitted provided that the following conditions
8101704Smjacob# are met:
9101704Smjacob# 1. Redistributions of source code must retain the above copyright
10101704Smjacob#    notice, this list of conditions and the following disclaimer.
11101704Smjacob# 2. Redistributions in binary form must reproduce the above copyright
12101704Smjacob#    notice, this list of conditions and the following disclaimer in the
13101704Smjacob#    documentation and/or other materials provided with the distribution.
14101704Smjacob#
15101704Smjacob# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16101704Smjacob# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17101704Smjacob# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18101704Smjacob# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19101704Smjacob# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20101704Smjacob# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21101704Smjacob# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22101704Smjacob# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23101704Smjacob# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24101704Smjacob# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25101704Smjacob# SUCH DAMAGE.
26101704Smjacob#
27101704Smjacob# $FreeBSD: head/etc/rc.d/bluetooth 180618 2008-07-19 20:11:33Z marcel $
28101704Smjacob
29101704Smjacob# PROVIDE: bluetooth
30101704Smjacob# REQUIRE: DAEMON
31101704Smjacob# KEYWORD: nojail nostart
32101704Smjacob
33101704Smjacob. /etc/rc.subr
34102199Smjacob
35101704Smjacobname="bluetooth"
36101704Smjacobrcvar=
37101704Smjacobstart_cmd="bluetooth_start"
38101704Smjacobstop_cmd="bluetooth_stop"
39101704Smjacobrequired_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket"
40101704Smjacob
41101704Smjacob##############################################################################
42102199Smjacob# Read and parse Bluetooth device configuration file
43102199Smjacob##############################################################################
44101704Smjacob
45101704Smjacobbluetooth_read_conf()
46102199Smjacob{
47101704Smjacob	local _err _file _line _namespace
48101704Smjacob
49101704Smjacob	_file=$1
50101704Smjacob	_namespace=$2
51101704Smjacob	_err=0
52102199Smjacob
53101704Smjacob	if [ ! -e $_file ]; then
54101704Smjacob		return 0
55101704Smjacob	fi
56101704Smjacob
57101704Smjacob	if [ ! -f $_file -o ! -r $_file ]; then
58101704Smjacob		err 1 "Bluetooth configuration file $_file is not a file or not readable"
59102199Smjacob	fi
60101704Smjacob
61101704Smjacob	while read _line
62101704Smjacob	do
63101704Smjacob		case "$_line" in
64101704Smjacob		\#*)
65101704Smjacob			continue
66101704Smjacob			;;
67101704Smjacob
68101704Smjacob		*)
69101704Smjacob			if [ -z "$_line" ]; then
70101704Smjacob				continue;
71101704Smjacob			fi
72101704Smjacob
73101704Smjacob
74101704Smjacob			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
75102199Smjacob				eval "${_namespace}${_line}"
76101704Smjacob			else
77101704Smjacob				warn "Unable to parse line \"$_line\" in $_file"
78101704Smjacob				_err=1
79101704Smjacob			fi
80101704Smjacob			;;
81101704Smjacob		esac
82101704Smjacob	done < $_file
83101704Smjacob
84101704Smjacob	return $_err
85101704Smjacob}
86101704Smjacob
87101704Smjacob##############################################################################
88101704Smjacob# Setup Bluetooth stack. Create and connect nodes
89101704Smjacob##############################################################################
90102199Smjacob
91101704Smjacobbluetooth_setup_stack()
92101704Smjacob{
93101704Smjacob	dev=$1
94101704Smjacob	shift
95101704Smjacob	hook=$1
96101704Smjacob	shift
97101704Smjacob
98101704Smjacob	# Setup HCI 
99101704Smjacob	ngctl mkpeer ${dev}: hci ${hook} drv \
100101704Smjacob		> /dev/null 2>&1 || return 1
101102199Smjacob
102101704Smjacob	ngctl name ${dev}:${hook} ${dev}hci \
103101704Smjacob		> /dev/null 2>&1 || return 1
104101704Smjacob
105101704Smjacob	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
106101704Smjacob		> /dev/null 2>&1 || return 1
107101704Smjacob
108101704Smjacob	# Setup L2CAP
109101704Smjacob	ngctl mkpeer ${dev}hci: l2cap acl hci \
110101704Smjacob		> /dev/null 2>&1 || return 1
111101704Smjacob
112101704Smjacob	ngctl name ${dev}hci:acl ${dev}l2cap \
113101704Smjacob		> /dev/null 2>&1 || return 1
114101704Smjacob
115101704Smjacob	ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
116101704Smjacob		> /dev/null 2>&1 || return 1
117101704Smjacob
118101704Smjacob	# Connect HCI node to the Bluetooth sockets layer
119102199Smjacob	ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
120101704Smjacob		> /dev/null 2>&1 || return 1
121101704Smjacob
122101704Smjacob	# Connect L2CAP node to Bluetooth sockets layer
123101704Smjacob	ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
124101704Smjacob		> /dev/null 2>&1 || return 1
125101704Smjacob
126101704Smjacob	ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
127101704Smjacob		> /dev/null 2>&1 || return 1
128101704Smjacob
129101704Smjacob	# Initilalize HCI node
130101704Smjacob	${hccontrol} -n ${dev}hci reset \
131101704Smjacob		> /dev/null 2>&1 || return 1
132101704Smjacob
133101704Smjacob	${hccontrol} -n ${dev}hci read_bd_addr \
134101704Smjacob		> /dev/null 2>&1 || return 1
135101704Smjacob
136101704Smjacob	${hccontrol} -n ${dev}hci read_local_supported_features \
137101704Smjacob		> /dev/null 2>&1 || return 1
138101704Smjacob
139101704Smjacob	${hccontrol} -n ${dev}hci read_buffer_size \
140101704Smjacob		> /dev/null 2>&1 || return 1
141101704Smjacob
142101704Smjacob	if checkyesno bluetooth_device_discoverable; then
143101704Smjacob		if checkyesno bluetooth_device_connectable; then
144101704Smjacob			${hccontrol} -n ${dev}hci write_scan_enable 3 \
145101704Smjacob				> /dev/null 2>&1 || return 1
146101704Smjacob		else
147101704Smjacob			${hccontrol} -n ${dev}hci write_scan_enable 1 \
148101704Smjacob				> /dev/null 2>&1 || return 1
149101704Smjacob		fi
150101704Smjacob	else
151101704Smjacob		if checkyesno bluetooth_device_connectable; then
152101704Smjacob			${hccontrol} -n ${dev}hci write_scan_enable 2 \
153101704Smjacob				> /dev/null 2>&1 || return 1
154101704Smjacob		else
155101704Smjacob			${hccontrol} -n ${dev}hci write_scan_enable 0 \
156101704Smjacob				> /dev/null 2>&1 || return 1
157101704Smjacob		fi
158101704Smjacob	fi
159101704Smjacob
160101704Smjacob
161101704Smjacob	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
162101704Smjacob		> /dev/null 2>&1 || return 1
163102199Smjacob
164101704Smjacob	if checkyesno bluetooth_device_authentication_enable; then
165101704Smjacob		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
166101704Smjacob			> /dev/null 2>&1 || return 1
167101704Smjacob	else
168101704Smjacob		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
169101704Smjacob			> /dev/null 2>&1 || return 1
170101704Smjacob	fi
171101704Smjacob
172101704Smjacob	case "${bluetooth_device_encryption_mode}" in
173101704Smjacob	[Nn][Oo][Nn][Ee]|0)
174101704Smjacob		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
175101704Smjacob			> /dev/null 2>&1 || return 1
176101704Smjacob		;;
177101704Smjacob
178101704Smjacob	[Pp][2][Pp]|1)
179101704Smjacob		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
180101704Smjacob			> /dev/null 2>&1 || return 1
181101704Smjacob		;;
182101704Smjacob
183101704Smjacob	[Al][Ll][Ll]|2)
184101704Smjacob		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
185101704Smjacob			> /dev/null 2>&1 || return 1
186101704Smjacob		;;
187101704Smjacob
188101704Smjacob	*)
189101704Smjacob		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
190101704Smjacob		return 1
191101704Smjacob		;;
192101704Smjacob	esac
193101704Smjacob
194101704Smjacob	if checkyesno bluetooth_device_role_switch; then
195101704Smjacob		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
196101704Smjacob			> /dev/null 2>&1 || return 1
197101704Smjacob	else
198101704Smjacob		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
199101704Smjacob			> /dev/null 2>&1 || return 1
200101704Smjacob	fi
201101704Smjacob
202101704Smjacob	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
203101704Smjacob		> /dev/null 2>&1 || return 1
204101704Smjacob
205101704Smjacob	${hccontrol} -n ${dev}hci initialize \
206101704Smjacob		> /dev/null 2>&1 || return 1
207102199Smjacob
208101704Smjacob	return 0
209101704Smjacob}
210101704Smjacob
211101704Smjacob##############################################################################
212101704Smjacob# Shutdown Bluetooth stack. Destroy all nodes
213101704Smjacob##############################################################################
214101704Smjacob
215101704Smjacobbluetooth_shutdown_stack()
216101704Smjacob{
217101704Smjacob	dev=$1
218101704Smjacob
219101704Smjacob	ngctl shutdown ${dev}hci: > /dev/null 2>&1
220101704Smjacob	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
221101704Smjacob
222101704Smjacob	return 0
223101704Smjacob}
224101704Smjacob
225101704Smjacob##############################################################################
226101704Smjacob# bluetooth_start()
227101704Smjacob##############################################################################
228102199Smjacob
229101704Smjacobbluetooth_start()
230101704Smjacob{
231101704Smjacob	local _file
232101704Smjacob
233101704Smjacob	dev=$1
234101704Smjacob
235101704Smjacob	# Try to figure out device type by looking at device name
236101704Smjacob	case "${dev}" in
237101704Smjacob	# uartX - serial/UART Bluetooth device
238101704Smjacob	uart*)
239101704Smjacob		load_kld ng_h4 || return 1
240101704Smjacob
241102199Smjacob		hook="hook"
242101704Smjacob
243101704Smjacob		# Obtain unit number from device.
244101704Smjacob		unit=`expr ${dev} : 'uart\([0-9]\{1,\}\)'`
245101704Smjacob		if [ -z "${unit}" ]; then
246101704Smjacob			err 1 "Unable to get uart unit number: ${dev}"
247101704Smjacob		fi
248101704Smjacob
249101704Smjacob		${hcseriald} -f /dev/cuau${unit} -n ${dev}
250101704Smjacob		sleep 1 # wait a little bit
251101704Smjacob
252101704Smjacob		if [ ! -f "/var/run/hcseriald.${dev}.pid" ]; then
253101704Smjacob			err 1 "Unable to start hcseriald on ${dev}"
254101704Smjacob		fi
255101704Smjacob		;;
256101704Smjacob
257101704Smjacob	# 3Com Bluetooth Adapter 3CRWB60-A
258101704Smjacob	btccc*)
259101704Smjacob		hook="hook"
260102199Smjacob
261101704Smjacob		# Obtain unit number from device.
262101704Smjacob		unit=`expr ${dev} : 'btccc\([0-9]\{1,\}\)'`
263101704Smjacob		if [ -z "${unit}" ]; then
264101704Smjacob			err 1 "Unable to get bt3c unit number: ${dev}"
265101704Smjacob		fi
266102304Smjacob		;;
267102304Smjacob
268101704Smjacob	# USB Bluetooth adapters
269101704Smjacob	ubt*)
270101704Smjacob		hook="hook"
271101704Smjacob
272101704Smjacob		# Obtain unit number from device.
273101704Smjacob		unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
274101704Smjacob		if [ -z "${unit}" ]; then
275101704Smjacob			err 1 "Unable to get ubt unit number: ${dev}"
276101704Smjacob		fi
277101704Smjacob		;;
278101704Smjacob
279101704Smjacob	# Unknown
280101704Smjacob	*)
281101704Smjacob		err 1 "Unsupported device: ${dev}"
282101704Smjacob		;;
283101704Smjacob	esac
284101704Smjacob
285101704Smjacob	# Be backward compatible and setup reasonable defaults 
286101704Smjacob	bluetooth_device_authentication_enable="0"
287101704Smjacob	bluetooth_device_class="ff:01:0c"
288102199Smjacob	bluetooth_device_connectable="1"
289101704Smjacob	bluetooth_device_discoverable="1"
290101704Smjacob	bluetooth_device_encryption_mode="0"
291101704Smjacob	bluetooth_device_hci_debug_level="3"
292101704Smjacob	bluetooth_device_l2cap_debug_level="3"
293101704Smjacob	bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
294101704Smjacob	bluetooth_device_role_switch="1"
295102199Smjacob
296101704Smjacob	# Load default device configuration parameters
297101704Smjacob	_file="/etc/defaults/bluetooth.device.conf"
298101704Smjacob
299101704Smjacob	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
300101704Smjacob		err 1 "Unable to read default Bluetooth configuration from $_file"
301101704Smjacob	fi
302101704Smjacob
303101704Smjacob	# Load device specific overrides
304101704Smjacob	_file="/etc/bluetooth/$dev.conf"
305101704Smjacob
306101704Smjacob	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
307102199Smjacob		err 1 "Unable to read Bluetooth device configuration from $_file"
308101704Smjacob	fi
309101704Smjacob
310101704Smjacob	# Setup stack
311101704Smjacob	if ! bluetooth_setup_stack ${dev} ${hook} ; then
312101704Smjacob		bluetooth_shutdown_stack $dev
313101704Smjacob		err 1 "Unable to setup Bluetooth stack for device ${dev}"
314101704Smjacob	fi
315101704Smjacob		
316101704Smjacob	return 0
317101704Smjacob}
318101704Smjacob
319101704Smjacob##############################################################################
320101704Smjacob# bluetooth_stop()
321101704Smjacob##############################################################################
322101704Smjacob
323101704Smjacobbluetooth_stop()
324101704Smjacob{
325101704Smjacob	dev=$1
326101704Smjacob
327101704Smjacob	# Try to figure out device type by looking at device name
328101704Smjacob	case "${dev}" in
329101704Smjacob	# uartX - serial/UART Bluetooth device
330101704Smjacob	uart*)
331101704Smjacob		if [ -f "/var/run/hcseriald.${dev}.pid" ]; then
332101704Smjacob			kill `cat /var/run/hcseriald.${dev}.pid`
333101704Smjacob			sleep 1 # wait a little bit
334101704Smjacob		fi
335101704Smjacob		;;
336101704Smjacob
337101704Smjacob	# 3Com Bluetooth Adapter 3CRWB60-A
338101704Smjacob	btccc*)
339101704Smjacob		;;
340101704Smjacob
341101704Smjacob	# USB Bluetooth adapters
342101704Smjacob	ubt*)
343101704Smjacob		;;
344101704Smjacob
345101704Smjacob	# Unknown
346101704Smjacob	*)
347101704Smjacob		err 1 "Unsupported device: ${dev}"
348101704Smjacob		;;
349101704Smjacob	esac
350101704Smjacob
351101704Smjacob	bluetooth_shutdown_stack ${dev}
352101704Smjacob
353101704Smjacob	return 0
354101704Smjacob}
355101704Smjacob
356101704Smjacob##############################################################################
357101704Smjacob# Start here
358101704Smjacob##############################################################################
359101704Smjacob
360101704Smjacobload_rc_config $name
361101704Smjacobhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
362101704Smjacobhcseriald="${bluetooth_hcseriald:-/usr/sbin/hcseriald}"
363101704Smjacob
364101704Smjacobrun_rc_command $*
365101704Smjacob
366101704Smjacob