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