xref: /freebsd/libexec/rc/rc.d/bluetooth (revision d0b2dbfa)
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
1300696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci reset \
1310696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1320696600cSBjoern A. Zeeb
1330696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_bd_addr \
1340696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1350696600cSBjoern A. Zeeb
1360696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_local_supported_features \
1370696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1380696600cSBjoern A. Zeeb
1390696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci read_buffer_size \
1400696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1410696600cSBjoern A. Zeeb
1420696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_discoverable; then
1430696600cSBjoern A. Zeeb		if checkyesno bluetooth_device_connectable; then
1440696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 3 \
1450696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1460696600cSBjoern A. Zeeb		else
1470696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 1 \
1480696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1490696600cSBjoern A. Zeeb		fi
1500696600cSBjoern A. Zeeb	else
1510696600cSBjoern A. Zeeb		if checkyesno bluetooth_device_connectable; then
1520696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 2 \
1530696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1540696600cSBjoern A. Zeeb		else
1550696600cSBjoern A. Zeeb			${hccontrol} -n ${dev}hci write_scan_enable 0 \
1560696600cSBjoern A. Zeeb				> /dev/null 2>&1 || return 1
1570696600cSBjoern A. Zeeb		fi
1580696600cSBjoern A. Zeeb	fi
1590696600cSBjoern A. Zeeb
1600696600cSBjoern A. Zeeb
1610696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
1620696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
1630696600cSBjoern A. Zeeb
1640696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_authentication_enable; then
1650696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_authentication_enable 1 \
1660696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1670696600cSBjoern A. Zeeb	else
1680696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_authentication_enable 0 \
1690696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1700696600cSBjoern A. Zeeb	fi
1710696600cSBjoern A. Zeeb
1720696600cSBjoern A. Zeeb	case "${bluetooth_device_encryption_mode}" in
1730696600cSBjoern A. Zeeb	[Nn][Oo][Nn][Ee]|0)
1740696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 0 \
1750696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1760696600cSBjoern A. Zeeb		;;
1770696600cSBjoern A. Zeeb
1780696600cSBjoern A. Zeeb	[Pp][2][Pp]|1)
1790696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 1 \
1800696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1810696600cSBjoern A. Zeeb		;;
1820696600cSBjoern A. Zeeb
1830696600cSBjoern A. Zeeb	[Al][Ll][Ll]|2)
1840696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_encryption_mode 2 \
1850696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1860696600cSBjoern A. Zeeb		;;
1870696600cSBjoern A. Zeeb
1880696600cSBjoern A. Zeeb	*)
1890696600cSBjoern A. Zeeb		warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
1900696600cSBjoern A. Zeeb		return 1
1910696600cSBjoern A. Zeeb		;;
1920696600cSBjoern A. Zeeb	esac
1930696600cSBjoern A. Zeeb
1940696600cSBjoern A. Zeeb	if checkyesno bluetooth_device_role_switch; then
1950696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_node_role_switch 1 \
1960696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
1970696600cSBjoern A. Zeeb	else
1980696600cSBjoern A. Zeeb		${hccontrol} -n ${dev}hci write_node_role_switch 0 \
1990696600cSBjoern A. Zeeb			> /dev/null 2>&1 || return 1
2000696600cSBjoern A. Zeeb	fi
2010696600cSBjoern A. Zeeb
2020696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
2030696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
2040696600cSBjoern A. Zeeb
2050696600cSBjoern A. Zeeb	${hccontrol} -n ${dev}hci initialize \
2060696600cSBjoern A. Zeeb		> /dev/null 2>&1 || return 1
2070696600cSBjoern A. Zeeb
2080696600cSBjoern A. Zeeb	return 0
2090696600cSBjoern A. Zeeb}
2100696600cSBjoern A. Zeeb
2110696600cSBjoern A. Zeeb##############################################################################
2120696600cSBjoern A. Zeeb# Shutdown Bluetooth stack. Destroy all nodes
2130696600cSBjoern A. Zeeb##############################################################################
2140696600cSBjoern A. Zeeb
2150696600cSBjoern A. Zeebbluetooth_shutdown_stack()
2160696600cSBjoern A. Zeeb{
2170696600cSBjoern A. Zeeb	dev=$1
2180696600cSBjoern A. Zeeb
2190696600cSBjoern A. Zeeb	ngctl shutdown ${dev}hci: > /dev/null 2>&1
2200696600cSBjoern A. Zeeb	ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
2210696600cSBjoern A. Zeeb
2220696600cSBjoern A. Zeeb	return 0
2230696600cSBjoern A. Zeeb}
2240696600cSBjoern A. Zeeb
2250696600cSBjoern A. Zeeb##############################################################################
2260696600cSBjoern A. Zeeb# bluetooth_start()
2270696600cSBjoern A. Zeeb##############################################################################
2280696600cSBjoern A. Zeeb
2290696600cSBjoern A. Zeebbluetooth_start()
2300696600cSBjoern A. Zeeb{
2310696600cSBjoern A. Zeeb	local _file
2320696600cSBjoern A. Zeeb
2330696600cSBjoern A. Zeeb	dev=$1
2340696600cSBjoern A. Zeeb
2350696600cSBjoern A. Zeeb	# Try to figure out device type by looking at device name
2360696600cSBjoern A. Zeeb	case "${dev}" in
2370696600cSBjoern A. Zeeb	# USB Bluetooth adapters
2380696600cSBjoern A. Zeeb	ubt*)
2390696600cSBjoern A. Zeeb		hook="hook"
2400696600cSBjoern A. Zeeb
2410696600cSBjoern A. Zeeb		# Obtain unit number from device.
2420696600cSBjoern A. Zeeb		unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
2430696600cSBjoern A. Zeeb		if [ -z "${unit}" ]; then
2440696600cSBjoern A. Zeeb			err 1 "Unable to get ubt unit number: ${dev}"
2450696600cSBjoern A. Zeeb		fi
2460696600cSBjoern A. Zeeb		;;
2470696600cSBjoern A. Zeeb
2480696600cSBjoern A. Zeeb	# Unknown
2490696600cSBjoern A. Zeeb	*)
2500696600cSBjoern A. Zeeb		err 1 "Unsupported device: ${dev}"
2510696600cSBjoern A. Zeeb		;;
2520696600cSBjoern A. Zeeb	esac
2530696600cSBjoern A. Zeeb
2540696600cSBjoern A. Zeeb	# Be backward compatible and setup reasonable defaults
2550696600cSBjoern A. Zeeb	bluetooth_device_authentication_enable="0"
2560696600cSBjoern A. Zeeb	bluetooth_device_class="ff:01:0c"
2570696600cSBjoern A. Zeeb	bluetooth_device_connectable="1"
2580696600cSBjoern A. Zeeb	bluetooth_device_discoverable="0"
2590696600cSBjoern A. Zeeb	bluetooth_device_encryption_mode="0"
2600696600cSBjoern A. Zeeb	bluetooth_device_hci_debug_level="3"
2610696600cSBjoern A. Zeeb	bluetooth_device_l2cap_debug_level="3"
2620696600cSBjoern A. Zeeb	bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
2630696600cSBjoern A. Zeeb	bluetooth_device_role_switch="1"
2640696600cSBjoern A. Zeeb
2650696600cSBjoern A. Zeeb	# Load default device configuration parameters
2660696600cSBjoern A. Zeeb	_file="/etc/defaults/bluetooth.device.conf"
2670696600cSBjoern A. Zeeb
2680696600cSBjoern A. Zeeb	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
2690696600cSBjoern A. Zeeb		err 1 "Unable to read default Bluetooth configuration from $_file"
2700696600cSBjoern A. Zeeb	fi
2710696600cSBjoern A. Zeeb
2720696600cSBjoern A. Zeeb	# Load device specific overrides
2730696600cSBjoern A. Zeeb	_file="/etc/bluetooth/$dev.conf"
2740696600cSBjoern A. Zeeb
2750696600cSBjoern A. Zeeb	if ! bluetooth_read_conf $_file bluetooth_device_ ; then
2760696600cSBjoern A. Zeeb		err 1 "Unable to read Bluetooth device configuration from $_file"
2770696600cSBjoern A. Zeeb	fi
2780696600cSBjoern A. Zeeb
2790696600cSBjoern A. Zeeb	# Setup stack
2800696600cSBjoern A. Zeeb	if ! bluetooth_setup_stack ${dev} ${hook} ; then
2810696600cSBjoern A. Zeeb		bluetooth_shutdown_stack $dev
2820696600cSBjoern A. Zeeb		err 1 "Unable to setup Bluetooth stack for device ${dev}"
2830696600cSBjoern A. Zeeb	fi
2840696600cSBjoern A. Zeeb
2850696600cSBjoern A. Zeeb	return 0
2860696600cSBjoern A. Zeeb}
2870696600cSBjoern A. Zeeb
2880696600cSBjoern A. Zeeb##############################################################################
2890696600cSBjoern A. Zeeb# bluetooth_stop()
2900696600cSBjoern A. Zeeb##############################################################################
2910696600cSBjoern A. Zeeb
2920696600cSBjoern A. Zeebbluetooth_stop()
2930696600cSBjoern A. Zeeb{
2940696600cSBjoern A. Zeeb	dev=$1
2950696600cSBjoern A. Zeeb
2960696600cSBjoern A. Zeeb	# Try to figure out device type by looking at device name
2970696600cSBjoern A. Zeeb	case "${dev}" in
2980696600cSBjoern A. Zeeb	# USB Bluetooth adapters
2990696600cSBjoern A. Zeeb	ubt*)
3000696600cSBjoern A. Zeeb		;;
3010696600cSBjoern A. Zeeb
3020696600cSBjoern A. Zeeb	# Unknown
3030696600cSBjoern A. Zeeb	*)
3040696600cSBjoern A. Zeeb		err 1 "Unsupported device: ${dev}"
3050696600cSBjoern A. Zeeb		;;
3060696600cSBjoern A. Zeeb	esac
3070696600cSBjoern A. Zeeb
3080696600cSBjoern A. Zeeb	bluetooth_shutdown_stack ${dev}
3090696600cSBjoern A. Zeeb
3100696600cSBjoern A. Zeeb	return 0
3110696600cSBjoern A. Zeeb}
3120696600cSBjoern A. Zeeb
3130696600cSBjoern A. Zeeb##############################################################################
3140696600cSBjoern A. Zeeb# Start here
3150696600cSBjoern A. Zeeb##############################################################################
3160696600cSBjoern A. Zeeb
3170696600cSBjoern A. Zeebload_rc_config $name
3180696600cSBjoern A. Zeebhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
3190696600cSBjoern A. Zeeb
3200696600cSBjoern A. Zeebrun_rc_command $*
3210696600cSBjoern A. Zeeb
322