sco - Man Page

SCO transport

Synopsis

#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sco.h>

sco_socket = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);

Description

The SCO logical transport, is a symmetric, point-to-point transport between the Central and a specific Peripheral. The SCO logical transport reserves slots and can therefore be considered as a circuit-switched connection between the Central and the Peripheral.

In addition to the reserved slots, when eSCO is supported, a retransmission window follows immediately after. Together, the reserved slots and the retransmission window form the complete eSCO window.

Socket Address

struct sockaddr_sco {
    sa_family_t     sco_family;
    bdaddr_t        sco_bdaddr;
};

Example:

struct sockaddr_sco addr;

memset(&addr, 0, sizeof(addr));
addr.sco_family = AF_BLUETOOTH;
bacpy(&addr.sco_bdaddr, bdaddr);

Socket Options

The socket options listed below can be set by using setsockopt(2) and read with getsockopt(2) with the socket level set to SOL_BLUETOOTH.

BT_SECURITY (since Linux 2.6.30)

Channel security level, possible values:

ValueSecurity LevelLink Key TypeEncryption
BT_SECURITY_SDP0 (SDP Only)NoneNot required
BT_SECURITY_LOW1 (Low)UnauthenticatedNot required
BT_SECURITY_MEDIUM2 (Medium - default)UnauthenticatedDesired
BT_SECURITY_HIGH3 (High)AuthenticatedRequired
BT_SECURITY_FIPS (since Linux 3.15)4 (Secure Only)Authenticated (P-256 based Secure Simple Pairing and Secure Authentication)Required

Example:

int level = BT_SECURITY_HIGH;
int err = setsockopt(sco_socket, SOL_BLUETOOTH, BT_SECURITY, &level,
                     sizeof(level));
if (err == -1) {
    perror("setsockopt");
    return 1;
}

BT_DEFER_SETUP (since Linux 2.6.30)

Channel defer connection setup, this control if the connection procedure needs to be authorized by userspace before responding which allows authorization at profile level, possible values:

ValueDescriptionAuthorization
0Disable (default)Not required
1EnableRequired

Example:

int defer_setup = 1;
int err = setsockopt(sco_socket, SOL_BLUETOOTH, BT_DEFER_SETUP,
                     &defer_setup, sizeof(defer_setup));
if (err == -1) {
    perror("setsockopt");
    return err;
}

err = listen(sco_socket, 5);
if (err) {
    perror("listen");
    return err;
}

struct sockaddr_sco remote_addr = {0};
socklen_t addr_len = sizeof(remote_addr);
int new_socket = accept(sco_socket, (struct sockaddr*)&remote_addr,
                        &addr_len);
if (new_socket < 0) {
    perror("accept");
    return new_socket;
}

/* To complete the connection setup of new_socket read 1 byte */
char c;
struct pollfd pfd;

memset(&pfd, 0, sizeof(pfd));
pfd.fd = new_socket;
pfd.events = POLLOUT;

err = poll(&pfd, 1, 0);
if (err) {
    perror("poll");
    return err;
}

if (!(pfd.revents & POLLOUT)) {
    err = read(sk, &c, 1);
    if (err < 0) {
        perror("read");
        return err;
    }
}

BT_VOICE (since Linux 3.11)

Transport voice settings, possible values:

struct bt_voice {
    uint16_t setting;
};
DefineValueDescription
BT_VOICE_TRANSPARENT0x0003Transparent output
BT_VOICE_CVSD_16BIT0x0060C-VSD output PCM 16-bit input
BT_VOICE_TRANSPARENT_16BIT0x0063Transparent output PCM 16-bit input

Example:

struct bt_voice voice;

memset(&voice, 0, sizeof(voice));
voice.setting = BT_VOICE_TRANSPARENT;
int err = setsockopt(sco_socket, SOL_BLUETOOTH, BT_VOICE, &voice,
                     sizeof(voice));
if (err == -1) {
    perror("setsockopt");
    return 1;
}

BT_PHY (since Linux 5.10)

Transport supported PHY(s), possible values:

DefineValueDescription
BT_PHY_BR_1M_1SLOTBIT 0BR 1Mbps 1SLOT
BT_PHY_BR_1M_3SLOTBIT 1BR 1Mbps 3SLOT
BT_PHY_BR_2M_1SLOTBIT 3EDR 2Mbps 1SLOT
BT_PHY_BR_2M_3SLOTBIT 4EDR 2Mbps 3SLOT
BT_PHY_BR_3M_1SLOTBIT 6EDR 3Mbps 1SLOT
BT_PHY_BR_3M_3SLOTBIT 7EDR 3Mbps 3SLOT

BT_CODEC (since Linux 5.14)

Transport codec offload, possible values:

struct bt_codec {
    uint8_t id;
    uint16_t cid;
    uint16_t vid;
    uint8_t data_path_id;
    uint8_t num_caps;
    struct codec_caps {
        uint8_t len;
        uint8_t data[];
    } caps[];
} __attribute__((packed));

struct bt_codecs {
    uint8_t num_codecs;
    struct bt_codec codecs[];
} __attribute__((packed));

Example:

char buffer[sizeof(struct bt_codecs) + sizeof(struct bt_codec)];
struct bt_codec *codecs = (void *)buffer;

memset(codecs, 0, sizeof(codecs));
codec->num_codecs = 1;
codecs->codecs[0].id = 0x05;
codecs->codecs[0].data_path_id = 1;

int err = setsockopt(sco_socket, SOL_BLUETOOTH, BT_CODEC, codecs,
                     sizeof(buffer));
if (err == -1) {
    perror("setsockopt");
    return 1;
}

Resources

<http://www.bluez.org>

Reporting Bugs

<linux-bluetooth@vger.kernel.org>

See Also

socket(7), scotest(1)

Info

March 2025 BlueZ Linux System Administration