| 324 | } |
| 325 | |
| 326 | void stopUsbHidInput() { |
| 327 | if (!s_ctx) return; |
| 328 | auto* ctx = s_ctx; |
| 329 | s_ctx = nullptr; |
| 330 | |
| 331 | ctx->running = false; |
| 332 | |
| 333 | if (xSemaphoreTake(ctx->task_done, pdMS_TO_TICKS(STOP_TIMEOUT_MS)) != pdTRUE) { |
| 334 | LOGGER.warn("task stop timed out, force terminating"); |
| 335 | vTaskDelete(ctx->task); |
| 336 | // Task was killed before it could clean up LVGL objects; do it here to |
| 337 | // prevent mouse_read_cb / keyboard_read_cb from running with a freed ctx. |
| 338 | if (lock(pdMS_TO_TICKS(200))) { |
| 339 | if (ctx->mouse_indev) { lv_indev_delete(ctx->mouse_indev); ctx->mouse_indev = nullptr; } |
| 340 | if (ctx->mouse_cursor) { lv_obj_delete(ctx->mouse_cursor); ctx->mouse_cursor = nullptr; } |
| 341 | if (ctx->kb_indev) { |
| 342 | hardware_keyboard_set_indev(nullptr); |
| 343 | lv_indev_delete(ctx->kb_indev); |
| 344 | ctx->kb_indev = nullptr; |
| 345 | } |
| 346 | unlock(); |
| 347 | } |
| 348 | } |
| 349 | ctx->task = nullptr; |
| 350 | |
| 351 | if (ctx->subscribed) { |
| 352 | struct Device* hid_dev = device_find_first_active_by_type(&USB_HOST_HID_TYPE); |
| 353 | if (hid_dev) usb_host_hid_unsubscribe(hid_dev, ctx->hid_queue); |
| 354 | } |
| 355 | vQueueDelete(ctx->hid_queue); |
| 356 | vQueueDelete(ctx->key_queue); |
| 357 | vSemaphoreDelete(ctx->task_done); |
| 358 | delete ctx; |
| 359 | |
| 360 | LOGGER.info("stopped"); |
| 361 | } |
| 362 | |
| 363 | } // namespace tt::lvgl |
| 364 |
no test coverage detected