C++ Bluetooth headphones under Linux over BlueZ

2019-08-24 07:06发布

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条回答
Juvenile、少年°
2楼-- · 2019-08-24 07:35

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

查看更多
登录 后发表回答