The open source OpenXR runtime

ipc: Refactor client device to share more code

I didn't completely remove the ipc_client_device and ipc_client_hmd
structs if in the future we want them to have different behaviour.

Part-of: <https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2466>

authored by

Jakob Bornecrantz and committed by
Marge Bot
f59526cf bd9a43c9

+569 -530
+2
src/xrt/ipc/CMakeLists.txt
··· 70 70 client/ipc_client_space_overseer.c 71 71 client/ipc_client_system.c 72 72 client/ipc_client_system_devices.c 73 + client/ipc_client_xdev.c 74 + client/ipc_client_xdev.h 73 75 ) 74 76 target_include_directories( 75 77 ipc_client PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
-26
src/xrt/ipc/client/ipc_client.h
··· 166 166 #endif // XRT_OS_ANDROID 167 167 }; 168 168 169 - /*! 170 - * An IPC client proxy for an @ref xrt_device. 171 - * 172 - * @implements xrt_device 173 - * @ingroup ipc_client 174 - */ 175 - struct ipc_client_xdev 176 - { 177 - struct xrt_device base; 178 - 179 - struct ipc_connection *ipc_c; 180 - 181 - uint32_t device_id; 182 - }; 183 - 184 169 185 170 /* 186 171 * 187 172 * Internal functions. 188 173 * 189 174 */ 190 - 191 - /*! 192 - * Convenience helper to go from a xdev to @ref ipc_client_xdev. 193 - * 194 - * @ingroup ipc_client 195 - */ 196 - static inline struct ipc_client_xdev * 197 - ipc_client_xdev(struct xrt_device *xdev) 198 - { 199 - return (struct ipc_client_xdev *)xdev; 200 - } 201 175 202 176 /*! 203 177 * Create an IPC client system compositor.
+8 -239
src/xrt/ipc/client/ipc_client_device.c
··· 1 1 // Copyright 2020-2024, Collabora, Ltd. 2 + // Copyright 2025, NVIDIA CORPORATION. 2 3 // SPDX-License-Identifier: BSL-1.0 3 4 /*! 4 5 * @file ··· 21 22 22 23 #include "client/ipc_client.h" 23 24 #include "client/ipc_client_connection.h" 25 + #include "client/ipc_client_xdev.h" 24 26 #include "ipc_client_generated.h" 25 27 26 28 #include <math.h> ··· 66 68 // Remove the variable tracking. 67 69 u_var_remove_root(icd); 68 70 69 - // We do not own these, so don't free them. 70 - icd->base.inputs = NULL; 71 - icd->base.outputs = NULL; 71 + // Free and de-init the shared things. 72 + ipc_client_xdev_fini(icd); 72 73 73 74 // Free this device with the helper. 74 75 u_device_free(&icd->base); 75 76 } 76 77 77 - static xrt_result_t 78 - ipc_client_device_update_inputs(struct xrt_device *xdev) 79 - { 80 - ipc_client_device_t *icd = ipc_client_device(xdev); 81 - 82 - xrt_result_t xret = ipc_call_device_update_input(icd->ipc_c, icd->device_id); 83 - IPC_CHK_ALWAYS_RET(icd->ipc_c, xret, "ipc_call_device_update_input"); 84 - } 85 - 86 - static xrt_result_t 87 - ipc_client_device_get_tracked_pose(struct xrt_device *xdev, 88 - enum xrt_input_name name, 89 - int64_t at_timestamp_ns, 90 - struct xrt_space_relation *out_relation) 91 - { 92 - ipc_client_device_t *icd = ipc_client_device(xdev); 93 - 94 - xrt_result_t xret = ipc_call_device_get_tracked_pose( // 95 - icd->ipc_c, // 96 - icd->device_id, // 97 - name, // 98 - at_timestamp_ns, // 99 - out_relation); // 100 - IPC_CHK_ALWAYS_RET(icd->ipc_c, xret, "ipc_call_device_get_tracked_pose"); 101 - } 102 - 103 - static void 104 - ipc_client_device_get_hand_tracking(struct xrt_device *xdev, 105 - enum xrt_input_name name, 106 - int64_t at_timestamp_ns, 107 - struct xrt_hand_joint_set *out_value, 108 - int64_t *out_timestamp_ns) 109 - { 110 - ipc_client_device_t *icd = ipc_client_device(xdev); 111 - 112 - xrt_result_t xret = ipc_call_device_get_hand_tracking( // 113 - icd->ipc_c, // 114 - icd->device_id, // 115 - name, // 116 - at_timestamp_ns, // 117 - out_value, // 118 - out_timestamp_ns); // 119 - IPC_CHK_ONLY_PRINT(icd->ipc_c, xret, "ipc_call_device_get_hand_tracking"); 120 - } 121 - 122 - static xrt_result_t 123 - ipc_client_device_get_face_tracking(struct xrt_device *xdev, 124 - enum xrt_input_name facial_expression_type, 125 - int64_t at_timestamp_ns, 126 - struct xrt_facial_expression_set *out_value) 127 - { 128 - ipc_client_device_t *icd = ipc_client_device(xdev); 129 - 130 - xrt_result_t xret = ipc_call_device_get_face_tracking( // 131 - icd->ipc_c, // 132 - icd->device_id, // 133 - facial_expression_type, // 134 - at_timestamp_ns, // 135 - out_value); // 136 - IPC_CHK_ALWAYS_RET(icd->ipc_c, xret, "ipc_call_device_get_face_tracking"); 137 - } 138 - 139 - static xrt_result_t 140 - ipc_client_device_get_body_skeleton(struct xrt_device *xdev, 141 - enum xrt_input_name body_tracking_type, 142 - struct xrt_body_skeleton *out_value) 143 - { 144 - ipc_client_device_t *icd = ipc_client_device(xdev); 145 - 146 - xrt_result_t xret = ipc_call_device_get_body_skeleton( // 147 - icd->ipc_c, // 148 - icd->device_id, // 149 - body_tracking_type, // 150 - out_value); // 151 - IPC_CHK_ALWAYS_RET(icd->ipc_c, xret, "ipc_call_device_get_body_skeleton"); 152 - } 153 - 154 - static xrt_result_t 155 - ipc_client_device_get_body_joints(struct xrt_device *xdev, 156 - enum xrt_input_name body_tracking_type, 157 - int64_t desired_timestamp_ns, 158 - struct xrt_body_joint_set *out_value) 159 - { 160 - ipc_client_device_t *icd = ipc_client_device(xdev); 161 - 162 - xrt_result_t xret = ipc_call_device_get_body_joints( // 163 - icd->ipc_c, // 164 - icd->device_id, // 165 - body_tracking_type, // 166 - desired_timestamp_ns, // 167 - out_value); // 168 - IPC_CHK_ALWAYS_RET(icd->ipc_c, xret, "ipc_call_device_get_body_joints"); 169 - } 170 - 171 - static void 172 - ipc_client_device_get_view_poses(struct xrt_device *xdev, 173 - const struct xrt_vec3 *default_eye_relation, 174 - int64_t at_timestamp_ns, 175 - uint32_t view_count, 176 - struct xrt_space_relation *out_head_relation, 177 - struct xrt_fov *out_fovs, 178 - struct xrt_pose *out_poses) 179 - { 180 - // Empty 181 - assert(false); 182 - } 183 - 184 - static void 185 - ipc_client_device_set_output(struct xrt_device *xdev, enum xrt_output_name name, const struct xrt_output_value *value) 186 - { 187 - ipc_client_device_t *icd = ipc_client_device(xdev); 188 - struct ipc_connection *ipc_c = icd->ipc_c; 189 - 190 - xrt_result_t xret; 191 - if (value->type == XRT_OUTPUT_VALUE_TYPE_PCM_VIBRATION) { 192 - uint32_t samples_sent = MIN(value->pcm_vibration.sample_rate, 4000); 193 - 194 - struct ipc_pcm_haptic_buffer samples = { 195 - .append = value->pcm_vibration.append, 196 - .num_samples = samples_sent, 197 - .sample_rate = value->pcm_vibration.sample_rate, 198 - }; 199 - 200 - ipc_client_connection_lock(ipc_c); 201 - 202 - xret = ipc_send_device_set_haptic_output_locked(ipc_c, icd->device_id, name, &samples); 203 - IPC_CHK_WITH_RET(ipc_c, xret, "ipc_send_device_set_haptic_output_locked", ); 204 - 205 - xrt_result_t alloc_xret; 206 - xret = ipc_receive(&ipc_c->imc, &alloc_xret, sizeof alloc_xret); 207 - if (xret != XRT_SUCCESS || alloc_xret != XRT_SUCCESS) { 208 - goto send_haptic_output_end; 209 - } 210 - 211 - xret = ipc_send(&ipc_c->imc, value->pcm_vibration.buffer, sizeof(float) * samples_sent); 212 - if (xret != XRT_SUCCESS) { 213 - goto send_haptic_output_end; 214 - } 215 - 216 - xret = ipc_receive(&ipc_c->imc, value->pcm_vibration.samples_consumed, 217 - sizeof(*value->pcm_vibration.samples_consumed)); 218 - if (xret != XRT_SUCCESS) { 219 - goto send_haptic_output_end; 220 - } 221 - 222 - send_haptic_output_end: 223 - ipc_client_connection_unlock(ipc_c); 224 - } else { 225 - xret = ipc_call_device_set_output(ipc_c, icd->device_id, name, value); 226 - IPC_CHK_ONLY_PRINT(ipc_c, xret, "ipc_call_device_set_output"); 227 - } 228 - } 229 - 230 - xrt_result_t 231 - ipc_client_device_get_output_limits(struct xrt_device *xdev, struct xrt_output_limits *limits) 232 - { 233 - ipc_client_device_t *icd = ipc_client_device(xdev); 234 - 235 - xrt_result_t xret = ipc_call_device_get_output_limits(icd->ipc_c, icd->device_id, limits); 236 - IPC_CHK_ONLY_PRINT(icd->ipc_c, xret, "ipc_call_device_get_output_limits"); 237 - 238 - return xret; 239 - } 240 - 241 - static xrt_result_t 242 - ipc_client_device_get_visibility_mask(struct xrt_device *xdev, 243 - enum xrt_visibility_mask_type type, 244 - uint32_t view_index, 245 - struct xrt_visibility_mask **out_mask) 246 - { 247 - assert(false); 248 - return XRT_ERROR_IPC_FAILURE; 249 - } 250 - 251 78 /*! 252 79 * @public @memberof ipc_client_device 253 80 */ 254 81 struct xrt_device * 255 82 ipc_client_device_create(struct ipc_connection *ipc_c, struct xrt_tracking_origin *xtrack, uint32_t device_id) 256 83 { 257 - // Helpers. 258 - struct ipc_shared_memory *ism = ipc_c->ism; 259 - struct ipc_shared_device *isdev = &ism->isdevs[device_id]; 260 - 261 84 // Allocate and setup the basics. 262 85 enum u_device_alloc_flags flags = (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD); 263 86 ipc_client_device_t *icd = U_DEVICE_ALLOCATE(ipc_client_device_t, flags, 0, 0); 264 - icd->ipc_c = ipc_c; 265 - icd->base.update_inputs = ipc_client_device_update_inputs; 266 - icd->base.get_tracked_pose = ipc_client_device_get_tracked_pose; 267 - icd->base.get_hand_tracking = ipc_client_device_get_hand_tracking; 268 - icd->base.get_face_tracking = ipc_client_device_get_face_tracking; 269 - icd->base.get_body_skeleton = ipc_client_device_get_body_skeleton; 270 - icd->base.get_body_joints = ipc_client_device_get_body_joints; 271 - icd->base.get_view_poses = ipc_client_device_get_view_poses; 272 - icd->base.set_output = ipc_client_device_set_output; 273 - icd->base.get_output_limits = ipc_client_device_get_output_limits; 274 - icd->base.get_visibility_mask = ipc_client_device_get_visibility_mask; 275 - icd->base.destroy = ipc_client_device_destroy; 276 87 277 - // Start copying the information from the isdev. 278 - icd->base.tracking_origin = xtrack; 279 - icd->base.name = isdev->name; 280 - icd->device_id = device_id; 88 + // Fills in almost everything a regular device needs. 89 + ipc_client_xdev_init(icd, ipc_c, xtrack, device_id); 281 90 282 - // Print name. 283 - snprintf(icd->base.str, XRT_DEVICE_NAME_LEN, "%s", isdev->str); 284 - snprintf(icd->base.serial, XRT_DEVICE_NAME_LEN, "%s", isdev->serial); 285 - 286 - // Setup inputs, by pointing directly to the shared memory. 287 - assert(isdev->input_count > 0); 288 - icd->base.inputs = &ism->inputs[isdev->first_input_index]; 289 - icd->base.input_count = isdev->input_count; 290 - 291 - // Setup outputs, if any point directly into the shared memory. 292 - icd->base.output_count = isdev->output_count; 293 - if (isdev->output_count > 0) { 294 - icd->base.outputs = &ism->outputs[isdev->first_output_index]; 295 - } else { 296 - icd->base.outputs = NULL; 297 - } 298 - 299 - if (isdev->binding_profile_count > 0) { 300 - icd->base.binding_profiles = 301 - U_TYPED_ARRAY_CALLOC(struct xrt_binding_profile, isdev->binding_profile_count); 302 - icd->base.binding_profile_count = isdev->binding_profile_count; 303 - } 304 - 305 - for (size_t i = 0; i < isdev->binding_profile_count; i++) { 306 - struct xrt_binding_profile *xbp = &icd->base.binding_profiles[i]; 307 - struct ipc_shared_binding_profile *isbp = 308 - &ism->binding_profiles[isdev->first_binding_profile_index + i]; 309 - 310 - xbp->name = isbp->name; 311 - if (isbp->input_count > 0) { 312 - xbp->inputs = &ism->input_pairs[isbp->first_input_index]; 313 - xbp->input_count = isbp->input_count; 314 - } 315 - if (isbp->output_count > 0) { 316 - xbp->outputs = &ism->output_pairs[isbp->first_output_index]; 317 - xbp->output_count = isbp->output_count; 318 - } 319 - } 91 + // Need to set the destroy function. 92 + icd->base.destroy = ipc_client_device_destroy; 320 93 321 94 // Setup variable tracker. 322 95 u_var_add_root(icd, icd->base.str, true); 323 96 u_var_add_ro_u32(icd, &icd->device_id, "device_id"); 324 - 325 - // Copy information. 326 - icd->base.device_type = isdev->device_type; 327 - icd->base.supported = isdev->supported; 328 97 329 98 return &icd->base; 330 99 }
+29 -262
src/xrt/ipc/client/ipc_client_hmd.c
··· 1 1 // Copyright 2020-2024, Collabora, Ltd. 2 + // Copyright 2025, NVIDIA CORPORATION. 2 3 // SPDX-License-Identifier: BSL-1.0 3 4 /*! 4 5 * @file ··· 22 23 #include "util/u_distortion_mesh.h" 23 24 24 25 #include "client/ipc_client.h" 26 + #include "client/ipc_client_xdev.h" 25 27 #include "client/ipc_client_connection.h" 26 28 #include "ipc_client_generated.h" 27 29 ··· 125 127 */ 126 128 127 129 static void 128 - ipc_client_hmd_destroy(struct xrt_device *xdev) 129 - { 130 - ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 131 - 132 - // Remove the variable tracking. 133 - u_var_remove_root(ich); 134 - 135 - // We do not own these, so don't free them. 136 - ich->base.inputs = NULL; 137 - ich->base.outputs = NULL; 138 - 139 - // Free this device with the helper. 140 - u_device_free(&ich->base); 141 - } 142 - 143 - static xrt_result_t 144 - ipc_client_hmd_update_inputs(struct xrt_device *xdev) 145 - { 146 - ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 147 - 148 - xrt_result_t xret = ipc_call_device_update_input(ich->ipc_c, ich->device_id); 149 - IPC_CHK_ALWAYS_RET(ich->ipc_c, xret, "ipc_call_device_update_input"); 150 - } 151 - 152 - static xrt_result_t 153 - ipc_client_hmd_get_tracked_pose(struct xrt_device *xdev, 154 - enum xrt_input_name name, 155 - int64_t at_timestamp_ns, 156 - struct xrt_space_relation *out_relation) 157 - { 158 - ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 159 - xrt_result_t xret; 160 - 161 - xret = ipc_call_device_get_tracked_pose( // 162 - ich->ipc_c, // 163 - ich->device_id, // 164 - name, // 165 - at_timestamp_ns, // 166 - out_relation); // 167 - IPC_CHK_ALWAYS_RET(ich->ipc_c, xret, "ipc_call_device_get_tracked_pose"); 168 - } 169 - 170 - static void 171 130 ipc_client_hmd_get_view_poses(struct xrt_device *xdev, 172 131 const struct xrt_vec3 *default_eye_relation, 173 132 int64_t at_timestamp_ns, ··· 216 175 } 217 176 } 218 177 219 - static xrt_result_t 220 - ipc_client_hmd_get_face_tracking(struct xrt_device *xdev, 221 - enum xrt_input_name facial_expression_type, 222 - int64_t at_timestamp_ns, 223 - struct xrt_facial_expression_set *out_value) 224 - { 225 - ipc_client_hmd_t *icd = ipc_client_hmd(xdev); 226 - 227 - xrt_result_t xret = ipc_call_device_get_face_tracking( // 228 - icd->ipc_c, // 229 - icd->device_id, // 230 - facial_expression_type, // 231 - at_timestamp_ns, // 232 - out_value); // 233 - IPC_CHK_ALWAYS_RET(icd->ipc_c, xret, "ipc_call_device_get_face_tracking"); 234 - } 235 - 236 178 static bool 237 179 ipc_client_hmd_compute_distortion( 238 180 struct xrt_device *xdev, uint32_t view, float u, float v, struct xrt_uv_triplet *out_result) ··· 271 213 return available; 272 214 } 273 215 274 - static enum xrt_result 275 - ipc_client_hmd_begin_plane_detection_ext(struct xrt_device *xdev, 276 - const struct xrt_plane_detector_begin_info_ext *begin_info, 277 - uint64_t plane_detection_id, 278 - uint64_t *out_plane_detection_id) 279 - { 280 - ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 281 - 282 - ich->ipc_c->ism->plane_begin_info_ext = *begin_info; 283 - 284 - xrt_result_t r = ipc_call_device_begin_plane_detection_ext(ich->ipc_c, ich->device_id, plane_detection_id, 285 - out_plane_detection_id); 286 - if (r != XRT_SUCCESS) { 287 - IPC_ERROR(ich->ipc_c, "Error sending hmd_begin_plane_detection_ext!"); 288 - return r; 289 - } 290 - 291 - return XRT_SUCCESS; 292 - } 293 - 294 - static enum xrt_result 295 - ipc_client_hmd_destroy_plane_detection_ext(struct xrt_device *xdev, uint64_t plane_detection_id) 296 - { 297 - ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 298 - 299 - xrt_result_t r = ipc_call_device_destroy_plane_detection_ext(ich->ipc_c, ich->device_id, plane_detection_id); 300 - if (r != XRT_SUCCESS) { 301 - IPC_ERROR(ich->ipc_c, "Error sending destroy_plane_detection_ext!"); 302 - return r; 303 - } 304 - 305 - return XRT_SUCCESS; 306 - } 307 - 308 - /*! 309 - * Helper function for @ref xrt_device::get_plane_detection_state. 310 - * 311 - * @public @memberof xrt_device 312 - */ 313 - static inline enum xrt_result 314 - ipc_client_hmd_get_plane_detection_state_ext(struct xrt_device *xdev, 315 - uint64_t plane_detection_id, 316 - enum xrt_plane_detector_state_ext *out_state) 317 - { 318 - ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 319 - 320 - xrt_result_t r = 321 - ipc_call_device_get_plane_detection_state_ext(ich->ipc_c, ich->device_id, plane_detection_id, out_state); 322 - if (r != XRT_SUCCESS) { 323 - IPC_ERROR(ich->ipc_c, "Error sending get_plane_detection_state_ext!"); 324 - return r; 325 - } 326 - 327 - return XRT_SUCCESS; 328 - } 329 - 330 - /*! 331 - * Helper function for @ref xrt_device::get_plane_detections. 332 - * 333 - * @public @memberof xrt_device 334 - */ 335 - static inline enum xrt_result 336 - ipc_client_hmd_get_plane_detections_ext(struct xrt_device *xdev, 337 - uint64_t plane_detection_id, 338 - struct xrt_plane_detections_ext *out_detections) 339 - { 340 - ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 341 - struct ipc_connection *ipc_c = ich->ipc_c; 342 - 343 - ipc_client_connection_lock(ipc_c); 344 - 345 - xrt_result_t xret = ipc_send_device_get_plane_detections_ext_locked(ipc_c, ich->device_id, plane_detection_id); 346 - IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_send_device_get_plane_detections_ext_locked", out); 347 - 348 - // in this case, size == count 349 - uint32_t location_size = 0; 350 - uint32_t polygon_size = 0; 351 - uint32_t vertex_size = 0; 352 - 353 - xret = ipc_receive_device_get_plane_detections_ext_locked(ipc_c, &location_size, &polygon_size, &vertex_size); 354 - IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive_device_get_plane_detections_ext_locked", out); 355 - 356 - 357 - // With no locations, the service won't send anything else 358 - if (location_size < 1) { 359 - out_detections->location_count = 0; 360 - goto out; 361 - } 362 - 363 - // realloc arrays in out_detections if necessary, then receive contents 364 - 365 - out_detections->location_count = location_size; 366 - if (out_detections->location_size < location_size) { 367 - U_ARRAY_REALLOC_OR_FREE(out_detections->locations, struct xrt_plane_detector_location_ext, 368 - location_size); 369 - U_ARRAY_REALLOC_OR_FREE(out_detections->polygon_info_start_index, uint32_t, location_size); 370 - out_detections->location_size = location_size; 371 - } 372 - 373 - if (out_detections->polygon_info_size < polygon_size) { 374 - U_ARRAY_REALLOC_OR_FREE(out_detections->polygon_infos, struct xrt_plane_polygon_info_ext, polygon_size); 375 - out_detections->polygon_info_size = polygon_size; 376 - } 377 - 378 - if (out_detections->vertex_size < vertex_size) { 379 - U_ARRAY_REALLOC_OR_FREE(out_detections->vertices, struct xrt_vec2, vertex_size); 380 - out_detections->vertex_size = vertex_size; 381 - } 382 - 383 - if ((location_size > 0 && 384 - (out_detections->locations == NULL || out_detections->polygon_info_start_index == NULL)) || 385 - (polygon_size > 0 && out_detections->polygon_infos == NULL) || 386 - (vertex_size > 0 && out_detections->vertices == NULL)) { 387 - IPC_ERROR(ich->ipc_c, "Error allocating memory for plane detections!"); 388 - out_detections->location_size = 0; 389 - out_detections->polygon_info_size = 0; 390 - out_detections->vertex_size = 0; 391 - xret = XRT_ERROR_IPC_FAILURE; 392 - goto out; 393 - } 394 - 395 - if (location_size > 0) { 396 - // receive location_count * locations 397 - xret = ipc_receive(&ipc_c->imc, out_detections->locations, 398 - sizeof(struct xrt_plane_detector_location_ext) * location_size); 399 - IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(1)", out); 400 - 401 - // receive location_count * polygon_info_start_index 402 - xret = ipc_receive(&ipc_c->imc, out_detections->polygon_info_start_index, 403 - sizeof(uint32_t) * location_size); 404 - IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(2)", out); 405 - } 406 - 407 - 408 - if (polygon_size > 0) { 409 - // receive polygon_count * polygon_infos 410 - xret = ipc_receive(&ipc_c->imc, out_detections->polygon_infos, 411 - sizeof(struct xrt_plane_polygon_info_ext) * polygon_size); 412 - IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(3)", out); 413 - } 414 - 415 - if (vertex_size > 0) { 416 - // receive vertex_count * vertices 417 - xret = ipc_receive(&ipc_c->imc, out_detections->vertices, sizeof(struct xrt_vec2) * vertex_size); 418 - IPC_CHK_WITH_GOTO(ich->ipc_c, xret, "ipc_receive(4)", out); 419 - } 420 - 421 - out: 422 - ipc_client_connection_unlock(ipc_c); 423 - return xret; 424 - } 425 - 426 216 static xrt_result_t 427 217 ipc_client_hmd_get_visibility_mask(struct xrt_device *xdev, 428 218 enum xrt_visibility_mask_type type, ··· 464 254 return XRT_ERROR_IPC_FAILURE; 465 255 } 466 256 257 + static void 258 + ipc_client_hmd_destroy(struct xrt_device *xdev) 259 + { 260 + ipc_client_hmd_t *ich = ipc_client_hmd(xdev); 261 + 262 + // Remove the variable tracking. 263 + u_var_remove_root(ich); 264 + 265 + // Free and de-init the shared things. 266 + ipc_client_xdev_fini(ich); 267 + 268 + // Free this device with the helper. 269 + u_device_free(&ich->base); 270 + } 271 + 467 272 /*! 468 273 * @public @memberof ipc_client_hmd 469 274 */ 470 275 struct xrt_device * 471 276 ipc_client_hmd_create(struct ipc_connection *ipc_c, struct xrt_tracking_origin *xtrack, uint32_t device_id) 472 277 { 278 + // Convenience helper. 473 279 struct ipc_shared_memory *ism = ipc_c->ism; 474 - struct ipc_shared_device *isdev = &ism->isdevs[device_id]; 475 280 476 - 477 - 281 + // Allocate a HMD device. 478 282 enum u_device_alloc_flags flags = (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD); 479 283 ipc_client_hmd_t *ich = U_DEVICE_ALLOCATE(ipc_client_hmd_t, flags, 0, 0); 480 - ich->ipc_c = ipc_c; 481 - ich->device_id = device_id; 482 - ich->base.update_inputs = ipc_client_hmd_update_inputs; 483 - ich->base.get_tracked_pose = ipc_client_hmd_get_tracked_pose; 484 - ich->base.get_face_tracking = ipc_client_hmd_get_face_tracking; 284 + 285 + // Fills in almost everything a regular device needs. 286 + ipc_client_xdev_init(ich, ipc_c, xtrack, device_id); 287 + 288 + // Fill in needed HMD functions, and destroy. 485 289 ich->base.get_view_poses = ipc_client_hmd_get_view_poses; 486 290 ich->base.compute_distortion = ipc_client_hmd_compute_distortion; 487 - ich->base.begin_plane_detection_ext = ipc_client_hmd_begin_plane_detection_ext; 488 - ich->base.destroy_plane_detection_ext = ipc_client_hmd_destroy_plane_detection_ext; 489 - ich->base.get_plane_detection_state_ext = ipc_client_hmd_get_plane_detection_state_ext; 490 - ich->base.get_plane_detections_ext = ipc_client_hmd_get_plane_detections_ext; 491 - ich->base.destroy = ipc_client_hmd_destroy; 492 291 ich->base.is_form_factor_available = ipc_client_hmd_is_form_factor_available; 493 292 ich->base.get_visibility_mask = ipc_client_hmd_get_visibility_mask; 494 - 495 - // Start copying the information from the isdev. 496 - ich->base.tracking_origin = xtrack; 497 - ich->base.name = isdev->name; 498 - ich->device_id = device_id; 499 - 500 - // Print name. 501 - snprintf(ich->base.str, XRT_DEVICE_NAME_LEN, "%s", isdev->str); 502 - snprintf(ich->base.serial, XRT_DEVICE_NAME_LEN, "%s", isdev->serial); 503 - 504 - // Setup inputs, by pointing directly to the shared memory. 505 - assert(isdev->input_count > 0); 506 - ich->base.inputs = &ism->inputs[isdev->first_input_index]; 507 - ich->base.input_count = isdev->input_count; 508 - 509 - #if 0 510 - // Setup info. 511 - struct u_device_simple_info info; 512 - info.display.w_pixels = 1920; 513 - info.display.h_pixels = 1080; 514 - info.display.w_meters = 0.13f; 515 - info.display.h_meters = 0.07f; 516 - info.lens_horizontal_separation_meters = 0.13f / 2.0f; 517 - info.lens_vertical_position_meters = 0.07f / 2.0f; 518 - info.views[0].fov = 85.0f * (M_PI / 180.0f); 519 - info.views[1].fov = 85.0f * (M_PI / 180.0f); 293 + ich->base.destroy = ipc_client_hmd_destroy; 520 294 521 - if (!u_device_setup_split_side_by_side(&ich->base, &info)) { 522 - IPC_ERROR(ich->ipc_c, "Failed to setup basic device info"); 523 - ipc_client_hmd_destroy(&ich->base); 524 - return NULL; 525 - } 526 - #endif 295 + // Setup blend-modes. 296 + ich->base.hmd->blend_mode_count = ipc_c->ism->hmd.blend_mode_count; 527 297 for (int i = 0; i < XRT_MAX_DEVICE_BLEND_MODES; i++) { 528 298 ich->base.hmd->blend_modes[i] = ipc_c->ism->hmd.blend_modes[i]; 529 299 } 300 + 301 + // Setup the views. 530 302 ich->base.hmd->view_count = ism->hmd.view_count; 531 - ich->base.hmd->blend_mode_count = ipc_c->ism->hmd.blend_mode_count; 532 303 for (uint32_t i = 0; i < ich->base.hmd->view_count; ++i) { 533 304 ich->base.hmd->views[i].display.w_pixels = ipc_c->ism->hmd.views[i].display.w_pixels; 534 305 ich->base.hmd->views[i].display.h_pixels = ipc_c->ism->hmd.views[i].display.h_pixels; ··· 540 311 // Setup variable tracker. 541 312 u_var_add_root(ich, ich->base.str, true); 542 313 u_var_add_ro_u32(ich, &ich->device_id, "device_id"); 543 - 544 - // Copy information. 545 - ich->base.device_type = isdev->device_type; 546 - ich->base.supported = isdev->supported; 547 314 548 315 return &ich->base; 549 316 }
+6 -3
src/xrt/ipc/client/ipc_client_space_overseer.c
··· 7 7 * @ingroup ipc_client 8 8 */ 9 9 10 + #include "xrt/xrt_defines.h" 11 + #include "xrt/xrt_space.h" 12 + 13 + #include "shared/ipc_message_channel.h" 14 + 10 15 #include "client/ipc_client.h" 16 + #include "client/ipc_client_xdev.h" 11 17 #include "client/ipc_client_connection.h" 12 - #include "shared/ipc_message_channel.h" 13 - #include "xrt/xrt_defines.h" 14 - #include "xrt/xrt_space.h" 15 18 16 19 #include "ipc_client_generated.h" 17 20
+449
src/xrt/ipc/client/ipc_client_xdev.c
··· 1 + // Copyright 2020-2024, Collabora, Ltd. 2 + // Copyright 2025, NVIDIA CORPORATION. 3 + // SPDX-License-Identifier: BSL-1.0 4 + /*! 5 + * @file 6 + * @brief Shared functions for IPC client @ref xrt_device. 7 + * @author Jakob Bornecrantz <jakob@collabora.com> 8 + * @author Jakob Bornecrantz <tbornecrantz@nvidia.com> 9 + * @author Korcan Hussein <korcan.hussein@collabora.com> 10 + * @ingroup ipc_client 11 + */ 12 + 13 + #include "xrt/xrt_device.h" 14 + 15 + #include "os/os_time.h" 16 + 17 + #include "math/m_api.h" 18 + 19 + #include "util/u_var.h" 20 + #include "util/u_misc.h" 21 + #include "util/u_debug.h" 22 + #include "util/u_device.h" 23 + 24 + #include "client/ipc_client.h" 25 + #include "client/ipc_client_connection.h" 26 + #include "client/ipc_client_xdev.h" 27 + #include "ipc_client_generated.h" 28 + 29 + 30 + /* 31 + * 32 + * Functions from xrt_device. 33 + * 34 + */ 35 + 36 + static xrt_result_t 37 + ipc_client_xdev_update_inputs(struct xrt_device *xdev) 38 + { 39 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 40 + 41 + xrt_result_t xret = ipc_call_device_update_input(icx->ipc_c, icx->device_id); 42 + IPC_CHK_ALWAYS_RET(icx->ipc_c, xret, "ipc_call_device_update_input"); 43 + } 44 + 45 + static xrt_result_t 46 + ipc_client_xdev_get_tracked_pose(struct xrt_device *xdev, 47 + enum xrt_input_name name, 48 + int64_t at_timestamp_ns, 49 + struct xrt_space_relation *out_relation) 50 + { 51 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 52 + 53 + xrt_result_t xret = ipc_call_device_get_tracked_pose( // 54 + icx->ipc_c, // 55 + icx->device_id, // 56 + name, // 57 + at_timestamp_ns, // 58 + out_relation); // 59 + IPC_CHK_ALWAYS_RET(icx->ipc_c, xret, "ipc_call_device_get_tracked_pose"); 60 + } 61 + 62 + static void 63 + ipc_client_xdev_get_hand_tracking(struct xrt_device *xdev, 64 + enum xrt_input_name name, 65 + int64_t at_timestamp_ns, 66 + struct xrt_hand_joint_set *out_value, 67 + int64_t *out_timestamp_ns) 68 + { 69 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 70 + 71 + xrt_result_t xret = ipc_call_device_get_hand_tracking( // 72 + icx->ipc_c, // 73 + icx->device_id, // 74 + name, // 75 + at_timestamp_ns, // 76 + out_value, // 77 + out_timestamp_ns); // 78 + IPC_CHK_ONLY_PRINT(icx->ipc_c, xret, "ipc_call_device_get_hand_tracking"); 79 + } 80 + 81 + static xrt_result_t 82 + ipc_client_xdev_get_face_tracking(struct xrt_device *xdev, 83 + enum xrt_input_name facial_expression_type, 84 + int64_t at_timestamp_ns, 85 + struct xrt_facial_expression_set *out_value) 86 + { 87 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 88 + 89 + xrt_result_t xret = ipc_call_device_get_face_tracking( // 90 + icx->ipc_c, // 91 + icx->device_id, // 92 + facial_expression_type, // 93 + at_timestamp_ns, // 94 + out_value); // 95 + IPC_CHK_ALWAYS_RET(icx->ipc_c, xret, "ipc_call_device_get_face_tracking"); 96 + } 97 + 98 + static xrt_result_t 99 + ipc_client_xdev_get_body_skeleton(struct xrt_device *xdev, 100 + enum xrt_input_name body_tracking_type, 101 + struct xrt_body_skeleton *out_value) 102 + { 103 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 104 + 105 + xrt_result_t xret = ipc_call_device_get_body_skeleton( // 106 + icx->ipc_c, // 107 + icx->device_id, // 108 + body_tracking_type, // 109 + out_value); // 110 + IPC_CHK_ALWAYS_RET(icx->ipc_c, xret, "ipc_call_device_get_body_skeleton"); 111 + } 112 + 113 + static xrt_result_t 114 + ipc_client_xdev_get_body_joints(struct xrt_device *xdev, 115 + enum xrt_input_name body_tracking_type, 116 + int64_t desired_timestamp_ns, 117 + struct xrt_body_joint_set *out_value) 118 + { 119 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 120 + 121 + xrt_result_t xret = ipc_call_device_get_body_joints( // 122 + icx->ipc_c, // 123 + icx->device_id, // 124 + body_tracking_type, // 125 + desired_timestamp_ns, // 126 + out_value); // 127 + IPC_CHK_ALWAYS_RET(icx->ipc_c, xret, "ipc_call_device_get_body_joints"); 128 + } 129 + 130 + static void 131 + ipc_client_xdev_set_output(struct xrt_device *xdev, enum xrt_output_name name, const struct xrt_output_value *value) 132 + { 133 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 134 + struct ipc_connection *ipc_c = icx->ipc_c; 135 + 136 + xrt_result_t xret; 137 + if (value->type == XRT_OUTPUT_VALUE_TYPE_PCM_VIBRATION) { 138 + uint32_t samples_sent = MIN(value->pcm_vibration.sample_rate, 4000); 139 + 140 + struct ipc_pcm_haptic_buffer samples = { 141 + .append = value->pcm_vibration.append, 142 + .num_samples = samples_sent, 143 + .sample_rate = value->pcm_vibration.sample_rate, 144 + }; 145 + 146 + ipc_client_connection_lock(ipc_c); 147 + 148 + xret = ipc_send_device_set_haptic_output_locked(ipc_c, icx->device_id, name, &samples); 149 + IPC_CHK_WITH_RET(ipc_c, xret, "ipc_send_device_set_haptic_output_locked", ); 150 + 151 + xrt_result_t alloc_xret; 152 + xret = ipc_receive(&ipc_c->imc, &alloc_xret, sizeof alloc_xret); 153 + if (xret != XRT_SUCCESS || alloc_xret != XRT_SUCCESS) { 154 + goto send_haptic_output_end; 155 + } 156 + 157 + xret = ipc_send(&ipc_c->imc, value->pcm_vibration.buffer, sizeof(float) * samples_sent); 158 + if (xret != XRT_SUCCESS) { 159 + goto send_haptic_output_end; 160 + } 161 + 162 + xret = ipc_receive(&ipc_c->imc, value->pcm_vibration.samples_consumed, 163 + sizeof(*value->pcm_vibration.samples_consumed)); 164 + if (xret != XRT_SUCCESS) { 165 + goto send_haptic_output_end; 166 + } 167 + 168 + send_haptic_output_end: 169 + ipc_client_connection_unlock(ipc_c); 170 + } else { 171 + xret = ipc_call_device_set_output(ipc_c, icx->device_id, name, value); 172 + IPC_CHK_ONLY_PRINT(ipc_c, xret, "ipc_call_device_set_output"); 173 + } 174 + } 175 + 176 + xrt_result_t 177 + ipc_client_xdev_get_output_limits(struct xrt_device *xdev, struct xrt_output_limits *limits) 178 + { 179 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 180 + 181 + xrt_result_t xret = ipc_call_device_get_output_limits(icx->ipc_c, icx->device_id, limits); 182 + IPC_CHK_ONLY_PRINT(icx->ipc_c, xret, "ipc_call_device_get_output_limits"); 183 + 184 + return xret; 185 + } 186 + 187 + 188 + /* 189 + * 190 + * Plane detection functions. 191 + * 192 + */ 193 + 194 + static xrt_result_t 195 + ipc_client_xdev_begin_plane_detection_ext(struct xrt_device *xdev, 196 + const struct xrt_plane_detector_begin_info_ext *begin_info, 197 + uint64_t plane_detection_id, 198 + uint64_t *out_plane_detection_id) 199 + { 200 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 201 + 202 + icx->ipc_c->ism->plane_begin_info_ext = *begin_info; 203 + 204 + xrt_result_t r = ipc_call_device_begin_plane_detection_ext(icx->ipc_c, icx->device_id, plane_detection_id, 205 + out_plane_detection_id); 206 + if (r != XRT_SUCCESS) { 207 + IPC_ERROR(icx->ipc_c, "Error sending hmd_begin_plane_detection_ext!"); 208 + return r; 209 + } 210 + 211 + return XRT_SUCCESS; 212 + } 213 + 214 + static xrt_result_t 215 + ipc_client_xdev_destroy_plane_detection_ext(struct xrt_device *xdev, uint64_t plane_detection_id) 216 + { 217 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 218 + 219 + xrt_result_t r = ipc_call_device_destroy_plane_detection_ext(icx->ipc_c, icx->device_id, plane_detection_id); 220 + if (r != XRT_SUCCESS) { 221 + IPC_ERROR(icx->ipc_c, "Error sending destroy_plane_detection_ext!"); 222 + return r; 223 + } 224 + 225 + return XRT_SUCCESS; 226 + } 227 + 228 + /*! 229 + * Helper function for @ref xrt_device::get_plane_detection_state. 230 + * 231 + * @public @memberof xrt_device 232 + */ 233 + static xrt_result_t 234 + ipc_client_xdev_get_plane_detection_state_ext(struct xrt_device *xdev, 235 + uint64_t plane_detection_id, 236 + enum xrt_plane_detector_state_ext *out_state) 237 + { 238 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 239 + 240 + xrt_result_t r = 241 + ipc_call_device_get_plane_detection_state_ext(icx->ipc_c, icx->device_id, plane_detection_id, out_state); 242 + if (r != XRT_SUCCESS) { 243 + IPC_ERROR(icx->ipc_c, "Error sending get_plane_detection_state_ext!"); 244 + return r; 245 + } 246 + 247 + return XRT_SUCCESS; 248 + } 249 + 250 + /*! 251 + * Helper function for @ref xrt_device::get_plane_detections. 252 + * 253 + * @public @memberof xrt_device 254 + */ 255 + static xrt_result_t 256 + ipc_client_xdev_get_plane_detections_ext(struct xrt_device *xdev, 257 + uint64_t plane_detection_id, 258 + struct xrt_plane_detections_ext *out_detections) 259 + { 260 + struct ipc_client_xdev *icx = ipc_client_xdev(xdev); 261 + struct ipc_connection *ipc_c = icx->ipc_c; 262 + 263 + ipc_client_connection_lock(ipc_c); 264 + 265 + xrt_result_t xret = ipc_send_device_get_plane_detections_ext_locked(ipc_c, icx->device_id, plane_detection_id); 266 + IPC_CHK_WITH_GOTO(icx->ipc_c, xret, "ipc_send_device_get_plane_detections_ext_locked", out); 267 + 268 + // in this case, size == count 269 + uint32_t location_size = 0; 270 + uint32_t polygon_size = 0; 271 + uint32_t vertex_size = 0; 272 + 273 + xret = ipc_receive_device_get_plane_detections_ext_locked(ipc_c, &location_size, &polygon_size, &vertex_size); 274 + IPC_CHK_WITH_GOTO(icx->ipc_c, xret, "ipc_receive_device_get_plane_detections_ext_locked", out); 275 + 276 + 277 + // With no locations, the service won't send anything else 278 + if (location_size < 1) { 279 + out_detections->location_count = 0; 280 + goto out; 281 + } 282 + 283 + // realloc arrays in out_detections if necessary, then receive contents 284 + 285 + out_detections->location_count = location_size; 286 + if (out_detections->location_size < location_size) { 287 + U_ARRAY_REALLOC_OR_FREE(out_detections->locations, struct xrt_plane_detector_location_ext, 288 + location_size); 289 + U_ARRAY_REALLOC_OR_FREE(out_detections->polygon_info_start_index, uint32_t, location_size); 290 + out_detections->location_size = location_size; 291 + } 292 + 293 + if (out_detections->polygon_info_size < polygon_size) { 294 + U_ARRAY_REALLOC_OR_FREE(out_detections->polygon_infos, struct xrt_plane_polygon_info_ext, polygon_size); 295 + out_detections->polygon_info_size = polygon_size; 296 + } 297 + 298 + if (out_detections->vertex_size < vertex_size) { 299 + U_ARRAY_REALLOC_OR_FREE(out_detections->vertices, struct xrt_vec2, vertex_size); 300 + out_detections->vertex_size = vertex_size; 301 + } 302 + 303 + if ((location_size > 0 && 304 + (out_detections->locations == NULL || out_detections->polygon_info_start_index == NULL)) || 305 + (polygon_size > 0 && out_detections->polygon_infos == NULL) || 306 + (vertex_size > 0 && out_detections->vertices == NULL)) { 307 + IPC_ERROR(icx->ipc_c, "Error allocating memory for plane detections!"); 308 + out_detections->location_size = 0; 309 + out_detections->polygon_info_size = 0; 310 + out_detections->vertex_size = 0; 311 + xret = XRT_ERROR_IPC_FAILURE; 312 + goto out; 313 + } 314 + 315 + if (location_size > 0) { 316 + // receive location_count * locations 317 + xret = ipc_receive(&ipc_c->imc, out_detections->locations, 318 + sizeof(struct xrt_plane_detector_location_ext) * location_size); 319 + IPC_CHK_WITH_GOTO(icx->ipc_c, xret, "ipc_receive(1)", out); 320 + 321 + // receive location_count * polygon_info_start_index 322 + xret = ipc_receive(&ipc_c->imc, out_detections->polygon_info_start_index, 323 + sizeof(uint32_t) * location_size); 324 + IPC_CHK_WITH_GOTO(icx->ipc_c, xret, "ipc_receive(2)", out); 325 + } 326 + 327 + 328 + if (polygon_size > 0) { 329 + // receive polygon_count * polygon_infos 330 + xret = ipc_receive(&ipc_c->imc, out_detections->polygon_infos, 331 + sizeof(struct xrt_plane_polygon_info_ext) * polygon_size); 332 + IPC_CHK_WITH_GOTO(icx->ipc_c, xret, "ipc_receive(3)", out); 333 + } 334 + 335 + if (vertex_size > 0) { 336 + // receive vertex_count * vertices 337 + xret = ipc_receive(&ipc_c->imc, out_detections->vertices, sizeof(struct xrt_vec2) * vertex_size); 338 + IPC_CHK_WITH_GOTO(icx->ipc_c, xret, "ipc_receive(4)", out); 339 + } 340 + 341 + out: 342 + ipc_client_connection_unlock(ipc_c); 343 + return xret; 344 + } 345 + 346 + 347 + /* 348 + * 349 + * 'Exported' functions. 350 + * 351 + */ 352 + 353 + void 354 + ipc_client_xdev_init(struct ipc_client_xdev *icx, 355 + struct ipc_connection *ipc_c, 356 + struct xrt_tracking_origin *xtrack, 357 + uint32_t device_id) 358 + { 359 + // Helpers. 360 + struct ipc_shared_memory *ism = ipc_c->ism; 361 + struct ipc_shared_device *isdev = &ism->isdevs[device_id]; 362 + 363 + // Important fields. 364 + icx->ipc_c = ipc_c; 365 + icx->device_id = device_id; 366 + 367 + // Shared implemented functions. 368 + icx->base.update_inputs = ipc_client_xdev_update_inputs; 369 + icx->base.get_tracked_pose = ipc_client_xdev_get_tracked_pose; 370 + icx->base.get_hand_tracking = ipc_client_xdev_get_hand_tracking; 371 + icx->base.get_face_tracking = ipc_client_xdev_get_face_tracking; 372 + icx->base.get_body_skeleton = ipc_client_xdev_get_body_skeleton; 373 + icx->base.get_body_joints = ipc_client_xdev_get_body_joints; 374 + icx->base.set_output = ipc_client_xdev_set_output; 375 + icx->base.get_output_limits = ipc_client_xdev_get_output_limits; 376 + 377 + // Plane detection EXT. 378 + icx->base.begin_plane_detection_ext = ipc_client_xdev_begin_plane_detection_ext; 379 + icx->base.destroy_plane_detection_ext = ipc_client_xdev_destroy_plane_detection_ext; 380 + icx->base.get_plane_detection_state_ext = ipc_client_xdev_get_plane_detection_state_ext; 381 + icx->base.get_plane_detections_ext = ipc_client_xdev_get_plane_detections_ext; 382 + 383 + // Not implemented functions, some get overridden. 384 + icx->base.get_view_poses = u_device_ni_get_view_poses; 385 + icx->base.compute_distortion = u_device_ni_compute_distortion; 386 + icx->base.get_visibility_mask = u_device_ni_get_visibility_mask; 387 + icx->base.is_form_factor_available = u_device_ni_is_form_factor_available; 388 + icx->base.get_battery_status = u_device_ni_get_battery_status; 389 + 390 + // Copying the information from the isdev. 391 + icx->base.device_type = isdev->device_type; 392 + icx->base.supported = isdev->supported; 393 + icx->base.tracking_origin = xtrack; 394 + icx->base.name = isdev->name; 395 + 396 + // Print name. 397 + snprintf(icx->base.str, XRT_DEVICE_NAME_LEN, "%s", isdev->str); 398 + snprintf(icx->base.serial, XRT_DEVICE_NAME_LEN, "%s", isdev->serial); 399 + 400 + // Setup inputs, by pointing directly to the shared memory. 401 + assert(isdev->input_count > 0); 402 + icx->base.inputs = &ism->inputs[isdev->first_input_index]; 403 + icx->base.input_count = isdev->input_count; 404 + 405 + // Setup outputs, if any point directly into the shared memory. 406 + icx->base.output_count = isdev->output_count; 407 + if (isdev->output_count > 0) { 408 + icx->base.outputs = &ism->outputs[isdev->first_output_index]; 409 + } else { 410 + icx->base.outputs = NULL; 411 + } 412 + 413 + // Setup binding profiles. 414 + icx->base.binding_profile_count = isdev->binding_profile_count; 415 + if (isdev->binding_profile_count > 0) { 416 + icx->base.binding_profiles = 417 + U_TYPED_ARRAY_CALLOC(struct xrt_binding_profile, isdev->binding_profile_count); 418 + } 419 + 420 + for (size_t i = 0; i < isdev->binding_profile_count; i++) { 421 + struct xrt_binding_profile *xbp = &icx->base.binding_profiles[i]; 422 + struct ipc_shared_binding_profile *isbp = 423 + &ism->binding_profiles[isdev->first_binding_profile_index + i]; 424 + 425 + xbp->name = isbp->name; 426 + if (isbp->input_count > 0) { 427 + xbp->inputs = &ism->input_pairs[isbp->first_input_index]; 428 + xbp->input_count = isbp->input_count; 429 + } 430 + if (isbp->output_count > 0) { 431 + xbp->outputs = &ism->output_pairs[isbp->first_output_index]; 432 + xbp->output_count = isbp->output_count; 433 + } 434 + } 435 + } 436 + 437 + void 438 + ipc_client_xdev_fini(struct ipc_client_xdev *icx) 439 + { 440 + // We do not own these, so don't free them. 441 + icx->base.inputs = NULL; 442 + icx->base.outputs = NULL; 443 + 444 + // We allocated the bindings profiles. 445 + if (icx->base.binding_profiles != NULL) { 446 + free(icx->base.binding_profiles); 447 + icx->base.binding_profiles = NULL; 448 + } 449 + }
+75
src/xrt/ipc/client/ipc_client_xdev.h
··· 1 + // Copyright 2020-2023, Collabora, Ltd. 2 + // Copyright 2025, NVIDIA CORPORATION. 3 + // SPDX-License-Identifier: BSL-1.0 4 + /*! 5 + * @file 6 + * @brief Shared functions for IPC client @ref xrt_device. 7 + * @author Pete Black <pblack@collabora.com> 8 + * @author Jakob Bornecrantz <jakob@collabora.com> 9 + * @author Jakob Bornecrantz <tbornecrantz@nvidia.com> 10 + * @author Rylie Pavlik <rylie.pavlik@collabora.com> 11 + * @ingroup ipc_client 12 + */ 13 + 14 + #pragma once 15 + 16 + #ifdef __cplusplus 17 + extern "C" { 18 + #endif 19 + 20 + 21 + struct ipc_connection; 22 + 23 + /*! 24 + * An IPC client proxy for an @ref xrt_device. 25 + * 26 + * @implements xrt_device 27 + * @ingroup ipc_client 28 + */ 29 + struct ipc_client_xdev 30 + { 31 + struct xrt_device base; 32 + 33 + struct ipc_connection *ipc_c; 34 + 35 + uint32_t device_id; 36 + }; 37 + 38 + /*! 39 + * Convenience helper to go from a xdev to @ref ipc_client_xdev. 40 + * 41 + * @ingroup ipc_client 42 + */ 43 + static inline struct ipc_client_xdev * 44 + ipc_client_xdev(struct xrt_device *xdev) 45 + { 46 + return (struct ipc_client_xdev *)xdev; 47 + } 48 + 49 + /*! 50 + * Initializes a ipc_client_xdev so that it's basically fully usable as a 51 + * @ref xrt_device object. Does not fill in the destroy function or the any 52 + * if the HMD components / functions. 53 + * 54 + * @ingroup ipc_client 55 + * @public @memberof ipc_client_xdev 56 + */ 57 + void 58 + ipc_client_xdev_init(struct ipc_client_xdev *icx, 59 + struct ipc_connection *ipc_c, 60 + struct xrt_tracking_origin *xtrack, 61 + uint32_t device_id); 62 + 63 + /*! 64 + * Frees any memory that was allocated as part of init and resets some pointers. 65 + * 66 + * @ingroup ipc_client 67 + * @public @memberof ipc_client_xdev 68 + */ 69 + void 70 + ipc_client_xdev_fini(struct ipc_client_xdev *icx); 71 + 72 + 73 + #ifdef __cplusplus 74 + } 75 + #endif