Start integrating Bluetooth into rc.d system.

Introduce /etc/rc.d/bluetooth script to start/stop Bluetooth devices. It
will be called from devd(8) in response to device arrival/departure events.
It is also possible to call it by hand to start/stop particular device
without unplugging it.

Introduce generic way to set configuration parameters for Bluetooth devices.
By default /etc/rc.d/bluetooth script has hardwired defaults compatible
with old rc.bluetooth from /usr/share/netgraph/bluetooth/examples. These
can be overridden using /etc/defaults/bluetooth.device.conf file (system
wide defaults). Finally, there could be another device specific override
file located in /etc/bluetooth/$device.conf (where $device is ubt0, btccc0
etc.)

The list of configuration parameters and their meaning described in the
/etc/defaults/bluetooth.device.conf file. Even though Bluetooth device
configuration files are not shell scripts, they must follow basic sh(1) syntax.

The bluetooth.device.conf(5) and handbook update will follow shortly.

Inspired by:	Panagiotis Astithas ( past at ebs dot gr )
Reviewed by:	brooks, yar
MFC after:	1 week
This commit is contained in:
Maksim Yevmenkin 2005-11-10 19:09:22 +00:00
parent e4a93f1ef8
commit cdf98ad3e7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=152286
6 changed files with 483 additions and 5 deletions

View File

@ -7,5 +7,4 @@
#
# BD_ADDR Name [ alias0 alias1 ... ]
ff:ff:ff:00:00:00 localhost local # Magic sdpd address
# 00:11:22:33:44:55 phone

View File

@ -3,7 +3,8 @@
#
# Bluetooth Protocol/Service Multiplexor (PSM) names and numbers
#
# See also http://www.bluetoothsig.org/assigned-numbers/
# See also
# https://www.bluetooth.org/foundry/assignnumb/document/assigned_numbers
#
# Protocol PSM Alias Reference

View File

@ -1,6 +1,6 @@
# $FreeBSD$
FILES= devfs.rules pccard.conf periodic.conf rc.conf
FILES= bluetooth.device.conf devfs.rules pccard.conf periodic.conf rc.conf
NO_OBJ=
FILESDIR= /etc/defaults
FILESMODE= 444

View File

@ -0,0 +1,112 @@
# Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
# The authentication_enable parameter controls if the device requires to
# authenticate the remote device at connection setup. At connection setup,
# only the devices with the authentication_enable parameter enabled will
# try to authenticate the other device.
#
# Possible values:
#
# NO or 0 authentication disabled (default);
# YES or 1 authentication enabled.
# authentication_enable="NO"
# The class parameter is used to indicate the capabilities of the device to
# other devices.
#
# For more details see
# https://www.bluetooth.org/foundry/assignnumb/document/baseband
#
# Possible value:
#
# xx:xx:xx where xx is a hex number
# class="ff:01:0c"
# The connectable parameter controls whether or not the device should
# periodically scan for page attempts from other devices.
#
# Possible values:
#
# NO or 0 do not scan for page attempts;
# YES or 1 scan for page attempts (default).
# connectable="YES"
# The discoverable parameter controls whether or not the device should
# periodically scan for inquiry requests from other devices.
#
# Possible values:
#
# NO or 0 do not scan for inquiry requests;
# YES or 1 scan for inquiry requests (default).
# discoverable="YES"
# The encryption_mode parameter controls if the device requires encryption
# to the remote device at connection setup. At connection setup, only the
# devices with the authentication_enable parameter enabled and encryption_mode
# parameter enabled will try to encrypt the connection to the other device.
#
# Possible values:
#
# NONE or 0 encryption disabled (default);
# P2P or 1 encryption only for point-to-point packets;
# ALL or 2 encryption for both point-to-point and broadcast packets.
# encryption_mode="NONE"
# HCI node debug level. Higher values mean more verbose output.
#
# Possible values: 0 - 4
# hci_debug_level="3"
# L2CAP node debug level. Higher values mean more verbose output.
#
# Possible values: 0 - 4
# l2cap_debug_level="3"
# The local_name parameter provides the ability to modify the user friendly
# name for the device.
# local_name="My device"
# The role_switch parameter controls whether the local device should perform
# role switch. By default, if role switch is supported, the local device will
# try to perform role switch and become Master on incoming connection. Some
# devices do not support role switch and thus incomming connections from such
# devices will fail. If role switch is disabled then accepting device will
# remain Slave.
#
# NO or 0 do not perform role switch;
# YES or 1 perform role switch (default).
# role_switch="YES"

View File

@ -4,7 +4,7 @@
FILES= DAEMON LOGIN NETWORKING SERVERS \
abi accounting addswap adjkerntz amd \
apm apmd archdep atm1 atm2 atm3 \
bgfsck bootparams bsnmpd \
bgfsck bluetooth bootparams bsnmpd \
ccd cleanvar cleartmp cron \
devd devfs dhclient \
dmesg dumpon \

366
etc/rc.d/bluetooth Normal file
View File

@ -0,0 +1,366 @@
#!/bin/sh
#
# Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
# PROVIDE: bluetooth
# REQUIRE: DAEMON
# KEYWORD: nojail nostart
. /etc/rc.subr
name="bluetooth"
rcvar=
start_cmd="bluetooth_start"
stop_cmd="bluetooth_stop"
##############################################################################
# Read and parse Bluetooth device configuration file
##############################################################################
bluetooth_read_conf()
{
_file=$1
_namespace=$2
_err=0
if [ ! -e $_file ]; then
return 0
fi
if [ ! -f $_file -o ! -r $_file ]; then
err 1 "Bluetooth configuration file $_file is not a file or not readable"
fi
while read _line
do
case "$_line" in
\#*)
continue
;;
*)
if [ -z "$_line" ]; then
continue;
fi
if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
eval "${_namespace}${_line}"
else
warn "Unable to parse line \"$_line\" in $_file"
_err=1
fi
;;
esac
done < $_file
return $_err
}
##############################################################################
# Setup Bluetooth stack. Create and connect nodes
##############################################################################
bluetooth_setup_stack()
{
dev=$1
shift
hook=$1
shift
# Setup HCI
ngctl mkpeer ${dev}: hci ${hook} drv \
> /dev/null 2>&1 || return 1
ngctl name ${dev}:${hook} ${dev}hci \
> /dev/null 2>&1 || return 1
ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
> /dev/null 2>&1 || return 1
# Setup L2CAP
ngctl mkpeer ${dev}hci: l2cap acl hci \
> /dev/null 2>&1 || return 1
ngctl name ${dev}hci:acl ${dev}l2cap \
> /dev/null 2>&1 || return 1
ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
> /dev/null 2>&1 || return 1
# Connect HCI node to the Bluetooth sockets layer
ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
> /dev/null 2>&1 || return 1
# Connect L2CAP node to Bluetooth sockets layer
ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
> /dev/null 2>&1 || return 1
ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
> /dev/null 2>&1 || return 1
# Initilalize HCI node
${hccontrol} -n ${dev}hci reset \
> /dev/null 2>&1 || return 1
${hccontrol} -n ${dev}hci read_bd_addr \
> /dev/null 2>&1 || return 1
${hccontrol} -n ${dev}hci read_local_supported_features \
> /dev/null 2>&1 || return 1
${hccontrol} -n ${dev}hci read_buffer_size \
> /dev/null 2>&1 || return 1
if checkyesno bluetooth_device_discoverable; then
if checkyesno bluetooth_device_connectable; then
${hccontrol} -n ${dev}hci write_scan_enable 3 \
> /dev/null 2>&1 || return 1
else
${hccontrol} -n ${dev}hci write_scan_enable 1 \
> /dev/null 2>&1 || return 1
fi
else
if checkyesno bluetooth_device_connectable; then
${hccontrol} -n ${dev}hci write_scan_enable 2 \
> /dev/null 2>&1 || return 1
else
${hccontrol} -n ${dev}hci write_scan_enable 0 \
> /dev/null 2>&1 || return 1
fi
fi
${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
> /dev/null 2>&1 || return 1
if checkyesno bluetooth_device_authentication_enable; then
${hccontrol} -n ${dev}hci write_authentication_enable 1 \
> /dev/null 2>&1 || return 1
else
${hccontrol} -n ${dev}hci write_authentication_enable 0 \
> /dev/null 2>&1 || return 1
fi
case "${bluetooth_device_encryption_mode}" in
[Nn][Oo][Nn][Ee]|0)
${hccontrol} -n ${dev}hci write_encryption_mode 0 \
> /dev/null 2>&1 || return 1
;;
[Pp][2][Pp]|1)
${hccontrol} -n ${dev}hci write_encryption_mode 1 \
> /dev/null 2>&1 || return 1
;;
[Al][Ll][Ll]|2)
${hccontrol} -n ${dev}hci write_encryption_mode 2 \
> /dev/null 2>&1 || return 1
;;
*)
warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
return 1
;;
esac
if checkyesno bluetooth_device_role_switch; then
${hccontrol} -n ${dev}hci write_node_role_switch 1 \
> /dev/null 2>&1 || return 1
else
${hccontrol} -n ${dev}hci write_node_role_switch 0 \
> /dev/null 2>&1 || return 1
fi
${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
> /dev/null 2>&1 || return 1
${hccontrol} -n ${dev}hci initialize \
> /dev/null 2>&1 || return 1
return 0
}
##############################################################################
# Shutdown Bluetooth stack. Destroy all nodes
##############################################################################
bluetooth_shutdown_stack()
{
dev=$1
ngctl shutdown ${dev}hci: > /dev/null 2>&1
ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
return 0
}
##############################################################################
# bluetooth_start()
##############################################################################
bluetooth_start()
{
dev=$1
# Automatically load modules
kldload ng_bluetooth > /dev/null 2>&1
kldload ng_hci > /dev/null 2>&1
kldload ng_l2cap > /dev/null 2>&1
kldload ng_btsocket > /dev/null 2>&1
# Try to figure out device type by looking at device name
case "${dev}" in
# sioX - serial/UART Bluetooth device
sio*)
kldload ng_h4 > /dev/null 2>&1
hook="hook"
# Obtain unit number from device.
unit=`expr ${dev} : 'sio\([0-9]\{1,\}\)'`
if [ -z "${unit}" ]; then
err 1 "Unable to get sio unit number: ${dev}"
fi
${hcseriald} -f /dev/cuad${unit} -n ${dev}
sleep 1 # wait a little bit
if [ ! -f "/var/run/hcseriald.${dev}.pid" ]; then
err 1 "Unable to start hcseriald on ${dev}"
fi
;;
# 3Com Bluetooth Adapter 3CRWB60-A
btccc*)
hook="hook"
# Obtain unit number from device.
unit=`expr ${dev} : 'btccc\([0-9]\{1,\}\)'`
if [ -z "${unit}" ]; then
err 1 "Unable to get bt3c unit number: ${dev}"
fi
;;
# USB Bluetooth adapters
ubt*)
hook="hook"
# Obtain unit number from device.
unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
if [ -z "${unit}" ]; then
err 1 "Unable to get ubt unit number: ${dev}"
fi
;;
# Unknown
*)
err 1 "Unsupported device: ${dev}"
;;
esac
# Be backward compatible and setup reasonable defaults
bluetooth_device_authentication_enable="0"
bluetooth_device_class="ff:01:0c"
bluetooth_device_connectable="1"
bluetooth_device_discoverable="1"
bluetooth_device_encryption_mode="0"
bluetooth_device_hci_debug_level="3"
bluetooth_device_l2cap_debug_level="3"
bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
bluetooth_device_role_switch="1"
# Load default device configuration parameters
_file="/etc/defaults/bluetooth.device.conf"
if ! bluetooth_read_conf $_file bluetooth_device_ ; then
err 1 "Unable to read default Bluetooth configuration from $_file"
fi
# Load device specific overrides
_file="/etc/bluetooth/$dev.conf"
if ! bluetooth_read_conf $_file bluetooth_device_ ; then
err 1 "Unable to read Bluetooth device configuration from $_file"
fi
# Setup stack
if ! bluetooth_setup_stack ${dev} ${hook} ; then
bluetooth_shutdown_stack $dev
err 1 "Unable to setup Bluetooth stack for device ${dev}"
fi
return 0
}
##############################################################################
# bluetooth_stop()
##############################################################################
bluetooth_stop()
{
dev=$1
# Try to figure out device type by looking at device name
case "${dev}" in
# sioX - serial/UART Bluetooth device
sio*)
if [ -f "/var/run/hcseriald.${dev}.pid" ]; then
kill `cat /var/run/hcseriald.${dev}.pid`
sleep 1 # wait a little bit
fi
;;
# 3Com Bluetooth Adapter 3CRWB60-A
btccc*)
;;
# USB Bluetooth adapters
ubt*)
;;
# Unknown
*)
err 1 "Unsupported device: ${dev}"
;;
esac
bluetooth_shutdown_stack ${dev}
return 0
}
##############################################################################
# Start here
##############################################################################
load_rc_config $name
hccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
hcseriald="${bluetooth_hcseriald:-/usr/sbin/hcseriald}"
run_rc_command $*