xref: /freebsd/libexec/rc/rc.d/bluetooth (revision 78807c196c9481cdd88b5ce611b488903f52fbd0)
10696600cSBjoern A. Zeeb#!/bin/sh
20696600cSBjoern A. Zeeb#
30696600cSBjoern A. Zeeb# Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
40696600cSBjoern A. Zeeb# All rights reserved.
50696600cSBjoern A. Zeeb#
60696600cSBjoern A. Zeeb# Redistribution and use in source and binary forms, with or without
70696600cSBjoern A. Zeeb# modification, are permitted provided that the following conditions
80696600cSBjoern A. Zeeb# are met:
90696600cSBjoern A. Zeeb# 1. Redistributions of source code must retain the above copyright
100696600cSBjoern A. Zeeb#    notice, this list of conditions and the following disclaimer.
110696600cSBjoern A. Zeeb# 2. Redistributions in binary form must reproduce the above copyright
120696600cSBjoern A. Zeeb#    notice, this list of conditions and the following disclaimer in the
130696600cSBjoern A. Zeeb#    documentation and/or other materials provided with the distribution.
140696600cSBjoern A. Zeeb#
150696600cSBjoern A. Zeeb# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
160696600cSBjoern A. Zeeb# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
170696600cSBjoern A. Zeeb# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
180696600cSBjoern A. Zeeb# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
190696600cSBjoern A. Zeeb# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
200696600cSBjoern A. Zeeb# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
210696600cSBjoern A. Zeeb# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
220696600cSBjoern A. Zeeb# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
230696600cSBjoern A. Zeeb# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
240696600cSBjoern A. Zeeb# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
250696600cSBjoern A. Zeeb# SUCH DAMAGE.
260696600cSBjoern A. Zeeb#
270696600cSBjoern A. Zeeb
280696600cSBjoern A. Zeeb# PROVIDE: bluetooth
290696600cSBjoern A. Zeeb# REQUIRE: DAEMON
300696600cSBjoern A. Zeeb# KEYWORD: nojail nostart
310696600cSBjoern A. Zeeb
320696600cSBjoern A. Zeeb. /etc/rc.subr
330696600cSBjoern A. Zeeb
340696600cSBjoern A. Zeebname="bluetooth"
350696600cSBjoern A. Zeebdesc="Bluetooth setup script"
360696600cSBjoern A. Zeebrcvar=
370696600cSBjoern A. Zeebstart_cmd="bluetooth_start"
380696600cSBjoern A. Zeebstop_cmd="bluetooth_stop"
390696600cSBjoern A. Zeebrequired_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket"
400696600cSBjoern A. Zeeb
410696600cSBjoern A. Zeeb##############################################################################
420696600cSBjoern A. Zeeb# Read and parse Bluetooth device configuration file
430696600cSBjoern A. Zeeb##############################################################################
440696600cSBjoern A. Zeeb
450696600cSBjoern A. Zeebbluetooth_read_conf()
460696600cSBjoern A. Zeeb{
470696600cSBjoern A. Zeeb	local _err _file _line _namespace
480696600cSBjoern A. Zeeb
490696600cSBjoern A. Zeeb	_file=$1
500696600cSBjoern A. Zeeb	_namespace=$2
510696600cSBjoern A. Zeeb	_err=0
520696600cSBjoern A. Zeeb
530696600cSBjoern A. Zeeb	if [ ! -e $_file ]; then
540696600cSBjoern A. Zeeb		return 0
550696600cSBjoern A. Zeeb	fi
560696600cSBjoern A. Zeeb
570696600cSBjoern A. Zeeb	if [ ! -f $_file -o ! -r $_file ]; then
580696600cSBjoern A. Zeeb		err 1 "Bluetooth configuration file $_file is not a file or not readable"
590696600cSBjoern A. Zeeb	fi
600696600cSBjoern A. Zeeb
610696600cSBjoern A. Zeeb	while read _line
620696600cSBjoern A. Zeeb	do
630696600cSBjoern A. Zeeb		case "$_line" in
640696600cSBjoern A. Zeeb		\#*)
650696600cSBjoern A. Zeeb			continue
660696600cSBjoern A. Zeeb			;;
670696600cSBjoern A. Zeeb
680696600cSBjoern A. Zeeb		*)
690696600cSBjoern A. Zeeb			if [ -z "$_line" ]; then
700696600cSBjoern A. Zeeb				continue;
710696600cSBjoern A. Zeeb			fi
720696600cSBjoern A. Zeeb
730696600cSBjoern A. Zeeb
740696600cSBjoern A. Zeeb			if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
750696600cSBjoern A. Zeeb				eval "${_namespace}${_line}"
760696600cSBjoern A. Zeeb			else
770696600cSBjoern A. Zeeb				warn "Unable to parse line \"$_line\" in $_file"
780696600cSBjoern A. Zeeb				_err=1
790696600cSBjoern A. Zeeb			fi
800696600cSBjoern A. Zeeb			;;
810696600cSBjoern A. Zeeb		esac
820696600cSBjoern A. Zeeb	done < $_file
830696600cSBjoern A. Zeeb
840696600cSBjoern A. Zeeb	return $_err
850696600cSBjoern A. Zeeb}
860696600cSBjoern A. Zeeb
870696600cSBjoern A. Zeeb##############################################################################
880696600cSBjoern A. Zeeb# Setup Bluetooth stack. Create and connect nodes
890696600cSBjoern A. Zeeb##############################################################################
900696600cSBjoern A. Zeeb
910696600cSBjoern A. Zeebbluetooth_setup_stack()
920696600cSBjoern A. Zeeb{
930696600cSBjoern A. Zeeb	dev=$1
940696600cSBjoern A. Zeeb	shift
950696600cSBjoern A. Zeeb	hook=$1
960696600cSBjoern A. Zeeb	shift
970696600cSBjoern A. Zeeb
980696600cSBjoern A. Zeeb	# Setup HCI
990696600cSBjoern A. Zeeb	ngctl mkpeer ${dev}: hci ${hook} drv \
1000696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1010696600cSBjoern A. Zeeb
1020696600cSBjoern A. Zeeb	ngctl name ${dev}:${hook} ${dev}hci \
1030696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1040696600cSBjoern A. Zeeb
1050696600cSBjoern A. Zeeb	ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
1060696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1070696600cSBjoern A. Zeeb
1080696600cSBjoern A. Zeeb	# Setup L2CAP
1090696600cSBjoern A. Zeeb	ngctl mkpeer ${dev}hci: l2cap acl hci \
1100696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1110696600cSBjoern A. Zeeb
1120696600cSBjoern A. Zeeb	ngctl name ${dev}hci:acl ${dev}l2cap \
1130696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1140696600cSBjoern A. Zeeb
1150696600cSBjoern A. Zeeb	ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
1160696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1170696600cSBjoern A. Zeeb
1180696600cSBjoern A. Zeeb	# Connect HCI node to the Bluetooth sockets layer
1190696600cSBjoern A. Zeeb	ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
1200696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1210696600cSBjoern A. Zeeb
1220696600cSBjoern A. Zeeb	# Connect L2CAP node to Bluetooth sockets layer
1230696600cSBjoern A. Zeeb	ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
1240696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1250696600cSBjoern A. Zeeb
1260696600cSBjoern A. Zeeb	ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
1270696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1280696600cSBjoern A. Zeeb
1290696600cSBjoern A. Zeeb	# Initilalize HCI node
13040652f86SStephen Hurd	for loop in 1 2 3
13140652f86SStephen Hurd	do
1320696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci reset \
133*78807c19SBjoern A. Zeeb			> /dev/null 2>&1 && break
13440652f86SStephen Hurd		if [ ${loop} -eq 3 ]
13540652f86SStephen Hurd		then
13640652f86SStephen Hurd			warn Reset failed three times, giving up.
13740652f86SStephen Hurd			return 1
13840652f86SStephen Hurd		fi
13940652f86SStephen Hurd		warn Reset failed, retrying.
14040652f86SStephen Hurd	done
1410696600cSBjoern A. Zeeb
1420696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_bd_addr \
1430696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1440696600cSBjoern A. Zeeb
1450696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_local_supported_features \
1460696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1470696600cSBjoern A. Zeeb
1480696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_buffer_size \
1490696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1500696600cSBjoern A. Zeeb
1510696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_discoverable; then
1520696600cSBjoern A. Zeeb		if checkyesno bluetooth_device_connectable; then
1530696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 3 \
1540696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1550696600cSBjoern A. Zeeb		else
1560696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 1 \
1570696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1580696600cSBjoern A. Zeeb		fi
1590696600cSBjoern A. Zeeb	else
1600696600cSBjoern A. Zeeb		if checkyesno bluetooth_device_connectable; then
1610696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 2 \
1620696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1630696600cSBjoern A. Zeeb		else
1640696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 0 \
1650696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1660696600cSBjoern A. Zeeb		fi
1670696600cSBjoern A. Zeeb	fi
1680696600cSBjoern A. Zeeb
1690696600cSBjoern A. Zeeb
1700696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
1710696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1720696600cSBjoern A. Zeeb
1730696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_authentication_enable; then
1740696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
1750696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1760696600cSBjoern A. Zeeb	else
1770696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
1780696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1790696600cSBjoern A. Zeeb	fi
1800696600cSBjoern A. Zeeb
1810696600cSBjoern A. Zeeb	case "${bluetooth_device_encryption_mode}" in
1820696600cSBjoern A. Zeeb	[Nn][Oo][Nn][Ee]|0)
1830696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
1840696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1850696600cSBjoern A. Zeeb		;;
1860696600cSBjoern A. Zeeb
1870696600cSBjoern A. Zeeb	[Pp][2][Pp]|1)
1880696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
1890696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1900696600cSBjoern A. Zeeb		;;
1910696600cSBjoern A. Zeeb
1920696600cSBjoern A. Zeeb	[Al][Ll][Ll]|2)
1930696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
1940696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1950696600cSBjoern A. Zeeb		;;
1960696600cSBjoern A. Zeeb
1970696600cSBjoern A. Zeeb	*)
1980696600cSBjoern A. Zeeb		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
1990696600cSBjoern A. Zeeb		return 1
2000696600cSBjoern A. Zeeb		;;
2010696600cSBjoern A. Zeeb	esac
2020696600cSBjoern A. Zeeb
2030696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_role_switch; then
2040696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
2050696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
2060696600cSBjoern A. Zeeb	else
2070696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
2080696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
2090696600cSBjoern A. Zeeb	fi
2100696600cSBjoern A. Zeeb
2110696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
2120696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
2130696600cSBjoern A. Zeeb
2140696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci initialize \
2150696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
2160696600cSBjoern A. Zeeb
2170696600cSBjoern A. Zeeb	return 0
2180696600cSBjoern A. Zeeb}
2190696600cSBjoern A. Zeeb
2200696600cSBjoern A. Zeeb##############################################################################
2210696600cSBjoern A. Zeeb# Shutdown Bluetooth stack. Destroy all nodes
2220696600cSBjoern A. Zeeb##############################################################################
2230696600cSBjoern A. Zeeb
2240696600cSBjoern A. Zeebbluetooth_shutdown_stack()
2250696600cSBjoern A. Zeeb{
2260696600cSBjoern A. Zeeb	dev=$1
2270696600cSBjoern A. Zeeb
2280696600cSBjoern A. Zeeb	ngctl shutdown ${dev}hci: > /dev/null 2>&1
2290696600cSBjoern A. Zeeb	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
2300696600cSBjoern A. Zeeb
2310696600cSBjoern A. Zeeb	return 0
2320696600cSBjoern A. Zeeb}
2330696600cSBjoern A. Zeeb
2340696600cSBjoern A. Zeeb##############################################################################
2350696600cSBjoern A. Zeeb# bluetooth_start()
2360696600cSBjoern A. Zeeb##############################################################################
2370696600cSBjoern A. Zeeb
2380696600cSBjoern A. Zeebbluetooth_start()
2390696600cSBjoern A. Zeeb{
2400696600cSBjoern A. Zeeb	local _file
2410696600cSBjoern A. Zeeb
2420696600cSBjoern A. Zeeb	dev=$1
2430696600cSBjoern A. Zeeb
2440696600cSBjoern A. Zeeb	# Try to figure out device type by looking at device name
2450696600cSBjoern A. Zeeb	case "${dev}" in
2460696600cSBjoern A. Zeeb	# USB Bluetooth adapters
2470696600cSBjoern A. Zeeb	ubt*)
2480696600cSBjoern A. Zeeb		hook="hook"
2490696600cSBjoern A. Zeeb
2500696600cSBjoern A. Zeeb		# Obtain unit number from device.
2510696600cSBjoern A. Zeeb		unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
2520696600cSBjoern A. Zeeb		if [ -z "${unit}" ]; then
2530696600cSBjoern A. Zeeb			err 1 "Unable to get ubt unit number: ${dev}"
2540696600cSBjoern A. Zeeb		fi
2550696600cSBjoern A. Zeeb		;;
2560696600cSBjoern A. Zeeb
2570696600cSBjoern A. Zeeb	# Unknown
2580696600cSBjoern A. Zeeb	*)
2590696600cSBjoern A. Zeeb		err 1 "Unsupported device: ${dev}"
2600696600cSBjoern A. Zeeb		;;
2610696600cSBjoern A. Zeeb	esac
2620696600cSBjoern A. Zeeb
2630696600cSBjoern A. Zeeb	# Be backward compatible and setup reasonable defaults
2640696600cSBjoern A. Zeeb	bluetooth_device_authentication_enable="0"
2650696600cSBjoern A. Zeeb	bluetooth_device_class="ff:01:0c"
2660696600cSBjoern A. Zeeb	bluetooth_device_connectable="1"
2670696600cSBjoern A. Zeeb	bluetooth_device_discoverable="0"
2680696600cSBjoern A. Zeeb	bluetooth_device_encryption_mode="0"
2690696600cSBjoern A. Zeeb	bluetooth_device_hci_debug_level="3"
2700696600cSBjoern A. Zeeb	bluetooth_device_l2cap_debug_level="3"
2710696600cSBjoern A. Zeeb	bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
2720696600cSBjoern A. Zeeb	bluetooth_device_role_switch="1"
2730696600cSBjoern A. Zeeb
2740696600cSBjoern A. Zeeb	# Load default device configuration parameters
2750696600cSBjoern A. Zeeb	_file="/etc/defaults/bluetooth.device.conf"
2760696600cSBjoern A. Zeeb
2770696600cSBjoern A. Zeeb	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
2780696600cSBjoern A. Zeeb		err 1 "Unable to read default Bluetooth configuration from $_file"
2790696600cSBjoern A. Zeeb	fi
2800696600cSBjoern A. Zeeb
2810696600cSBjoern A. Zeeb	# Load device specific overrides
2820696600cSBjoern A. Zeeb	_file="/etc/bluetooth/$dev.conf"
2830696600cSBjoern A. Zeeb
2840696600cSBjoern A. Zeeb	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
2850696600cSBjoern A. Zeeb		err 1 "Unable to read Bluetooth device configuration from $_file"
2860696600cSBjoern A. Zeeb	fi
2870696600cSBjoern A. Zeeb
2880696600cSBjoern A. Zeeb	# Setup stack
2890696600cSBjoern A. Zeeb	if ! bluetooth_setup_stack ${dev} ${hook} ; then
2900696600cSBjoern A. Zeeb		bluetooth_shutdown_stack $dev
2910696600cSBjoern A. Zeeb		err 1 "Unable to setup Bluetooth stack for device ${dev}"
2920696600cSBjoern A. Zeeb	fi
2930696600cSBjoern A. Zeeb
2940696600cSBjoern A. Zeeb	return 0
2950696600cSBjoern A. Zeeb}
2960696600cSBjoern A. Zeeb
2970696600cSBjoern A. Zeeb##############################################################################
2980696600cSBjoern A. Zeeb# bluetooth_stop()
2990696600cSBjoern A. Zeeb##############################################################################
3000696600cSBjoern A. Zeeb
3010696600cSBjoern A. Zeebbluetooth_stop()
3020696600cSBjoern A. Zeeb{
3030696600cSBjoern A. Zeeb	dev=$1
3040696600cSBjoern A. Zeeb
3050696600cSBjoern A. Zeeb	# Try to figure out device type by looking at device name
3060696600cSBjoern A. Zeeb	case "${dev}" in
3070696600cSBjoern A. Zeeb	# USB Bluetooth adapters
3080696600cSBjoern A. Zeeb	ubt*)
3090696600cSBjoern A. Zeeb		;;
3100696600cSBjoern A. Zeeb
3110696600cSBjoern A. Zeeb	# Unknown
3120696600cSBjoern A. Zeeb	*)
3130696600cSBjoern A. Zeeb		err 1 "Unsupported device: ${dev}"
3140696600cSBjoern A. Zeeb		;;
3150696600cSBjoern A. Zeeb	esac
3160696600cSBjoern A. Zeeb
3170696600cSBjoern A. Zeeb	bluetooth_shutdown_stack ${dev}
3180696600cSBjoern A. Zeeb
3190696600cSBjoern A. Zeeb	return 0
3200696600cSBjoern A. Zeeb}
3210696600cSBjoern A. Zeeb
3220696600cSBjoern A. Zeeb##############################################################################
3230696600cSBjoern A. Zeeb# Start here
3240696600cSBjoern A. Zeeb##############################################################################
3250696600cSBjoern A. Zeeb
3260696600cSBjoern A. Zeebload_rc_config $name
3270696600cSBjoern A. Zeebhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
3280696600cSBjoern A. Zeeb
329f99f0ee1SAlexander Leidinger# doesn't make sense to run in a svcj: nojail keyword
330f99f0ee1SAlexander Leidingerbluetooth_svcj="NO"
331f99f0ee1SAlexander Leidinger
3320696600cSBjoern A. Zeebrun_rc_command $*
3330696600cSBjoern A. Zeeb
334