2023-01-24 10:39:33 +01:00
|
|
|
#include "bluetooth.h"
|
|
|
|
|
|
|
|
|
|
#ifdef FF_HAVE_DBUS
|
|
|
|
|
#include "common/dbus.h"
|
|
|
|
|
|
|
|
|
|
/* Example dbus reply, striped to only the relevant parts:
|
|
|
|
|
array [ //root
|
|
|
|
|
dict entry( //object
|
|
|
|
|
object path "/org/bluez/hci0/dev_03_21_8B_91_16_4D"
|
|
|
|
|
array [
|
2023-01-27 18:03:57 +01:00
|
|
|
dict entry( //property
|
|
|
|
|
string "org.bluez.Device1"
|
|
|
|
|
array [
|
2023-01-27 18:21:42 +01:00
|
|
|
dict entry( //value
|
2023-01-27 18:03:57 +01:00
|
|
|
string "Address"
|
|
|
|
|
variant string "03:21:8B:91:16:4D"
|
|
|
|
|
)
|
2023-01-27 18:21:42 +01:00
|
|
|
dict entry( //value
|
2023-01-27 18:03:57 +01:00
|
|
|
string "Name"
|
|
|
|
|
variant string "JBL TUNE160BT"
|
|
|
|
|
)
|
2023-01-27 18:21:42 +01:00
|
|
|
dict entry( //value
|
2023-01-27 18:03:57 +01:00
|
|
|
string "Icon"
|
|
|
|
|
variant string "audio-headset"
|
|
|
|
|
)
|
2023-01-27 18:21:42 +01:00
|
|
|
dict entry( //value
|
2023-01-27 18:03:57 +01:00
|
|
|
string "Connected"
|
|
|
|
|
variant boolean true
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
dict entry( //property
|
|
|
|
|
string "org.bluez.Battery1"
|
|
|
|
|
array [
|
2023-01-27 18:21:42 +01:00
|
|
|
dict entry( //value
|
2023-01-27 18:03:57 +01:00
|
|
|
string "Percentage"
|
|
|
|
|
variant byte 100
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
)
|
2023-01-24 10:39:33 +01:00
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
*/
|
|
|
|
|
|
2023-01-27 18:21:42 +01:00
|
|
|
static void detectBluetoothValue(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
|
|
|
|
{
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DBusMessageIter dictIter;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
|
|
|
|
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const char* deviceProperty;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &deviceProperty);
|
|
|
|
|
|
|
|
|
|
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
|
|
|
|
|
|
|
|
|
if(strcmp(deviceProperty, "Address") == 0)
|
|
|
|
|
ffDBusGetValue(dbus, &dictIter, &device->address);
|
|
|
|
|
else if(strcmp(deviceProperty, "Name") == 0)
|
|
|
|
|
ffDBusGetValue(dbus, &dictIter, &device->name);
|
|
|
|
|
else if(strcmp(deviceProperty, "Icon") == 0)
|
|
|
|
|
ffDBusGetValue(dbus, &dictIter, &device->type);
|
|
|
|
|
else if(strcmp(deviceProperty, "Percentage") == 0)
|
|
|
|
|
ffDBusGetByte(dbus, &dictIter, &device->battery);
|
|
|
|
|
else if(strcmp(deviceProperty, "Connected") == 0)
|
|
|
|
|
ffDBusGetBool(dbus, &dictIter, &device->connected);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-24 12:02:20 +01:00
|
|
|
static void detectBluetoothProperty(FFDBusData* dbus, DBusMessageIter* iter, FFBluetoothDevice* device)
|
2023-01-24 10:39:33 +01:00
|
|
|
{
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DBusMessageIter dictIter;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
|
|
|
|
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_STRING)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const char* propertyType;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &propertyType);
|
|
|
|
|
|
|
|
|
|
if(strstr(propertyType, "Device") == NULL && strstr(propertyType, "Battery") == NULL)
|
|
|
|
|
return; //We don't care about other properties
|
|
|
|
|
|
|
|
|
|
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
|
|
|
|
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DBusMessageIter arrayIter;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
|
|
|
|
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
2023-01-27 18:21:42 +01:00
|
|
|
detectBluetoothValue(dbus, &arrayIter, device);
|
2023-01-24 10:39:33 +01:00
|
|
|
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-24 12:02:20 +01:00
|
|
|
static void detectBluetoothObject(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
2023-01-24 10:39:33 +01:00
|
|
|
{
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY)
|
2023-01-24 12:02:20 +01:00
|
|
|
return;
|
2023-01-24 10:39:33 +01:00
|
|
|
|
|
|
|
|
DBusMessageIter dictIter;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_recurse(iter, &dictIter);
|
|
|
|
|
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_OBJECT_PATH)
|
2023-01-24 12:02:20 +01:00
|
|
|
return;
|
2023-01-24 10:39:33 +01:00
|
|
|
|
|
|
|
|
const char* objectPath;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_get_basic(&dictIter, &objectPath);
|
|
|
|
|
|
|
|
|
|
//We don't want adapter objects
|
|
|
|
|
if(strstr(objectPath, "dev_") == NULL)
|
2023-01-24 12:02:20 +01:00
|
|
|
return;
|
2023-01-24 10:39:33 +01:00
|
|
|
|
|
|
|
|
dbus->lib->ffdbus_message_iter_next(&dictIter);
|
|
|
|
|
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(&dictIter) != DBUS_TYPE_ARRAY)
|
2023-01-24 12:02:20 +01:00
|
|
|
return;
|
2023-01-24 10:39:33 +01:00
|
|
|
|
|
|
|
|
DBusMessageIter arrayIter;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_recurse(&dictIter, &arrayIter);
|
|
|
|
|
|
2023-01-24 12:02:20 +01:00
|
|
|
FFBluetoothDevice* device = ffListAdd(&bluetooth->devices);
|
|
|
|
|
ffStrbufInit(&device->name);
|
|
|
|
|
ffStrbufInit(&device->address);
|
|
|
|
|
ffStrbufInit(&device->type);
|
|
|
|
|
device->battery = 0;
|
|
|
|
|
device->connected = false;
|
2023-01-24 10:39:33 +01:00
|
|
|
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
2023-01-24 12:02:20 +01:00
|
|
|
detectBluetoothProperty(dbus, &arrayIter, device);
|
2023-01-24 10:39:33 +01:00
|
|
|
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-24 12:02:20 +01:00
|
|
|
if(device->name.length == 0)
|
2023-01-24 10:39:33 +01:00
|
|
|
{
|
2023-01-24 12:02:20 +01:00
|
|
|
ffStrbufDestroy(&device->name);
|
|
|
|
|
ffStrbufDestroy(&device->address);
|
|
|
|
|
ffStrbufDestroy(&device->type);
|
|
|
|
|
--bluetooth->devices.length;
|
2023-01-24 10:39:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void detectBluetoothRoot(FFBluetoothResult* bluetooth, FFDBusData* dbus, DBusMessageIter* iter)
|
|
|
|
|
{
|
|
|
|
|
if(dbus->lib->ffdbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
DBusMessageIter arrayIter;
|
|
|
|
|
dbus->lib->ffdbus_message_iter_recurse(iter, &arrayIter);
|
|
|
|
|
|
|
|
|
|
while(true)
|
|
|
|
|
{
|
2023-01-24 12:02:20 +01:00
|
|
|
detectBluetoothObject(bluetooth, dbus, &arrayIter);
|
2023-01-24 10:39:33 +01:00
|
|
|
FF_DBUS_ITER_CONTINUE(dbus, &arrayIter);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char* detectBluetooth(const FFinstance* instance, FFBluetoothResult* bluetooth)
|
|
|
|
|
{
|
|
|
|
|
FFDBusData dbus;
|
|
|
|
|
const char* error = ffDBusLoadData(instance, DBUS_BUS_SYSTEM, &dbus);
|
|
|
|
|
if(error)
|
|
|
|
|
return error;
|
|
|
|
|
|
|
|
|
|
DBusMessage* managedObjects = ffDBusGetMethodReply(&dbus, "org.bluez", "/", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
|
|
|
|
|
if(!managedObjects)
|
|
|
|
|
return "Failed to call GetManagedObjects";
|
|
|
|
|
|
|
|
|
|
DBusMessageIter rootIter;
|
|
|
|
|
if(!dbus.lib->ffdbus_message_iter_init(managedObjects, &rootIter))
|
|
|
|
|
{
|
|
|
|
|
dbus.lib->ffdbus_message_unref(managedObjects);
|
|
|
|
|
return "Failed to get root iterator of GetManagedObjects";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
detectBluetoothRoot(bluetooth, &dbus, &rootIter);
|
|
|
|
|
|
|
|
|
|
dbus.lib->ffdbus_message_unref(managedObjects);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void ffDetectBluetoothImpl(const FFinstance* instance, FFBluetoothResult* bluetooth)
|
|
|
|
|
{
|
|
|
|
|
#ifdef FF_HAVE_DBUS
|
|
|
|
|
ffStrbufAppendS(&bluetooth->error, detectBluetooth(instance, bluetooth));
|
|
|
|
|
#else
|
2023-02-06 14:45:38 +08:00
|
|
|
FF_UNUSED(instance);
|
2023-01-24 10:39:33 +01:00
|
|
|
ffStrbufAppendS(&bluetooth->error, "Fastfetch was compiled without DBus support");
|
|
|
|
|
#endif
|
|
|
|
|
}
|