1*0696600cSBjoern A. Zeeb#!/bin/sh 2*0696600cSBjoern A. Zeeb# 3*0696600cSBjoern A. Zeeb# Copyright (c) 2005 Maksim Yevmenkin <[email protected]> 4*0696600cSBjoern A. Zeeb# All rights reserved. 5*0696600cSBjoern A. Zeeb# 6*0696600cSBjoern A. Zeeb# Redistribution and use in source and binary forms, with or without 7*0696600cSBjoern A. Zeeb# modification, are permitted provided that the following conditions 8*0696600cSBjoern A. Zeeb# are met: 9*0696600cSBjoern A. Zeeb# 1. Redistributions of source code must retain the above copyright 10*0696600cSBjoern A. Zeeb# notice, this list of conditions and the following disclaimer. 11*0696600cSBjoern A. Zeeb# 2. Redistributions in binary form must reproduce the above copyright 12*0696600cSBjoern A. Zeeb# notice, this list of conditions and the following disclaimer in the 13*0696600cSBjoern A. Zeeb# documentation and/or other materials provided with the distribution. 14*0696600cSBjoern A. Zeeb# 15*0696600cSBjoern A. Zeeb# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*0696600cSBjoern A. Zeeb# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*0696600cSBjoern A. Zeeb# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*0696600cSBjoern A. Zeeb# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*0696600cSBjoern A. Zeeb# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*0696600cSBjoern A. Zeeb# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*0696600cSBjoern A. Zeeb# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*0696600cSBjoern A. Zeeb# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*0696600cSBjoern A. Zeeb# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*0696600cSBjoern A. Zeeb# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*0696600cSBjoern A. Zeeb# SUCH DAMAGE. 26*0696600cSBjoern A. Zeeb# 27*0696600cSBjoern A. Zeeb 28*0696600cSBjoern A. Zeeb# PROVIDE: bluetooth 29*0696600cSBjoern A. Zeeb# REQUIRE: DAEMON 30*0696600cSBjoern A. Zeeb# KEYWORD: nojail nostart 31*0696600cSBjoern A. Zeeb 32*0696600cSBjoern A. Zeeb. /etc/rc.subr 33*0696600cSBjoern A. Zeeb 34*0696600cSBjoern A. Zeebname="bluetooth" 35*0696600cSBjoern A. Zeebdesc="Bluetooth setup script" 36*0696600cSBjoern A. Zeebrcvar= 37*0696600cSBjoern A. Zeebstart_cmd="bluetooth_start" 38*0696600cSBjoern A. Zeebstop_cmd="bluetooth_stop" 39*0696600cSBjoern A. Zeebrequired_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket" 40*0696600cSBjoern A. Zeeb 41*0696600cSBjoern A. Zeeb############################################################################## 42*0696600cSBjoern A. Zeeb# Read and parse Bluetooth device configuration file 43*0696600cSBjoern A. Zeeb############################################################################## 44*0696600cSBjoern A. Zeeb 45*0696600cSBjoern A. Zeebbluetooth_read_conf() 46*0696600cSBjoern A. Zeeb{ 47*0696600cSBjoern A. Zeeb local _err _file _line _namespace 48*0696600cSBjoern A. Zeeb 49*0696600cSBjoern A. Zeeb _file=$1 50*0696600cSBjoern A. Zeeb _namespace=$2 51*0696600cSBjoern A. Zeeb _err=0 52*0696600cSBjoern A. Zeeb 53*0696600cSBjoern A. Zeeb if [ ! -e $_file ]; then 54*0696600cSBjoern A. Zeeb return 0 55*0696600cSBjoern A. Zeeb fi 56*0696600cSBjoern A. Zeeb 57*0696600cSBjoern A. Zeeb if [ ! -f $_file -o ! -r $_file ]; then 58*0696600cSBjoern A. Zeeb err 1 "Bluetooth configuration file $_file is not a file or not readable" 59*0696600cSBjoern A. Zeeb fi 60*0696600cSBjoern A. Zeeb 61*0696600cSBjoern A. Zeeb while read _line 62*0696600cSBjoern A. Zeeb do 63*0696600cSBjoern A. Zeeb case "$_line" in 64*0696600cSBjoern A. Zeeb \#*) 65*0696600cSBjoern A. Zeeb continue 66*0696600cSBjoern A. Zeeb ;; 67*0696600cSBjoern A. Zeeb 68*0696600cSBjoern A. Zeeb *) 69*0696600cSBjoern A. Zeeb if [ -z "$_line" ]; then 70*0696600cSBjoern A. Zeeb continue; 71*0696600cSBjoern A. Zeeb fi 72*0696600cSBjoern A. Zeeb 73*0696600cSBjoern A. Zeeb 74*0696600cSBjoern A. Zeeb if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then 75*0696600cSBjoern A. Zeeb eval "${_namespace}${_line}" 76*0696600cSBjoern A. Zeeb else 77*0696600cSBjoern A. Zeeb warn "Unable to parse line \"$_line\" in $_file" 78*0696600cSBjoern A. Zeeb _err=1 79*0696600cSBjoern A. Zeeb fi 80*0696600cSBjoern A. Zeeb ;; 81*0696600cSBjoern A. Zeeb esac 82*0696600cSBjoern A. Zeeb done < $_file 83*0696600cSBjoern A. Zeeb 84*0696600cSBjoern A. Zeeb return $_err 85*0696600cSBjoern A. Zeeb} 86*0696600cSBjoern A. Zeeb 87*0696600cSBjoern A. Zeeb############################################################################## 88*0696600cSBjoern A. Zeeb# Setup Bluetooth stack. Create and connect nodes 89*0696600cSBjoern A. Zeeb############################################################################## 90*0696600cSBjoern A. Zeeb 91*0696600cSBjoern A. Zeebbluetooth_setup_stack() 92*0696600cSBjoern A. Zeeb{ 93*0696600cSBjoern A. Zeeb dev=$1 94*0696600cSBjoern A. Zeeb shift 95*0696600cSBjoern A. Zeeb hook=$1 96*0696600cSBjoern A. Zeeb shift 97*0696600cSBjoern A. Zeeb 98*0696600cSBjoern A. Zeeb # Setup HCI 99*0696600cSBjoern A. Zeeb ngctl mkpeer ${dev}: hci ${hook} drv \ 100*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 101*0696600cSBjoern A. Zeeb 102*0696600cSBjoern A. Zeeb ngctl name ${dev}:${hook} ${dev}hci \ 103*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 104*0696600cSBjoern A. Zeeb 105*0696600cSBjoern A. Zeeb ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \ 106*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 107*0696600cSBjoern A. Zeeb 108*0696600cSBjoern A. Zeeb # Setup L2CAP 109*0696600cSBjoern A. Zeeb ngctl mkpeer ${dev}hci: l2cap acl hci \ 110*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 111*0696600cSBjoern A. Zeeb 112*0696600cSBjoern A. Zeeb ngctl name ${dev}hci:acl ${dev}l2cap \ 113*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 114*0696600cSBjoern A. Zeeb 115*0696600cSBjoern A. Zeeb ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \ 116*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 117*0696600cSBjoern A. Zeeb 118*0696600cSBjoern A. Zeeb # Connect HCI node to the Bluetooth sockets layer 119*0696600cSBjoern A. Zeeb ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \ 120*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 121*0696600cSBjoern A. Zeeb 122*0696600cSBjoern A. Zeeb # Connect L2CAP node to Bluetooth sockets layer 123*0696600cSBjoern A. Zeeb ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \ 124*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 125*0696600cSBjoern A. Zeeb 126*0696600cSBjoern A. Zeeb ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \ 127*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 128*0696600cSBjoern A. Zeeb 129*0696600cSBjoern A. Zeeb # Initilalize HCI node 130*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci reset \ 131*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 132*0696600cSBjoern A. Zeeb 133*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci read_bd_addr \ 134*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 135*0696600cSBjoern A. Zeeb 136*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci read_local_supported_features \ 137*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 138*0696600cSBjoern A. Zeeb 139*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci read_buffer_size \ 140*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 141*0696600cSBjoern A. Zeeb 142*0696600cSBjoern A. Zeeb if checkyesno bluetooth_device_discoverable; then 143*0696600cSBjoern A. Zeeb if checkyesno bluetooth_device_connectable; then 144*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_scan_enable 3 \ 145*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 146*0696600cSBjoern A. Zeeb else 147*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_scan_enable 1 \ 148*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 149*0696600cSBjoern A. Zeeb fi 150*0696600cSBjoern A. Zeeb else 151*0696600cSBjoern A. Zeeb if checkyesno bluetooth_device_connectable; then 152*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_scan_enable 2 \ 153*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 154*0696600cSBjoern A. Zeeb else 155*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_scan_enable 0 \ 156*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 157*0696600cSBjoern A. Zeeb fi 158*0696600cSBjoern A. Zeeb fi 159*0696600cSBjoern A. Zeeb 160*0696600cSBjoern A. Zeeb 161*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \ 162*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 163*0696600cSBjoern A. Zeeb 164*0696600cSBjoern A. Zeeb if checkyesno bluetooth_device_authentication_enable; then 165*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_authentication_enable 1 \ 166*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 167*0696600cSBjoern A. Zeeb else 168*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_authentication_enable 0 \ 169*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 170*0696600cSBjoern A. Zeeb fi 171*0696600cSBjoern A. Zeeb 172*0696600cSBjoern A. Zeeb case "${bluetooth_device_encryption_mode}" in 173*0696600cSBjoern A. Zeeb [Nn][Oo][Nn][Ee]|0) 174*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_encryption_mode 0 \ 175*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 176*0696600cSBjoern A. Zeeb ;; 177*0696600cSBjoern A. Zeeb 178*0696600cSBjoern A. Zeeb [Pp][2][Pp]|1) 179*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_encryption_mode 1 \ 180*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 181*0696600cSBjoern A. Zeeb ;; 182*0696600cSBjoern A. Zeeb 183*0696600cSBjoern A. Zeeb [Al][Ll][Ll]|2) 184*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_encryption_mode 2 \ 185*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 186*0696600cSBjoern A. Zeeb ;; 187*0696600cSBjoern A. Zeeb 188*0696600cSBjoern A. Zeeb *) 189*0696600cSBjoern A. Zeeb warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}" 190*0696600cSBjoern A. Zeeb return 1 191*0696600cSBjoern A. Zeeb ;; 192*0696600cSBjoern A. Zeeb esac 193*0696600cSBjoern A. Zeeb 194*0696600cSBjoern A. Zeeb if checkyesno bluetooth_device_role_switch; then 195*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_node_role_switch 1 \ 196*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 197*0696600cSBjoern A. Zeeb else 198*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci write_node_role_switch 0 \ 199*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 200*0696600cSBjoern A. Zeeb fi 201*0696600cSBjoern A. Zeeb 202*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \ 203*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 204*0696600cSBjoern A. Zeeb 205*0696600cSBjoern A. Zeeb ${hccontrol} -n ${dev}hci initialize \ 206*0696600cSBjoern A. Zeeb > /dev/null 2>&1 || return 1 207*0696600cSBjoern A. Zeeb 208*0696600cSBjoern A. Zeeb return 0 209*0696600cSBjoern A. Zeeb} 210*0696600cSBjoern A. Zeeb 211*0696600cSBjoern A. Zeeb############################################################################## 212*0696600cSBjoern A. Zeeb# Shutdown Bluetooth stack. Destroy all nodes 213*0696600cSBjoern A. Zeeb############################################################################## 214*0696600cSBjoern A. Zeeb 215*0696600cSBjoern A. Zeebbluetooth_shutdown_stack() 216*0696600cSBjoern A. Zeeb{ 217*0696600cSBjoern A. Zeeb dev=$1 218*0696600cSBjoern A. Zeeb 219*0696600cSBjoern A. Zeeb ngctl shutdown ${dev}hci: > /dev/null 2>&1 220*0696600cSBjoern A. Zeeb ngctl shutdown ${dev}l2cap: > /dev/null 2>&1 221*0696600cSBjoern A. Zeeb 222*0696600cSBjoern A. Zeeb return 0 223*0696600cSBjoern A. Zeeb} 224*0696600cSBjoern A. Zeeb 225*0696600cSBjoern A. Zeeb############################################################################## 226*0696600cSBjoern A. Zeeb# bluetooth_start() 227*0696600cSBjoern A. Zeeb############################################################################## 228*0696600cSBjoern A. Zeeb 229*0696600cSBjoern A. Zeebbluetooth_start() 230*0696600cSBjoern A. Zeeb{ 231*0696600cSBjoern A. Zeeb local _file 232*0696600cSBjoern A. Zeeb 233*0696600cSBjoern A. Zeeb dev=$1 234*0696600cSBjoern A. Zeeb 235*0696600cSBjoern A. Zeeb # Try to figure out device type by looking at device name 236*0696600cSBjoern A. Zeeb case "${dev}" in 237*0696600cSBjoern A. Zeeb # USB Bluetooth adapters 238*0696600cSBjoern A. Zeeb ubt*) 239*0696600cSBjoern A. Zeeb hook="hook" 240*0696600cSBjoern A. Zeeb 241*0696600cSBjoern A. Zeeb # Obtain unit number from device. 242*0696600cSBjoern A. Zeeb unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'` 243*0696600cSBjoern A. Zeeb if [ -z "${unit}" ]; then 244*0696600cSBjoern A. Zeeb err 1 "Unable to get ubt unit number: ${dev}" 245*0696600cSBjoern A. Zeeb fi 246*0696600cSBjoern A. Zeeb ;; 247*0696600cSBjoern A. Zeeb 248*0696600cSBjoern A. Zeeb # Unknown 249*0696600cSBjoern A. Zeeb *) 250*0696600cSBjoern A. Zeeb err 1 "Unsupported device: ${dev}" 251*0696600cSBjoern A. Zeeb ;; 252*0696600cSBjoern A. Zeeb esac 253*0696600cSBjoern A. Zeeb 254*0696600cSBjoern A. Zeeb # Be backward compatible and setup reasonable defaults 255*0696600cSBjoern A. Zeeb bluetooth_device_authentication_enable="0" 256*0696600cSBjoern A. Zeeb bluetooth_device_class="ff:01:0c" 257*0696600cSBjoern A. Zeeb bluetooth_device_connectable="1" 258*0696600cSBjoern A. Zeeb bluetooth_device_discoverable="0" 259*0696600cSBjoern A. Zeeb bluetooth_device_encryption_mode="0" 260*0696600cSBjoern A. Zeeb bluetooth_device_hci_debug_level="3" 261*0696600cSBjoern A. Zeeb bluetooth_device_l2cap_debug_level="3" 262*0696600cSBjoern A. Zeeb bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})" 263*0696600cSBjoern A. Zeeb bluetooth_device_role_switch="1" 264*0696600cSBjoern A. Zeeb 265*0696600cSBjoern A. Zeeb # Load default device configuration parameters 266*0696600cSBjoern A. Zeeb _file="/etc/defaults/bluetooth.device.conf" 267*0696600cSBjoern A. Zeeb 268*0696600cSBjoern A. Zeeb if ! bluetooth_read_conf $_file bluetooth_device_ ; then 269*0696600cSBjoern A. Zeeb err 1 "Unable to read default Bluetooth configuration from $_file" 270*0696600cSBjoern A. Zeeb fi 271*0696600cSBjoern A. Zeeb 272*0696600cSBjoern A. Zeeb # Load device specific overrides 273*0696600cSBjoern A. Zeeb _file="/etc/bluetooth/$dev.conf" 274*0696600cSBjoern A. Zeeb 275*0696600cSBjoern A. Zeeb if ! bluetooth_read_conf $_file bluetooth_device_ ; then 276*0696600cSBjoern A. Zeeb err 1 "Unable to read Bluetooth device configuration from $_file" 277*0696600cSBjoern A. Zeeb fi 278*0696600cSBjoern A. Zeeb 279*0696600cSBjoern A. Zeeb # Setup stack 280*0696600cSBjoern A. Zeeb if ! bluetooth_setup_stack ${dev} ${hook} ; then 281*0696600cSBjoern A. Zeeb bluetooth_shutdown_stack $dev 282*0696600cSBjoern A. Zeeb err 1 "Unable to setup Bluetooth stack for device ${dev}" 283*0696600cSBjoern A. Zeeb fi 284*0696600cSBjoern A. Zeeb 285*0696600cSBjoern A. Zeeb return 0 286*0696600cSBjoern A. Zeeb} 287*0696600cSBjoern A. Zeeb 288*0696600cSBjoern A. Zeeb############################################################################## 289*0696600cSBjoern A. Zeeb# bluetooth_stop() 290*0696600cSBjoern A. Zeeb############################################################################## 291*0696600cSBjoern A. Zeeb 292*0696600cSBjoern A. Zeebbluetooth_stop() 293*0696600cSBjoern A. Zeeb{ 294*0696600cSBjoern A. Zeeb dev=$1 295*0696600cSBjoern A. Zeeb 296*0696600cSBjoern A. Zeeb # Try to figure out device type by looking at device name 297*0696600cSBjoern A. Zeeb case "${dev}" in 298*0696600cSBjoern A. Zeeb # USB Bluetooth adapters 299*0696600cSBjoern A. Zeeb ubt*) 300*0696600cSBjoern A. Zeeb ;; 301*0696600cSBjoern A. Zeeb 302*0696600cSBjoern A. Zeeb # Unknown 303*0696600cSBjoern A. Zeeb *) 304*0696600cSBjoern A. Zeeb err 1 "Unsupported device: ${dev}" 305*0696600cSBjoern A. Zeeb ;; 306*0696600cSBjoern A. Zeeb esac 307*0696600cSBjoern A. Zeeb 308*0696600cSBjoern A. Zeeb bluetooth_shutdown_stack ${dev} 309*0696600cSBjoern A. Zeeb 310*0696600cSBjoern A. Zeeb return 0 311*0696600cSBjoern A. Zeeb} 312*0696600cSBjoern A. Zeeb 313*0696600cSBjoern A. Zeeb############################################################################## 314*0696600cSBjoern A. Zeeb# Start here 315*0696600cSBjoern A. Zeeb############################################################################## 316*0696600cSBjoern A. Zeeb 317*0696600cSBjoern A. Zeebload_rc_config $name 318*0696600cSBjoern A. Zeebhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}" 319*0696600cSBjoern A. Zeeb 320*0696600cSBjoern A. Zeebrun_rc_command $* 321*0696600cSBjoern A. Zeeb 322