C++ Bluetooth headphones under Linux over BlueZ

早过忘川 提交于 2019-12-13 02:58:30

问题


I'm trying to write audio application for Bluetooth headphones under Linux (over BlueZ stack). It's embedded version so I want to use only C++ and BlueZ without any DBus or Python. For now I could successfully inquire devices and pair with them. But after few seconds connection gets lost.

As far as I understand - there's should be some link established after pairing to prevent disconnection. But I can't figure out what am I doing wrong..

Here is my code sample:

int main(int argc, char** argv) {

    int max_rsp, num_rsp;
    int dev_id, sock, len, flags;

    inquiry_info*   ii      = NULL;
    char        addr[19]    = {0};
    char        name[248]   = {0};
    uint8_t     cod[3]      = {0};

    const char localName[8] = "TestKIT";

    dev_id  = hci_get_route(NULL);

    sock    = hci_open_dev(dev_id);
    if (dev_id < 0 || sock < 0) {

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

    }
    hci_write_local_name(sock, localName, 8);

    std::cout << std::endl;
    std::cout << "Device name set to:\t\"" << localName << "\"" << std::endl;

    len = 8;
    max_rsp = 255;
    flags   = IREQ_CACHE_FLUSH;
    ii  = new inquiry_info[max_rsp * sizeof(inquiry_info)];

    num_rsp = hci_inquiry(dev_id, len, max_rsp, NULL, &ii, flags);
    if (num_rsp < 0) {

        std::cerr << "HCI inquiry: " << strerror(errno) << std::endl;

    }

    std::cout << std::endl;
    std::cout << "=========================================================================" << std::endl;
    std::cout << " #\t" << "BTA\t\t\t" << "Name\t\t\t\t" << "COD" << std::endl;
    std::cout << "-------------------------------------------------------------------------" << std::endl;

        for (int i = 0; i < num_rsp; ++i) {

        ba2str(&ii[i].bdaddr, addr);
        memset(name, 0, sizeof(name));

        if (hci_read_remote_name(sock, &ii[i].bdaddr, sizeof(name), name, 0) < 0) {

            strcpy(name, "[unknown]");

        }

        hci_read_class_of_dev(sock, cod, 0);

        std::cout << std::setw(2) << std::setfill(' ') << i + 1 << '.' << "\t";
        std::cout << addr << "\t";
        std::cout << std::setw(30) << std::left << name << "\t" << std::right;
        std::cout << "0x";
        std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<unsigned int>(cod[2]);
        std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<unsigned int>(cod[1]);
        std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<unsigned int>(cod[0]);
        std::cout << std::endl;

    }

    std::cout << "=========================================================================" << std::endl;

    unsigned int userChoise = 0;

    std::cout << std::endl;
    std::cout << "Device to connect: ";

    std::cin >> userChoise;

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

    if (userChoise > 0 && userChoise <= num_rsp) {

        std::cout << "Connecting to device #" << userChoise << " ..." << std::endl;
        std::cout << std::endl;

        if (hci_create_connection(sock, &ii[userChoise - 1].bdaddr, htobs(ptype), 0, 0, &handle, 0) < 0) {

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

        } else {

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

        }

        if (hci_authenticate_link(sock, handle, 0) < 0) {

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

        } else {

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

        }

        if (hci_encrypt_link(sock, handle, 1, 0) < 0) {

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

        } else {

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

        }

    } else {

        std::cout << "Wrong device number: " <<  userChoise << " (should be ";

        if (num_rsp > 1) {

            std::cout << "in range [1 .. " << num_rsp << "]";

        } else {

            std::cout << "1";

        }

        std::cout << ")" << std::endl;

    }

    hci_close_dev(sock);

    close(sock);

    // Connection to prevent disconnect
    struct sockaddr_l2 rAddr;
    int sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);

    if (sk < 0) {

        std::cerr << "Socket:\t" << strerror(errno) << std::endl;

    }

    memset(&rAddr, 0, sizeof(rAddr));
    rAddr.l2_family = AF_BLUETOOTH;
    rAddr.l2_psm = 0x1001;
    rAddr.l2_bdaddr = ii[userChoise - 1].bdaddr;

    if (connect(sk, (struct sockaddr *) &rAddr, sizeof(rAddr)) < 0 ) {

        std::cerr << "Connect:\t" << strerror(errno) << std::endl;

    } 

    std::cout << "Socket "sk": " << sk << std::endl;

    delete [] ii;
    ii = NULL;

    return 0;

}

回答1:


Okay, thanks to all who helped me (yes, you Google and you Github). The sollution was to init all SDP routine to get required channel for required protocol befor connecting. For now RFCOMM connection establishing successfully



来源:https://stackoverflow.com/questions/48932249/c-bluetooth-headphones-under-linux-over-bluez

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!