From 00f68ea8c44017569c99fc9b34fb6e4622539b14 Mon Sep 17 00:00:00 2001
From: Jakob Bornecrantz <jakob@collabora.com>
Date: Thu, 28 Dec 2023 23:00:03 +0000
Subject: [PATCH] t/libmonado: Add property enum and getters for devices

---
 src/xrt/targets/libmonado/monado.c | 86 +++++++++++++++++++++++++++
 src/xrt/targets/libmonado/monado.h | 95 +++++++++++++++++++++++++++++-
 2 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/src/xrt/targets/libmonado/monado.c b/src/xrt/targets/libmonado/monado.c
index 265967972..0317fb78b 100644
--- a/src/xrt/targets/libmonado/monado.c
+++ b/src/xrt/targets/libmonado/monado.c
@@ -294,6 +294,92 @@ mnd_root_get_device_count(mnd_root_t *root, uint32_t *out_device_count)
 	return MND_SUCCESS;
 }
 
+mnd_result_t
+mnd_root_get_device_info_bool(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, bool *out_bool)
+{
+	CHECK_NOT_NULL(root);
+	CHECK_NOT_NULL(out_bool);
+
+	if (device_index >= root->ipc_c.ism->isdev_count) {
+		PE("Invalid device index (%u)", device_index);
+		return MND_ERROR_INVALID_VALUE;
+	}
+
+	PE("Is not a valid boolean property (%u)", prop);
+
+	return MND_ERROR_INVALID_PROPERTY;
+}
+
+mnd_result_t
+mnd_root_get_device_info_i32(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, uint32_t *out_i32)
+{
+	CHECK_NOT_NULL(root);
+	CHECK_NOT_NULL(out_i32);
+
+	if (device_index >= root->ipc_c.ism->isdev_count) {
+		PE("Invalid device index (%u)", device_index);
+		return MND_ERROR_INVALID_VALUE;
+	}
+
+	PE("Is not a valid i32 property (%u)", prop);
+
+	return MND_ERROR_INVALID_PROPERTY;
+}
+
+mnd_result_t
+mnd_root_get_device_info_u32(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, uint32_t *out_u32)
+{
+	CHECK_NOT_NULL(root);
+	CHECK_NOT_NULL(out_u32);
+
+	if (device_index >= root->ipc_c.ism->isdev_count) {
+		PE("Invalid device index (%u)", device_index);
+		return MND_ERROR_INVALID_VALUE;
+	}
+
+	PE("Is not a valid u32 property (%u)", prop);
+
+	return MND_ERROR_INVALID_PROPERTY;
+}
+
+mnd_result_t
+mnd_root_get_device_info_float(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, float *out_float)
+{
+	CHECK_NOT_NULL(root);
+	CHECK_NOT_NULL(out_float);
+
+	if (device_index >= root->ipc_c.ism->isdev_count) {
+		PE("Invalid device index (%u)", device_index);
+		return MND_ERROR_INVALID_VALUE;
+	}
+
+	PE("Is not a valid float property (%u)", prop);
+
+	return MND_ERROR_INVALID_PROPERTY;
+}
+
+mnd_result_t
+mnd_root_get_device_info_string(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, const char **out_string)
+{
+	CHECK_NOT_NULL(root);
+	CHECK_NOT_NULL(out_string);
+
+	if (device_index >= root->ipc_c.ism->isdev_count) {
+		PE("Invalid device index (%u)", device_index);
+		return MND_ERROR_INVALID_VALUE;
+	}
+
+	const struct ipc_shared_device *shared_device = &root->ipc_c.ism->isdevs[device_index];
+
+	switch (prop) {
+	case MND_PROPERTY_NAME_STRING: *out_string = shared_device->str; break;
+	case MND_PROPERTY_SERIAL_STRING: *out_string = shared_device->serial; break;
+	default: PE("Is not a valid string property (%u)", prop); return MND_ERROR_INVALID_PROPERTY;
+	}
+
+	return MND_SUCCESS;
+}
+
 mnd_result_t
 mnd_root_get_device_info(mnd_root_t *root, uint32_t device_index, uint32_t *out_device_id, const char **out_dev_name)
 {
diff --git a/src/xrt/targets/libmonado/monado.h b/src/xrt/targets/libmonado/monado.h
index b9f8eb005..6eae4e62e 100644
--- a/src/xrt/targets/libmonado/monado.h
+++ b/src/xrt/targets/libmonado/monado.h
@@ -8,6 +8,7 @@
  */
 
 #include <stdint.h>
+#include <stdbool.h>
 
 
 #ifdef __cplusplus
@@ -24,7 +25,7 @@ extern "C" {
 //! Major version of the API.
 #define MND_API_VERSION_MAJOR 1
 //! Minor version of the API.
-#define MND_API_VERSION_MINOR 1
+#define MND_API_VERSION_MINOR 2
 //! Patch version of the API.
 #define MND_API_VERSION_PATCH 0
 
@@ -41,6 +42,8 @@ typedef enum mnd_result
 	MND_ERROR_OPERATION_FAILED = -4,
 	//! Supported in version 1.1 and above.
 	MND_ERROR_RECENTERING_NOT_SUPPORTED = -5,
+	//! Supported in version 1.2 and above.
+	MND_ERROR_INVALID_PROPERTY = -6,
 } mnd_result_t;
 
 /*!
@@ -56,6 +59,19 @@ typedef enum mnd_client_flags
 	MND_CLIENT_IO_ACTIVE = (1u << 5u),
 } mnd_client_flags_t;
 
+/*!
+ * A property to get from a thing (currently only devices).
+ *
+ * Supported in version 1.2 and above.
+ */
+typedef enum mnd_property
+{
+	//! Supported in version 1.2 and above.
+	MND_PROPERTY_NAME_STRING = 0,
+	//! Supported in version 1.2 and above.
+	MND_PROPERTY_SERIAL_STRING = 1,
+} mnd_property_t;
+
 /*!
  * Opaque type for libmonado state
  */
@@ -216,9 +232,86 @@ mnd_root_toggle_client_io_active(mnd_root_t *root, uint32_t client_id);
 mnd_result_t
 mnd_root_get_device_count(mnd_root_t *root, uint32_t *out_device_count);
 
+/*!
+ * Get boolean property for the device at the given index.
+ *
+ * Supported in version 1.2 and above.
+ *
+ * @param root          The libmonado state.
+ * @param device_index  Index of device to retrieve name from.
+ * @param prop          A boolean property enum.
+ * @param[out] out_bool Pointer to populate with the boolean.
+ *
+ * @return MND_SUCCESS on success
+ */
+mnd_result_t
+mnd_root_get_device_info_bool(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, bool *out_bool);
+
+/*!
+ * Get int32_t property for the device at the given index.
+ *
+ * Supported in version 1.2 and above.
+ *
+ * @param root         The libmonado state.
+ * @param device_index Index of device to retrieve name from.
+ * @param prop         A int32_t property enum.
+ * @param[out] out_i32 Pointer to populate with the int32_t.
+ *
+ * @return MND_SUCCESS on success
+ */
+mnd_result_t
+mnd_root_get_device_info_i32(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, uint32_t *out_i32);
+
+/*!
+ * Get uint32_t property for the device at the given index.
+ *
+ * Supported in version 1.2 and above.
+ *
+ * @param root          The libmonado state.
+ * @param device_index  Index of device to retrieve name from.
+ * @param prop          A uint32_t property enum.
+ * @param[out] out_u32 Pointer to populate with the uint32_t.
+ *
+ * @return MND_SUCCESS on success
+ */
+mnd_result_t
+mnd_root_get_device_info_u32(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, uint32_t *out_u32);
+
+/*!
+ * Get float property for the device at the given index.
+ *
+ * Supported in version 1.2 and above.
+ *
+ * @param root           The libmonado state.
+ * @param device_index   Index of device to retrieve name from.
+ * @param prop           A float property enum.
+ * @param[out] out_float Pointer to populate with the float.
+ *
+ * @return MND_SUCCESS on success
+ */
+mnd_result_t
+mnd_root_get_device_info_float(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, float *out_float);
+
+/*!
+ * Get string property for the device at the given index.
+ *
+ * Supported in version 1.2 and above.
+ *
+ * @param root            The libmonado state.
+ * @param device_index    Index of device to retrieve name from.
+ * @param prop            A string property enum.
+ * @param[out] out_string Pointer to populate with the string.
+ *
+ * @return MND_SUCCESS on success
+ */
+mnd_result_t
+mnd_root_get_device_info_string(mnd_root_t *root, uint32_t device_index, mnd_property_t prop, const char **out_string);
+
 /*!
  * Get device info at the given index.
  *
+ * @deprecated Deprecated in version 1.2, scheduled for removal in version 2.0.0 currently.
+ *
  * @param root               The libmonado state.
  * @param device_index       Index of device to retrieve name from.
  * @param[out] out_device_id Pointer to value to populate with the device id at the given index.