diff options
author | Marijn Suijten <marijns95@gmail.com> | 2021-01-19 00:11:16 +0100 |
---|---|---|
committer | Marijn Suijten <marijns95@gmail.com> | 2021-02-02 18:22:41 +0100 |
commit | 98cf71fbcc2f560ee4929328c9fd9f0cc15d38ee (patch) | |
tree | b23b74cafc5b63106bd5014c67db84c6a1874569 | |
parent | e294444496e8bbcd91a3605874f59562e14c34ec (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.c | 94 |
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; } |