Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-73328

QBluetoothServiceInfo::setAttribute() with values needing hex-encoded strings (for byte array) fails on BlueZ.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.12.2
    • 5.11.3, 5.12.0
    • None
    • Linux Raspbian Stretch 2018-11-13
      Linux Mint 19
    • Linux/Wayland, Linux/X11

    Description

      I need to publish a Bluetooth HID service profile, which needs to include a byte-encoded description of the USB-spec HID service reports (example below).

      There doesn't seem to be a way to do this using QBluetoothServiceInfo, at least the BlueZ 5 version. If I set the attribute as a QString, it comes out in the registration as a "normal" encoded string, which clearly doesn't work. If I set it as a QByteArray, the parser says the variant type is unrecognized. Am I missing something?

      See this code for what is going on (qbluetoothserviceinfo_bluez.cpp::writeAttribute() where is converts a QString type).

      I have only tried with Linux/BlueZ 5, so I don't know if this is a problem on other platforms or how one would set a byte array in a descriptor attribute there either.

      As as workaround: I made my own BlueZ registration routine using essentially the same code as qbluetoothserviceinfo_bluez, but the XML attribute writer recognizes a QByteArray type and writes it as a hex-encoded string. It works, but a lot of code duplication for just one issue. I also had SDP registration working with a static XML file (skipping QBluetoothServiceInfo entirely), which worked... but I wanted to a) have dynamic attributes/values, and b) standardize the descriptor interface using a QBluetoothServiceInfo instance).

      Basic code to attempt to create this attribute in any random QBluetoothServiceInfo object is below. Also how I ended up writing the attribute to XML in the end. I can attach more examples if needed.

      Thanks!
      -Max

      Example desired XML output for an HID report descriptor:

      <!-- HIDDescriptorList [0x0206] (USB Report/Physical Descriptors) -->
      <attribute id="0x0206">
        <sequence>
          <sequence>
            <uint8 value="0x22" />  <!-- Report type -->
            <!-- This is the "standard" descriptor for keyboard and mouse from the USB HID v1.11 spec examples. -->
            <text encoding="hex" value="05010906a101850105079508750119e029e7150025018102950175088103050795067508150026FF00190029FF8100050895057501190129059102950175039103c005010902a10185020901a1000509190129031500250175019503810275059501810105010930093109381581257f750895038106c0c0" />
            <!-- Nice parser: https://eleccelerator.com/usbdescreqparser/ -->
          </sequence>
        </sequence>
      </attribute>
      

      Example code to (attempt to) create above attribute:

      const QByteArray hidSvcDescript = QByteArray::fromHex("05010906a101850105079508750119e029e7150025018102950175088103050795067508150026FF00190029FF8100050895057501190129059102950175039103c005010902a10185020901a1000509190129031500250175019503810275059501810105010930093109381581257f750895038106c0c0");
      const QBluetoothServiceInfo::Sequence hidDescriptorList({
          QVariant::fromValue(quint8(0x22)),  // Report type
          QString(hidSvcDescript.toHex())     // Our descriptor array
      });
      // need to wrap it in another sequence
      const QBluetoothServiceInfo::Sequence hidDescriptorListSeq({
          QVariant::fromValue(hidDescriptorList)
      });
      // svcInfo = QBluetoothServiceInfo()
      svcInfo.setAttribute(0x0206, QVariant::fromValue(hidDescriptorListSeq));
      

      Here's how I convert a QByteArray type to XML attribute (so QBluetoothServiceInfo::setAttribute() gets passed a QByteArray value, instead of QString):

      // new case handler for writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
          case QMetaType::QByteArray:
              stream->writeEmptyElement(QStringLiteral("text"));
              stream->writeAttribute(QStringLiteral("encoding"), QStringLiteral("hex"));
              stream->writeAttribute(QStringLiteral("value"), QString(attribute.value<QByteArray>().toHex()));
              break;
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            ablasche Alex Blasche
            mpaperno Maxim Paperno
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes