The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipc: Make it possible to toggle inputs on and off

authored by

Jakob Bornecrantz and committed by
Jakob Bornecrantz
4e6a137c 557dacbb

+252 -65
+3
doc/changes/ipc/mr.511.md
··· 1 + ipc: Add functionality to disable a device input via the `monado-ctl` utility, 2 + this allows us to pass the conformance tests that requires the runtime to turn 3 + off a device.
+5
src/xrt/include/xrt/xrt_results.h
··· 31 31 * Could not allocate native image buffer(s). 32 32 */ 33 33 XRT_ERROR_ALLOCATION = -7, 34 + /* 35 + * The pose is no longer active, this happens when the application 36 + * tries to access a pose that is no longer active. 37 + */ 38 + XRT_ERROR_POSE_NOT_ACTIVE = -8, 34 39 } xrt_result_t;
+11 -11
src/xrt/ipc/ipc_client_device.c
··· 139 139 { 140 140 // Helpers. 141 141 struct ipc_shared_memory *ism = ipc_c->ism; 142 - struct ipc_shared_device *idev = &ism->idevs[device_id]; 142 + struct ipc_shared_device *isdev = &ism->isdevs[device_id]; 143 143 144 144 // Allocate and setup the basics. 145 145 enum u_device_alloc_flags flags = ··· 153 153 icd->base.set_output = ipc_client_device_set_output; 154 154 icd->base.destroy = ipc_client_device_destroy; 155 155 156 - // Start copying the information from the idev. 156 + // Start copying the information from the isdev. 157 157 icd->base.tracking_origin = xtrack; 158 - icd->base.name = idev->name; 158 + icd->base.name = isdev->name; 159 159 icd->device_id = device_id; 160 160 161 161 // Print name. 162 - snprintf(icd->base.str, XRT_DEVICE_NAME_LEN, "%s", idev->str); 162 + snprintf(icd->base.str, XRT_DEVICE_NAME_LEN, "%s", isdev->str); 163 163 164 164 // Setup inputs, by pointing directly to the shared memory. 165 - assert(idev->num_inputs > 0); 166 - icd->base.inputs = &ism->inputs[idev->first_input_index]; 167 - icd->base.num_inputs = idev->num_inputs; 165 + assert(isdev->num_inputs > 0); 166 + icd->base.inputs = &ism->inputs[isdev->first_input_index]; 167 + icd->base.num_inputs = isdev->num_inputs; 168 168 169 169 // Setup outputs, if any point directly into the shared memory. 170 - icd->base.num_outputs = idev->num_outputs; 171 - if (idev->num_outputs > 0) { 172 - icd->base.outputs = &ism->outputs[idev->first_output_index]; 170 + icd->base.num_outputs = isdev->num_outputs; 171 + if (isdev->num_outputs > 0) { 172 + icd->base.outputs = &ism->outputs[isdev->first_output_index]; 173 173 } else { 174 174 icd->base.outputs = NULL; 175 175 } ··· 178 178 u_var_add_root(icd, icd->base.str, true); 179 179 u_var_add_ro_u32(icd, &icd->device_id, "device_id"); 180 180 181 - icd->base.device_type = idev->device_type; 181 + icd->base.device_type = isdev->device_type; 182 182 return &icd->base; 183 183 }
+10 -10
src/xrt/ipc/ipc_client_hmd.c
··· 130 130 uint32_t device_id) 131 131 { 132 132 struct ipc_shared_memory *ism = ipc_c->ism; 133 - struct ipc_shared_device *idev = &ism->idevs[device_id]; 133 + struct ipc_shared_device *isdev = &ism->isdevs[device_id]; 134 134 135 135 136 136 ··· 145 145 ich->base.get_view_pose = ipc_client_hmd_get_view_pose; 146 146 ich->base.destroy = ipc_client_hmd_destroy; 147 147 148 - // Start copying the information from the idev. 148 + // Start copying the information from the isdev. 149 149 ich->base.tracking_origin = xtrack; 150 - ich->base.name = idev->name; 150 + ich->base.name = isdev->name; 151 151 ich->device_id = device_id; 152 152 153 153 // Print name. 154 - snprintf(ich->base.str, XRT_DEVICE_NAME_LEN, "%s", idev->str); 154 + snprintf(ich->base.str, XRT_DEVICE_NAME_LEN, "%s", isdev->str); 155 155 156 156 // Setup inputs, by pointing directly to the shared memory. 157 - assert(idev->num_inputs > 0); 158 - ich->base.inputs = &ism->inputs[idev->first_input_index]; 159 - ich->base.num_inputs = idev->num_inputs; 157 + assert(isdev->num_inputs > 0); 158 + ich->base.inputs = &ism->inputs[isdev->first_input_index]; 159 + ich->base.num_inputs = isdev->num_inputs; 160 160 161 161 #if 0 162 162 // Setup info. ··· 198 198 u_var_add_ro_u32(ich, &ich->device_id, "device_id"); 199 199 200 200 ich->base.orientation_tracking_supported = 201 - idev->orientation_tracking_supported; 201 + isdev->orientation_tracking_supported; 202 202 ich->base.position_tracking_supported = 203 - idev->position_tracking_supported; 204 - ich->base.device_type = idev->device_type; 203 + isdev->position_tracking_supported; 204 + ich->base.device_type = isdev->device_type; 205 205 206 206 return &ich->base; 207 207 }
+4 -4
src/xrt/ipc/ipc_client_instance.c
··· 283 283 284 284 // Query the server for how many devices it has. 285 285 count = 0; 286 - for (uint32_t i = 0; i < ism->num_idevs; i++) { 287 - struct ipc_shared_device *idev = &ism->idevs[i]; 288 - xtrack = ii->xtracks[idev->tracking_origin_index]; 286 + for (uint32_t i = 0; i < ism->num_isdevs; i++) { 287 + struct ipc_shared_device *isdev = &ism->isdevs[i]; 288 + xtrack = ii->xtracks[isdev->tracking_origin_index]; 289 289 290 - if (idev->name == XRT_DEVICE_GENERIC_HMD) { 290 + if (isdev->name == XRT_DEVICE_GENERIC_HMD) { 291 291 ii->xdevs[count++] = 292 292 ipc_client_hmd_create(&ii->ipc_c, xtrack, i); 293 293 } else {
+6 -5
src/xrt/ipc/ipc_protocol.h
··· 127 127 * struct xrt_input * 128 128 * helper(struct ipc_shared_memory *ism, uin32_t device_id, size_t input) 129 129 * { 130 - * size_t index = ism->idevs[device_id]->first_input_index + input; 130 + * size_t index = ism->isdevs[device_id]->first_input_index + input; 131 131 * return &ism->inputs[index]; 132 132 * } 133 133 * ``` ··· 149 149 struct ipc_shared_tracking_origin itracks[IPC_SHARED_MAX_DEVICES]; 150 150 151 151 /*! 152 - * Number of elements in @ref idevs that are populated/valid. 152 + * Number of elements in @ref isdevs that are populated/valid. 153 153 */ 154 - size_t num_idevs; 154 + size_t num_isdevs; 155 155 156 156 /*! 157 157 * @brief Array of shared data per device. 158 158 * 159 - * Only @ref num_idevs elements are populated/valid. 159 + * Only @ref num_isdevs elements are populated/valid. 160 160 */ 161 - struct ipc_shared_device idevs[IPC_SHARED_MAX_DEVICES]; 161 + struct ipc_shared_device isdevs[IPC_SHARED_MAX_DEVICES]; 162 162 163 163 struct 164 164 { ··· 213 213 bool session_visible; 214 214 bool session_focused; 215 215 bool session_overlay; 216 + bool io_active; 216 217 uint32_t z_order; 217 218 pid_t pid; 218 219 struct xrt_instance_info info;
+42 -1
src/xrt/ipc/ipc_server.h
··· 108 108 //! Compositor for this client. 109 109 struct xrt_compositor *xc; 110 110 111 + //! Is the inputs and outputs active. 112 + bool io_active; 113 + 111 114 //! Number of swapchains in use by client 112 115 uint32_t num_swapchains; 113 116 ··· 150 153 volatile struct ipc_client_state ics; 151 154 }; 152 155 156 + 157 + /*! 158 + * 159 + */ 160 + struct ipc_device 161 + { 162 + //! The actual device. 163 + struct xrt_device *xdev; 164 + 165 + //! Is the IO suppressed for this device. 166 + bool io_active; 167 + }; 168 + 153 169 /*! 154 170 * Main IPC object for the server. 155 171 * ··· 162 178 struct xrt_compositor *xc; 163 179 struct xrt_compositor_native *xcn; 164 180 165 - struct xrt_device *xdevs[IPC_SERVER_NUM_XDEVS]; 181 + struct ipc_device idevs[IPC_SERVER_NUM_XDEVS]; 166 182 struct xrt_tracking_origin *xtracks[IPC_SERVER_NUM_XDEVS]; 167 183 168 184 struct ipc_shared_memory *ism; ··· 221 237 */ 222 238 void * 223 239 ipc_server_client_thread(void *_cs); 240 + 241 + 242 + /* 243 + * 244 + * Helpers 245 + * 246 + */ 247 + 248 + /*! 249 + * Get a xdev with the given device_id. 250 + */ 251 + static inline struct xrt_device * 252 + get_xdev(volatile struct ipc_client_state *ics, uint32_t device_id) 253 + { 254 + return ics->server->idevs[device_id].xdev; 255 + } 256 + 257 + /*! 258 + * Get a idev with the given device_id. 259 + */ 260 + static inline struct ipc_device * 261 + get_idev(volatile struct ipc_client_state *ics, uint32_t device_id) 262 + { 263 + return &ics->server->idevs[device_id]; 264 + } 224 265 225 266 226 267 #ifdef __cplusplus
+102 -8
src/xrt/ipc/ipc_server_client.c
··· 260 260 } 261 261 262 262 *out_client_desc = ics->client_state; 263 + out_client_desc->io_active = ics->io_active; 263 264 264 265 //@todo: track this data in the ipc_client_state struct 265 266 out_client_desc->primary_application = false; ··· 306 307 { 307 308 printf("UNIMPLEMENTED: system setting focused client to %d\n", 308 309 client_id); 310 + 311 + return XRT_SUCCESS; 312 + } 313 + 314 + xrt_result_t 315 + ipc_handle_system_toggle_io_client(volatile struct ipc_client_state *_ics, 316 + uint32_t client_id) 317 + { 318 + volatile struct ipc_client_state *ics = NULL; 319 + 320 + if (client_id >= IPC_MAX_CLIENTS) { 321 + return XRT_ERROR_IPC_FAILURE; 322 + } 323 + 324 + ics = &_ics->server->threads[client_id].ics; 325 + 326 + if (ics->imc.socket_fd <= 0) { 327 + return XRT_ERROR_IPC_FAILURE; 328 + } 329 + 330 + ics->io_active = !ics->io_active; 331 + 332 + return XRT_SUCCESS; 333 + } 334 + 335 + xrt_result_t 336 + ipc_handle_system_toggle_io_device(volatile struct ipc_client_state *ics, 337 + uint32_t device_id) 338 + { 339 + if (device_id >= IPC_MAX_DEVICES) { 340 + return XRT_ERROR_IPC_FAILURE; 341 + } 342 + 343 + struct ipc_device *idev = &ics->server->idevs[device_id]; 344 + 345 + idev->io_active = !idev->io_active; 309 346 310 347 return XRT_SUCCESS; 311 348 } ··· 466 503 // To make the code a bit more readable. 467 504 uint32_t device_id = id; 468 505 struct ipc_shared_memory *ism = ics->server->ism; 469 - struct xrt_device *xdev = ics->server->xdevs[device_id]; 470 - struct ipc_shared_device *idev = &ism->idevs[device_id]; 506 + struct ipc_device *idev = get_idev(ics, device_id); 507 + struct xrt_device *xdev = idev->xdev; 508 + struct ipc_shared_device *isdev = &ism->isdevs[device_id]; 471 509 472 510 // Update inputs. 473 511 xrt_device_update_inputs(xdev); 474 512 475 513 // Copy data into the shared memory. 476 514 struct xrt_input *src = xdev->inputs; 477 - struct xrt_input *dst = &ism->inputs[idev->first_input_index]; 478 - memcpy(dst, src, sizeof(struct xrt_input) * idev->num_inputs); 515 + struct xrt_input *dst = &ism->inputs[isdev->first_input_index]; 516 + size_t size = sizeof(struct xrt_input) * isdev->num_inputs; 517 + 518 + bool io_active = ics->io_active && idev->io_active; 519 + if (io_active) { 520 + memcpy(dst, src, size); 521 + } else { 522 + memset(dst, 0, size); 523 + 524 + for (uint32_t i = 0; i < isdev->num_inputs; i++) { 525 + dst[i].name = src[i].name; 526 + 527 + // Special case the rotation of the head. 528 + if (dst[i].name == XRT_INPUT_GENERIC_HEAD_POSE) { 529 + dst[i].active = src[i].active; 530 + } 531 + } 532 + } 479 533 480 534 // Reply. 481 535 return XRT_SUCCESS; 482 536 } 483 537 538 + static struct xrt_input * 539 + find_input(volatile struct ipc_client_state *ics, 540 + uint32_t device_id, 541 + enum xrt_input_name name) 542 + { 543 + struct ipc_shared_memory *ism = ics->server->ism; 544 + struct ipc_shared_device *isdev = &ism->isdevs[device_id]; 545 + struct xrt_input *io = &ism->inputs[isdev->first_input_index]; 546 + 547 + for (uint32_t i = 0; i < isdev->num_inputs; i++) { 548 + if (io[i].name == name) { 549 + return &io[i]; 550 + } 551 + } 552 + 553 + return NULL; 554 + } 555 + 484 556 xrt_result_t 485 557 ipc_handle_device_get_tracked_pose(volatile struct ipc_client_state *ics, 486 558 uint32_t id, ··· 492 564 493 565 // To make the code a bit more readable. 494 566 uint32_t device_id = id; 495 - struct xrt_device *xdev = ics->server->xdevs[device_id]; 567 + struct ipc_device *isdev = &ics->server->idevs[device_id]; 568 + struct xrt_device *xdev = isdev->xdev; 569 + 570 + // Find the input 571 + struct xrt_input *input = find_input(ics, device_id, name); 572 + if (input == NULL) { 573 + return XRT_ERROR_IPC_FAILURE; 574 + } 575 + 576 + // Special case the headpose. 577 + bool disabled = (!isdev->io_active || !ics->io_active) && 578 + name != XRT_INPUT_GENERIC_HEAD_POSE; 579 + bool active_on_client = input->active; 580 + 581 + // We have been disabled but the client hasn't called update. 582 + if (disabled && active_on_client) { 583 + U_ZERO(out_relation); 584 + *out_timestamp = at_timestamp; 585 + return XRT_SUCCESS; 586 + } 587 + 588 + if (disabled || !active_on_client) { 589 + return XRT_ERROR_POSE_NOT_ACTIVE; 590 + } 496 591 497 592 // Get the pose. 498 593 xrt_device_get_tracked_pose(xdev, name, at_timestamp, out_timestamp, ··· 508 603 uint32_t view_index, 509 604 struct xrt_pose *out_pose) 510 605 { 511 - 512 606 // To make the code a bit more readable. 513 607 uint32_t device_id = id; 514 - struct xrt_device *xdev = ics->server->xdevs[device_id]; 608 + struct xrt_device *xdev = get_xdev(ics, device_id); 515 609 516 610 // Get the pose. 517 611 xrt_device_get_view_pose(xdev, eye_relation, view_index, out_pose); ··· 527 621 { 528 622 // To make the code a bit more readable. 529 623 uint32_t device_id = id; 530 - struct xrt_device *xdev = ics->server->xdevs[device_id]; 624 + struct xrt_device *xdev = get_xdev(ics, device_id); 531 625 532 626 // Set the output. 533 627 xrt_device_set_output(xdev, name, value);
+57 -26
src/xrt/ipc/ipc_server_process.c
··· 56 56 int32_t z_order; 57 57 }; 58 58 59 + static void 60 + init_idev(struct ipc_device *idev, struct xrt_device *xdev) 61 + { 62 + if (xdev != NULL) { 63 + idev->io_active = true; 64 + idev->xdev = xdev; 65 + } else { 66 + idev->io_active = false; 67 + } 68 + } 69 + 70 + static void 71 + teardown_idev(struct ipc_device *idev) 72 + { 73 + xrt_device_destroy(&idev->xdev); 74 + idev->io_active = false; 75 + } 76 + 59 77 60 78 /* 61 79 * ··· 71 89 xrt_comp_destroy(&s->xc); 72 90 73 91 for (size_t i = 0; i < IPC_SERVER_NUM_XDEVS; i++) { 74 - xrt_device_destroy(&s->xdevs[i]); 92 + teardown_idev(&s->idevs[i]); 75 93 } 76 94 77 95 xrt_instance_destroy(&s->xinst); ··· 95 113 init_tracking_origins(struct ipc_server *s) 96 114 { 97 115 for (size_t i = 0; i < IPC_SERVER_NUM_XDEVS; i++) { 98 - if (s->xdevs[i] == NULL) { 116 + struct xrt_device *xdev = s->idevs[i].xdev; 117 + if (xdev == NULL) { 99 118 continue; 100 119 } 101 120 102 - struct xrt_device *xdev = s->xdevs[i]; 103 121 struct xrt_tracking_origin *xtrack = xdev->tracking_origin; 104 122 assert(xtrack != NULL); 105 123 size_t index = 0; ··· 166 184 uint32_t input_index = 0; 167 185 uint32_t output_index = 0; 168 186 for (size_t i = 0; i < IPC_SERVER_NUM_XDEVS; i++) { 169 - struct xrt_device *xdev = s->xdevs[i]; 187 + struct xrt_device *xdev = s->idevs[i].xdev; 170 188 if (xdev == NULL) { 171 189 continue; 172 190 } 173 191 174 - struct ipc_shared_device *idev = &ism->idevs[count++]; 192 + struct ipc_shared_device *isdev = &ism->isdevs[count++]; 175 193 176 - idev->name = xdev->name; 177 - memcpy(idev->str, xdev->str, sizeof(idev->str)); 194 + isdev->name = xdev->name; 195 + memcpy(isdev->str, xdev->str, sizeof(isdev->str)); 178 196 179 - idev->orientation_tracking_supported = 197 + isdev->orientation_tracking_supported = 180 198 xdev->orientation_tracking_supported; 181 - idev->position_tracking_supported = 199 + isdev->position_tracking_supported = 182 200 xdev->position_tracking_supported; 183 - idev->device_type = xdev->device_type; 201 + isdev->device_type = xdev->device_type; 184 202 185 203 // Is this a HMD? 186 204 if (xdev->hmd != NULL) { ··· 197 215 } 198 216 199 217 // Setup the tracking origin. 200 - idev->tracking_origin_index = (uint32_t)-1; 218 + isdev->tracking_origin_index = (uint32_t)-1; 201 219 for (size_t k = 0; k < IPC_SERVER_NUM_XDEVS; k++) { 202 220 if (xdev->tracking_origin != s->xtracks[k]) { 203 221 continue; 204 222 } 205 223 206 - idev->tracking_origin_index = k; 224 + isdev->tracking_origin_index = k; 207 225 break; 208 226 } 209 227 210 - assert(idev->tracking_origin_index != (uint32_t)-1); 228 + assert(isdev->tracking_origin_index != (uint32_t)-1); 211 229 212 230 // Initial update. 213 231 xrt_device_update_inputs(xdev); ··· 220 238 221 239 // Setup the 'offsets' and number of inputs. 222 240 if (input_start != input_index) { 223 - idev->num_inputs = input_index - input_start; 224 - idev->first_input_index = input_start; 241 + isdev->num_inputs = input_index - input_start; 242 + isdev->first_input_index = input_start; 225 243 } 226 244 227 245 // Copy the initial state and also count the number in outputs. ··· 232 250 233 251 // Setup the 'offsets' and number of outputs. 234 252 if (output_start != output_index) { 235 - idev->num_outputs = output_index - output_start; 236 - idev->first_output_index = output_start; 253 + isdev->num_outputs = output_index - output_start; 254 + isdev->first_output_index = output_start; 237 255 } 238 256 } 239 257 240 258 // Finally tell the client how many devices we have. 241 - s->ism->num_idevs = count; 259 + s->ism->num_isdevs = count; 242 260 243 261 return 0; 244 262 } ··· 382 400 return ret; 383 401 } 384 402 385 - ret = xrt_instance_select(s->xinst, s->xdevs, IPC_SERVER_NUM_XDEVS); 403 + struct xrt_device *xdevs[IPC_SERVER_NUM_XDEVS] = {0}; 404 + ret = xrt_instance_select(s->xinst, xdevs, IPC_SERVER_NUM_XDEVS); 386 405 if (ret < 0) { 387 406 teardown_all(s); 388 407 return ret; 389 408 } 390 409 391 - if (s->xdevs[0] == NULL) { 410 + // Copy the devices over into the idevs array. 411 + for (size_t i = 0; i < IPC_SERVER_NUM_XDEVS; i++) { 412 + if (xdevs[i] == NULL) { 413 + continue; 414 + } 415 + 416 + init_idev(&s->idevs[i], xdevs[i]); 417 + xdevs[i] = NULL; 418 + } 419 + 420 + // If we don't have a HMD shutdown. 421 + if (s->idevs[0].xdev == NULL) { 392 422 teardown_all(s); 393 423 return -1; 394 424 } ··· 399 429 return -1; 400 430 } 401 431 402 - ret = xrt_instance_create_native_compositor(s->xinst, s->xdevs[0], 432 + ret = xrt_instance_create_native_compositor(s->xinst, s->idevs[0].xdev, 403 433 &s->xcn); 404 434 if (ret < 0) { 405 435 teardown_all(s); ··· 506 536 ics->imc.socket_fd = fd; 507 537 ics->server = vs; 508 538 ics->server_thread_index = cs_index; 539 + ics->io_active = true; 509 540 os_thread_start(&it->thread, ipc_server_client_thread, (void *)ics); 510 541 511 542 // Unlock when we are done. ··· 599 630 uint32_t i) 600 631 { 601 632 // xdev 602 - uint32_t xdevi = layer->xdev_id; 633 + uint32_t device_id = layer->xdev_id; 603 634 // left 604 635 uint32_t lxsci = layer->swapchain_ids[0]; 605 636 // right 606 637 uint32_t rxsci = layer->swapchain_ids[1]; 607 638 608 - struct xrt_device *xdev = ics->server->xdevs[xdevi]; 639 + struct xrt_device *xdev = get_xdev(ics, device_id); 609 640 struct xrt_swapchain *lxcs = ics->xscs[lxsci]; 610 641 struct xrt_swapchain *rxcs = ics->xscs[rxsci]; 611 642 ··· 645 676 // right 646 677 uint32_t r_d_xsci = layer->swapchain_ids[3]; 647 678 648 - struct xrt_device *xdev = ics->server->xdevs[xdevi]; 679 + struct xrt_device *xdev = get_xdev(ics, xdevi); 649 680 struct xrt_swapchain *l_xcs = ics->xscs[l_xsci]; 650 681 struct xrt_swapchain *r_xcs = ics->xscs[r_xsci]; 651 682 struct xrt_swapchain *l_d_xcs = ics->xscs[l_d_xsci]; ··· 682 713 struct xrt_swapchain **out_xcs, 683 714 struct xrt_layer_data **out_data) 684 715 { 685 - uint32_t xdevi = layer->xdev_id; 716 + uint32_t device_id = layer->xdev_id; 686 717 uint32_t sci = layer->swapchain_ids[0]; 687 718 688 - struct xrt_device *xdev = ics->server->xdevs[xdevi]; 719 + struct xrt_device *xdev = get_xdev(ics, device_id); 689 720 struct xrt_swapchain *xcs = ics->xscs[sci]; 690 721 691 722 if (xcs == NULL) {
+12
src/xrt/ipc/proto.json
··· 38 38 ] 39 39 }, 40 40 41 + "system_toggle_io_client": { 42 + "in": [ 43 + {"name": "id", "type": "uint32_t"} 44 + ] 45 + }, 46 + 47 + "system_toggle_io_device": { 48 + "in": [ 49 + {"name": "id", "type": "uint32_t"} 50 + ] 51 + }, 52 + 41 53 "session_create": { 42 54 "in": [ 43 55 {"name": "overlay_info", "type": "const struct xrt_session_prepare_info"}