File:  [NetBSD Developer Wiki] / wikisrc / guide / bluetooth.mdwn
Revision 1.2: download - view: text, annotated - select for diffs
Thu Mar 21 11:11:20 2013 UTC (12 months, 3 weeks ago) by jdf
Branches: MAIN
CVS tags: HEAD
Add TOCs to all chapters.

**Contents**

[[!toc levels=3]]

# Bluetooth on NetBSD

## Introduction

Bluetooth is a digital radio protocol used for short range and low power
communications. NetBSD 4.0 introduced support for the Bluetooth protocol stack,
and some integration of service profiles into the NetBSD device framework.

The lower layers of the Bluetooth protocol stack pertaining to actual radio
links between devices are handled inside the Bluetooth Controller, which
communicates with the Host computer using the *Host Controller Interface* (HCI)
protocol which can be accessed via a raw packet BTPROTO\_HCI socket interface.

Most of the Bluetooth protocols or services layer atop the *Link Layer Control
and Adaptation Protocol (L2CAP)*, which can be accessed via a BTPROTO\_L2CAP
socket interface. This provides sequential packet connections to remote devices,
with up to 64k channels. When an L2CAP channel is opened, the protocol or
service that is required is identified by a *Protocol/Service Multiplexer (PSM)*
value.

Service Discovery in the Bluetooth environment is provided for by the
[sdp(3)](http://netbsd.gw.com/cgi-bin/man-cgi?sdp+3+NetBSD-5.0.1+i386) library
functions and the
[sdpd(8)](http://netbsd.gw.com/cgi-bin/man-cgi?sdpd+8+NetBSD-5.0.1+i386) daemon,
which keeps a database of locally registered services and makes the information
available to remote devices performing queries. The
[sdpquery(1)](http://netbsd.gw.com/cgi-bin/man-cgi?sdpquery+1+NetBSD-5.0.1+i386)
tool can be used to query local and remote service databases.

Security on Bluetooth links can be enabled by encryption and authentication
options to
[btconfig(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btconfig+8+NetBSD-5.0.1+i386)
which apply to all baseband links that a controller makes, or encryption and
authentication can be enabled for individual RFCOMM and L2CAP links as required.
When authentication is requested, a PIN is presented by each side (generally
entered by the operator, some limited input devices have a fixed PIN). The
controller uses this PIN to generate a Link Key and reports this to the Host
which may be asked to produce it to authenticate subsequent connections. On
NetBSD, the
[bthcid(8)](http://netbsd.gw.com/cgi-bin/man-cgi?bthcid+8+NetBSD-5.0.1+i386)
daemon is responsible for storing link keys and responding to Link Key Requests,
and also provides an interface to allow unprivileged users to specify a PIN with
a PIN client, such as
[btpin(1)](http://netbsd.gw.com/cgi-bin/man-cgi?btpin+1+NetBSD-5.0.1+i386).

## Supported Hardware

Because Bluetooth controllers normally use the standard HCI protocol as
specified in the *Bluetooth 2.0 Core* documentation to communicate with the
host, the NetBSD Bluetooth stack is compatible with most controllers, only
requiring an interface driver, with the following drivers available in NetBSD
5.0:

 * [bcsp(4)](http://netbsd.gw.com/cgi-bin/man-cgi?bcsp+4+NetBSD-5.0.1+i386)
   provides a
   [tty(4)](http://netbsd.gw.com/cgi-bin/man-cgi?tty+4+NetBSD-5.0.1+i386) line
   discipline to send and receive BlueCore Serial Protocol packets over a serial
   line as described in the *BlueCore Serial Protocol (BCSP)* specification.
 * [bt3c(4)](http://netbsd.gw.com/cgi-bin/man-cgi?bt3c+4+NetBSD-5.0.1+i386)
   provides an interface to the 3Com Bluetooth PC Card, model 3CRWB6096-A.
 * [btbc(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btbc+4+NetBSD-5.0.1+i386)
   provides support for the AnyCom BlueCard (LSE041, LSE039, LSE139) PCMCIA
   devices.
 * [btuart(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btuart+4+NetBSD-5.0.1+i386)
   provides a
   [tty(4)](http://netbsd.gw.com/cgi-bin/man-cgi?tty+4+NetBSD-5.0.1+i386) line
   discipline to send and receive Bluetooth packets over a serial line as
   described in the *Bluetooth Host Controller Interface [Transport Layer]
   specification, Vol 4 part A*.
 * [sbt(4)](http://netbsd.gw.com/cgi-bin/man-cgi?sbt+4+NetBSD-5.0.1+i386)
   provides support for Secure Digital IO Bluetooth adapters.
 * [ubt(4)](http://netbsd.gw.com/cgi-bin/man-cgi?ubt+4+NetBSD-5.0.1+i386)
   interfaces to all USB Bluetooth controllers conforming to the *HCI USB
   Transport Layer* specification.

If support for the NetBSD Bluetooth stack is enabled in the kernel,
autoconfiguration messages will show up in the
[dmesg(8)](http://netbsd.gw.com/cgi-bin/man-cgi/man?dmesg+8+NetBSD-current)
output, for example:

    bt3c0 at pcmcia0 function 0: <3COM, 3CRWB60-A, Bluetooth PC Card>
    
    ubt0 at uhub1 port 4 configuration 1 interface 0
    ubt0: Cambridge Silicon Radio Bluetooth USB Adapter, rev 2.00/19.58, addr 4
    
    ubt1 at uhub1 port 2 configuration 1 interface 0
    ubt1: Broadcom Belkin Bluetooth Device, rev 1.10/0.01, addr 5

When support is not already compiled in, it can be added to the kernel
configuration file for any platform that supports USB and/or PCMCIA (see
[[Kernel Tuning|guide/tuning]]), using the following declarations, as required:

    # Bluetooth Controller and Device support
    
    pseudo-device   bcsp                   # BlueCore Serial Protocol
    pseudo-device   btuart                 # Bluetooth HCI UART
    
    # Bluetooth PCMCIA Controllers
    bt3c* at pcmcia? function ?             # 3Com 3CRWB6096-A
    btbc* at pcmcia? function ?             # AnyCom BlueCard LSE041/039/139
    
    # Bluetooth SDIO Controllers
    sbt* at sdmmc?
    
    # Bluetooth USB Controllers
    ubt* at uhub? port ?
    
    # Bluetooth Device Hub
    bthub* at bcsp?
    bthub* at bt3c?
    bthub* at btbc?
    bthub* at btuart?
    bthub* at sbt?
    bthub* at ubt?
    
    # Bluetooth HID support
    bthidev* at bthub?
    
    # Bluetooth Mouse
    btms* at bthidev? reportid ?
    wsmouse* at btms? mux 0
    
    # Bluetooth Keyboard
    btkbd* at bthidev? reportid ?
    wskbd* at btkbd? console ? mux 1
    
    # Bluetooth Audio support
    btsco* at bthub?
        

Some older USB Bluetooth dongles based on the Broadcom BCM2033 chip require
firmware to be loaded before they can function, and these devices will be
attached to
[ugen(4)](http://netbsd.gw.com/cgi-bin/man-cgi?ugen+4+NetBSD-5.0.1+i386). Use
the `sysutils/bcmfw` package from the NetBSD Package Collection, to load
firmware and enable these.

## System Configuration

To fully enable Bluetooth services on NetBSD, the following line should be added
to the `/etc/rc.conf` file.

    bluetooth=YES

and either reboot, or execute the following command:

    # /etc/rc.d/bluetooth start

*Note*: Configuration of Bluetooth controllers is done with the
[btconfig(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btconfig+8+NetBSD-5.0.1+i386)
program, and the above argument enables only basic functionality, see the manual
page for other useful options.

**Important**:
[bthcid(8)](http://netbsd.gw.com/cgi-bin/man-cgi?bthcid+8+NetBSD-5.0.1+i386)
*must* be running in order to make authenticated connections with remote
devices, and authentication may be requested by either device.

## Human Interface Devices

Support for *Human Interface Devices (HIDs)*, which operate using the USB HID
protocol over a pair of L2CAP channels is provided by the
[bthidev(4)](http://netbsd.gw.com/cgi-bin/man-cgi?bthidev+4+NetBSD-5.0.1+i386)
driver. Currently, keyboards and mice are catered for, and attach to
[wscons(4)](http://netbsd.gw.com/cgi-bin/man-cgi?wscons+4+NetBSD-5.0.1+i386) as
normal.

### Mice

Bluetooth Mice can be attached to the system with the
[btms(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btms+4+NetBSD-5.0.1+i386) driver,
using
[btdevctl(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btdevctl+8+NetBSD-5.0.1+i386).

First, you must discover the BDADDR of the device. This may be printed on the
box, but the easiest way is to place the device into discoverable mode and
perform a device inquiry with the appropriate controller:

    # btconfig ubt0 inquiry
    Device Discovery on ubt0 .... 1 response
      1: bdaddr 00:14:51:c1:b9:2d (unknown)
       : name "Mighty Mouse"
       : class: [0x002580] Peripheral Mouse <Limited Discoverable>
       : page scan rep mode 0x01
       : page scan period mode 0x02
       : page scan mode 0x00
       : clock offset 6944

For ease of use, you may want to add the address to the `/etc/bluetooth/hosts`
file, so that you can refer to the mouse by alias:

    # echo "00:14:51:c1:b9:2d mouse" >>/etc/bluetooth/hosts

Now, you can query the mouse, which will likely request authentication before it
accepts connections. The fixed PIN should be listed in the documentation, though
`0000` is often used. Set the PIN first using the
[btpin(1)](http://netbsd.gw.com/cgi-bin/man-cgi?btpin+1+NetBSD-5.0.1+i386)
program:

    # btpin -d ubt0 -a mouse -p 0000
    # btdevctl -d ubt0 -a mouse -s HID
    local bdaddr: 00:08:1b:8d:ba:6d
    remote bdaddr: 00:14:51:c1:b9:2d
    link mode: auth
    device type: bthidev
    control psm: 0x0011
    interrupt psm: 0x0013
    Collection page=Generic_Desktop usage=Mouse
      Input id=2 size=1 count=1 page=Button usage=Button_1 Variable, logical range 0..1
      Input id=2 size=1 count=1 page=Button usage=Button_2 Variable, logical range 0..1
      Input id=2 size=1 count=1 page=Button usage=Button_3 Variable, logical range 0..1
      Input id=2 size=1 count=1 page=Button usage=Button_4 Variable, logical range 0..1
      Input id=2 size=4 count=1 page=0x0000 usage=0x0000 Const Variable, logical range 0..1
    Collection page=Generic_Desktop usage=Pointer
      Input id=2 size=8 count=1 page=Generic_Desktop usage=X Variable Relative, logical range -127..127
      Input id=2 size=8 count=1 page=Generic_Desktop usage=Y Variable Relative, logical range -127..127
      Input id=2 size=8 count=1 page=Consumer usage=AC_Pan Variable Relative, logical range -127..127
      Input id=2 size=8 count=1 page=Generic_Desktop usage=Wheel Variable Relative, logical range -127..127
    End collection
      Input id=2 size=8 count=1 page=0x00ff usage=0x00c0 Variable, logical range -127..127
    Feature id=71 size=8 count=1 page=0x0006 usage=0x0020 Variable NoPref Volatile, logical range 0..100
    End collection

This tells you that the mouse has responded to an SDP query, and the device
capabilities are shown. Note that authentication is enabled by default for
Bluetooth mice. You may now attach to the system:

    # btdevctl -d ubt0 -a mouse -s HID -A

which should generate some messages on the system console:

    bthidev0 at bthub0 remote-bdaddr 00:14:51:c1:b9:2d link-mode auth
    btms0 at bthidev1 reportid 2: 4 buttons, W and Z dirs.
    wsmouse1 at btms0 mux 0
    bthidev1: reportid 71 not configured
    bthidev1: connected

and the mouse should work.

The device capabilities are cached by
[btdevctl(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btdevctl+8+NetBSD-5.0.1+i386),
and to reattach the mouse at system startup, place an entry in
`/etc/bluetooth/btdevctl.conf`. The
[bthidev(4)](http://netbsd.gw.com/cgi-bin/man-cgi?bthidev+4+NetBSD-5.0.1+i386)
driver will attempt to connect once, though mice will usually be sleeping and
may require a tap on the shoulder to awaken, in which case they should initiate
the connection to the host computer.

### Keyboards

Bluetooth Keyboards can be attached to the system with the
[btkbd(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btkbd+4+NetBSD-5.0.1+i386)
driver, using
[btdevctl(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btdevctl+8+NetBSD-5.0.1+i386).

First, you must discover the BDADDR of the device. This may be printed on the
box, but the easiest way is to place the device into discoverable mode and
perform a device inquiry with the appropriate controller:

    # btconfig ubt0 inquiry
    Device Discovery on ubt0 .... 1 response
      1: bdaddr 00:0a:95:45:a4:a0 (unknown)
       : name "Apple Wireless Keyboard"
       : class: [0x002540] Peripheral Keyboard <Limited Discoverable>
       : page scan rep mode 0x01
       : page scan period mode 0x00
       : page scan mode 0x00
       : clock offset 18604

For ease of use, you may want to add the address to the `/etc/bluetooth/hosts`
file, so that you can refer to the keyboard by alias:

    # echo "00:0a:95:45:a4:a0 keyboard" >>/etc/bluetooth/hosts

Now, you can query the keyboard, which will likely request authentication before
it accepts connections. The PIN will need to be entered on the keyboard, and we
can generate a random PIN, using the
[btpin(1)](http://netbsd.gw.com/cgi-bin/man-cgi?btpin+1+NetBSD-5.0.1+i386)
program.

    # btpin -d ubt0 -a keyboard -r -l 8
    PIN: 18799632
    # btdevctl -d ubt0 -a keyboard -s HID
    
        < ENTER PIN ON BLUETOOTH KEYBOARD NOW >
    
    local bdaddr: 00:08:1b:8d:ba:6d
    remote bdaddr: 00:0a:95:45:a4:a0
    link mode: encrypt
    device type: bthidev
    control psm: 0x0011
    interrupt psm: 0x0013
    Collection page=Generic_Desktop usage=Keyboard
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_LeftControl Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_LeftShift Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_LeftAlt Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_Left_GUI Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_RightControl Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_RightShift Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_RightAlt Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Keyboard usage=Keyboard_Right_GUI Variable, logical range 0..1
      Input id=1 size=8 count=1 page=0x0000 usage=0x0000 Const, logical range 0..1
     Output id=1 size=1 count=1 page=LEDs usage=Num_Lock Variable, logical range 0..1
     Output id=1 size=1 count=1 page=LEDs usage=Caps_Lock Variable, logical range 0..1
     Output id=1 size=1 count=1 page=LEDs usage=Scroll_Lock Variable, logical range 0..1
     Output id=1 size=1 count=1 page=LEDs usage=Compose Variable, logical range 0..1
     Output id=1 size=1 count=1 page=LEDs usage=Kana Variable, logical range 0..1
     Output id=1 size=3 count=1 page=0x0000 usage=0x0000 Const, logical range 0..1
      Input id=1 size=8 count=6 page=Keyboard usage=No_Event, logical range 0..255
      Input id=1 size=1 count=1 page=Consumer usage=Eject Variable Relative, logical range 0..1
      Input id=1 size=1 count=1 page=Consumer usage=Mute Variable Relative, logical range 0..1
      Input id=1 size=1 count=1 page=Consumer usage=Volume_Up Variable, logical range 0..1
      Input id=1 size=1 count=1 page=Consumer usage=Volume_Down Variable, logical range 0..1
      Input id=1 size=1 count=4 page=0x0000 usage=0x0000 Const, logical range 0..1
    End collection
          

This tells you that the keyboard has responded to an SDP query, and the device
capabilities are shown. Note that encryption is enabled by default, since
encrypted connection support is mandatory for Bluetooth keyboards. You may now
attach to the system:

    # btdevctl -d ubt0 -a keyboard -s HID -A

which should generate some messages on the system console:

    bthidev1 at bthub0 remote-bdaddr 00:0a:95:45:a4:a0 link-mode encrypt
    btkbd0 at bthidev0 reportid 1
    wskbd1 at btkbd0 mux 1
    wskbd1: connecting to wsdisplay0
    bthidev1: connected

and the keyboard should work.

The device capabilities are cached by
[btdevctl(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btdevctl+8+NetBSD-5.0.1+i386),
and to reattach the keyboard at system startup, place an entry in
`/etc/bluetooth/btdevctl.conf`. The
[bthidev(4)](http://netbsd.gw.com/cgi-bin/man-cgi?bthidev+4+NetBSD-5.0.1+i386)
driver will attempt to connect once when attached, but if the keyboard is not
available at that time, you may find that pressing a key will cause it to wake
up and initiate a connection to the last paired host.

## Personal Area Networking

Personal Area Networking services over Bluetooth are provided by the
[btpand(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btpand+8+NetBSD-5.0.1+i386)
daemon which can assume all roles from the PAN profile and connects remote
devices to the system through a
[tap(4)](http://netbsd.gw.com/cgi-bin/man-cgi?tap+4+NetBSD-5.0.1+i386) virtual
Ethernet interface.

### Personal Area Networking User

The "Personal Area Networking User" role is the client that accesses Network
services on another device. For instance, in order to connect to the Internet
via a smart phone with the NAP profile, make sure that the phone is
discoverable, then:

    # btconfig ubt0 inquiry
    Device Discovery from device: ubt0 .... 1 response
      1: bdaddr 00:17:83:30:bd:5e (unknown)
       : name "HTC Touch"
       : class: [0x5a020c] Smart Phone <Networking> <Capturing> <Object Transfer>
        <Telephony>
       : page scan rep mode 0x01
       : clock offset 9769
       : rssi -42
    
    # echo "00:17:83:30:bd:5e phone" >>/etc/bluetooth/hosts

You will see that the phone should have the `<Networking>` flag set in the Class
of Device. Checking for the NAP service:

    # sdpquery -a phone search NAP
    ServiceRecordHandle: 0x00010000
    ServiceClassIDList:
        Network Access Point
    ProtocolDescriptorList:
        L2CAP (PSM 0x000f)
        BNEP (v1.0; IPv4, ARP, IPv6)
    LanguageBaseAttributeIDList:
        en.UTF-8 base 0x0100
    BluetoothProfileDescriptorList:
        Network Access Point, v1.0
    ServiceName: "Network Access Point"
    ServiceDescription: "Bluetooth NAP Service"
    SecurityDescription: None
    NetAccessType: 100Mb Ethernet
    MaxNetAccessRate: 100000

reveals that the NAP service is available and that it provides IPv4, ARP and IPv6 protocols.

Most likely, the phone will request authentication before it allows connections
to the NAP service, so before you make the first connection you may need to
provide a PIN, which can be randomly generated. Then start
[btpand(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btpand+8+NetBSD-5.0.1+i386):

    # btpin -d ubt0 -a phone -r -l 6
    PIN: 862048
    # btpand -d ubt0 -a phone -s NAP
    
        < ENTER PIN ON PHONE NOW >
    
    Searching for NAP service at 00:17:83:30:bd:5e
    Found PSM 15 for service NAP
    Opening connection to service 0x1116 at 00:17:83:30:bd:5e
    Using interface tap0 with addr 00:10:60:e1:50:3d

Finally, you will need to configure the
[tap(4)](http://netbsd.gw.com/cgi-bin/man-cgi?tap+4+NetBSD-5.0.1+i386)
interface, but the phone should have a DHCP server so
[dhcpcd(8)](http://netbsd.gw.com/cgi-bin/man-cgi?dhcpcd+8+NetBSD-5.0.1+i386)
will do that for you.

    # dhcpcd tap0

Now you can surf the World Wide Web, but watch your data usage unless you have a
comprehensive data plan.

## Serial Connections

Serial connections over Bluetooth are provided for by the RFCOMM protocol, which
provides up to 30 channels multiplexed over a single L2CAP channel. This
streamed data protocol can be accessed using the BTPROTO\_RFCOMM socket
interface, or via the
[rfcomm\_sppd(1)](http://netbsd.gw.com/cgi-bin/man-cgi?rfcomm_sppd+1+NetBSD-5.0.1+i386)
program.

For instance, you can make a serial connection to the *Dial Up Networking (DUN)*
service of a mobile phone in order to connect to the Internet with PPP. First
you should discover the BDADDR of the phone, and add this to your
`/etc/bluetooth/hosts` for ease of use. Place the phone into Discoverable mode,
and perform an inquiry from the appropriate controller:

    # btconfig ubt0 inquiry
    Device Discovery from device: ubt0 ..... 1 response
      1: bdaddr 00:16:bc:00:e8:48 (unknown)
       : name "Nokia 6103"
       : class: [0x520204] Cellular Phone <Networking> <Object Transfer> <Telephony>
       : page scan rep mode 0x01
       : page scan period mode 0x02
       : page scan mode 0x00
       : clock offset 30269
    
    # echo "00:16:bc:00:e8:48 phone" >>/etc/bluetooth/hosts

Now, you can query the phone to confirm that it supports the DUN profile:

    # sdpquery -d ubt0 -a phone search DUN
    ServiceRecordHandle: 0x00010003
    ServiceClassIDList:
        Dialup Networking
        Generic Networking
    ProtocolDescriptorList:
        L2CAP
        RFCOMM (channel 1)
    BrowseGroupList:
        Public Browse Root
    LanguageBaseAttributeIDList:
        en.UTF-8 base 0x0100
    BluetoothProfileDescriptorList:
        Dialup Networking, v1.0
    ServiceName: "Dial-up networking"

Most likely, the phone will request authentication before it allows connections
to the DUN service, so before you make the first connection you may need to
provide a PIN, which can be randomly generated. You can use `rfcomm_sppd` in
stdio mode to check that the connection is working ok, press `^C` to
disconnect and return to the shell, for example:

    # btpin -d ubt0 -a phone -r -l 6
    PIN: 904046
    # rfcomm_sppd -d ubt0 -a phone -s DUN
    
        < ENTER PIN ON PHONE NOW >
    
    rfcomm_sppd[24635]: Starting on stdio...
    at
    OK
    ati
    Nokia
    
    OK
    ati3
    Nokia 6103
    
    OK
    at&v
    ACTIVE PROFILE:
    E1 Q0 V1 X5 &C1 &D2 &S0 &Y0
    +CMEE=0 +CSTA=129 +CBST=0,0,1 +CRLP=61,61,48,6 +CR=0 +CRC=0 +CLIP=0,2
    +CLIR=0,2 +CSNS=0 +CVHU=1 +DS=0,0,2048,32 +DR=0 +ILRR=0
    +CHSN=0,0,0,0 +CHSR=0 +CPBS="SM"
    S00:000 S01:000 S02:043 S03:013 S04:010 S05:008 S07:060 S08:002
    S10:100 S12:050 S25:000
    
    OK
    ^C
    rfcomm_sppd[24635]: Completed on stdio

To have [pppd(8)](http://netbsd.gw.com/cgi-bin/man-cgi?pppd+8+NetBSD-5.0.1+i386)
connect to the DUN service of your phone automatically when making outbound
connections, add the following line to the `/etc/ppp/options` file in place of
the normal tty declaration:

    pty "rfcomm_sppd -d ubt0 -a phone -s DUN -m encrypt"

## Audio

Isochronous (SCO) Audio connections may be created on a baseband radio link
using either the BTPROTO\_SCO socket interface, or the
[btsco(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btsco+4+NetBSD-5.0.1+i386) audio
device driver. While the specification says that up to three such links can be
made between devices, the current Bluetooth stack can only handle one with any
dignity.

**Important**: When using SCO Audio with USB Bluetooth controllers, you will
need to enable isochronous data, and calculate the MTU that the device will use,
see [ubt(4)](http://netbsd.gw.com/cgi-bin/man-cgi?ubt+4+NetBSD-5.0.1+i386) and
[btconfig(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btconfig+8+NetBSD-5.0.1+i386).

*Note*: SCO Audio does not work properly with the
[bt3c(4)](http://netbsd.gw.com/cgi-bin/man-cgi?bt3c+4+NetBSD-5.0.1+i386) driver,
use a USB controller for best results.

*Note*: SCO Audio will not work with
[ehci(4)](http://netbsd.gw.com/cgi-bin/man-cgi?ehci+4+NetBSD-5.0.1+i386) USB
controllers, since support for Isochronous data over EHCI is missing in NetBSD.

### SCO Audio Headsets

Audio connections to Bluetooth Headsets are possible using the
[btsco(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btsco+4+NetBSD-5.0.1+i386) audio
driver, and the
[bthset(1)](http://netbsd.gw.com/cgi-bin/man-cgi?bthset+1+NetBSD-5.0.1+i386)
program. First, you need to discover the BDADDR of the headset, and will
probably wish to make an alias in your `/etc/bluetooth/hosts` file for ease of
use. Place the headset into discoverable mode and perform an inquiry with the
appropriate controller:

    # btconfig ubt0 inquiry
    Device Discovery from device: ubt0 ..... 1 response
     1: bdaddr 00:07:a4:23:10:83 (unknown)
      : name "JABRA 250"
      : class: [0x200404] Wearable Headset <Audio>
      : page scan rep mode 0x01
      : page scan period mode 0x00
      : page scan mode 0x00
      : clock offset 147
    
    # echo "00:07:a4:23:10:83 headset" >>/etc/bluetooth/hosts

You will need to pair with the headset the first time you connect, the fixed PIN
should be listed in the manual (often, `0000` is used).
[btdevctl(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btdevctl+8+NetBSD-5.0.1+i386)
will query the device and attach the
[btsco(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btsco+4+NetBSD-5.0.1+i386) audio
driver.

    # btpin -d ubt0 -a headset -p 0000
    # btdevctl -d ubt0 -a headset -s HSET -A
    local bdaddr: 00:08:1b:8d:ba:6d
    remote bdaddr: 00:07:a4:23:10:83
    link mode: none
    device type: btsco
    mode: connect
    channel: 1

which should generate some messages on the system console:

    btsco0 at bthub0 remote-bdaddr 00:07:a4:23:10:83 channel 1
    audio1 at btsco0: full duplex

In order to use the audio device, you will need to open a control connection
with
[bthset(1)](http://netbsd.gw.com/cgi-bin/man-cgi?bthset+1+NetBSD-5.0.1+i386)
which conveys volume information to the mixer device.

    # bthset -m /dev/mixer1 -v
    Headset Info:
            mixer: /dev/mixer1
            laddr: 00:08:1b:8d:ba:6d
            raddr: 00:07:a4:23:10:83
            channel: 1
            vgs.dev: 0, vgm.dev: 1

and you should now be able to transfer 8khz samples to and from `/dev/audio1`
using any program that supports audio, such as
[audioplay(1)](http://netbsd.gw.com/cgi-bin/man-cgi?audioplay+1+NetBSD-5.0.1+i386)
or
[audiorecord(1)](http://netbsd.gw.com/cgi-bin/man-cgi?audiorecord+1+NetBSD-5.0.1+i386).
Adjusting the mixer values should work when playing though you may find that
when opening a connection, the headset will reset the volume to the last known
settings.

    # audiorecord -d /dev/audio1 voice.au
            < TALK NONSENSE NOW >
    ^C
    # audioplay -d /dev/audio voice.au
            < THATS REALLY WHAT YOU SOUND LIKE >
    # audioplay -d /dev/audio1 voice.au
            < IN THE HEADSET >

The device capabilities are cached by
[btdevctl(8)](http://netbsd.gw.com/cgi-bin/man-cgi?btdevctl+8+NetBSD-5.0.1+i386),
and to reattach the
[btsco(4)](http://netbsd.gw.com/cgi-bin/man-cgi?btsco+4+NetBSD-5.0.1+i386)
driver at system startup, add an entry to `/etc/bluetooth/btdevctl.conf`.

### SCO Audio Handsfree

Audio connections to Bluetooth mobile phones using the Handsfree profile are
possible with the `comms/bthfp` program from the NetBSD Package Collection.

First, you need to discover the BDADDR of the phone, and will probably wish to
make an alias in your `/etc/bluetooth/hosts` file for ease of use. Place the
phone into discoverable mode and perform an inquiry with the appropriate
controller:

    # btconfig ubt0 inquiry
    Device Discovery from device: ubt0 ..... 1 response
      1: bdaddr 00:16:bc:00:e8:48 (unknown)
       : name "Nokia 6103"
       : class: [0x520204] Cellular Phone <Networking;gt; <Object Transfer;gt; <Telephony;gt;
       : page scan rep mode 0x01
       : page scan period mode 0x02
       : page scan mode 0x00
       : clock offset 10131
    
    # echo "00:16:bc:00:e8:48 phone" >>/etc/bluetooth/hosts

Now, you should be able to query the phone to confirm that it supports the
Handsfree profile:

    # sdpquery -d ubt0 -a phone search HF
    ServiceRecordHandle: 0x00010006
    ServiceClassIDList:
        Handsfree Audio Gateway
        Generic Audio
    ProtocolDescriptorList:
        L2CAP
        RFCOMM (channel 13)
    BrowseGroupList:
        Public Browse Root
    LanguageBaseAttributeIDList:
        en.UTF-8 base 0x0100
    BluetoothProfileDescriptorList:
        Handsfree, v1.5
    ServiceName: "Voice Gateway"
    Network: Ability to reject a call
    SupportedFeatures:
        3 Way Calling
        Echo Cancellation/Noise Reduction
        Voice Recognition
        In-band Ring Tone

and you will be able to use the bthfp program to access the Handsfree profile.
The first time you connect, you may need to use a PIN to pair with the phone,
which can be generated randomly by
[btpin(1)](http://netbsd.gw.com/cgi-bin/man-cgi?btpin+1+NetBSD-5.0.1+i386):

    # btpin -d ubt0 -a phone -r -l 6
    PIN: 349163
    # bthfp -d ubt0 -a phone -v
    
          < ENTER PIN ON PHONE NOW >
    Handsfree channel: 13
    Press ? for commands
    Connecting.. ok
    < AT+BRSF=20
    > +BRSF: 47
    Features: [0x002f] <3 way calling> <EC/NR> <Voice Recognition> <In-band ringtone> <reject ability>
    > OK
    < AT+CIND=?
    > +CIND: ("call",(0,1)),("service",(0,1)),("call_setup",(0-3)),("callsetup",(0-3))
    > OK
    < AT+CIND?
    > +CIND: 0,1,0,0
    > OK
    < AT+CMER=3,0,0,1
    > OK
    < AT+CLIP=1
    > OK
    Service Level established

When the phone rings, just press `a` to answer, and audio should be routed
through the `/dev/audio` device. Note that you will need a microphone connected
in order to speak to the remote party.

## Object Exchange

NetBSD does not currently have any native OBEX capability, see the
`comms/obexapp` or `comms/obexftp` packages from the NetBSD Package Collection.

## Troubleshooting

When nothing seems to be happening, it may be useful to try the hcidump program
from the `sysutils/netbt-hcidump` package in the NetBSD Package Collection. This
has the capability to dump packets entering and leaving Bluetooth controllers on
NetBSD, which is greatly helpful in pinpointing problems.


CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb