Linux Embedded - подключение профилей Bluetooth A2DP, HFP, разъем RFCOMM

Я работаю над приложением Qt C++ для подключения bluetooth Walketalkie (с кнопкой Push-To-Talk) к интегрированному устройству на основе встроенного Linux (Cortex-A9 Core). В моем устройстве есть встроенный адаптер Bluetooth 450-0159 с чипом Cypress/Broadcom CYW4343W / BCM4343W BT/WLAN. Я использую bluez-5.43 и bluez-alsa для подключения аудиоуслуг Bluetooth (A2DP и ​​HFP). В моем приложении через библиотеки Bluetooth я могу правильно управлять адаптером Bluetooth, включением, выключением питания, сопряжением, но я не могу подключить профили аудио Bluetooth. Таким образом, я реализовал следующие методы для подключения / отключения Bluetooth Walketalkie:

void BluetoothMgmt::connectDevice(QString address) {
    QString command = "echo -e \"connect " + address + "\nquit\" | bluetoothctl";
    QString output = execSystemCommand(command);
    qDebug() << "OUTPUT EXEC SYSTEM COMMAND 1:" << output;
}

void BluetoothMgmt::disconnectDevice(QString address) {
    QString command = "echo -e \"disconnect " + address + "\nquit\" | bluetoothctl";
    QString output = execSystemCommand(command);
    qDebug() << "OUTPUT EXEC SYSTEM COMMAND 1:" << output;
}

bool BluetoothMgmt::isDeviceConnected(QString address) {
    bool connected = false;

    QString command = "echo -e \"info " + address + "\nquit\" | bluetoothctl | grep Connected";
    QString output = execSystemCommand(command);
    qDebug() << "command output:" << output;

    QStringList outputParts = output.split(WHITESPACE_CHAR);
    QString status = outputParts.at(1);

    if(status.contains("yes", Qt::CaseInsensitive))
        connected = true;

    return connected;
}

После вызова функции "connectDevice" моя Walketalkie правильно подключена к профилю A2DP и ​​HFP, и я использую функцию "isDeviceConnected", чтобы узнать состояние устройства Bluetooth, подключено оно или нет. Теперь я должен получить информацию о сокете RFCOMM, чтобы узнать статус кнопки Push-To-Talk, если нажата или нет, поэтому я реализовал этот код для подключения сокета RFCOMM:

QBluetoothSocket *socket;
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);

connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnect()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket()));
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socketError(QBluetoothSocket::SocketError)));

void BluetoothMgmt::socketConnected() {
    qDebug() << "Socket connected:" << socket->peerName();
}

void BluetoothMgmt::socketDisconnect() {
    qDebug() << "Socket disconnected";
}

void BluetoothMgmt::readSocket() {
    QString message;
    message = QString::fromLatin1(socket->readAll().data());
    /* Code to parse Push-To-Talk button status */
}

void BluetoothMgmt::socketError(QBluetoothSocket::SocketError error) {
    qDebug() << "Socket Error:" << socket->errorString();
}

/* To connect QBluetoothSocket */
int channel = 11
socket->connectToService(bluetooth_device_address, channel);

Чтобы узнать канал для подключения к сокету, я запустил "sdptool records bluetooth_device_address" из командной строки. Результат моего устройства следующий:

root@localhost:/dev# sdptool records 00:1F:82:3A:6E:5F
Service RecHandle: 0x10002
Service Class ID List:
  "Audio Sink" (0x110b)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 25
  "AVDTP" (0x0019)
    uint16: 0x0103
Profile Descriptor List:
  "Advanced Audio" (0x110d)
    Version: 0x0103

Service RecHandle: 0x10003
Service Class ID List:
  "PnP Information" (0x1200)

Service RecHandle: 0x10004
Service Class ID List:
  "AV Remote" (0x110e)
  "AV Remote Controller" (0x110f)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 23
  "AVCTP" (0x0017)
    uint16: 0x0104
Profile Descriptor List:
  "AV Remote" (0x110e)
    Version: 0x0106

Service RecHandle: 0x10005
Service Class ID List:
  "AV Remote Target" (0x110c)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 23
  "AVCTP" (0x0017)
    uint16: 0x0104
Profile Descriptor List:
  "AV Remote" (0x110e)
    Version: 0x0106

Service Name: Headset
Service RecHandle: 0x1000a
Service Class ID List:
  "Headset" (0x1108)
  "" (0x1131)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 13
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Headset" (0x1108)
    Version: 0x0102

Service Name: Hands-Free unit
Service RecHandle: 0x1000d
Service Class ID List:
  "Handsfree" (0x111e)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 12
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Handsfree" (0x111e)
    Version: 0x0105

Я использую канал номер 13 для подключения к сокету (RfcommProtocol).

RFCOMM-соединение работает нормально, и я могу читать статус кнопки Push-To-Talk. Проблема в том, что я могу подключить аудиоуслуги (A2DP и ​​HFP) или соединение RFCOMM, но мне нужно подключить все профили одновременно. Как я могу читать сообщения RFCOMM после подключения устройства с помощью инструмента "bluetoothctl"? Единственный способ показать пакеты Bluetooth с сообщениями Push-To-Talk - запустить "btmon" (монитор Bluetooth) из командной строки, но я считаю, что это неправильный способ, и также я не знаю, как интегрировать его в свой C++. заявление. К сожалению, с библиотеками Qt невозможно подключить аудио-профили Bluetooth, по этой причине я использую инструмент bluetoothctl. "Bluetoothctl", вероятно, отправляет сообщения dbus, разрешающие "bluez-library"для подключения профиля A2DP и ​​SCO и создания виртуальной звуковой карты PCM с драйвером alsa. Какие-либо предложения? Спасибо за совет.

0 ответов

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