]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - etc/rc.d/bluetooth
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / etc / rc.d / bluetooth
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
35 name="bluetooth"
36 rcvar=
37 start_cmd="bluetooth_start"
38 stop_cmd="bluetooth_stop"
39
40 ##############################################################################
41 # Read and parse Bluetooth device configuration file
42 ##############################################################################
43
44 bluetooth_read_conf()
45 {
46         local _err _file _line _namespace
47
48         _file=$1
49         _namespace=$2
50         _err=0
51
52         if [ ! -e $_file ]; then
53                 return 0
54         fi
55
56         if [ ! -f $_file -o ! -r $_file ]; then
57                 err 1 "Bluetooth configuration file $_file is not a file or not readable"
58         fi
59
60         while read _line
61         do
62                 case "$_line" in
63                 \#*)
64                         continue
65                         ;;
66
67                 *)
68                         if [ -z "$_line" ]; then
69                                 continue;
70                         fi
71
72
73                         if expr "$_line" : "[a-zA-Z0-9_]*=" > /dev/null 2>&1; then
74                                 eval "${_namespace}${_line}"
75                         else
76                                 warn "Unable to parse line \"$_line\" in $_file"
77                                 _err=1
78                         fi
79                         ;;
80                 esac
81         done < $_file
82
83         return $_err
84 }
85
86 ##############################################################################
87 # Setup Bluetooth stack. Create and connect nodes
88 ##############################################################################
89
90 bluetooth_setup_stack()
91 {
92         dev=$1
93         shift
94         hook=$1
95         shift
96
97         # Setup HCI 
98         ngctl mkpeer ${dev}: hci ${hook} drv \
99                 > /dev/null 2>&1 || return 1
100
101         ngctl name ${dev}:${hook} ${dev}hci \
102                 > /dev/null 2>&1 || return 1
103
104         ngctl msg ${dev}hci: set_debug ${bluetooth_device_hci_debug_level} \
105                 > /dev/null 2>&1 || return 1
106
107         # Setup L2CAP
108         ngctl mkpeer ${dev}hci: l2cap acl hci \
109                 > /dev/null 2>&1 || return 1
110
111         ngctl name ${dev}hci:acl ${dev}l2cap \
112                 > /dev/null 2>&1 || return 1
113
114         ngctl msg ${dev}l2cap: set_debug ${bluetooth_device_l2cap_debug_level} \
115                 > /dev/null 2>&1 || return 1
116
117         # Connect HCI node to the Bluetooth sockets layer
118         ngctl connect ${dev}hci: btsock_hci_raw: raw ${dev}raw \
119                 > /dev/null 2>&1 || return 1
120
121         # Connect L2CAP node to Bluetooth sockets layer
122         ngctl connect ${dev}l2cap: btsock_l2c_raw: ctl ${dev}ctl \
123                 > /dev/null 2>&1 || return 1
124
125         ngctl connect ${dev}l2cap: btsock_l2c: l2c ${dev}l2c \
126                 > /dev/null 2>&1 || return 1
127
128         # Initilalize HCI node
129         ${hccontrol} -n ${dev}hci reset \
130                 > /dev/null 2>&1 || return 1
131
132         ${hccontrol} -n ${dev}hci read_bd_addr \
133                 > /dev/null 2>&1 || return 1
134
135         ${hccontrol} -n ${dev}hci read_local_supported_features \
136                 > /dev/null 2>&1 || return 1
137
138         ${hccontrol} -n ${dev}hci read_buffer_size \
139                 > /dev/null 2>&1 || return 1
140
141         if checkyesno bluetooth_device_discoverable; then
142                 if checkyesno bluetooth_device_connectable; then
143                         ${hccontrol} -n ${dev}hci write_scan_enable 3 \
144                                 > /dev/null 2>&1 || return 1
145                 else
146                         ${hccontrol} -n ${dev}hci write_scan_enable 1 \
147                                 > /dev/null 2>&1 || return 1
148                 fi
149         else
150                 if checkyesno bluetooth_device_connectable; then
151                         ${hccontrol} -n ${dev}hci write_scan_enable 2 \
152                                 > /dev/null 2>&1 || return 1
153                 else
154                         ${hccontrol} -n ${dev}hci write_scan_enable 0 \
155                                 > /dev/null 2>&1 || return 1
156                 fi
157         fi
158
159
160         ${hccontrol} -n ${dev}hci write_class_of_device ${bluetooth_device_class} \
161                 > /dev/null 2>&1 || return 1
162
163         if checkyesno bluetooth_device_authentication_enable; then
164                 ${hccontrol} -n ${dev}hci write_authentication_enable 1 \
165                         > /dev/null 2>&1 || return 1
166         else
167                 ${hccontrol} -n ${dev}hci write_authentication_enable 0 \
168                         > /dev/null 2>&1 || return 1
169         fi
170
171         case "${bluetooth_device_encryption_mode}" in
172         [Nn][Oo][Nn][Ee]|0)
173                 ${hccontrol} -n ${dev}hci write_encryption_mode 0 \
174                         > /dev/null 2>&1 || return 1
175                 ;;
176
177         [Pp][2][Pp]|1)
178                 ${hccontrol} -n ${dev}hci write_encryption_mode 1 \
179                         > /dev/null 2>&1 || return 1
180                 ;;
181
182         [Al][Ll][Ll]|2)
183                 ${hccontrol} -n ${dev}hci write_encryption_mode 2 \
184                         > /dev/null 2>&1 || return 1
185                 ;;
186
187         *)
188                 warn "Unsupported encryption mode ${bluetooth_device_encryption_mode} for device ${dev}"
189                 return 1
190                 ;;
191         esac
192
193         if checkyesno bluetooth_device_role_switch; then
194                 ${hccontrol} -n ${dev}hci write_node_role_switch 1 \
195                         > /dev/null 2>&1 || return 1
196         else
197                 ${hccontrol} -n ${dev}hci write_node_role_switch 0 \
198                         > /dev/null 2>&1 || return 1
199         fi
200
201         ${hccontrol} -n ${dev}hci change_local_name "${bluetooth_device_local_name}" \
202                 > /dev/null 2>&1 || return 1
203
204         ${hccontrol} -n ${dev}hci initialize \
205                 > /dev/null 2>&1 || return 1
206
207         return 0
208 }
209
210 ##############################################################################
211 # Shutdown Bluetooth stack. Destroy all nodes
212 ##############################################################################
213
214 bluetooth_shutdown_stack()
215 {
216         dev=$1
217
218         ngctl shutdown ${dev}hci: > /dev/null 2>&1
219         ngctl shutdown ${dev}l2cap: > /dev/null 2>&1
220
221         return 0
222 }
223
224 ##############################################################################
225 # bluetooth_start()
226 ##############################################################################
227
228 bluetooth_start()
229 {
230         local _file
231
232         dev=$1
233
234         # Automatically load modules
235         kldload ng_bluetooth > /dev/null 2>&1
236         kldload ng_hci > /dev/null 2>&1
237         kldload ng_l2cap > /dev/null 2>&1
238         kldload ng_btsocket > /dev/null 2>&1
239
240         # Try to figure out device type by looking at device name
241         case "${dev}" in
242         # sioX - serial/UART Bluetooth device
243         sio*)
244                 kldload ng_h4 > /dev/null 2>&1
245
246                 hook="hook"
247
248                 # Obtain unit number from device.
249                 unit=`expr ${dev} : 'sio\([0-9]\{1,\}\)'`
250                 if [ -z "${unit}" ]; then
251                         err 1 "Unable to get sio unit number: ${dev}"
252                 fi
253
254                 ${hcseriald} -f /dev/cuad${unit} -n ${dev}
255                 sleep 1 # wait a little bit
256
257                 if [ ! -f "/var/run/hcseriald.${dev}.pid" ]; then
258                         err 1 "Unable to start hcseriald on ${dev}"
259                 fi
260                 ;;
261
262         # 3Com Bluetooth Adapter 3CRWB60-A
263         btccc*)
264                 hook="hook"
265
266                 # Obtain unit number from device.
267                 unit=`expr ${dev} : 'btccc\([0-9]\{1,\}\)'`
268                 if [ -z "${unit}" ]; then
269                         err 1 "Unable to get bt3c unit number: ${dev}"
270                 fi
271                 ;;
272
273         # USB Bluetooth adapters
274         ubt*)
275                 hook="hook"
276
277                 # Obtain unit number from device.
278                 unit=`expr ${dev} : 'ubt\([0-9]\{1,\}\)'`
279                 if [ -z "${unit}" ]; then
280                         err 1 "Unable to get ubt unit number: ${dev}"
281                 fi
282                 ;;
283
284         # Unknown
285         *)
286                 err 1 "Unsupported device: ${dev}"
287                 ;;
288         esac
289
290         # Be backward compatible and setup reasonable defaults 
291         bluetooth_device_authentication_enable="0"
292         bluetooth_device_class="ff:01:0c"
293         bluetooth_device_connectable="1"
294         bluetooth_device_discoverable="1"
295         bluetooth_device_encryption_mode="0"
296         bluetooth_device_hci_debug_level="3"
297         bluetooth_device_l2cap_debug_level="3"
298         bluetooth_device_local_name="`/usr/bin/uname -n` (${dev})"
299         bluetooth_device_role_switch="1"
300
301         # Load default device configuration parameters
302         _file="/etc/defaults/bluetooth.device.conf"
303
304         if ! bluetooth_read_conf $_file bluetooth_device_ ; then
305                 err 1 "Unable to read default Bluetooth configuration from $_file"
306         fi
307
308         # Load device specific overrides
309         _file="/etc/bluetooth/$dev.conf"
310
311         if ! bluetooth_read_conf $_file bluetooth_device_ ; then
312                 err 1 "Unable to read Bluetooth device configuration from $_file"
313         fi
314
315         # Setup stack
316         if ! bluetooth_setup_stack ${dev} ${hook} ; then
317                 bluetooth_shutdown_stack $dev
318                 err 1 "Unable to setup Bluetooth stack for device ${dev}"
319         fi
320                 
321         return 0
322 }
323
324 ##############################################################################
325 # bluetooth_stop()
326 ##############################################################################
327
328 bluetooth_stop()
329 {
330         dev=$1
331
332         # Try to figure out device type by looking at device name
333         case "${dev}" in
334         # sioX - serial/UART Bluetooth device
335         sio*)
336                 if [ -f "/var/run/hcseriald.${dev}.pid" ]; then
337                         kill `cat /var/run/hcseriald.${dev}.pid`
338                         sleep 1 # wait a little bit
339                 fi
340                 ;;
341
342         # 3Com Bluetooth Adapter 3CRWB60-A
343         btccc*)
344                 ;;
345
346         # USB Bluetooth adapters
347         ubt*)
348                 ;;
349
350         # Unknown
351         *)
352                 err 1 "Unsupported device: ${dev}"
353                 ;;
354         esac
355
356         bluetooth_shutdown_stack ${dev}
357
358         return 0
359 }
360
361 ##############################################################################
362 # Start here
363 ##############################################################################
364
365 load_rc_config $name
366 hccontrol="${bluetooth_hccontrol:-/usr/sbin/hccontrol}"
367 hcseriald="${bluetooth_hcseriald:-/usr/sbin/hcseriald}"
368
369 run_rc_command $*
370