summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarijn Suijten <marijns95@gmail.com>2021-01-19 00:11:16 +0100
committerMarijn Suijten <marijns95@gmail.com>2021-02-02 18:22:41 +0100
commit98cf71fbcc2f560ee4929328c9fd9f0cc15d38ee (patch)
treeb23b74cafc5b63106bd5014c67db84c6a1874569
parente294444496e8bbcd91a3605874f59562e14c34ec (diff)
linux: Parse kind from Class if Appearance is not available
Not all headsets have a GAP profile revealing their appearance, but they do have a class.
-rw-r--r--src/linux/up-device-bluez.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/linux/up-device-bluez.c b/src/linux/up-device-bluez.c
index f4480ba..2234b83 100644
--- a/src/linux/up-device-bluez.c
+++ b/src/linux/up-device-bluez.c
@@ -63,6 +63,94 @@ appearance_to_kind (guint16 appearance)
}
/**
+ * class_to_kind:
+ * @class: a Bluetooth device class
+ *
+ * Returns value: the type of device corresponding to the given @class value.
+ **/
+static UpDeviceKind
+class_to_kind (guint32 class)
+{
+ /*
+ * See Bluetooth Assigned Numbers for Baseband
+ * https://www.bluetooth.com/specifications/assigned-numbers/baseband/
+ */
+
+ switch ((class & 0x1f00) >> 8) {
+ case 0x01:
+ return UP_DEVICE_KIND_COMPUTER;
+ case 0x02:
+ switch ((class & 0xfc) >> 2) {
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x05:
+ return UP_DEVICE_KIND_PHONE;
+ case 0x04:
+ return UP_DEVICE_KIND_MODEM;
+ }
+ break;
+ case 0x03:
+ return UP_DEVICE_KIND_NETWORK;
+ case 0x04:
+ switch ((class & 0xfc) >> 2) {
+ case 0x01:
+ case 0x02:
+ return UP_DEVICE_KIND_HEADSET;
+ case 0x05:
+ return UP_DEVICE_KIND_SPEAKERS;
+ case 0x06:
+ return UP_DEVICE_KIND_HEADPHONES;
+ case 0x0b: /* VCR */
+ case 0x0c: /* Video Camera */
+ case 0x0d: /* Camcorder */
+ return UP_DEVICE_KIND_VIDEO;
+ default:
+ return UP_DEVICE_KIND_OTHER_AUDIO;
+ }
+ break;
+ case 0x05:
+ switch ((class & 0xc0) >> 6) {
+ case 0x00:
+ switch ((class & 0x1e) >> 2) {
+ case 0x01:
+ case 0x02:
+ return UP_DEVICE_KIND_GAMING_INPUT;
+ case 0x03:
+ return UP_DEVICE_KIND_REMOTE_CONTROL;
+ }
+ break;
+ case 0x01:
+ return UP_DEVICE_KIND_KEYBOARD;
+ case 0x02:
+ switch ((class & 0x1e) >> 2) {
+ case 0x05:
+ return UP_DEVICE_KIND_TABLET;
+ default:
+ return UP_DEVICE_KIND_MOUSE;
+ }
+ }
+ break;
+ case 0x06:
+ if (class & 0x80)
+ return UP_DEVICE_KIND_PRINTER;
+ if (class & 0x40)
+ return UP_DEVICE_KIND_SCANNER;
+ if (class & 0x20)
+ return UP_DEVICE_KIND_CAMERA;
+ if (class & 0x10)
+ return UP_DEVICE_KIND_MONITOR;
+ break;
+ case 0x07:
+ return UP_DEVICE_KIND_WEARABLE;
+ case 0x08:
+ return UP_DEVICE_KIND_TOY;
+ }
+
+ return UP_DEVICE_KIND_UNKNOWN;
+}
+
+/**
* up_device_bluez_coldplug:
*
* Return %TRUE on success, %FALSE if we failed to get data and should be removed
@@ -103,6 +191,12 @@ up_device_bluez_coldplug (UpDevice *device)
appearance = g_variant_get_uint16 (v);
kind = appearance_to_kind (appearance);
g_variant_unref (v);
+ } else if ((v = g_dbus_proxy_get_cached_property (proxy, "Class"))) {
+ guint32 class;
+
+ class = g_variant_get_uint32 (v);
+ kind = class_to_kind (class);
+ g_variant_unref (v);
} else {
kind = UP_DEVICE_KIND_UNKNOWN;
}