emu_present.c 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // emu_present.c — drive the active emulated controller from g_in (see .h).
  2. //
  3. // SPDX-License-Identifier: AGPL-3.0-or-later
  4. #include "puck/emu_present.h"
  5. #include "puck/emu.h"
  6. #include "puck/slots.h"
  7. #include "usb/usb_tx.h"
  8. #include "usb/usb_descriptors.h"
  9. #include "config/modes.h"
  10. #include "sys/settings.h"
  11. #include "pico/time.h"
  12. #define EMU_STREAM_MS 4u // ~250 Hz, matching OpenPuck's USB_STREAM_MS
  13. static uint32_t s_last_ms;
  14. // Interface i maps 1:1 to controller slot i. Each emulated HID interface streams
  15. // its slot's g_in (neutral when that slot is disconnected, keeping the interface
  16. // alive as an idle pad). Report callbacks route the same way.
  17. void emu_present_task(void)
  18. {
  19. const emu_mode_t *e = emu_mode_for(settings_mode());
  20. if (!e)
  21. return;
  22. uint32_t t = to_ms_since_boot(get_absolute_time());
  23. if (t - s_last_ms < EMU_STREAM_MS)
  24. return;
  25. s_last_ms = t;
  26. uint8_t nif = usb_emu_iface_count();
  27. for (uint8_t i = 0; i < nif; i++) {
  28. uint8_t body[64];
  29. uint8_t rid = 0;
  30. uint16_t n = e->build(i, body, &rid);
  31. if (n)
  32. usb_tx_hid(i, rid, body, n);
  33. }
  34. }
  35. uint16_t emu_get_report(uint8_t instance, uint8_t report_id, uint8_t type,
  36. uint8_t *buf, uint16_t reqlen)
  37. {
  38. const emu_mode_t *e = emu_mode_for(settings_mode());
  39. if (e && e->get_report)
  40. return e->get_report(instance, report_id, type, buf, reqlen);
  41. return 0;
  42. }
  43. void emu_set_report(uint8_t instance, uint8_t report_id, uint8_t type,
  44. const uint8_t *buf, uint16_t len)
  45. {
  46. const emu_mode_t *e = emu_mode_for(settings_mode());
  47. if (e && e->set_report)
  48. e->set_report(instance, report_id, type, buf, len);
  49. }