Linux 上 C blueZ 中的蓝牙配对

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14820004/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:59:51  来源:igfitidea点击:

Bluetooth pairing in C blueZ on Linux

clinuxbluetoothbluez

提问by okipol

I cannot find any reference on how to pair a bluetooth device on linux in a program written in C using the BlueZ Bluetooth libraries. I already managed to do a HCI level query to get devices along with thier RSSI levels (during the device discovery) but currently I am stuck with this. I saw a suggestion to use the DBUS api for the blueZ-simple-agent - but is there any way to avoid this and just use some C level methods from BlueZ?

在使用 BlueZ 蓝牙库用 C 编写的程序中,我找不到关于如何在 linux 上配对蓝牙设备的任何参考。我已经设法进行 HCI 级别查询以获取设备及其 RSSI 级别(在设备发现期间),但目前我坚持这一点。我看到了将 DBUS api 用于 blueZ-simple-agent 的建议 - 但是有什么方法可以避免这种情况而只使用 BlueZ 的一些 C 级方法吗?

回答by progo

You can download the newest version of the source code here: http://www.bluez.org/There ist the tool "btmgmt" and also the bluez-simple-agent that can be used for pairing. The code is all in the sources and there is also some documentation (in docs folder). Maybe you can use code of one of these tools for your desires or maybe it helps you understand the pairing.

您可以在此处下载最新版本的源代码:http: //www.bluez.org/有“btmgmt”工具和可用于配对的bluez-simple-agent。代码全部在源代码中,还有一些文档(在 docs 文件夹中)。也许您可以根据自己的需要使用这些工具之一的代码,或者它可以帮助您理解配对。

I want to pair 2 device with the bluez bluetooth library in the first place but I happend to find helpful code in the source for the bluez-tools. There is the file "btmgmt.c" and some files that are include in it which implement the pairing.

我想首先将 2 个设备与 bluez 蓝牙库配对,但我碰巧在 bluez-tools 的源代码中找到了有用的代码。有文件“btmgmt.c”和其中包含的一些实现配对的文件。

For me unfortunately it is not working and I can't understand why. But maybe you have more success with it. Here is how you can test it.

不幸的是,对我来说它不起作用,我不明白为什么。但也许你在这方面取得了更大的成功。这是您可以测试它的方法。

If you haven't already, download the newest version of the source code here: http://www.bluez.org/Extract it and open a terminal in the bluez folder.

如果您还没有,请在此处下载最新版本的源代码:http: //www.bluez.org/ 解压缩并在 bluez 文件夹中打开一个终端。

Then run the following in the terminal:

然后在终端中运行以下命令:

./configure --prefix=/usr    \
        --sysconfdir=/etc    \
        --localstatedir=/var \
        --enable-tools       \
        --disable-test       \
        --disable-systemd

I don't remember all packages you need to install but you can run this command and check why it fails, then install the package and rerun it till it works. Ask google if you don't know which package you need to install. Afterwards:

我不记得你需要安装的所有包,但你可以运行这个命令并检查它失败的原因,然后安装包并重新运行它直到它工作。如果您不知道需要安装哪个软件包,请询问 google。然后:

make

Now you can switch into tools folder from terminal and type ./btmgmt to see how to use it. You can also intall it to be able to use it by just typing "btmgmt" regardless of your location.

现在您可以从终端切换到工具文件夹并键入 ./btmgmt 以查看如何使用它。无论您身在何处,您也可以通过键入“btmgmt”来安装它以使用它。

sudo /usr/bin/install -c tools/btmgmt /usr/bin/btmgmt

You need sudo rights to use it.

您需要 sudo 权限才能使用它。

回答by disable13

Authentication code from hcitool(original source code can see at http://git.kernel.org/cgit/bluetooth/bluez.git/tree/tools/hcitool.c)

身份验证代码来自hcitool(原始源代码可以在http://git.kernel.org/cgit/bluetooth/bluez.git/tree/tools/hcitool.c看到)

/* Request authentication */

static void cmd_auth(int dev_id, int argc, char **argv)
{
        struct hci_conn_info_req *cr;
        bdaddr_t bdaddr;
        int opt, dd;

        for_each_opt(opt, auth_options, NULL) {
            switch (opt) {
            default:
                printf("%s", auth_help);
                return;
            }
        }
        helper_arg(1, 1, &argc, &argv, auth_help);

        str2ba(argv[0], &bdaddr);

        if (dev_id < 0) {
            dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr);
            if (dev_id < 0) {
                fprintf(stderr, "Not connected.\n");
                exit(1);
            }
        }

        dd = hci_open_dev(dev_id);
        if (dd < 0) {
            perror("HCI device open failed");
            exit(1);
        }

        cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
        if (!cr) {
            perror("Can't allocate memory");
            exit(1);
        }

        bacpy(&cr->bdaddr, &bdaddr);
        cr->type = ACL_LINK;
        if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) {
            perror("Get connection info failed");
            exit(1);
        }

        if (hci_authenticate_link(dd, htobs(cr->conn_info->handle), 25000) < 0) {
            perror("HCI authentication request failed");
            exit(1);
        }

        free(cr);

        hci_close_dev(dd);
}

And setting up PIN

并设置 PIN

/* Activate encryption */

static void cmd_enc(int dev_id, int argc, char **argv)
{
    struct hci_conn_info_req *cr;
    bdaddr_t bdaddr;
    uint8_t encrypt;
    int opt, dd;

    for_each_opt(opt, enc_options, NULL) {
        switch (opt) {
        default:
            printf("%s", enc_help);
            return;
        }
    }
    helper_arg(1, 2, &argc, &argv, enc_help);

    str2ba(argv[0], &bdaddr);

    if (dev_id < 0) {
        dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr);
        if (dev_id < 0) {
            fprintf(stderr, "Not connected.\n");
            exit(1);
        }
    }

    dd = hci_open_dev(dev_id);
    if (dd < 0) {
        perror("HCI device open failed");
        exit(1);
    }

    cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
    if (!cr) {
        perror("Can't allocate memory");
        exit(1);
    }

    bacpy(&cr->bdaddr, &bdaddr);
    cr->type = ACL_LINK;
    if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) {
        perror("Get connection info failed");
        exit(1);
    }

    encrypt = (argc > 1) ? atoi(argv[1]) : 1;

    if (hci_encrypt_link(dd, htobs(cr->conn_info->handle), encrypt, 25000) < 0) {
        perror("HCI set encryption request failed");
        exit(1);
    }

    free(cr);

    hci_close_dev(dd);
}

回答by Sreedevi Srinivasan

This dbus command can be used to initiate pairing

此 dbus 命令可用于启动配对

 dbus-send --system --print-reply --dest=org.bluez /org/bluez/1301/hci0 org.bluez.Adapter.CreatePairedDevice string:"XX:XX:XX:XX:XX:XX" objpath:/org/bluez/agent_1317 string:"NoInputNoOutput"

Here 1301 is the process id of bluetoothd

这里1301是bluetoothd的进程id

/org/bluez/agent_1317 is the bluetooth pairing agent.The bluezagent that comes as agent.c in bluez/test can be used for this purpose.

/org/bluez/agent_1317 是蓝牙配对代理。 bluez/test 中作为 agent.c 的 bluezagent 可以用于此目的。

回答by IGR94

I used to play around with Bluez in C/C++. As far as I can understand, C/C++ interface is not really welcome in BlueZ for users, it do prefers python.

我曾经在 C/C++ 中使用 Bluez。据我所知,C/C++ 接口在 BlueZ 中并不是很受用户欢迎,它确实更喜欢 python。

So the main idea is to take a look at BlueZ repo, at directory /tools which implements some of required features in C.

因此,主要想法是查看 BlueZ 存储库,位于 /tools 目录中,它在 C 中实现了一些必需的功能。

Also, you can take a look at this article which shows some possibilities of BlueZ usage from plain C: https://people.csail.mit.edu/albert/bluez-intro/c404.html

此外,您可以查看这篇文章,其中显示了从普通 C 语言使用 BlueZ 的一些可能性:https: //people.csail.mit.edu/albert/bluez-intro/c404.html

Here is what i came up with (based on hcidump): https://github.com/IGR2014/Alsa-BlueZ-Example(inspired by https://github.com/pauloborges/bluez, https://git.kernel.org/pub/scm/bluetooth/bluez.git)

以下是我想出了(基于hcidump): https://github.com/IGR2014/Alsa-BlueZ-Example(灵感https://github.com/pauloborges/bluezHTTPS://git.kernel .org/pub/scm/bluetooth/bluez.git)

Small example of possible implementation for connect function:

连接功能可能实现的小例子:

// Connect to device
bool btCore::connect(const char* address) {

    std::cout << "Connecting to device\t" << address << " ..." << std::endl;
    std::cout << std::endl;

    uint16_t     handle;
    unsigned int ptype      = HCI_DM1 | HCI_DM3 | HCI_DM5 | HCI_DH1 | HCI_DH3 | HCI_DH5;

    char         addr[19]   = {0};

    bdaddr_t     bdaddr;

    str2ba(address, &bdaddr);

    // Open local HCI device
    int sk      = hci_open_dev(dev_id);
    if (sk < 0) {

        std::cerr << "HCI open device:\t\t" << strerror(errno) << std::endl;
        return false;

    }

    // Establish HCI connection with device
    if (hci_create_connection(sk, &bdaddr, htobs(ptype), 0, 0, &handle, 0) < 0) {

        std::cerr << "HCI create connection:\t" << strerror(errno) << std::endl;
        close(sk);
        return false;

    } else {

        std::cout << "Connection:\t\tOK" << std::endl;

    }

    // Authenticate HCI link (without pin)
    if (hci_authenticate_link(sk, handle, 0) < 0) {

        std::cerr << "HCI authenticate connection:\t" << strerror(errno) << std::endl;
        close(sk);
        return false;

    } else {

        std::cout << "Authentication:\t\tOK" << std::endl;

    }

    // Encrypt HCI link
    if (hci_encrypt_link(sk, handle, 1, 0) < 0) {

        std::cerr << "HCI encrypt connection:\t" << strerror(errno) << std::endl;
        close(sk);
                return false;

    } else {

        std::cout << "Encryption:\t\tOK" << std::endl;

    }

    close(sk);

    return true;

}

Next thing you have to do is discover services (https://www.bluetooth.com/specifications/assigned-numbers/service-discovery)

接下来你要做的是发现服务(https://www.bluetooth.com/specifications/assigned-numbers/service-discovery

Also here is my old question which can lead you to answer: C++ Bluetooth headphones under Linux over BlueZ

这也是我的老问题,它可以引导您回答:Linux over BlueZ 下的 C++ 蓝牙耳机

Please note: All of the API (if we can name those internal functions "API") is not guaranteed to be same for other versions of BlueZ. At least, there is no any warranty of such behavior.

请注意:不能保证所有 API(如果我们可以将这些内部函数命名为“API”)与其他版本的 BlueZ 相同。至少,对于此类行为没有任何保证。