usbd_display.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright (c) 2026, sakumisu
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "usbd_core.h"
  7. #include "usbd_display.h"
  8. struct usbd_display_priv {
  9. struct usb_mempool pool;
  10. struct usbd_endpoint out_ep;
  11. struct usbd_endpoint in_ep;
  12. struct usbd_display_frame *current_frame;
  13. } g_usbd_display;
  14. int usbd_display_frame_create(struct usbd_display_frame *frame, uint32_t count)
  15. {
  16. return usb_mempool_create(&g_usbd_display.pool, frame, sizeof(struct usbd_display_frame), count);
  17. }
  18. struct usbd_display_frame *usbd_display_frame_alloc(void)
  19. {
  20. return (struct usbd_display_frame *)usb_mempool_alloc(&g_usbd_display.pool);
  21. }
  22. int usbd_display_frame_free(struct usbd_display_frame *frame)
  23. {
  24. return usb_mempool_free(&g_usbd_display.pool, (uintptr_t *)frame);
  25. }
  26. int usbd_display_frame_send(struct usbd_display_frame *frame)
  27. {
  28. return usb_mempool_send(&g_usbd_display.pool, (uintptr_t *)frame);
  29. }
  30. int usbd_display_frame_recv(struct usbd_display_frame **frame, uint32_t timeout)
  31. {
  32. return usb_mempool_recv(&g_usbd_display.pool, (uintptr_t **)frame, timeout);
  33. }
  34. uint8_t usb_dispay_dummy[512];
  35. volatile uint32_t usb_display_buf_offset;
  36. volatile bool usb_display_ignore_frame;
  37. static void display_notify_handler(uint8_t busid, uint8_t event, void *arg)
  38. {
  39. switch (event) {
  40. case USBD_EVENT_RESET:
  41. break;
  42. case USBD_EVENT_CONFIGURED:
  43. usb_display_buf_offset = 0;
  44. usb_display_ignore_frame = true;
  45. g_usbd_display.current_frame = NULL;
  46. usb_mempool_reset(&g_usbd_display.pool);
  47. usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, usb_dispay_dummy, usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr));
  48. break;
  49. default:
  50. break;
  51. }
  52. }
  53. void usbd_display_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
  54. {
  55. if (usb_display_ignore_frame) {
  56. // alloc frame for next at the end of current frame
  57. if ((nbytes % usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr)) || (nbytes == 0)) {
  58. if (g_usbd_display.current_frame == NULL) {
  59. g_usbd_display.current_frame = usbd_display_frame_alloc();
  60. if (g_usbd_display.current_frame) {
  61. usb_display_ignore_frame = false;
  62. usb_display_buf_offset = 0;
  63. goto get_frame;
  64. } else {
  65. goto drop_frame;
  66. }
  67. } else {
  68. usb_display_ignore_frame = false;
  69. usb_display_buf_offset = 0;
  70. goto get_frame;
  71. }
  72. } else {
  73. goto drop_frame;
  74. }
  75. } else {
  76. struct usbd_disp_frame_header *header = (struct usbd_disp_frame_header *)&g_usbd_display.current_frame->frame_buf[0];
  77. struct usbd_display_frame *frame;
  78. if (header->payload_total > g_usbd_display.current_frame->frame_bufsize) {
  79. USB_LOG_ERR("frame overflow, drop it\r\n");
  80. usb_display_ignore_frame = true;
  81. goto drop_frame;
  82. }
  83. usb_display_buf_offset += nbytes;
  84. if ((nbytes % usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr)) || (nbytes == 0)) {
  85. frame = g_usbd_display.current_frame;
  86. g_usbd_display.current_frame = NULL;
  87. frame->frame_format = header->type;
  88. frame->frame_size = header->payload_total;
  89. usbd_display_frame_send(frame);
  90. g_usbd_display.current_frame = usbd_display_frame_alloc();
  91. if (g_usbd_display.current_frame) {
  92. usb_display_ignore_frame = false;
  93. usb_display_buf_offset = 0;
  94. goto get_frame;
  95. } else {
  96. usb_display_ignore_frame = true;
  97. goto drop_frame;
  98. }
  99. } else {
  100. goto get_frame;
  101. }
  102. }
  103. return;
  104. drop_frame:
  105. // drop current frame
  106. usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, usb_dispay_dummy, usbd_get_ep_mps(0, g_usbd_display.out_ep.ep_addr));
  107. return;
  108. get_frame:
  109. usbd_ep_start_read(busid, g_usbd_display.out_ep.ep_addr, &g_usbd_display.current_frame->frame_buf[usb_display_buf_offset], 16384);
  110. return;
  111. }
  112. void usbd_display_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
  113. {
  114. }
  115. struct usbd_interface *usbd_display_init_intf(struct usbd_interface *intf,
  116. const uint8_t out_ep,
  117. const uint8_t in_ep,
  118. struct usbd_display_frame *frame,
  119. uint32_t count)
  120. {
  121. intf->class_interface_handler = NULL;
  122. intf->class_endpoint_handler = NULL;
  123. intf->vendor_handler = NULL;
  124. intf->notify_handler = display_notify_handler;
  125. g_usbd_display.out_ep.ep_addr = out_ep;
  126. g_usbd_display.out_ep.ep_cb = usbd_display_bulk_out;
  127. g_usbd_display.in_ep.ep_addr = in_ep;
  128. g_usbd_display.in_ep.ep_cb = usbd_display_bulk_in;
  129. usbd_add_endpoint(0, &g_usbd_display.out_ep);
  130. usbd_add_endpoint(0, &g_usbd_display.in_ep);
  131. for (uint32_t i = 0; i < count; i++) {
  132. USB_ASSERT_MSG(frame[i].frame_bufsize % 16384, "frame_bufsize must be the multiple of 16384");
  133. }
  134. usbd_display_frame_create(frame, count);
  135. return intf;
  136. }
  137. int usbd_display_dequeue(struct usbd_display_frame **frame, uint32_t timeout)
  138. {
  139. return usbd_display_frame_recv(frame, timeout);
  140. }
  141. int usbd_display_enqueue(struct usbd_display_frame *frame)
  142. {
  143. return usbd_display_frame_free(frame);
  144. }