@@ -879,8 +879,31 @@ static void usb_device_intr(void) {
879879 HWREG (USB_0_OTGBASE + USB_0_END_OF_INTR ) = 0 ;
880880}
881881
882+ /**
883+ * Pybricks system command handler.
884+ */
885+ static pbdrv_usb_receive_handler_t pbdrv_usb_receive_handler ;
886+
887+ void pbdrv_usb_set_receive_handler (pbdrv_usb_receive_handler_t handler ) {
888+ pbdrv_usb_receive_handler = handler ;
889+ }
890+
891+ /**
892+ * Buffer for scheduled status message.
893+ */
894+ static uint8_t pbdrv_usb_status_data [PBIO_PYBRICKS_EVENT_STATUS_REPORT_SIZE ];
895+ static bool pbdrv_usb_status_data_pending ;
896+
882897void pbdrv_usb_schedule_status_update (const uint8_t * status_msg ) {
883- // todo
898+ // Ignore if message identical to last.
899+ if (!memcmp (pbdrv_usb_status_data , status_msg , sizeof (pbdrv_usb_status_data ))) {
900+ return ;
901+ }
902+
903+ // Schedule to send whenever the USB process gets round to it.
904+ memcpy (pbdrv_usb_status_data , status_msg , sizeof (pbdrv_usb_status_data ));
905+ pbdrv_usb_status_data_pending = true;
906+ pbio_os_request_poll ();
884907}
885908
886909static pbio_os_process_t pbdrv_usb_ev3_process ;
@@ -891,16 +914,14 @@ static pbio_error_t pbdrv_usb_ev3_process_thread(pbio_os_state_t *state, void *c
891914 static pbio_os_timer_t keepalive_timer ;
892915 static bool was_transmitting = false;
893916 static bool is_transmitting = false;
894- static uint32_t prev_status_flags = ~0 ;
895- static uint32_t new_status_flags = 0 ;
896917
897918 PBIO_OS_ASYNC_BEGIN (state );
898919
899920 for (;;) {
900921 if (pbdrv_usb_config == 0 ) {
901922 pbdrv_usb_is_events_subscribed = false;
902923 // Resend status flags when host subscribes
903- prev_status_flags = ~ 0 ;
924+ pbdrv_usb_status_data_pending = true ;
904925 }
905926
906927 if (usb_rx_is_ready ) {
@@ -925,7 +946,10 @@ static pbio_error_t pbdrv_usb_ev3_process_thread(pbio_os_state_t *state, void *c
925946 usb_send_response = true;
926947 break ;
927948 case PBIO_PYBRICKS_OUT_EP_MSG_COMMAND :
928- result = pbsys_command (ep1_rx_buf + 1 , usb_rx_sz - 1 );
949+ if (!pbdrv_usb_receive_handler ) {
950+ break ;
951+ }
952+ result = pbdrv_usb_receive_handler (ep1_rx_buf + 1 , usb_rx_sz - 1 );
929953 ep1_tx_response_buf [0 ] = PBIO_PYBRICKS_IN_EP_MSG_RESPONSE ;
930954 pbio_set_uint32_le (& ep1_tx_response_buf [1 ], result );
931955 usb_send_response = true;
@@ -945,26 +969,24 @@ static pbio_error_t pbdrv_usb_ev3_process_thread(pbio_os_state_t *state, void *c
945969 }
946970
947971 // Send status flags if they've changed (and we can)
948- new_status_flags = pbsys_status_get_flags ();
949972 if (pbdrv_usb_is_events_subscribed && !usb_tx_status_is_not_ready &&
950- (new_status_flags != prev_status_flags || pbio_os_timer_is_expired (& keepalive_timer ))) {
973+ (pbdrv_usb_status_data_pending || pbio_os_timer_is_expired (& keepalive_timer ))) {
951974 ep1_tx_status_buf [0 ] = PBIO_PYBRICKS_IN_EP_MSG_EVENT ;
952975 uint32_t usb_status_sz = PBIO_PYBRICKS_USB_MESSAGE_SIZE (pbsys_status_get_status_report (& ep1_tx_status_buf [1 ]));
953976
954977 usb_tx_status_is_not_ready = true;
955978 pbdrv_cache_prepare_before_dma (ep1_tx_status_buf , sizeof (ep1_tx_status_buf ));
956979 usb_setup_tx_dma_desc (CPPI_DESC_TX_STATUS , ep1_tx_status_buf , usb_status_sz );
957980
958- prev_status_flags = new_status_flags ;
959-
960- if (new_status_flags != prev_status_flags ) {
981+ if (pbdrv_usb_status_data_pending ) {
961982 // If we are sending a status because the flags have changed,
962983 // we can bump out the keepalive timer.
963984 pbio_os_timer_set (& keepalive_timer , 1000 );
964985 } else {
965986 // Otherwise, we want to send keepalives at a particular rate.
966987 pbio_os_timer_extend (& keepalive_timer );
967988 }
989+ pbdrv_usb_status_data_pending = false;
968990 }
969991
970992 // Handle timeouts
@@ -985,7 +1007,7 @@ static pbio_error_t pbdrv_usb_ev3_process_thread(pbio_os_state_t *state, void *c
9851007 usb_tx_stdout_is_not_ready = false;
9861008 pbdrv_usb_is_events_subscribed = false;
9871009 // Resend status flags when host subscribes
988- prev_status_flags = ~ 0 ;
1010+ pbdrv_usb_status_data_pending = true ;
9891011 }
9901012 } else if (!was_transmitting && is_transmitting ) {
9911013 pbio_os_timer_set (& tx_timeout_timer , 50 );
0 commit comments