linux - BlueZ scotest 应用程序和 Linux 配置无法连接到 SCO 套接字

标签 linux bluetooth linux-kernel kernel bluez

我在内核 3.4.79+ 的嵌入式 Linux 项目上使用 BlueZ 4.101。正常的蓝牙操作效果很好,我可以在我的设备上使用许多耳机来传输音频。现在我正在努力实现蓝牙合规性,因此我正在使用蓝牙 SIG 的 USB PTS Dongle。我通过了所有测试,除了部分来电测试,我需要在使用 PTS 加密狗接受调用后打开 SCO 连接。

SCO 连接尝试适用于耳机,但不适用于 PTS 加密狗。错误是从 bluetoothd 给出的:

bluetoothd[6306]: audio/headset.c:headset_set_state() State changed /org/bluez/6306/hci0/dev_00_1B_DC_07_30_40: HEADSET_STATE_PLAY_IN_PROGRESS -> HEADSET_STATE_CONNECTED
bluetoothd[6306]: audio/headset.c:headset_set_state() State changed /org/bluez/6306/hci0/dev_00_1B_DC_07_30_40: HEADSET_STATE_CONNECTED -> HEADSET_STATE_PLAY_IN_PROGRESS
bluetoothd[6306]: Protocol not supported (93)

所以我从 BlueZ 的测试目录编译了 scotest 并在连接到加密狗后运行它并得到了相同的结果:

# ./scotest -s -b HELLO 00:1B:DC:07:30:40
scotest[1687]: Can't connect: Protocol not supported (93)
scotest[1687]: Can't connect to the server: Protocol not supported (93)

这是 scotest.c 中的 do_connect 函数,它失败了:

static int do_connect(char *svr)
{
    struct sockaddr_sco addr;
    struct sco_conninfo conn;
    socklen_t optlen;
    int sk;

    /* Create socket */
    sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
    if (sk < 0) {
        syslog(LOG_ERR, "Can't create socket: %s (%d)",
                            strerror(errno), errno);
        return -1;
    }

    /* Bind to local address */
    memset(&addr, 0, sizeof(addr));
    addr.sco_family = AF_BLUETOOTH;
    bacpy(&addr.sco_bdaddr, &bdaddr);

    if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        syslog(LOG_ERR, "Can't bind socket: %s (%d)",
                            strerror(errno), errno);
        goto error;
    }

    /* Connect to remote device */
    memset(&addr, 0, sizeof(addr));
    addr.sco_family = AF_BLUETOOTH;
    str2ba(svr, &addr.sco_bdaddr);

    if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        syslog(LOG_ERR, "Can't connect: %s (%d)",
                            strerror(errno), errno);
        goto error;
    }

    /* Get connection information */
    memset(&conn, 0, sizeof(conn));
    optlen = sizeof(conn);

    if (getsockopt(sk, SOL_SCO, SCO_CONNINFO, &conn, &optlen) < 0) {
        syslog(LOG_ERR, "Can't get SCO connection information: %s (%d)",
                            strerror(errno), errno);
        goto error;
    }

    syslog(LOG_INFO, "Connected [handle %d, class 0x%02x%02x%02x]",
        conn.hci_handle,
        conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]);

    return sk;

error:
    close(sk);
    return -1;
}

我在内核配置中缺少什么来允许 PTS 加密狗在打开 SCO 连接的情况下进入播放状态?

这是我的 Linux .config(我使用 backports-3.13.2-1 来支持 TI WL1271 BT/WiFi 模块):

CPTCFG_IPV6_SUBTREES=y
CPTCFG_NFT_RBTREE=m
CPTCFG_BRIDGE_NF_EBTABLES=m
CPTCFG_BRIDGE_EBT_BROUTE=m
CPTCFG_BRIDGE_EBT_T_FILTER=m
CPTCFG_BRIDGE_EBT_T_NAT=m
CPTCFG_BRIDGE_EBT_802_3=m
CPTCFG_BRIDGE_EBT_AMONG=m
CPTCFG_BRIDGE_EBT_ARP=m
CPTCFG_BRIDGE_EBT_IP=m
CPTCFG_BRIDGE_EBT_IP6=m
CPTCFG_BRIDGE_EBT_LIMIT=m
CPTCFG_BRIDGE_EBT_MARK=m
CPTCFG_BRIDGE_EBT_PKTTYPE=m
CPTCFG_BRIDGE_EBT_STP=m
CPTCFG_BRIDGE_EBT_VLAN=m
CPTCFG_BRIDGE_EBT_ARPREPLY=m
CPTCFG_BRIDGE_EBT_DNAT=m
CPTCFG_BRIDGE_EBT_MARK_T=m
CPTCFG_BRIDGE_EBT_REDIRECT=m
CPTCFG_BRIDGE_EBT_SNAT=m
CPTCFG_BRIDGE_EBT_LOG=m
CPTCFG_BRIDGE_EBT_NFLOG=m
CPTCFG_MAC_EMUMOUSEBTN=m
CPTCFG_RTLBTCOEXIST=m
CPTCFG_TABLET_USB_KBTAB=m
CPTCFG_INPUT_ATLAS_BTNS=m
CPTCFG_SND_BT87X=m
CPTCFG_LIRC_BT829=m
CPTCFG_USB_BTMTK=m
CPTCFG_TOSHIBA_BT_RFKILL=m
CPTCFG_BTRFS_FS=m
CPTCFG_BTRFS_FS_POSIX_ACL=y
CPTCFG_RBTREE_TEST=m
CPTCFG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CPTCFG_BTREE=y
CPTCFG_BACKPORT_OPTION_BT_SOCK_CREATE_NEEDS_KERN=y
CPTCFG_BT=m
CPTCFG_BT_RFCOMM=m
# CPTCFG_BT_RFCOMM_TTY is not set
CPTCFG_BT_BNEP=m
CPTCFG_BT_BNEP_MC_FILTER=y
CPTCFG_BT_BNEP_PROTO_FILTER=y
# CPTCFG_BT_CMTP is not set
CPTCFG_BT_HIDP=m
CPTCFG_BT_HCIBTUSB=m
CPTCFG_BT_HCIBTSDIO=m
CPTCFG_BT_HCIUART=m
CPTCFG_BT_HCIUART_H4=y
CPTCFG_BT_HCIUART_BCSP=y
# CPTCFG_BT_HCIUART_ATH3K is not set
CPTCFG_BT_HCIUART_LL=y
CPTCFG_BT_HCIUART_3WIRE=y
# CPTCFG_BT_HCIBCM203X is not set
# CPTCFG_BT_HCIBPA10X is not set
# CPTCFG_BT_HCIBFUSB is not set
# CPTCFG_BT_HCIDTL1 is not set
# CPTCFG_BT_HCIBT3C is not set
# CPTCFG_BT_HCIBLUECARD is not set
CPTCFG_BT_HCIBTUART=m
CPTCFG_BT_HCIVHCI=m
# CPTCFG_BT_MRVL is not set
# CPTCFG_BT_ATH3K is not set
CPTCFG_BT_WILINK=m

我用 printks 在内核中检测了 sco.c 文件。

使用普通耳机成功打开 SCO 连接后看起来像这样:

*** sco_sock_create
*** sco_sock_alloc
*** sco_sock_init
*** sco_sock_bind
*** sco_sock_connect
*** sco_connect
*** sco_conn_add
*** sco_chan_add
*** __sco_chan_add
*** sco_sock_set_timer
*** sco_connect_cfm
*** sco_conn_add
*** sco_conn_ready
*** sco_sock_clear_timer
*** sco_sock_getsockopt
*** sco_sock_setsockopt_old
*** sco_sock_getsockopt
*** sco_sock_setsockopt_old
*** sco_sock_sendmsg
*** sco_send_frame
*** sco_sock_sendmsg
*** sco_send_frame
*** sco_sock_sendmsg
*** sco_send_frame

失败时看起来像这样:

*** sco_sock_create
*** sco_sock_alloc
*** sco_sock_init
*** sco_sock_bind
*** sco_sock_connect
*** sco_connect
*** sco_conn_add
*** sco_chan_add
*** __sco_chan_add
*** sco_sock_set_timer
*** sco_connect_cfm
*** sco_conn_del
*** sco_chan_get
*** sco_sock_clear_timer
*** sco_chan_del
*** sco_sock_release
*** sco_sock_close
*** sco_sock_kill
*** sco_sock_clear_timer
*** __sco_sock_connect
*** sco_sock_kill
*** sco_sock_kill
*** sco_sock_destruct

进一步的检测显示失败发生在这个 sco.c 函数中:

void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
{

    printk("*** sco_connect_cfm start\n");

    BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
    printk("*** sco_connect_cfm_stat hcon %p bdaddr %pMR status %d\n", hcon, &hcon->dst, status);
    if (!status) {
        struct sco_conn *conn;

        conn = sco_conn_add(hcon);
        printk("*** sco_connect_cfm sco_conn_add: %d\n",conn);
        if (conn)
            printk("*** sco_connect_cfm ready\n");
            sco_conn_ready(conn);
    } else
        printk("*** sco_connect_delete: %d\n",status);
        sco_conn_del(hcon, bt_to_errno(status));
}

输出看起来像这样:

*** sco_sock_create
*** sco_sock_alloc
*** sco_sock_init
*** sco_sock_bind
*** sco_sock_connect
*** sco_connect
*** sco_conn_add
*** sco_chan_add
*** __sco_chan_add
*** sco_sock_set_timer
*** sco_connect_cfm start
*** sco_connect_cfm_stat hcon d9ec2400 bdaddr 40:30:07:dc:1b:00 status 26
*** sco_connect_delete: 26
*** sco_conn_del
*** sco_chan_get
*** sco_sock_clear_timer
*** sco_chan_del
*** sco_sock_release
*** sco_sock_close
*** sco_sock_clear_timer
*** sco_sock_kill
*** __sco_sock_connect
*** sco_sock_kill
*** sco_sock_kill
*** sco_sock_destruct

最佳答案

问题不在于内核的配置,而在于我使用的驱动程序集。我已经编译了蓝牙驱动程序的 linux backports ( http://drvbp1.linux-foundation.org/~mcgrof/rel-html/backports/ ) 版本,因为我需要 backported wifi 驱动程序,这给了我协议(protocol)不支持 (93) 错误。我切换回与内核 3.4.79+ 一起分发的驱动程序并且它工作正常。

关于linux - BlueZ scotest 应用程序和 Linux 配置无法连接到 SCO 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28631721/

相关文章:

linux - 关于 bash 中的函数

linux - 按字段数过滤行

Java 声音在 Windows 中完美运行,在 Linux 中我们得到 LineUnavailableException

java - 传输端点错误

android - 以编程方式自动接受传入的蓝牙文件

linux - 强制linux只能使用4G以上的内存?

linux - 为什么在linux内核中使用单哈希桶哈希表

linux - 在 fedora 20 上安装 checkinstall

iOS 音频流仅适用于**某些**蓝牙设备?

linux - 使用 perf 确定进程何时以及为何进入不间断 sleep