Merge pull request #2213 from Rocky04/patch-5
Adding support for a generic SOF callback
This commit is contained in:
		@@ -1835,7 +1835,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
 | 
				
			|||||||
            audio->feedback.frame_shift = desc_ep->bInterval -1;
 | 
					            audio->feedback.frame_shift = desc_ep->bInterval -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Enable SOF interrupt if callback is implemented
 | 
					            // Enable SOF interrupt if callback is implemented
 | 
				
			||||||
            if (tud_audio_feedback_interval_isr) usbd_sof_enable(rhport, true);
 | 
					            if (tud_audio_feedback_interval_isr) usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, true);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
 | 
					#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT
 | 
				
			||||||
@@ -1909,7 +1909,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (disable) usbd_sof_enable(rhport, false);
 | 
					  if (disable) usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, false);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
 | 
					#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,6 +56,10 @@ TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_is
 | 
				
			|||||||
  (void)in_isr;
 | 
					  (void)in_isr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TU_ATTR_WEAK void tud_sof_cb(uint32_t frame_count) {
 | 
				
			||||||
 | 
					  (void)frame_count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
// Device Data
 | 
					// Device Data
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
@@ -76,6 +80,7 @@ typedef struct {
 | 
				
			|||||||
  volatile uint8_t cfg_num; // current active configuration (0x00 is not configured)
 | 
					  volatile uint8_t cfg_num; // current active configuration (0x00 is not configured)
 | 
				
			||||||
  uint8_t speed;
 | 
					  uint8_t speed;
 | 
				
			||||||
  volatile uint8_t setup_count;
 | 
					  volatile uint8_t setup_count;
 | 
				
			||||||
 | 
					  volatile uint8_t sof_consumer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint8_t itf2drv[CFG_TUD_INTERFACE_MAX];   // map interface number to driver (0xff is invalid)
 | 
					  uint8_t itf2drv[CFG_TUD_INTERFACE_MAX];   // map interface number to driver (0xff is invalid)
 | 
				
			||||||
  uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each
 | 
					  uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each
 | 
				
			||||||
@@ -275,6 +280,7 @@ TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8
 | 
				
			|||||||
  return driver;
 | 
					  return driver;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
// DCD Event
 | 
					// DCD Event
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
@@ -382,6 +388,12 @@ bool tud_connect(void) {
 | 
				
			|||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool tud_sof_cb_enable(bool en)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  usbd_sof_enable(_usbd_rhport, SOF_CONSUMER_USER, en);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
// USBD Task
 | 
					// USBD Task
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
@@ -612,6 +624,12 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case DCD_EVENT_SOF:
 | 
					      case DCD_EVENT_SOF:
 | 
				
			||||||
 | 
					        if (tu_bit_test(_usbd_dev.sof_consumer, SOF_CONSUMER_USER)) {
 | 
				
			||||||
 | 
					          TU_LOG_USBD("\r\n");
 | 
				
			||||||
 | 
					          tud_sof_cb(event.sof.frame_count);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        TU_BREAKPOINT();
 | 
					        TU_BREAKPOINT();
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@@ -702,6 +720,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
 | 
				
			|||||||
              // already configured: need to clear all endpoints and driver first
 | 
					              // already configured: need to clear all endpoints and driver first
 | 
				
			||||||
              TU_LOG_USBD("  Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
 | 
					              TU_LOG_USBD("  Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              // disable SOF
 | 
				
			||||||
 | 
					              dcd_sof_enable(rhport, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              // close all non-control endpoints, cancel all pending transfers if any
 | 
					              // close all non-control endpoints, cancel all pending transfers if any
 | 
				
			||||||
              dcd_edpt_close_all(rhport);
 | 
					              dcd_edpt_close_all(rhport);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1101,6 +1122,14 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr)
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case DCD_EVENT_SOF:
 | 
					    case DCD_EVENT_SOF:
 | 
				
			||||||
 | 
					      // SOF driver handler in ISR context
 | 
				
			||||||
 | 
					      for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
 | 
				
			||||||
 | 
					        usbd_class_driver_t const* driver = get_driver(i);
 | 
				
			||||||
 | 
					        if (driver && driver->sof) {
 | 
				
			||||||
 | 
					          driver->sof(event->rhport, event->sof.frame_count);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup
 | 
					      // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup
 | 
				
			||||||
      // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational
 | 
					      // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational
 | 
				
			||||||
      if (_usbd_dev.suspended) {
 | 
					      if (_usbd_dev.suspended) {
 | 
				
			||||||
@@ -1110,15 +1139,10 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr)
 | 
				
			|||||||
        queue_event(&event_resume, in_isr);
 | 
					        queue_event(&event_resume, in_isr);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // SOF driver handler in ISR context
 | 
					      if (tu_bit_test(_usbd_dev.sof_consumer, SOF_CONSUMER_USER)) {
 | 
				
			||||||
      for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
 | 
					        dcd_event_t const event_sof = {.rhport = event->rhport, .event_id = DCD_EVENT_SOF};
 | 
				
			||||||
        usbd_class_driver_t const* driver = get_driver(i);
 | 
					        queue_event(&event_sof, in_isr);
 | 
				
			||||||
        if (driver && driver->sof) {
 | 
					 | 
				
			||||||
          driver->sof(event->rhport, event->sof.frame_count);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					 | 
				
			||||||
      // skip osal queue for SOF in usbd task
 | 
					 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case DCD_EVENT_SETUP_RECEIVED:
 | 
					    case DCD_EVENT_SETUP_RECEIVED:
 | 
				
			||||||
@@ -1355,12 +1379,21 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) {
 | 
				
			|||||||
  return;
 | 
					  return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbd_sof_enable(uint8_t rhport, bool en) {
 | 
					void usbd_sof_enable(uint8_t rhport, sof_consumer_t consumer, bool en) {
 | 
				
			||||||
  rhport = _usbd_rhport;
 | 
					  rhport = _usbd_rhport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: Check needed if all drivers including the user sof_cb does not need an active SOF ISR any more.
 | 
					  uint8_t consumer_old = _usbd_dev.sof_consumer;
 | 
				
			||||||
  // Only if all drivers switched off SOF calls the SOF interrupt may be disabled
 | 
					  // Keep track how many class instances need the SOF interrupt
 | 
				
			||||||
  dcd_sof_enable(rhport, en);
 | 
					  if (en) {
 | 
				
			||||||
 | 
					    _usbd_dev.sof_consumer |= (uint8_t)(1 << consumer);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    _usbd_dev.sof_consumer &= (uint8_t)(~(1 << consumer));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Test logically unequal
 | 
				
			||||||
 | 
					  if(!_usbd_dev.sof_consumer != !consumer_old) {
 | 
				
			||||||
 | 
					    dcd_sof_enable(rhport, _usbd_dev.sof_consumer);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
 | 
					bool usbd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,6 +97,9 @@ bool tud_disconnect(void);
 | 
				
			|||||||
// Return false on unsupported MCUs
 | 
					// Return false on unsupported MCUs
 | 
				
			||||||
bool tud_connect(void);
 | 
					bool tud_connect(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Enable or disable the Start Of Frame callback support
 | 
				
			||||||
 | 
					bool tud_sof_cb_enable(bool en);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Carry out Data and Status stage of control transfer
 | 
					// Carry out Data and Status stage of control transfer
 | 
				
			||||||
// - If len = 0, it is equivalent to sending status only
 | 
					// - If len = 0, it is equivalent to sending status only
 | 
				
			||||||
// - If len > wLength : it will be truncated
 | 
					// - If len > wLength : it will be truncated
 | 
				
			||||||
@@ -152,6 +155,9 @@ TU_ATTR_WEAK void tud_resume_cb(void);
 | 
				
			|||||||
// Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext()
 | 
					// Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext()
 | 
				
			||||||
void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr);
 | 
					void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Invoked when a new (micro) frame started
 | 
				
			||||||
 | 
					void tud_sof_cb(uint32_t frame_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Invoked when received control request with VENDOR TYPE
 | 
					// Invoked when received control request with VENDOR TYPE
 | 
				
			||||||
TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
 | 
					TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,15 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define TU_LOG_USBD(...)   TU_LOG(CFG_TUD_LOG_LEVEL, __VA_ARGS__)
 | 
					#define TU_LOG_USBD(...)   TU_LOG(CFG_TUD_LOG_LEVEL, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
 | 
					// MACRO CONSTANT TYPEDEF PROTYPES
 | 
				
			||||||
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					  SOF_CONSUMER_USER = 0,
 | 
				
			||||||
 | 
					  SOF_CONSUMER_AUDIO,
 | 
				
			||||||
 | 
					} sof_consumer_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
// Class Driver API
 | 
					// Class Driver API
 | 
				
			||||||
//--------------------------------------------------------------------+
 | 
					//--------------------------------------------------------------------+
 | 
				
			||||||
@@ -108,7 +117,7 @@ bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Enable SOF interrupt
 | 
					// Enable SOF interrupt
 | 
				
			||||||
void usbd_sof_enable(uint8_t rhport, bool en);
 | 
					void usbd_sof_enable(uint8_t rhport, sof_consumer_t consumer, bool en);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*------------------------------------------------------------------*/
 | 
					/*------------------------------------------------------------------*/
 | 
				
			||||||
/* Helper
 | 
					/* Helper
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user