1152286Semax#!/bin/sh 2152286Semax# 3152286Semax# Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com> 4152286Semax# All rights reserved. 5152286Semax# 6152286Semax# Redistribution and use in source and binary forms, with or without 7152286Semax# modification, are permitted provided that the following conditions 8152286Semax# are met: 9152286Semax# 1. Redistributions of source code must retain the above copyright 10152286Semax# notice, this list of conditions and the following disclaimer. 11152286Semax# 2. Redistributions in binary form must reproduce the above copyright 12152286Semax# notice, this list of conditions and the following disclaimer in the 13152286Semax# documentation and/or other materials provided with the distribution. 14152286Semax# 15152286Semax# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16152286Semax# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17152286Semax# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18152286Semax# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19152286Semax# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20152286Semax# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21152286Semax# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22152286Semax# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23152286Semax# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24152286Semax# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25152286Semax# SUCH DAMAGE. 26152286Semax# 27152286Semax# $FreeBSD$ 28152286Semax 29152286Semax# PROVIDE: bluetooth 30152286Semax# REQUIRE: DAEMON 31152286Semax# KEYWORD: nojail nostart 32152286Semax 33152286Semax. /etc/rc.subr 34152286Semax 35152286Semaxname="bluetooth" 36298514Slmedesc="Bluetooth setup script" 37152286Semaxrcvar= 38152286Semaxstart_cmd="bluetooth_start" 39152286Semaxstop_cmd="bluetooth_stop" 40165683Syarrequired_modules="ng_bluetooth ng_hci ng_l2cap ng_btsocket" 41152286Semax 42152286Semax############################################################################## 43152286Semax# Read and parse Bluetooth device configuration file 44152286Semax############################################################################## 45152286Semax 46152286Semaxbluetooth_read_conf() 47152286Semax{ 48165664Syar local _err _file _line _namespace 49165664Syar 50152286Semax _file=$1 51152286Semax _namespace=$2 52152286Semax _err=0 53152286Semax 54152286Semax if [ ! -e $_file ]; then 55152286Semax return 0 56152286Semax fi 57152286Semax 58152286Semax if [ ! -f $_file -o ! -r $_file ]; then 59152286Semax err 1 "Bluetooth configuration file $_file is not a file or not readable" 60152286Semax fi 61152286Semax 62152286Semax while read _line 63152286Semax do 64152286Semax case "$_line" in 65152286Semax \#*) 66152286Semax continue 67152286Semax ;; 68152286Semax 69152286Semax *) 70152286Semax if [ -z "$_line" ]; then 71152286Semax continue; 72152286Semax fi 73152286Semax 74152286Semax 75152286Semax if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then 76152286Semax eval "${_namespace}${_line}" 77152286Semax else 78152286Semax warn "Unable to parse line \"$_line\" in $_file" 79152286Semax _err=1 80152286Semax fi 81152286Semax ;; 82152286Semax esac 83152286Semax done < $_file 84152286Semax 85152286Semax return $_err 86152286Semax} 87152286Semax 88152286Semax############################################################################## 89152286Semax# Setup Bluetooth stack. Create and connect nodes 90152286Semax############################################################################## 91152286Semax 92152286Semaxbluetooth_setup_stack() 93152286Semax{ 94152286Semax dev=$1 95152286Semax shift 96152286Semax hook=$1 97152286Semax shift 98152286Semax 99208060Sdougb # Setup HCI 100152286Semax ngctl mkpeer ${dev}: hci ${hook} drv \ 101152286Semax > /dev/null 2>&1 || return 1 102152286Semax 103152286Semax ngctl name ${dev}:${hook} ${dev}hci \ 104152286Semax > /dev/null 2>&1 || return 1 105152286Semax 106152286Semax ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \ 107152286Semax > /dev/null 2>&1 || return 1 108152286Semax 109152286Semax # Setup L2CAP 110152286Semax ngctl mkpeer ${dev}hci: l2cap acl hci \ 111152286Semax > /dev/null 2>&1 || return 1 112152286Semax 113152286Semax ngctl name ${dev}hci:acl ${dev}l2cap \ 114152286Semax > /dev/null 2>&1 || return 1 115152286Semax 116152286Semax ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \ 117152286Semax > /dev/null 2>&1 || return 1 118152286Semax 119152286Semax # Connect HCI node to the Bluetooth sockets layer 120152286Semax ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \ 121152286Semax > /dev/null 2>&1 || return 1 122152286Semax 123152286Semax # Connect L2CAP node to Bluetooth sockets layer 124152286Semax ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \ 125152286Semax > /dev/null 2>&1 || return 1 126152286Semax 127152286Semax ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \ 128152286Semax > /dev/null 2>&1 || return 1 129152286Semax 130152286Semax # Initilalize HCI node 131152286Semax ${hccontrol} -n ${dev}hci reset \ 132152286Semax > /dev/null 2>&1 || return 1 133152286Semax 134152286Semax ${hccontrol} -n ${dev}hci read_bd_addr \ 135152286Semax > /dev/null 2>&1 || return 1 136152286Semax 137152286Semax ${hccontrol} -n ${dev}hci read_local_supported_features \ 138152286Semax > /dev/null 2>&1 || return 1 139152286Semax 140152286Semax ${hccontrol} -n ${dev}hci read_buffer_size \ 141152286Semax > /dev/null 2>&1 || return 1 142152286Semax 143152286Semax if checkyesno bluetooth_device_discoverable; then 144152286Semax if checkyesno bluetooth_device_connectable; then 145152286Semax ${hccontrol} -n ${dev}hci write_scan_enable 3 \ 146152286Semax > /dev/null 2>&1 || return 1 147152286Semax else 148152286Semax ${hccontrol} -n ${dev}hci write_scan_enable 1 \ 149152286Semax > /dev/null 2>&1 || return 1 150152286Semax fi 151152286Semax else 152152286Semax if checkyesno bluetooth_device_connectable; then 153152286Semax ${hccontrol} -n ${dev}hci write_scan_enable 2 \ 154152286Semax > /dev/null 2>&1 || return 1 155152286Semax else 156152286Semax ${hccontrol} -n ${dev}hci write_scan_enable 0 \ 157152286Semax > /dev/null 2>&1 || return 1 158152286Semax fi 159152286Semax fi 160152286Semax 161152286Semax 162152286Semax ${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \ 163152286Semax > /dev/null 2>&1 || return 1 164152286Semax 165152286Semax if checkyesno bluetooth_device_authentication_enable; then 166152286Semax ${hccontrol} -n ${dev}hci write_authentication_enable 1 \ 167152286Semax > /dev/null 2>&1 || return 1 168152286Semax else 169152286Semax ${hccontrol} -n ${dev}hci write_authentication_enable 0 \ 170152286Semax > /dev/null 2>&1 || return 1 171152286Semax fi 172152286Semax 173152286Semax case "${bluetooth_device_encryption_mode}" in 174152286Semax [Nn][Oo][Nn][Ee]|0) 175152286Semax ${hccontrol} -n ${dev}hci write_encryption_mode 0 \ 176152286Semax > /dev/null 2>&1 || return 1 177152286Semax ;; 178152286Semax 179152286Semax [Pp][2][Pp]|1) 180152286Semax ${hccontrol} -n ${dev}hci write_encryption_mode 1 \ 181152286Semax > /dev/null 2>&1 || return 1 182152286Semax ;; 183152286Semax 184152286Semax [Al][Ll][Ll]|2) 185152286Semax ${hccontrol} -n ${dev}hci write_encryption_mode 2 \ 186152286Semax > /dev/null 2>&1 || return 1 187152286Semax ;; 188152286Semax 189152286Semax *) 190152286Semax warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}" 191152286Semax return 1 192152286Semax ;; 193152286Semax esac 194152286Semax 195152286Semax if checkyesno bluetooth_device_role_switch; then 196152286Semax ${hccontrol} -n ${dev}hci write_node_role_switch 1 \ 197152286Semax > /dev/null 2>&1 || return 1 198152286Semax else 199152286Semax ${hccontrol} -n ${dev}hci write_node_role_switch 0 \ 200152286Semax > /dev/null 2>&1 || return 1 201152286Semax fi 202152286Semax 203152286Semax ${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \ 204152286Semax > /dev/null 2>&1 || return 1 205152286Semax 206152286Semax ${hccontrol} -n ${dev}hci initialize \ 207152286Semax > /dev/null 2>&1 || return 1 208152286Semax 209152286Semax return 0 210152286Semax} 211152286Semax 212152286Semax############################################################################## 213152286Semax# Shutdown Bluetooth stack. Destroy all nodes 214152286Semax############################################################################## 215152286Semax 216152286Semaxbluetooth_shutdown_stack() 217152286Semax{ 218152286Semax dev=$1 219152286Semax 220152286Semax ngctl shutdown ${dev}hci: > /dev/null 2>&1 221152286Semax ngctl shutdown ${dev}l2cap: > /dev/null 2>&1 222152286Semax 223152286Semax return 0 224152286Semax} 225152286Semax 226152286Semax############################################################################## 227152286Semax# bluetooth_start() 228152286Semax############################################################################## 229152286Semax 230152286Semaxbluetooth_start() 231152286Semax{ 232165664Syar local _file 233165664Syar 234152286Semax dev=$1 235152286Semax 236152286Semax # Try to figure out device type by looking at device name 237152286Semax case "${dev}" in 238180618Smarcel # uartX - serial/UART Bluetooth device 239180618Smarcel uart*) 240165683Syar load_kld ng_h4 || return 1 241152286Semax 242152286Semax hook="hook" 243152286Semax 244152286Semax # Obtain unit number from device. 245180618Smarcel unit=`expr ${dev} : 'uart\([0-9]\{1,\}\)'` 246152286Semax if [ -z "${unit}" ]; then 247180618Smarcel err 1 "Unable to get uart unit number: ${dev}" 248152286Semax fi 249152286Semax 250180618Smarcel ${hcseriald} -f /dev/cuau${unit} -n ${dev} 251152286Semax sleep 1 # wait a little bit 252152286Semax 253152286Semax if [ ! -f "/var/run/hcseriald.${dev}.pid" ]; then 254152286Semax err 1 "Unable to start hcseriald on ${dev}" 255152286Semax fi 256152286Semax ;; 257152286Semax 258152286Semax # 3Com Bluetooth Adapter 3CRWB60-A 259152286Semax btccc*) 260152286Semax hook="hook" 261152286Semax 262152286Semax # Obtain unit number from device. 263152286Semax unit=`expr ${dev} : 'btccc\([0-9]\{1,\}\)'` 264152286Semax if [ -z "${unit}" ]; then 265152286Semax err 1 "Unable to get bt3c unit number: ${dev}" 266152286Semax fi 267152286Semax ;; 268152286Semax 269152286Semax # USB Bluetooth adapters 270152286Semax ubt*) 271152286Semax hook="hook" 272152286Semax 273152286Semax # Obtain unit number from device. 274152286Semax unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'` 275152286Semax if [ -z "${unit}" ]; then 276152286Semax err 1 "Unable to get ubt unit number: ${dev}" 277152286Semax fi 278152286Semax ;; 279152286Semax 280152286Semax # Unknown 281152286Semax *) 282152286Semax err 1 "Unsupported device: ${dev}" 283152286Semax ;; 284152286Semax esac 285152286Semax 286208060Sdougb # Be backward compatible and setup reasonable defaults 287152286Semax bluetooth_device_authentication_enable="0" 288152286Semax bluetooth_device_class="ff:01:0c" 289152286Semax bluetooth_device_connectable="1" 290152286Semax bluetooth_device_discoverable="1" 291152286Semax bluetooth_device_encryption_mode="0" 292152286Semax bluetooth_device_hci_debug_level="3" 293152286Semax bluetooth_device_l2cap_debug_level="3" 294152286Semax bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})" 295152286Semax bluetooth_device_role_switch="1" 296152286Semax 297152286Semax # Load default device configuration parameters 298152286Semax _file="/etc/defaults/bluetooth.device.conf" 299152286Semax 300152286Semax if ! bluetooth_read_conf $_file bluetooth_device_ ; then 301152286Semax err 1 "Unable to read default Bluetooth configuration from $_file" 302152286Semax fi 303152286Semax 304152286Semax # Load device specific overrides 305152286Semax _file="/etc/bluetooth/$dev.conf" 306152286Semax 307152286Semax if ! bluetooth_read_conf $_file bluetooth_device_ ; then 308152286Semax err 1 "Unable to read Bluetooth device configuration from $_file" 309152286Semax fi 310152286Semax 311152286Semax # Setup stack 312152286Semax if ! bluetooth_setup_stack ${dev} ${hook} ; then 313152286Semax bluetooth_shutdown_stack $dev 314152286Semax err 1 "Unable to setup Bluetooth stack for device ${dev}" 315152286Semax fi 316208060Sdougb 317152286Semax return 0 318152286Semax} 319152286Semax 320152286Semax############################################################################## 321152286Semax# bluetooth_stop() 322152286Semax############################################################################## 323152286Semax 324152286Semaxbluetooth_stop() 325152286Semax{ 326152286Semax dev=$1 327152286Semax 328152286Semax # Try to figure out device type by looking at device name 329152286Semax case "${dev}" in 330180618Smarcel # uartX - serial/UART Bluetooth device 331180618Smarcel uart*) 332152286Semax if [ -f "/var/run/hcseriald.${dev}.pid" ]; then 333152286Semax kill `cat /var/run/hcseriald.${dev}.pid` 334152286Semax sleep 1 # wait a little bit 335152286Semax fi 336152286Semax ;; 337152286Semax 338152286Semax # 3Com Bluetooth Adapter 3CRWB60-A 339152286Semax btccc*) 340152286Semax ;; 341152286Semax 342152286Semax # USB Bluetooth adapters 343152286Semax ubt*) 344152286Semax ;; 345152286Semax 346152286Semax # Unknown 347152286Semax *) 348152286Semax err 1 "Unsupported device: ${dev}" 349152286Semax ;; 350152286Semax esac 351152286Semax 352152286Semax bluetooth_shutdown_stack ${dev} 353152286Semax 354152286Semax return 0 355152286Semax} 356152286Semax 357152286Semax############################################################################## 358152286Semax# Start here 359152286Semax############################################################################## 360152286Semax 361152286Semaxload_rc_config $name 362152286Semaxhccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}" 363152286Semaxhcseriald="${bluetooth_hcseriald:-/usr/sbin/hcseriald}" 364152286Semax 365152286Semaxrun_rc_command $* 366152286Semax 367