Bluetooth-соединение в C blueZ на Linux

Я не могу найти ссылки на то, как подключить устройство bluetooth к linux в программе, написанной на C, с использованием библиотек Bluetooth BlueZ. Мне уже удалось сделать запрос уровня HCI, чтобы получить устройства вместе с их уровнями RSSI (во время обнаружения устройства), но в настоящее время я застрял с этим. Я видел предложение использовать API-интерфейс DBUS для blueZ-simple-agent - но есть ли способ избежать этого и просто использовать некоторые методы уровня C от BlueZ?

4 ответа

Код аутентификации от 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);
}

И настройка 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);
}

Вы можете скачать новейшую версию исходного кода здесь: http://www.bluez.org/ Это инструмент "btmgmt", а также bluez-simple-agent, который можно использовать для сопряжения. Код все в источниках, а также есть некоторая документация (в папке docs). Может быть, вы можете использовать код одного из этих инструментов для ваших желаний, или, возможно, это поможет вам понять сопряжение.

Я хочу сначала соединить устройство 2 с библиотекой bluez bluetooth, но я случайно нашел полезный код в исходном коде для bluez-tools. Существует файл "btmgmt.c" и некоторые включенные в него файлы, которые реализуют сопряжение.

Для меня, к сожалению, это не работает, и я не могу понять, почему. Но, возможно, у вас будет больше успеха с этим. Вот как вы можете это проверить.

Если вы еще этого не сделали, загрузите самую новую версию исходного кода здесь: http://www.bluez.org/ Извлеките ее и откройте терминал в папке bluez.

Затем запустите следующее в терминале:

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

Я не помню все пакеты, которые вам нужно установить, но вы можете запустить эту команду и проверить, почему она не работает, затем установить пакет и перезапустить его, пока он не заработает. Спросите Google, если вы не знаете, какой пакет вам нужно установить. После этого:

make

Теперь вы можете переключиться в папку инструментов из терминала и набрать./btmgmt, чтобы увидеть, как его использовать. Вы также можете ввести его, чтобы иметь возможность использовать его, просто набрав "btmgmt" независимо от вашего местоположения.

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

Вам нужны права sudo, чтобы использовать его.

В этой области мне помогла действительно классная книга, которую я нашел: http://people.csail.mit.edu/rudolph/Teaching/Articles/BTBook.pdf

У него есть примеры на c и python по настройке, сопряжению и т. Д. Я хотел попробовать и использовать его для запуска классического (spp) соединения bluetooth на ipad, но не думаю, что в ядре есть то, что мне нужно.

Я играл с Bluez в C/C++. Насколько я понимаю, интерфейс C / C++ не очень полезен в BlueZ для пользователей, он предпочитает Python.

Итак, основная идея - взглянуть на репозиторий BlueZ, каталог / tools, который реализует некоторые необходимые функции в C.

Кроме того, вы можете взглянуть на эту статью, которая показывает некоторые возможности использования BlueZ с простого C: https://people.csail.mit.edu/albert/bluez-intro/c404.html

Вот что я придумал (основываясь на hcidump): https://github.com/IGR2014/Alsa-BlueZ-Example (вдохновлено https://github.com/pauloborges/bluez, https://git.kernel.org/pub/scm/bluetooth/bluez.git)

Небольшой пример возможной реализации функции подключения:

// 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;

}

Следующее, что вам нужно сделать, это обнаружить службы ( https://www.bluetooth.com/specifications/assigned-numbers/service-discovery)

Также вот мой старый вопрос, который может привести вас к ответу: Bluetooth наушники C++ под Linux поверх BlueZ

Обратите внимание: все API (если мы можем назвать эти внутренние функции "API") не обязательно будут одинаковыми для других версий BlueZ. По крайней мере, нет никаких гарантий такого поведения.

Эта команда 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"

Здесь 1301 - идентификатор процесса bluetoothd

/ org / bluez / agent_1317 является агентом сопряжения bluetooth. Для этой цели можно использовать bluezagent, который входит в состав agent.c в bluez/test.

Другие вопросы по тегам