mscd_init:
  357|      1|void mscd_init(void) {
  358|      1|  TU_LOG_INT(CFG_TUD_MSC_LOG_LEVEL, sizeof(mscd_interface_t));
  359|      1|  tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
  ------------------
  |  |  114|      1|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  ------------------
  360|      1|}
mscd_reset:
  366|  42.1k|void mscd_reset(uint8_t rhport) {
  367|  42.1k|  (void) rhport;
  368|  42.1k|  tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
  ------------------
  |  |  114|  42.1k|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  ------------------
  369|  42.1k|}
mscd_open:
  371|     67|uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
  372|       |  // only support SCSI's BOT protocol
  373|     67|  TU_VERIFY(TUSB_CLASS_MSC    == itf_desc->bInterfaceClass &&
  ------------------
  |  |  114|     67|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|     67|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  112|     67|#define TU_VERIFY_2ARGS(_cond, _ret)   TU_VERIFY_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|     67|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    268|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|     67|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  374|     67|            MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass &&
  375|     67|            MSC_PROTOCOL_BOT  == itf_desc->bInterfaceProtocol, 0);
  376|     67|  uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
  377|     67|  TU_ASSERT(max_len >= drv_len, 0); // Max length must be at least 1 interface + 2 endpoints
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  128|     67|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  378|       |
  379|     67|  mscd_interface_t * p_msc = &_mscd_itf;
  380|     67|  p_msc->itf_num = itf_desc->bInterfaceNumber;
  381|     67|  p_msc->rhport = rhport;
  382|       |
  383|       |  // Open endpoint pair
  384|     67|  TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0);
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  128|     67|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|     67|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|     67|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  385|       |
  386|       |  // Prepare for Command Block Wrapper
  387|      0|  TU_ASSERT(prepare_cbw(p_msc), drv_len);
  ------------------
  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  128|      0|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  388|       |
  389|      0|  return drv_len;
  390|      0|}

tusb_fifo.c:tu_min16:
  206|  79.6k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; }
  ------------------
  |  Branch (206:89): [True: 79.6k, False: 0]
  ------------------
usbd.c:tu_u16_low:
  197|  4.88k|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); }
  ------------------
  |  |   46|  4.88k|#define TU_U16_LOW(_u16)              ((uint8_t) ((uint16_t) (_u16) & 0x00ffu))
  ------------------
usbd.c:tu_desc_in_bounds:
  390|     67|TU_ATTR_ALWAYS_INLINE static inline bool tu_desc_in_bounds(const uint8_t *p_desc, const uint8_t *desc_end) {
  391|     67|  return p_desc < desc_end && tu_desc_next(p_desc) <= desc_end;
  ------------------
  |  Branch (391:10): [True: 67, False: 0]
  |  Branch (391:31): [True: 67, False: 0]
  ------------------
  392|     67|}
usbd.c:tu_desc_type:
  381|    134|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
  382|    134|  return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
  383|    134|}
usbd.c:tu_u16_high:
  196|    864|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); }
  ------------------
  |  |   45|    864|#define TU_U16_HIGH(_u16)             ((uint8_t) (((uint16_t) (_u16) >> 8) & 0x00ffu))
  ------------------
usbd.c:tu_unaligned_read16:
  271|    197|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void *mem) {
  272|    197|  tu_unaligned_uint16_t const *ua16 = (tu_unaligned_uint16_t const *) mem;
  273|    197|  return ua16->val;
  274|    197|}
usbd.c:tu_desc_len:
  376|    292|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
  377|    292|  return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
  378|    292|}
usbd.c:tu_desc_next:
  370|     67|TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
  371|     67|  uint8_t const* desc8 = (uint8_t const*) desc;
  372|     67|  return desc8 + desc8[DESC_OFFSET_LEN];
  373|     67|}
usbd_control.c:tu_min16:
  206|  7.62k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; }
  ------------------
  |  Branch (206:89): [True: 4.62k, False: 3.00k]
  ------------------
usbd_control.c:tu_memcpy_s:
  137|    696|TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) {
  138|    696|  if (dest == NULL) {
  ------------------
  |  Branch (138:7): [True: 0, False: 696]
  ------------------
  139|      0|    return -1;
  140|      0|  }
  141|       |
  142|    696|  if (count == 0u) {
  ------------------
  |  Branch (142:7): [True: 0, False: 696]
  ------------------
  143|      0|    return 0;
  144|      0|  }
  145|       |
  146|    696|  if (src == NULL) {
  ------------------
  |  Branch (146:7): [True: 0, False: 696]
  ------------------
  147|      0|    return -1;
  148|      0|  }
  149|       |
  150|    696|  if (count > destsz) {
  ------------------
  |  Branch (150:7): [True: 0, False: 696]
  ------------------
  151|      0|    return -1;
  152|      0|  }
  153|       |
  154|    696|  (void) memcpy(dest, src, count);
  155|    696|  return 0;
  156|    696|}
msc_device.c:tu_desc_next:
  370|     67|TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
  371|     67|  uint8_t const* desc8 = (uint8_t const*) desc;
  372|     67|  return desc8 + desc8[DESC_OFFSET_LEN];
  373|     67|}

tu_fifo_clear:
   81|      1|void tu_fifo_clear(tu_fifo_t *f) {
   82|      1|  ff_lock(f->mutex_wr);
   83|      1|  ff_lock(f->mutex_rd);
   84|       |
   85|      1|  f->rd_idx = 0;
   86|      1|  f->wr_idx = 0;
   87|       |
   88|      1|  ff_unlock(f->mutex_wr);
   89|      1|  ff_unlock(f->mutex_rd);
   90|      1|}
tu_fifo_peek_n_access_mode:
  463|   159k|                                    const tu_hwfifo_access_t *access_mode) {
  464|   159k|  uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
  465|   159k|  if (count == 0) {
  ------------------
  |  Branch (465:7): [True: 80.2k, False: 79.6k]
  ------------------
  466|  80.2k|    return 0; // nothing to peek
  467|  80.2k|  }
  468|       |
  469|       |  // Check overflow and correct if required
  470|  79.6k|  if (count > f->depth) {
  ------------------
  |  Branch (470:7): [True: 0, False: 79.6k]
  ------------------
  471|      0|    rd_idx = correct_read_index(f, wr_idx);
  472|      0|    count  = f->depth;
  473|      0|  }
  474|       |
  475|  79.6k|  if (count < n) {
  ------------------
  |  Branch (475:7): [True: 0, False: 79.6k]
  ------------------
  476|      0|    n = count; // limit to available count
  477|      0|  }
  478|       |
  479|  79.6k|  const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
  480|       |
  481|       |#if CFG_TUSB_FIFO_HWFIFO_API
  482|       |  if (access_mode != NULL) {
  483|       |    hwff_pull_n(f, p_buffer, n, rd_ptr, access_mode);
  484|       |  } else
  485|       |#endif
  486|  79.6k|  {
  487|  79.6k|    (void)access_mode;
  488|  79.6k|    ff_pull_n(f, p_buffer, n, rd_ptr);
  489|  79.6k|  }
  490|       |
  491|  79.6k|  return n;
  492|   159k|}
tu_fifo_read_n_access_mode:
  505|   159k|uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, const tu_hwfifo_access_t *access_mode) {
  506|   159k|  ff_lock(f->mutex_rd);
  507|       |
  508|       |  // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable
  509|   159k|  const uint16_t wr_idx = f->wr_idx;
  510|   159k|  n         = tu_fifo_peek_n_access_mode(f, buffer, n, wr_idx, f->rd_idx, access_mode);
  511|   159k|  f->rd_idx = advance_index(f->depth, f->rd_idx, n);
  512|       |
  513|   159k|  ff_unlock(f->mutex_rd);
  514|   159k|  return n;
  515|   159k|}
tu_fifo_write_n_access_mode:
  519|  79.6k|                                     const tu_hwfifo_access_t *access_mode) {
  520|  79.6k|  if (n == 0) {
  ------------------
  |  Branch (520:7): [True: 0, False: 79.6k]
  ------------------
  521|      0|    return 0;
  522|      0|  }
  523|       |
  524|  79.6k|  ff_lock(f->mutex_wr);
  525|       |
  526|  79.6k|  uint16_t wr_idx = f->wr_idx;
  527|  79.6k|  uint16_t rd_idx = f->rd_idx;
  528|       |
  529|  79.6k|  const uint8_t *buf8 = (const uint8_t *)data;
  530|       |
  531|  79.6k|  TU_LOG(TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u:  ", rd_idx, wr_idx,
  532|  79.6k|         tu_ff_overflow_count(f->depth, wr_idx, rd_idx), tu_ff_remaining_local(f->depth, wr_idx, rd_idx), n);
  533|       |
  534|  79.6k|  if (!f->overwritable) {
  ------------------
  |  Branch (534:7): [True: 79.6k, False: 0]
  ------------------
  535|       |    // limit up to full
  536|  79.6k|    const uint16_t remain = tu_ff_remaining_local(f->depth, wr_idx, rd_idx);
  537|  79.6k|    n                     = tu_min16(n, remain);
  538|  79.6k|  } else {
  539|       |    // In over-writable mode, fifo_write() is allowed even when fifo is full. In such case,
  540|       |    // oldest data in fifo i.e. at read pointer data will be overwritten
  541|       |    // Note: we can modify read buffer contents however we must not modify the read index itself within a write
  542|       |    // function! Since it would end up in a race condition with read functions!
  543|      0|    if (n >= f->depth) {
  ------------------
  |  Branch (543:9): [True: 0, False: 0]
  ------------------
  544|       |      // Only copy last part
  545|      0|      if (access_mode == NULL) {
  ------------------
  |  Branch (545:11): [True: 0, False: 0]
  ------------------
  546|      0|        buf8 += (n - f->depth);
  547|      0|      } else {
  548|       |        // TODO should read from hw fifo to discard data, however reading an odd number could
  549|       |        // accidentally discard data.
  550|      0|      }
  551|       |
  552|      0|      n = f->depth;
  553|       |
  554|       |      // We start writing at the read pointer's position since we fill the whole buffer
  555|      0|      wr_idx = rd_idx;
  556|      0|    } else {
  557|      0|      const uint16_t overflowable_count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
  558|      0|      if (overflowable_count + n >= 2 * f->depth) {
  ------------------
  |  Branch (558:11): [True: 0, False: 0]
  ------------------
  559|       |        // Double overflowed
  560|       |        // Index is bigger than the allowed range [0,2*depth)
  561|       |        // re-position write index to have a full fifo after pushed
  562|      0|        wr_idx = advance_index(f->depth, rd_idx, f->depth - n);
  563|       |
  564|       |        // TODO we should also shift out n bytes from read index since we avoid changing rd index !!
  565|       |        // However memmove() is expensive due to actual copying + wrapping consideration.
  566|       |        // Also race condition could happen anyway if read() is invoke while moving result in corrupted memory
  567|       |        // currently deliberately not implemented --> result in incorrect data read back
  568|      0|      } else {
  569|       |        // normal + single overflowed:
  570|       |        // Index is in the range of [0,2*depth) and thus detect and recoverable. Recovering is handled in read()
  571|       |        // Therefore we just increase write index
  572|       |        // we will correct (re-position) read index later on in fifo_read() function
  573|      0|      }
  574|      0|    }
  575|      0|  }
  576|       |
  577|  79.6k|  if (n) {
  ------------------
  |  Branch (577:7): [True: 79.6k, False: 0]
  ------------------
  578|  79.6k|    const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx);
  579|  79.6k|    TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr);
  580|       |
  581|       |#if CFG_TUSB_FIFO_HWFIFO_API
  582|       |    if (access_mode != NULL) {
  583|       |      hwff_push_n(f, buf8, n, wr_ptr, access_mode);
  584|       |    } else
  585|       |#endif
  586|  79.6k|    {
  587|  79.6k|      ff_push_n(f, buf8, n, wr_ptr);
  588|  79.6k|    }
  589|  79.6k|    f->wr_idx = advance_index(f->depth, wr_idx, n);
  590|       |
  591|  79.6k|    TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx);
  592|  79.6k|  }
  593|       |
  594|  79.6k|  ff_unlock(f->mutex_wr);
  595|       |
  596|  79.6k|  return n;
  597|  79.6k|}
tusb_fifo.c:idx2ptr:
  434|   159k|TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t idx) {
  435|       |  // Only run at most 3 times since index is limit in the range of [0..2*depth)
  436|   239k|  while (idx >= depth) {
  ------------------
  |  Branch (436:10): [True: 79.6k, False: 159k]
  ------------------
  437|  79.6k|    idx -= depth;
  438|  79.6k|  }
  439|   159k|  return idx;
  440|   159k|}
tusb_fifo.c:ff_pull_n:
  398|  79.6k|static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr) {
  399|  79.6k|  uint16_t       lin_bytes  = f->depth - rd_ptr;
  400|  79.6k|  uint16_t       wrap_bytes = n - lin_bytes; // only used if wrapped
  401|  79.6k|  const uint8_t *ff_buf     = f->buffer + rd_ptr;
  402|       |
  403|       |  // single byte access
  404|  79.6k|  if (n <= lin_bytes) {
  ------------------
  |  Branch (404:7): [True: 79.6k, False: 0]
  ------------------
  405|       |    // Linear only
  406|  79.6k|    memcpy(app_buf, ff_buf, n);
  407|  79.6k|  } else {
  408|       |    // Wrap around
  409|      0|    memcpy(app_buf, ff_buf, lin_bytes);                            // linear part
  410|      0|    memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part
  411|      0|  }
  412|  79.6k|}
tusb_fifo.c:advance_index:
  420|   239k|static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) {
  421|       |  // We limit the index space of p such that a correct wrap around happens
  422|       |  // Check for a wrap around or if we are in unused index space - This has to be checked first!!
  423|       |  // We are exploiting the wrap around to the correct index
  424|   239k|  uint16_t new_idx = (uint16_t)(idx + offset);
  425|   239k|  if ((idx > new_idx) || (new_idx >= 2 * depth)) {
  ------------------
  |  Branch (425:7): [True: 0, False: 239k]
  |  Branch (425:26): [True: 4.98k, False: 234k]
  ------------------
  426|  4.98k|    const uint16_t non_used_index_space = (uint16_t)(UINT16_MAX - (2 * depth - 1));
  427|  4.98k|    new_idx                             = (uint16_t)(new_idx + non_used_index_space);
  428|  4.98k|  }
  429|       |
  430|   239k|  return new_idx;
  431|   239k|}
tusb_fifo.c:ff_push_n:
  382|  79.6k|static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr) {
  383|  79.6k|  uint16_t lin_bytes  = f->depth - wr_ptr;
  384|  79.6k|  uint16_t wrap_bytes = n - lin_bytes;
  385|  79.6k|  uint8_t *ff_buf     = f->buffer + wr_ptr;
  386|       |
  387|  79.6k|  if (n <= lin_bytes) {
  ------------------
  |  Branch (387:7): [True: 79.6k, False: 0]
  ------------------
  388|       |    // Linear only case
  389|  79.6k|    memcpy(ff_buf, app_buf, n);
  390|  79.6k|  } else {
  391|       |    // Wrap around case
  392|      0|    memcpy(ff_buf, app_buf, lin_bytes);                                    // linear part
  393|      0|    memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part
  394|      0|  }
  395|  79.6k|}

tusb_fifo.c:tu_ff_overflow_count:
  262|   239k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_ff_overflow_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
  263|   239k|  const int32_t diff = (int32_t)wr_idx - (int32_t)rd_idx;
  264|   239k|  if (diff >= 0) {
  ------------------
  |  Branch (264:7): [True: 233k, False: 6.29k]
  ------------------
  265|   233k|    return (uint16_t)diff;
  266|   233k|  } else {
  267|  6.29k|    return (uint16_t)(2 * depth + diff);
  268|  6.29k|  }
  269|   239k|}
tusb_fifo.c:tu_ff_remaining_local:
  272|  79.6k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_ff_remaining_local(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
  273|  79.6k|  const uint16_t ovf_count = tu_ff_overflow_count(depth, wr_idx, rd_idx);
  274|  79.6k|  return (depth > ovf_count) ? (depth - ovf_count) : 0;
  ------------------
  |  Branch (274:10): [True: 79.6k, False: 0]
  ------------------
  275|  79.6k|}
usbd.c:tu_fifo_read_n:
  211|   159k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) {
  212|       |  return tu_fifo_read_n_access_mode(f, buffer, n, NULL);
  213|   159k|}
usbd.c:tu_fifo_write_n:
  224|  79.6k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) {
  225|       |  return tu_fifo_write_n_access_mode(f, data, n, NULL);
  226|  79.6k|}

usbd.c:tu_edpt_number:
  554|  8.99k|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) {
  555|  8.99k|  return (uint8_t) (addr & TUSB_EPNUM_MASK);
  556|  8.99k|}
usbd.c:tu_edpt_dir:
  549|  8.92k|TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) {
  550|  8.92k|  return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
  ------------------
  |  Branch (550:10): [True: 4.52k, False: 4.40k]
  ------------------
  551|  8.92k|}
dcd_fuzz.cc:_ZL12tu_edpt_addrhh:
  558|    105|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) {
  559|    105|  return (uint8_t) (num | (dir == (uint8_t)TUSB_DIR_IN ? (uint8_t)TUSB_DIR_IN_MASK : 0u));
  ------------------
  |  Branch (559:28): [True: 105, False: 0]
  ------------------
  560|    105|}
dcd_fuzz.cc:_ZL11tu_edpt_dirh:
  549|  5.91k|TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) {
  550|  5.91k|  return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
  ------------------
  |  Branch (550:10): [True: 4.16k, False: 1.74k]
  ------------------
  551|  5.91k|}

dcd_fuzz.cc:_ZL20dcd_event_bus_signalh13dcd_eventid_tb:
  200|  23.7k|TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) {
  201|  23.7k|  dcd_event_t event;
  202|  23.7k|  event.rhport = rhport;
  203|  23.7k|  event.event_id = eid;
  204|  23.7k|  dcd_event_handler(&event, in_isr);
  205|  23.7k|}
dcd_fuzz.cc:_ZL19dcd_event_bus_reseth12tusb_speed_tb:
  208|  28.7k|TU_ATTR_ALWAYS_INLINE static inline  void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) {
  209|  28.7k|  dcd_event_t event;
  210|  28.7k|  event.rhport = rhport;
  211|  28.7k|  event.event_id = DCD_EVENT_BUS_RESET;
  212|  28.7k|  event.bus_reset.speed = speed;
  213|  28.7k|  dcd_event_handler(&event, in_isr);
  214|  28.7k|}
dcd_fuzz.cc:_ZL24dcd_event_setup_receivedhPKhb:
  217|  28.7k|TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) {
  218|  28.7k|  dcd_event_t event;
  219|  28.7k|  event.rhport = rhport;
  220|  28.7k|  event.event_id = DCD_EVENT_SETUP_RECEIVED;
  221|  28.7k|  (void) memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t));
  222|  28.7k|  dcd_event_handler(&event, in_isr);
  223|  28.7k|}

tud_event_hook_cb:
   48|  79.6k|TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
   49|  79.6k|  (void) rhport; (void) eventid; (void) in_isr;
   50|  79.6k|}
tud_descriptor_bos_cb:
   56|     20|TU_ATTR_WEAK uint8_t const* tud_descriptor_bos_cb(void) {
   57|       |  return NULL;
   58|     20|}
tud_descriptor_device_qualifier_cb:
   60|    102|TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void) {
   61|       |  return NULL;
   62|    102|}
tud_descriptor_other_speed_configuration_cb:
   64|     15|TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
   65|     15|  (void) index;
   66|       |  return NULL;
   67|     15|}
tud_umount_cb:
   72|  13.4k|TU_ATTR_WEAK void tud_umount_cb(void) {
   73|  13.4k|}
tud_suspend_cb:
   75|  4.42k|TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en) {
   76|  4.42k|  (void) remote_wakeup_en;
   77|  4.42k|}
tud_resume_cb:
   79|  4.35k|TU_ATTR_WEAK void tud_resume_cb(void) {
   80|  4.35k|}
tud_vendor_control_xfer_cb:
   82|  7.67k|TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
   83|  7.67k|  (void) rhport; (void) stage; (void) request;
   84|       |  return false;
   85|  7.67k|}
usbd_app_driver_get_cb:
  431|      1|TU_ATTR_WEAK usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) {
  432|      1|  *driver_count = 0;
  433|       |  return NULL;
  434|      1|}
tud_inited:
  515|  81.0k|bool tud_inited(void) {
  516|  81.0k|  return _usbd_rhport != RHPORT_INVALID;
  517|  81.0k|}
tud_rhport_init:
  523|    807|bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
  524|    807|  if (tud_inited()) {
  ------------------
  |  Branch (524:7): [True: 806, False: 1]
  ------------------
  525|    806|    return true; // skip if already initialized
  526|    806|  }
  527|      1|  TU_ASSERT(rh_init);
  ------------------
  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  528|       | #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
  529|       |  char const* speed_str = 0;
  530|       |  switch (rh_init->speed) {
  531|       |    case TUSB_SPEED_HIGH:
  532|       |      speed_str = "High";
  533|       |    break;
  534|       |    case TUSB_SPEED_FULL:
  535|       |      speed_str = "Full";
  536|       |    break;
  537|       |    case TUSB_SPEED_LOW:
  538|       |      speed_str = "Low";
  539|       |    break;
  540|       |    case TUSB_SPEED_AUTO:
  541|       |      speed_str = "Auto";
  542|       |    break;
  543|       |  default:
  544|       |    break;
  545|       |  }
  546|       |  TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, speed_str);
  547|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t));
  548|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t));
  549|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t));
  550|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t));
  551|       |#endif
  552|       |
  553|      1|  tu_varclr(&_usbd_dev);
  ------------------
  |  |  115|      1|#define tu_varclr(_var)          tu_memclr(_var, sizeof(*(_var)))
  |  |  ------------------
  |  |  |  |  114|      1|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  |  |  ------------------
  ------------------
  554|      1|  _usbd_queued_setup = 0;
  555|       |
  556|      1|  osal_spin_init(&_usbd_spin);
  557|       |
  558|       |#if OSAL_MUTEX_REQUIRED
  559|       |  // Init device mutex
  560|       |  _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef);
  561|       |  TU_ASSERT(_usbd_mutex);
  562|       |#endif
  563|       |
  564|       |  // Init device queue & task
  565|      1|  _usbd_q = osal_queue_create(&_usbd_qdef);
  566|      1|  TU_ASSERT(_usbd_q);
  ------------------
  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  567|       |
  568|       |  // Get application driver if available
  569|      1|  _app_driver = usbd_app_driver_get_cb(&_app_driver_count);
  570|      1|  TU_ASSERT(_app_driver_count + BUILTIN_DRIVER_COUNT <= UINT8_MAX);
  ------------------
  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  571|       |
  572|       |  // Init class drivers
  573|      2|  for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
  ------------------
  |  |  358|      2|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + BUILTIN_DRIVER_COUNT))
  ------------------
  |  Branch (573:23): [True: 1, False: 1]
  ------------------
  574|      1|    usbd_class_driver_t const* driver = get_driver(i);
  575|      1|    TU_ASSERT(driver && driver->init);
  ------------------
  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      2|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 1, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 1, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  576|      1|    TU_LOG_USBD("%s init\r\n", driver->name);
  577|      1|    driver->init();
  578|      1|  }
  579|       |
  580|      1|  _usbd_rhport = rhport;
  581|       |
  582|       |  // Init device controller driver
  583|      1|  TU_ASSERT(dcd_init(rhport, rh_init));
  ------------------
  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  584|      1|  dcd_int_enable(rhport);
  585|       |
  586|       |  return true;
  587|      1|}
tud_task_ext:
  674|  80.2k|void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
  675|  80.2k|  (void) in_isr; // not implemented yet
  676|       |
  677|       |  // Skip if stack is not initialized
  678|  80.2k|  if (!tud_inited()) {
  ------------------
  |  Branch (678:7): [True: 0, False: 80.2k]
  ------------------
  679|      0|    return;
  680|      0|  }
  681|       |
  682|       |  // Loop until there are no more events in the queue or CFG_TUD_TASK_EVENTS_PER_RUN is reached
  683|   159k|  for (unsigned epr = 0;; epr++) {
  684|   159k|#if CFG_TUD_TASK_EVENTS_PER_RUN > 0
  685|   159k|    if (epr >= CFG_TUD_TASK_EVENTS_PER_RUN) {
  ------------------
  |  |  585|   159k|  #define CFG_TUD_TASK_EVENTS_PER_RUN  16
  ------------------
  |  Branch (685:9): [True: 0, False: 159k]
  ------------------
  686|      0|      TU_LOG_USBD("USBD event limit (" TU_XSTRING(CFG_TUD_TASK_EVENTS_PER_RUN) ") reached\r\n");
  687|      0|      break;
  688|      0|    }
  689|   159k|#endif
  690|   159k|    dcd_event_t event;
  691|   159k|    if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) {
  ------------------
  |  Branch (691:9): [True: 80.2k, False: 79.6k]
  ------------------
  692|  80.2k|      return;
  693|  80.2k|    }
  694|       |
  695|       |#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
  696|       |    if (event.event_id == DCD_EVENT_SETUP_RECEIVED) {
  697|       |      TU_LOG_USBD("\r\n"); // extra line for setup
  698|       |    }
  699|       |    TU_LOG_USBD("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED");
  700|       |#endif
  701|       |
  702|  79.6k|    switch (event.event_id) {
  703|  28.7k|      case DCD_EVENT_BUS_RESET:
  ------------------
  |  Branch (703:7): [True: 28.7k, False: 50.9k]
  ------------------
  704|  28.7k|        TU_LOG_USBD(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]);
  705|  28.7k|        usbd_reset(event.rhport);
  706|  28.7k|        _usbd_dev.speed = event.bus_reset.speed;
  707|  28.7k|        break;
  708|       |
  709|  13.4k|      case DCD_EVENT_UNPLUGGED:
  ------------------
  |  Branch (709:7): [True: 13.4k, False: 66.2k]
  ------------------
  710|  13.4k|        TU_LOG_USBD("\r\n");
  711|  13.4k|        usbd_reset(event.rhport);
  712|  13.4k|        tud_umount_cb();
  713|  13.4k|        break;
  714|       |
  715|  28.7k|      case DCD_EVENT_SETUP_RECEIVED:
  ------------------
  |  Branch (715:7): [True: 28.7k, False: 50.9k]
  ------------------
  716|  28.7k|        TU_ASSERT(_usbd_queued_setup > 0,);
  ------------------
  |  |  131|  28.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  28.7k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  28.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  128|  28.7k|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  28.7k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  28.7k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 28.7k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  28.7k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 28.7k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  717|  28.7k|        _usbd_queued_setup--;
  718|  28.7k|        TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8);
  719|  28.7k|        if (_usbd_queued_setup != 0) {
  ------------------
  |  Branch (719:13): [True: 0, False: 28.7k]
  ------------------
  720|      0|          TU_LOG_USBD("  Skipped since there is other SETUP in queue\r\n");
  721|      0|          break;
  722|      0|        }
  723|       |
  724|       |        // Mark as connected after receiving 1st setup packet.
  725|       |        // But it is easier to set it every time instead of wasting time to check then set
  726|  28.7k|        _usbd_dev.connected = 1;
  727|       |
  728|       |        // mark both in & out control as free
  729|  28.7k|        _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = 0;
  730|  28.7k|        _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0;
  731|  28.7k|        _usbd_dev.ep_status[0][TUSB_DIR_IN].busy = 0;
  732|  28.7k|        _usbd_dev.ep_status[0][TUSB_DIR_IN].claimed = 0;
  733|       |
  734|       |        // Process control request
  735|  28.7k|        if (!process_control_request(event.rhport, &event.setup_received)) {
  ------------------
  |  Branch (735:13): [True: 22.2k, False: 6.43k]
  ------------------
  736|  22.2k|          TU_LOG_USBD("  Stall EP0\r\n");
  737|       |          // Failed -> stall both control endpoint IN and OUT
  738|  22.2k|          dcd_edpt_stall(event.rhport, 0);
  739|  22.2k|          dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK);
  740|  22.2k|        }
  741|  28.7k|        break;
  742|       |
  743|      0|      case DCD_EVENT_XFER_COMPLETE: {
  ------------------
  |  Branch (743:7): [True: 0, False: 79.6k]
  ------------------
  744|       |        // Invoke the class callback associated with the endpoint address
  745|      0|        uint8_t const ep_addr = event.xfer_complete.ep_addr;
  746|      0|        uint8_t const epnum = tu_edpt_number(ep_addr);
  747|      0|        uint8_t const ep_dir = tu_edpt_dir(ep_addr);
  748|       |
  749|      0|        TU_LOG_USBD("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
  750|       |
  751|      0|        _usbd_dev.ep_status[epnum][ep_dir].busy = 0;
  752|      0|        _usbd_dev.ep_status[epnum][ep_dir].claimed = 0;
  753|       |
  754|      0|        if (0 == epnum) {
  ------------------
  |  Branch (754:13): [True: 0, False: 0]
  ------------------
  755|      0|          usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
  756|      0|        } else {
  757|      0|          usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]);
  758|      0|          TU_ASSERT(driver,);
  ------------------
  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  128|      0|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  759|       |
  760|      0|          TU_LOG_USBD("  %s xfer callback\r\n", driver->name);
  761|      0|          driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
  762|      0|        }
  763|      0|        break;
  764|      0|      }
  765|       |
  766|  4.42k|      case DCD_EVENT_SUSPEND:
  ------------------
  |  Branch (766:7): [True: 4.42k, False: 75.2k]
  ------------------
  767|       |        // NOTE: When plugging/unplugging device, the D+/D- state are unstable and
  768|       |        // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event
  769|       |        // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected
  770|  4.42k|        if (_usbd_dev.connected) {
  ------------------
  |  Branch (770:13): [True: 4.42k, False: 0]
  ------------------
  771|  4.42k|          TU_LOG_USBD(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en);
  772|  4.42k|          tud_suspend_cb(_usbd_dev.remote_wakeup_en);
  773|  4.42k|        } else {
  774|      0|          TU_LOG_USBD(" Skipped\r\n");
  775|      0|        }
  776|  4.42k|        break;
  777|       |
  778|  4.35k|      case DCD_EVENT_RESUME:
  ------------------
  |  Branch (778:7): [True: 4.35k, False: 75.3k]
  ------------------
  779|  4.35k|        if (_usbd_dev.connected) {
  ------------------
  |  Branch (779:13): [True: 4.35k, False: 0]
  ------------------
  780|  4.35k|          TU_LOG_USBD("\r\n");
  781|  4.35k|          tud_resume_cb();
  782|  4.35k|        } else {
  783|      0|          TU_LOG_USBD(" Skipped\r\n");
  784|      0|        }
  785|  4.35k|        break;
  786|       |
  787|      0|      case USBD_EVENT_FUNC_CALL:
  ------------------
  |  Branch (787:7): [True: 0, False: 79.6k]
  ------------------
  788|      0|        TU_LOG_USBD("\r\n");
  789|      0|        if (event.func_call.func != NULL) {
  ------------------
  |  Branch (789:13): [True: 0, False: 0]
  ------------------
  790|      0|          event.func_call.func(event.func_call.param);
  791|      0|        }
  792|      0|        break;
  793|       |
  794|      0|      case DCD_EVENT_SOF:
  ------------------
  |  Branch (794:7): [True: 0, False: 79.6k]
  ------------------
  795|      0|        if (tu_bit_test(_usbd_dev.sof_consumer, SOF_CONSUMER_USER)) {
  ------------------
  |  Branch (795:13): [True: 0, False: 0]
  ------------------
  796|      0|          TU_LOG_USBD("\r\n");
  797|      0|          tud_sof_cb(event.sof.frame_count);
  798|      0|        }
  799|      0|      break;
  800|       |
  801|      0|      default:
  ------------------
  |  Branch (801:7): [True: 0, False: 79.6k]
  ------------------
  802|      0|        TU_BREAKPOINT();
  ------------------
  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  ------------------
  ------------------
  803|      0|        break;
  804|  79.6k|    }
  805|       |
  806|       |    // allow to exit tud_task() if there is no event in the next run
  807|  79.6k|    timeout_ms = 0;
  808|  79.6k|  }
  809|  80.2k|}
dcd_event_handler:
 1238|  81.2k|TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) {
 1239|  81.2k|  bool send = false;
 1240|  81.2k|  switch (event->event_id) {
 1241|  13.4k|    case DCD_EVENT_UNPLUGGED:
  ------------------
  |  Branch (1241:5): [True: 13.4k, False: 67.7k]
  ------------------
 1242|  13.4k|      _usbd_dev.connected = 0;
 1243|  13.4k|      _usbd_dev.addressed = 0;
 1244|  13.4k|      _usbd_dev.cfg_num = 0;
 1245|  13.4k|      _usbd_dev.suspended = 0;
 1246|  13.4k|      send = true;
 1247|  13.4k|      break;
 1248|       |
 1249|  5.06k|    case DCD_EVENT_SUSPEND:
  ------------------
  |  Branch (1249:5): [True: 5.06k, False: 76.1k]
  ------------------
 1250|       |      // NOTE: When plugging/unplugging device, the D+/D- state are unstable and
 1251|       |      // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ).
 1252|       |      // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish
 1253|       |      // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected
 1254|  5.06k|      if (_usbd_dev.connected) {
  ------------------
  |  Branch (1254:11): [True: 4.42k, False: 638]
  ------------------
 1255|  4.42k|        _usbd_dev.suspended = 1;
 1256|  4.42k|        send = true;
 1257|  4.42k|      }
 1258|  5.06k|      break;
 1259|       |
 1260|  5.23k|    case DCD_EVENT_RESUME:
  ------------------
  |  Branch (1260:5): [True: 5.23k, False: 75.9k]
  ------------------
 1261|       |      // skip event if not connected (especially required for SAMD)
 1262|  5.23k|      if (_usbd_dev.connected) {
  ------------------
  |  Branch (1262:11): [True: 4.35k, False: 883]
  ------------------
 1263|  4.35k|        _usbd_dev.suspended = 0;
 1264|  4.35k|        send = true;
 1265|  4.35k|      }
 1266|  5.23k|      break;
 1267|       |
 1268|      0|    case DCD_EVENT_SOF:
  ------------------
  |  Branch (1268:5): [True: 0, False: 81.2k]
  ------------------
 1269|       |      // SOF driver handler in ISR context
 1270|      0|      for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
  ------------------
  |  |  358|      0|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + BUILTIN_DRIVER_COUNT))
  ------------------
  |  Branch (1270:27): [True: 0, False: 0]
  ------------------
 1271|      0|        usbd_class_driver_t const* driver = get_driver(i);
 1272|      0|        if (driver && driver->sof) {
  ------------------
  |  Branch (1272:13): [True: 0, False: 0]
  |  Branch (1272:23): [True: 0, False: 0]
  ------------------
 1273|      0|          driver->sof(event->rhport, event->sof.frame_count);
 1274|      0|        }
 1275|      0|      }
 1276|       |
 1277|       |      // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup
 1278|       |      // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational
 1279|      0|      if (_usbd_dev.suspended) {
  ------------------
  |  Branch (1279:11): [True: 0, False: 0]
  ------------------
 1280|      0|        _usbd_dev.suspended = 0;
 1281|       |
 1282|      0|        dcd_event_t const event_resume = {.rhport = event->rhport, .event_id = DCD_EVENT_RESUME};
 1283|      0|        queue_event(&event_resume, in_isr);
 1284|      0|      }
 1285|       |
 1286|      0|      if (tu_bit_test(_usbd_dev.sof_consumer, SOF_CONSUMER_USER)) {
  ------------------
  |  Branch (1286:11): [True: 0, False: 0]
  ------------------
 1287|      0|        dcd_event_t const event_sof = {.rhport = event->rhport, .event_id = DCD_EVENT_SOF, .sof.frame_count = event->sof.frame_count};
 1288|      0|        queue_event(&event_sof, in_isr);
 1289|      0|      }
 1290|      0|      break;
 1291|       |
 1292|  28.7k|    case DCD_EVENT_SETUP_RECEIVED:
  ------------------
  |  Branch (1292:5): [True: 28.7k, False: 52.4k]
  ------------------
 1293|  28.7k|      _usbd_queued_setup++;
 1294|  28.7k|      send = true;
 1295|  28.7k|      break;
 1296|       |
 1297|      0|    case DCD_EVENT_XFER_COMPLETE: {
  ------------------
  |  Branch (1297:5): [True: 0, False: 81.2k]
  ------------------
 1298|       |      // Invoke the class callback associated with the endpoint address
 1299|      0|      uint8_t const ep_addr = event->xfer_complete.ep_addr;
 1300|      0|      uint8_t const epnum = tu_edpt_number(ep_addr);
 1301|      0|      uint8_t const ep_dir = tu_edpt_dir(ep_addr);
 1302|       |
 1303|      0|      send = true;
 1304|      0|      if(epnum > 0) {
  ------------------
  |  Branch (1304:10): [True: 0, False: 0]
  ------------------
 1305|      0|        usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]);
 1306|       |
 1307|      0|        if (driver && driver->xfer_isr) {
  ------------------
  |  Branch (1307:13): [True: 0, False: 0]
  |  Branch (1307:23): [True: 0, False: 0]
  ------------------
 1308|      0|          _usbd_dev.ep_status[epnum][ep_dir].busy = 0;
 1309|      0|          _usbd_dev.ep_status[epnum][ep_dir].claimed = 0;
 1310|       |
 1311|      0|          send = !driver->xfer_isr(event->rhport, ep_addr, (xfer_result_t) event->xfer_complete.result, event->xfer_complete.len);
 1312|       |
 1313|       |          // xfer_isr() is deferred to xfer_cb(), revert busy/claimed status
 1314|      0|          if (send) {
  ------------------
  |  Branch (1314:15): [True: 0, False: 0]
  ------------------
 1315|      0|            _usbd_dev.ep_status[epnum][ep_dir].busy = 1;
 1316|      0|            _usbd_dev.ep_status[epnum][ep_dir].claimed = 1;
 1317|      0|          }
 1318|      0|        }
 1319|      0|      }
 1320|      0|      break;
 1321|      0|    }
 1322|       |
 1323|  28.7k|    default:
  ------------------
  |  Branch (1323:5): [True: 28.7k, False: 52.4k]
  ------------------
 1324|  28.7k|      send = true;
 1325|  28.7k|      break;
 1326|  81.2k|  }
 1327|       |
 1328|  81.2k|  if (send) {
  ------------------
  |  Branch (1328:7): [True: 79.6k, False: 1.52k]
  ------------------
 1329|  79.6k|    queue_event(event, in_isr);
 1330|  79.6k|  }
 1331|  81.2k|}
usbd_int_set:
 1337|   373k|void usbd_int_set(bool enabled) {
 1338|   373k|  if (enabled) {
  ------------------
  |  Branch (1338:7): [True: 186k, False: 186k]
  ------------------
 1339|   186k|    dcd_int_enable(_usbd_rhport);
 1340|   186k|  } else {
 1341|   186k|    dcd_int_disable(_usbd_rhport);
 1342|   186k|  }
 1343|   373k|}
usbd_open_edpt_pair:
 1354|     67|                         uint8_t *ep_in) {
 1355|     67|  for (int i = 0; i < ep_count; i++) {
  ------------------
  |  Branch (1355:19): [True: 67, False: 0]
  ------------------
 1356|     67|    const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc;
 1357|       |
 1358|     67|    TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer);
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|    134|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1359|     67|    TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|     67|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|     67|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1360|       |
 1361|      0|    if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
  ------------------
  |  Branch (1361:9): [True: 0, False: 0]
  ------------------
 1362|      0|      (*ep_in) = desc_ep->bEndpointAddress;
 1363|      0|    } else {
 1364|      0|      (*ep_out) = desc_ep->bEndpointAddress;
 1365|      0|    }
 1366|       |
 1367|      0|    p_desc = tu_desc_next(p_desc);
 1368|      0|  }
 1369|       |
 1370|      0|  return true;
 1371|     67|}
usbd_edpt_open:
 1389|     67|bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
 1390|     67|  rhport = _usbd_rhport;
 1391|       |
 1392|     67|  TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX);
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|     67|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|     67|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1393|      0|  TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t)_usbd_dev.speed));
  ------------------
  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|      0|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1394|       |
 1395|      0|  return dcd_edpt_open(rhport, desc_ep);
 1396|      0|}
usbd_edpt_xfer:
 1421|  5.81k|bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) {
 1422|  5.81k|  rhport = _usbd_rhport;
 1423|       |
 1424|  5.81k|  uint8_t const epnum = tu_edpt_number(ep_addr);
 1425|  5.81k|  uint8_t const dir = tu_edpt_dir(ep_addr);
 1426|       |
 1427|       |  // TODO skip ready() check for now since enumeration also use this API
 1428|       |  // TU_VERIFY(tud_ready());
 1429|       |
 1430|  5.81k|  TU_LOG_USBD("  Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes);
 1431|       |#if CFG_TUD_LOG_LEVEL >= 3
 1432|       |  if(dir == TUSB_DIR_IN) {
 1433|       |    TU_LOG_MEM(CFG_TUD_LOG_LEVEL, buffer, total_bytes, 2);
 1434|       |  }
 1435|       |#endif
 1436|       |
 1437|       |  // Attempt to transfer on a busy endpoint, sound like an race condition !
 1438|  5.81k|  TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);
  ------------------
  |  |  131|  5.81k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  5.81k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  5.81k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|  5.81k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  5.81k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  5.81k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 5.81k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  5.81k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 5.81k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1439|       |
 1440|       |  // Set busy first since the actual transfer can be complete before dcd_edpt_xfer()
 1441|       |  // could return and USBD task can preempt and clear the busy
 1442|  5.81k|  _usbd_dev.ep_status[epnum][dir].busy = 1;
 1443|       |
 1444|  5.81k|  if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes, is_isr)) {
  ------------------
  |  Branch (1444:7): [True: 3.49k, False: 2.31k]
  ------------------
 1445|  3.49k|    return true;
 1446|  3.49k|  } else {
 1447|       |    // DCD error, mark endpoint as ready to allow next transfer
 1448|  2.31k|    _usbd_dev.ep_status[epnum][dir].busy = 0;
 1449|  2.31k|    _usbd_dev.ep_status[epnum][dir].claimed = 0;
 1450|  2.31k|    TU_LOG_USBD("FAILED\r\n");
 1451|  2.31k|    TU_BREAKPOINT();
  ------------------
  |  |   96|  2.31k|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (96:40): [Folded, False: 2.31k]
  |  |  ------------------
  ------------------
 1452|       |    return false;
 1453|  2.31k|  }
 1454|  5.81k|}
usbd_edpt_stall:
 1506|    102|void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
 1507|    102|  rhport = _usbd_rhport;
 1508|       |
 1509|    102|  uint8_t const epnum = tu_edpt_number(ep_addr);
 1510|    102|  uint8_t const dir = tu_edpt_dir(ep_addr);
 1511|       |
 1512|       |  // only stalled if currently cleared
 1513|    102|  TU_LOG_USBD("    Stall EP %02X\r\n", ep_addr);
 1514|    102|  dcd_edpt_stall(rhport, ep_addr);
 1515|    102|  _usbd_dev.ep_status[epnum][dir].stalled = 1;
 1516|    102|  _usbd_dev.ep_status[epnum][dir].busy = 1;
 1517|    102|}
usbd_edpt_clear_stall:
 1519|     65|void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
 1520|     65|  rhport = _usbd_rhport;
 1521|       |
 1522|     65|  uint8_t const epnum = tu_edpt_number(ep_addr);
 1523|     65|  uint8_t const dir = tu_edpt_dir(ep_addr);
 1524|       |
 1525|       |  // only clear if currently stalled
 1526|     65|  TU_LOG_USBD("    Clear Stall EP %02X\r\n", ep_addr);
 1527|     65|  dcd_edpt_clear_stall(rhport, ep_addr);
 1528|     65|  _usbd_dev.ep_status[epnum][dir].stalled = 0;
 1529|     65|  _usbd_dev.ep_status[epnum][dir].busy = 0;
 1530|     65|}
usbd_edpt_stalled:
 1532|    404|bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) {
 1533|    404|  (void) rhport;
 1534|       |
 1535|    404|  uint8_t const epnum = tu_edpt_number(ep_addr);
 1536|    404|  uint8_t const dir = tu_edpt_dir(ep_addr);
 1537|       |
 1538|    404|  return _usbd_dev.ep_status[epnum][dir].stalled;
 1539|    404|}
usbd.c:get_driver:
  362|  45.0k|TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8_t drvid) {
  363|  45.0k|  usbd_class_driver_t const *driver = NULL;
  364|  45.0k|  if (drvid < _app_driver_count) {
  ------------------
  |  Branch (364:7): [True: 0, False: 45.0k]
  ------------------
  365|       |    // Application drivers
  366|      0|    driver = &_app_driver[drvid];
  367|  45.0k|  } else{
  368|  45.0k|    drvid -= _app_driver_count;
  369|  45.0k|    if (drvid < BUILTIN_DRIVER_COUNT) {
  ------------------
  |  Branch (369:9): [True: 42.2k, False: 2.74k]
  ------------------
  370|  42.2k|      driver = &_usbd_driver[drvid];
  371|  42.2k|    }
  372|  45.0k|  }
  373|       |
  374|  45.0k|  return driver;
  375|  45.0k|}
usbd.c:usbd_reset:
  647|  42.1k|static void usbd_reset(uint8_t rhport) {
  648|  42.1k|  configuration_reset(rhport);
  649|  42.1k|  usbd_control_reset();
  650|  42.1k|}
usbd.c:configuration_reset:
  635|  42.1k|static void configuration_reset(uint8_t rhport) {
  636|  84.3k|  for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
  ------------------
  |  |  358|  84.3k|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + BUILTIN_DRIVER_COUNT))
  ------------------
  |  Branch (636:23): [True: 42.1k, False: 42.1k]
  ------------------
  637|  42.1k|    usbd_class_driver_t const* driver = get_driver(i);
  638|  42.1k|    TU_ASSERT(driver,);
  ------------------
  |  |  131|  42.1k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  42.1k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  42.1k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  128|  42.1k|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  42.1k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  42.1k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 42.1k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  42.1k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 42.1k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  639|  42.1k|    driver->reset(rhport);
  640|  42.1k|  }
  641|       |
  642|  42.1k|  tu_varclr(&_usbd_dev);
  ------------------
  |  |  115|  42.1k|#define tu_varclr(_var)          tu_memclr(_var, sizeof(*(_var)))
  |  |  ------------------
  |  |  |  |  114|  42.1k|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  |  |  ------------------
  ------------------
  643|  42.1k|  (void)memset(_usbd_dev.itf2drv, TUSB_INDEX_INVALID_8, sizeof(_usbd_dev.itf2drv)); // invalid mapping
  644|  42.1k|  (void)memset(_usbd_dev.ep2drv, TUSB_INDEX_INVALID_8, sizeof(_usbd_dev.ep2drv));   // invalid mapping
  645|  42.1k|}
usbd.c:process_control_request:
  824|  28.7k|static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request) {
  825|  28.7k|  usbd_control_set_complete_callback(NULL);
  826|  28.7k|  TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID);
  ------------------
  |  |  131|  28.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  28.7k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  28.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|  28.7k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  28.7k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  28.7k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|  2.99k|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 2.99k]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|  2.99k|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 2.99k]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 2.99k, False: 25.7k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  28.7k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 25.7k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  827|       |
  828|       |  // Vendor request
  829|  25.7k|  if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) {
  ------------------
  |  Branch (829:8): [True: 7.67k, False: 18.0k]
  ------------------
  830|  7.67k|    usbd_control_set_complete_callback(tud_vendor_control_xfer_cb);
  831|  7.67k|    return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request);
  832|  7.67k|  }
  833|       |
  834|       |#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
  835|       |  if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) {
  836|       |    TU_LOG_USBD("  %s", tu_str_std_request[p_request->bRequest]);
  837|       |    if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) {
  838|       |      TU_LOG_USBD("\r\n");
  839|       |    }
  840|       |  }
  841|       |#endif
  842|       |
  843|  18.0k|  switch (p_request->bmRequestType_bit.recipient) { //-V2520
  844|       |    //------------- Device Requests e.g in enumeration -------------//
  845|  8.88k|    case TUSB_REQ_RCPT_DEVICE:
  ------------------
  |  Branch (845:5): [True: 8.88k, False: 9.16k]
  ------------------
  846|  8.88k|      if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) {
  ------------------
  |  Branch (846:12): [True: 415, False: 8.46k]
  ------------------
  847|    415|        uint8_t const itf = tu_u16_low(p_request->wIndex);
  848|    415|        TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
  ------------------
  |  |  114|    415|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    415|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    415|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    415|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    415|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    415|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 256, False: 159]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    256|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    256|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    415|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 159]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  849|       |
  850|    159|        usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]);
  851|    159|        TU_VERIFY(driver);
  ------------------
  |  |  114|    159|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    159|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    159|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    159|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    159|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    159|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 159, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    159|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    159|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    159|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  852|       |
  853|       |        // forward to class driver: "non-STD request to Interface"
  854|      0|        return invoke_class_control(rhport, driver, p_request);
  855|    159|      }
  856|       |
  857|  8.46k|      if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) {
  ------------------
  |  Branch (857:11): [True: 0, False: 8.46k]
  ------------------
  858|       |        // Non-standard request is not supported
  859|      0|        TU_BREAKPOINT();
  ------------------
  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  ------------------
  ------------------
  860|      0|        return false;
  861|      0|      }
  862|       |
  863|  8.46k|      switch (p_request->bRequest) { //-V2520
  864|    105|        case TUSB_REQ_SET_ADDRESS:
  ------------------
  |  Branch (864:9): [True: 105, False: 8.36k]
  ------------------
  865|       |          // Depending on mcu, status phase could be sent either before or after changing device address,
  866|       |          // or even require stack to not response with status at all
  867|       |          // Therefore DCD must take full responsibility to response and include zlp status packet if needed.
  868|    105|          usbd_control_set_request(p_request); // set request since DCD has no access to tud_control_status() API
  869|    105|          dcd_set_address(rhport, (uint8_t) p_request->wValue);
  870|       |          // skip tud_control_status()
  871|    105|          _usbd_dev.addressed = 1;
  872|    105|        break;
  873|       |
  874|    592|        case TUSB_REQ_GET_CONFIGURATION: {
  ------------------
  |  Branch (874:9): [True: 592, False: 7.87k]
  ------------------
  875|    592|          uint8_t cfg_num = _usbd_dev.cfg_num;
  876|    592|          tud_control_xfer(rhport, p_request, &cfg_num, 1);
  877|    592|        }
  878|    592|        break;
  879|       |
  880|    583|        case TUSB_REQ_SET_CONFIGURATION: {
  ------------------
  |  Branch (880:9): [True: 583, False: 7.88k]
  ------------------
  881|    583|          uint8_t const cfg_num = (uint8_t) p_request->wValue;
  882|       |
  883|       |          // Only process if new configure is different
  884|    583|          if (_usbd_dev.cfg_num != cfg_num) {
  ------------------
  |  Branch (884:15): [True: 67, False: 516]
  ------------------
  885|     67|            if (_usbd_dev.cfg_num != 0) {
  ------------------
  |  Branch (885:17): [True: 0, False: 67]
  ------------------
  886|       |              // already configured: need to clear all endpoints and driver first
  887|      0|              TU_LOG_USBD("  Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
  888|       |
  889|      0|              dcd_sof_enable(rhport, false);
  890|      0|              dcd_edpt_close_all(rhport);
  891|       |
  892|       |              // close all drivers and current configured state except bus speed
  893|      0|              const uint8_t speed = _usbd_dev.speed;
  894|      0|              configuration_reset(rhport);
  895|       |
  896|      0|              _usbd_dev.speed = speed; // restore speed
  897|      0|            }
  898|       |
  899|     67|            _usbd_dev.cfg_num = cfg_num;
  900|       |
  901|       |            // Handle the new configuration
  902|     67|            if (cfg_num == 0) {
  ------------------
  |  Branch (902:17): [True: 0, False: 67]
  ------------------
  903|      0|              tud_umount_cb();
  904|     67|            } else {
  905|     67|              if (!process_set_config(rhport, cfg_num)) {
  ------------------
  |  Branch (905:19): [True: 67, False: 0]
  ------------------
  906|     67|                _usbd_dev.cfg_num = 0;
  907|     67|                TU_ASSERT(false);
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|     67|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|     67|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 67, Folded]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  908|     67|              }
  909|      0|              tud_mount_cb();
  910|      0|            }
  911|     67|          }
  912|       |
  913|    516|          tud_control_status(rhport, p_request);
  914|    516|        }
  915|      0|        break;
  916|       |
  917|    864|        case TUSB_REQ_GET_DESCRIPTOR:
  ------------------
  |  Branch (917:9): [True: 864, False: 7.60k]
  ------------------
  918|    864|          TU_VERIFY(process_get_descriptor(rhport, p_request));
  ------------------
  |  |  114|    864|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    864|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    864|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    864|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    864|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    864|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 640, False: 224]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    640|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    640|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    864|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 224]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  919|    224|        break;
  920|       |
  921|    644|        case TUSB_REQ_SET_FEATURE:
  ------------------
  |  Branch (921:9): [True: 644, False: 7.82k]
  ------------------
  922|    644|          switch(p_request->wValue) { //-V2520
  923|     14|            case TUSB_REQ_FEATURE_REMOTE_WAKEUP:
  ------------------
  |  Branch (923:13): [True: 14, False: 630]
  ------------------
  924|     14|              TU_LOG_USBD("    Enable Remote Wakeup\r\n");
  925|       |              // Host may enable remote wake up before suspending especially HID device
  926|     14|              _usbd_dev.remote_wakeup_en = 1;
  927|     14|              tud_control_status(rhport, p_request);
  928|     14|              break;
  929|       |
  930|       |            #if CFG_TUD_TEST_MODE
  931|       |            case TUSB_REQ_FEATURE_TEST_MODE: {
  932|       |              // Only handle the test mode if supported and valid
  933|       |              TU_VERIFY(0 == tu_u16_low(p_request->wIndex));
  934|       |
  935|       |              uint8_t const selector = tu_u16_high(p_request->wIndex);
  936|       |              TU_VERIFY(TUSB_FEATURE_TEST_J <= selector && selector <= TUSB_FEATURE_TEST_FORCE_ENABLE);
  937|       |
  938|       |              usbd_control_set_complete_callback(process_test_mode_cb);
  939|       |              tud_control_status(rhport, p_request);
  940|       |              break;
  941|       |            }
  942|       |            #endif
  943|       |
  944|       |            // Stall unsupported feature selector
  945|    630|            default: return false;
  ------------------
  |  Branch (945:13): [True: 630, False: 14]
  ------------------
  946|    644|          }
  947|     14|        break;
  948|       |
  949|    447|        case TUSB_REQ_CLEAR_FEATURE:
  ------------------
  |  Branch (949:9): [True: 447, False: 8.01k]
  ------------------
  950|       |          // Only support remote wakeup for device feature
  951|    447|          TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
  ------------------
  |  |  114|    447|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    447|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    447|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    447|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    447|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    447|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 369, False: 78]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    369|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    369|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    447|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 78]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  952|     78|          TU_LOG_USBD("    Disable Remote Wakeup\r\n");
  953|       |
  954|       |          // Host may disable remote wake up after resuming
  955|     78|          _usbd_dev.remote_wakeup_en = 0;
  956|     78|          tud_control_status(rhport, p_request);
  957|     78|          break;
  958|       |
  959|  3.58k|        case TUSB_REQ_GET_STATUS: {
  ------------------
  |  Branch (959:9): [True: 3.58k, False: 4.88k]
  ------------------
  960|       |          // Device status bit mask
  961|       |          // - Bit 0: Self Powered TODO must invoke callback to get actual status
  962|       |          // - Bit 1: Remote Wakeup enabled
  963|  3.58k|          uint16_t status = (uint16_t)_usbd_dev.dev_state_bm;
  964|  3.58k|          tud_control_xfer(rhport, p_request, &status, 2);
  965|  3.58k|          break;
  966|    447|        }
  967|       |
  968|       |        // Unknown/Unsupported request
  969|  1.64k|        default: TU_BREAKPOINT(); return false;
  ------------------
  |  |   96|  1.64k|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (96:40): [Folded, False: 1.64k]
  |  |  ------------------
  ------------------
  |  Branch (969:9): [True: 1.64k, False: 6.82k]
  ------------------
  970|  8.46k|      }
  971|  5.11k|    break;
  972|       |
  973|       |    //------------- Class/Interface Specific Request -------------//
  974|  5.11k|    case TUSB_REQ_RCPT_INTERFACE: {
  ------------------
  |  Branch (974:5): [True: 1.06k, False: 16.9k]
  ------------------
  975|  1.06k|      uint8_t itf;
  976|       |      #if CFG_TUD_PRINTER
  977|       |      // Printer GET_DEVICE_ID has a weird wIndex = interface (high) | alt (low)
  978|       |      // attempt to interpret this as a printer request if matched
  979|       |      if (TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type &&
  980|       |          TUSB_DIR_IN == p_request->bmRequestType_bit.direction &&
  981|       |          TUSB_PRINTER_REQUEST_GET_DEVICE_ID == p_request->bRequest) {
  982|       |        itf = tu_u16_high(p_request->wIndex);
  983|       |        if (itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)) {
  984|       |          const usbd_class_driver_t * driver = get_driver(_usbd_dev.itf2drv[itf]);
  985|       |          if (driver != NULL && driver->control_xfer_cb == printerd_control_xfer_cb) {
  986|       |            if (invoke_class_control(rhport, driver, p_request)) {
  987|       |              return true;
  988|       |            }
  989|       |          }
  990|       |        }
  991|       |      }
  992|       |      #endif
  993|  1.06k|      itf = tu_u16_low(p_request->wIndex);
  994|  1.06k|      TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
  ------------------
  |  |  114|  1.06k|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  1.06k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|  1.06k|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|  1.06k|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|  1.06k|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|  1.06k|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 374, False: 691]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    374|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    374|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|  1.06k|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 691]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  995|       |
  996|    691|      usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]);
  997|    691|      TU_VERIFY(driver);
  ------------------
  |  |  114|    691|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    691|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    691|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    691|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    691|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    691|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 691, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    691|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    691|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    691|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  998|       |
  999|       |      // all requests to Interface (STD or Class) is forwarded to class driver.
 1000|       |      // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE
 1001|      0|      if (!invoke_class_control(rhport, driver, p_request)) {
  ------------------
  |  Branch (1001:11): [True: 0, False: 0]
  ------------------
 1002|       |        // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class
 1003|       |        // driver doesn't use alternate settings or implement this
 1004|      0|        TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type);
  ------------------
  |  |  114|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|      0|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|      0|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|      0|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|      0|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1005|       |
 1006|       |        // Clear complete callback if driver set since it can also stall the request.
 1007|      0|        usbd_control_set_complete_callback(NULL);
 1008|       |
 1009|      0|        switch (p_request->bRequest) { //-V2520
 1010|      0|          case TUSB_REQ_GET_INTERFACE: {
  ------------------
  |  Branch (1010:11): [True: 0, False: 0]
  ------------------
 1011|      0|            uint8_t alternate = 0;
 1012|      0|            tud_control_xfer(rhport, p_request, &alternate, 1);
 1013|      0|            break;
 1014|      0|          }
 1015|       |
 1016|      0|          case TUSB_REQ_SET_INTERFACE:
  ------------------
  |  Branch (1016:11): [True: 0, False: 0]
  ------------------
 1017|      0|            tud_control_status(rhport, p_request);
 1018|      0|            break;
 1019|       |
 1020|      0|          default: return false;
  ------------------
  |  Branch (1020:11): [True: 0, False: 0]
  ------------------
 1021|      0|        }
 1022|      0|      }
 1023|      0|      break;
 1024|      0|    }
 1025|       |
 1026|       |    //------------- Endpoint Request -------------//
 1027|  2.54k|    case TUSB_REQ_RCPT_ENDPOINT: {
  ------------------
  |  Branch (1027:5): [True: 2.54k, False: 15.4k]
  ------------------
 1028|  2.54k|      uint8_t const ep_addr = tu_u16_low(p_request->wIndex);
 1029|  2.54k|      uint8_t const ep_num  = tu_edpt_number(ep_addr);
 1030|  2.54k|      uint8_t const ep_dir  = tu_edpt_dir(ep_addr);
 1031|       |
 1032|  2.54k|      TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) );
  ------------------
  |  |  131|  2.54k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  2.54k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  2.54k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|  2.54k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  2.54k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  2.54k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|    652|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 652]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|    652|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 652]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 652, False: 1.89k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  2.54k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 1.89k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1033|  1.89k|      usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]);
 1034|       |
 1035|  1.89k|      if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) {
  ------------------
  |  Branch (1035:11): [True: 300, False: 1.59k]
  ------------------
 1036|       |        // Forward class request to its driver
 1037|    300|        TU_VERIFY(driver);
  ------------------
  |  |  114|    300|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    300|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    300|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    300|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    300|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    300|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 300, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    300|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    300|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    300|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1038|      0|        return invoke_class_control(rhport, driver, p_request);
 1039|  1.59k|      } else {
 1040|       |        // Handle STD request to endpoint
 1041|  1.59k|        switch (p_request->bRequest) { //-V2520
 1042|    404|          case TUSB_REQ_GET_STATUS: {
  ------------------
  |  Branch (1042:11): [True: 404, False: 1.18k]
  ------------------
 1043|    404|            uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001u : 0x0000u;
  ------------------
  |  Branch (1043:31): [True: 0, False: 404]
  ------------------
 1044|    404|            tud_control_xfer(rhport, p_request, &status, 2);
 1045|    404|          }
 1046|    404|          break;
 1047|       |
 1048|    208|          case TUSB_REQ_CLEAR_FEATURE:
  ------------------
  |  Branch (1048:11): [True: 208, False: 1.38k]
  ------------------
 1049|    916|          case TUSB_REQ_SET_FEATURE: {
  ------------------
  |  Branch (1049:11): [True: 708, False: 884]
  ------------------
 1050|    916|            if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) {
  ------------------
  |  Branch (1050:18): [True: 167, False: 749]
  ------------------
 1051|    167|              if ( TUSB_REQ_CLEAR_FEATURE ==  p_request->bRequest ) {
  ------------------
  |  Branch (1051:20): [True: 65, False: 102]
  ------------------
 1052|     65|                usbd_edpt_clear_stall(rhport, ep_addr);
 1053|    102|              }else {
 1054|    102|                usbd_edpt_stall(rhport, ep_addr);
 1055|    102|              }
 1056|    167|            }
 1057|       |
 1058|    916|            if (driver != NULL) {
  ------------------
  |  Branch (1058:17): [True: 0, False: 916]
  ------------------
 1059|       |              // Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request
 1060|       |              // We will also forward std request targeted endpoint to class drivers as well
 1061|       |
 1062|       |              // STD request must always be ACKed regardless of driver returned value
 1063|       |              // Also clear complete callback if driver set since it can also stall the request.
 1064|      0|              (void) invoke_class_control(rhport, driver, p_request);
 1065|      0|              usbd_control_set_complete_callback(NULL);
 1066|       |
 1067|       |              // skip ZLP status if driver already did that
 1068|      0|              if (!_usbd_dev.ep_status[0][TUSB_DIR_IN].busy) {
  ------------------
  |  Branch (1068:19): [True: 0, False: 0]
  ------------------
 1069|      0|                tud_control_status(rhport, p_request);
 1070|      0|              }
 1071|      0|            }
 1072|    916|          }
 1073|    916|          break;
 1074|       |
 1075|       |          // Unknown/Unsupported request
 1076|    272|          default:
  ------------------
  |  Branch (1076:11): [True: 272, False: 1.32k]
  ------------------
 1077|    272|            TU_BREAKPOINT();
  ------------------
  |  |   96|    272|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (96:40): [Folded, False: 272]
  |  |  ------------------
  ------------------
 1078|    272|            return false;
 1079|  1.59k|        }
 1080|  1.59k|      }
 1081|  1.32k|      break;
 1082|  1.89k|    }
 1083|       |
 1084|       |    // Unknown recipient
 1085|  5.55k|    default:
  ------------------
  |  Branch (1085:5): [True: 5.55k, False: 12.4k]
  ------------------
 1086|  5.55k|      TU_BREAKPOINT();
  ------------------
  |  |   96|  5.55k|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (96:40): [Folded, False: 5.55k]
  |  |  ------------------
  ------------------
 1087|  5.55k|      return false;
 1088|  18.0k|  }
 1089|       |
 1090|  6.43k|  return true;
 1091|  18.0k|}
usbd.c:process_set_config:
 1095|     67|static bool process_set_config(uint8_t rhport, uint8_t cfg_num) {
 1096|       |  // index is cfg_num-1
 1097|     67|  const tusb_desc_configuration_t *desc_cfg =
 1098|     67|    (const tusb_desc_configuration_t *)tud_descriptor_configuration_cb(cfg_num - 1);
 1099|     67|  TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION);
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|    134|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1100|       |
 1101|       |  // Parse configuration descriptor
 1102|     67|  _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1u : 0u;
  ------------------
  |  Branch (1102:28): [True: 0, False: 67]
  ------------------
 1103|       |
 1104|       |  // Parse interface descriptor
 1105|     67|  const uint8_t *p_desc   = ((const uint8_t *)desc_cfg) + sizeof(tusb_desc_configuration_t);
 1106|     67|  const uint8_t *desc_end = ((const uint8_t *)desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
  ------------------
  |  |  263|     67|  #define tu_le16toh(u16) (u16)
  ------------------
 1107|       |
 1108|     67|  while (tu_desc_in_bounds(p_desc, desc_end)) {
  ------------------
  |  Branch (1108:10): [True: 67, False: 0]
  ------------------
 1109|       |    // Class will always start with Interface Association (if any) and then Interface descriptor
 1110|     67|    if (TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc)) {
  ------------------
  |  Branch (1110:9): [True: 0, False: 67]
  ------------------
 1111|      0|      p_desc = tu_desc_next(p_desc); // next to Interface
 1112|      0|      continue;
 1113|      0|    }
 1114|       |
 1115|     67|    TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc));
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1116|     67|    const tusb_desc_interface_t *desc_itf = (const tusb_desc_interface_t *)p_desc;
 1117|       |
 1118|       |    // Find driver for this interface
 1119|     67|    const uint16_t remaining_len = (uint16_t)(desc_end - p_desc);
 1120|     67|    uint8_t        drv_id;
 1121|    134|    for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
  ------------------
  |  |  358|    134|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + BUILTIN_DRIVER_COUNT))
  ------------------
  |  Branch (1121:22): [True: 67, False: 67]
  ------------------
 1122|     67|      const usbd_class_driver_t *driver = get_driver(drv_id);
 1123|     67|      TU_ASSERT(driver);
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1124|     67|      const uint16_t drv_len = driver->open(rhport, desc_itf, remaining_len);
 1125|       |
 1126|     67|      if ((sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len)) {
  ------------------
  |  Branch (1126:11): [True: 0, False: 67]
  |  Branch (1126:57): [True: 0, False: 0]
  ------------------
 1127|       |        // Open successfully
 1128|      0|        TU_LOG_USBD("  %s opened\r\n", driver->name);
 1129|       |
 1130|       |        // bind found driver to all interfaces and endpoint within drv_len
 1131|      0|        TU_ASSERT(tu_bind_driver_to_ep_itf(drv_id, _usbd_dev.ep2drv, _usbd_dev.itf2drv, CFG_TUD_INTERFACE_MAX, p_desc,
  ------------------
  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|      0|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1132|      0|                                           drv_len));
 1133|       |
 1134|      0|        p_desc += drv_len; // next Interface
 1135|      0|        break; // exit driver find loop
 1136|      0|      }
 1137|     67|    }
 1138|       |
 1139|       |    // Failed if there is no supported drivers
 1140|     67|    TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT);
  ------------------
  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     67|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|     67|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|     67|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|     67|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|     67|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|     67|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|     67|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 67]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 67, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|     67|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1141|     67|  }
 1142|       |
 1143|      0|  return true;
 1144|     67|}
usbd.c:process_get_descriptor:
 1148|    864|{
 1149|    864|  tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue);
 1150|    864|  uint8_t const desc_index = tu_u16_low( p_request->wValue );
 1151|       |
 1152|    864|  switch(desc_type) { //-V2520
 1153|    133|    case TUSB_DESC_DEVICE: {
  ------------------
  |  Branch (1153:5): [True: 133, False: 731]
  ------------------
 1154|    133|      TU_LOG_USBD(" Device\r\n");
 1155|       |
 1156|    133|      void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb();
 1157|    133|      TU_ASSERT(desc_device);
  ------------------
  |  |  131|    133|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    133|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|    133|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|    133|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|    133|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|    133|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 133]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|    133|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 133]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1158|       |
 1159|       |      // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has.
 1160|       |      // This only happens with the very first get device descriptor and EP0 size = 8 or 16.
 1161|    133|      if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed &&
  ------------------
  |  |   90|    133|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
  |  Branch (1161:11): [Folded, False: 133]
  |  Branch (1161:68): [True: 0, False: 0]
  ------------------
 1162|      0|          ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) {
  ------------------
  |  Branch (1162:11): [True: 0, False: 0]
  ------------------
 1163|       |        // Hack here: we modify the request length to prevent usbd_control response with zlp
 1164|       |        // since we are responding with 1 packet & less data than wLength.
 1165|      0|        tusb_control_request_t mod_request = *p_request;
 1166|      0|        mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE;
  ------------------
  |  |   90|      0|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
 1167|       |
 1168|      0|        return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE);
  ------------------
  |  |   90|      0|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
 1169|    133|      }else {
 1170|    133|        return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t));
 1171|    133|      }
 1172|    133|    }
 1173|       |    // break; // unreachable
 1174|       |
 1175|     20|    case TUSB_DESC_BOS: {
  ------------------
  |  Branch (1175:5): [True: 20, False: 844]
  ------------------
 1176|     20|      TU_LOG_USBD(" BOS\r\n");
 1177|       |
 1178|       |      // requested by host if USB > 2.0 ( i.e 2.1 or 3.x )
 1179|     20|      uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb();
 1180|     20|      TU_VERIFY(desc_bos != 0);
  ------------------
  |  |  114|     20|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     20|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|     20|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|     20|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|     20|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|     20|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 20, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|     20|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|     20|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|     20|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1181|       |
 1182|       |      // Use offsetof to avoid pointer to the odd/misaligned address
 1183|      0|      uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) );
  ------------------
  |  |  263|      0|  #define tu_le16toh(u16) (u16)
  ------------------
 1184|       |
 1185|      0|      return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len);
 1186|     20|    }
 1187|       |    // break; // unreachable
 1188|       |
 1189|    197|    case TUSB_DESC_CONFIGURATION:
  ------------------
  |  Branch (1189:5): [True: 197, False: 667]
  ------------------
 1190|    212|    case TUSB_DESC_OTHER_SPEED_CONFIG: {
  ------------------
  |  Branch (1190:5): [True: 15, False: 849]
  ------------------
 1191|    212|      uintptr_t desc_config;
 1192|       |
 1193|    212|      if ( desc_type == TUSB_DESC_CONFIGURATION ) {
  ------------------
  |  Branch (1193:12): [True: 197, False: 15]
  ------------------
 1194|    197|        TU_LOG_USBD(" Configuration[%u]\r\n", desc_index);
 1195|    197|        desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index);
 1196|    197|        TU_ASSERT(desc_config != 0);
  ------------------
  |  |  131|    197|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    197|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|    197|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|    197|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|    197|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|    197|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 197]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|    197|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 197]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1197|    197|      }else {
 1198|       |        // Host only request this after getting Device Qualifier descriptor
 1199|     15|        TU_LOG_USBD(" Other Speed Configuration\r\n");
 1200|     15|        desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index);
 1201|     15|        TU_VERIFY(desc_config != 0);
  ------------------
  |  |  114|     15|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|     15|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|     15|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|     15|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|     15|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|     15|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 15, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|     15|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|     15|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|     15|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1202|     15|      }
 1203|       |
 1204|       |      // Use offsetof to avoid pointer to the odd/misaligned address
 1205|    197|      uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) );
  ------------------
  |  |  263|    197|  #define tu_le16toh(u16) (u16)
  ------------------
 1206|       |
 1207|    197|      return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len);
 1208|    212|    }
 1209|       |    // break; // unreachable
 1210|       |
 1211|    348|    case TUSB_DESC_STRING: {
  ------------------
  |  Branch (1211:5): [True: 348, False: 516]
  ------------------
 1212|    348|      TU_LOG_USBD(" String[%u]\r\n", desc_index);
 1213|       |
 1214|       |      // String Descriptor always uses the desc set from user
 1215|    348|      uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, tu_le16toh(p_request->wIndex));
  ------------------
  |  |  263|    348|  #define tu_le16toh(u16) (u16)
  ------------------
 1216|    348|      TU_VERIFY(desc_str);
  ------------------
  |  |  114|    348|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    348|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    348|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    348|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    348|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    348|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 56, False: 292]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|     56|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|     56|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    348|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 292]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1217|       |
 1218|       |      // first byte of descriptor is its size
 1219|    292|      return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str));
 1220|    348|    }
 1221|       |    // break; // unreachable
 1222|       |
 1223|    102|    case TUSB_DESC_DEVICE_QUALIFIER: {
  ------------------
  |  Branch (1223:5): [True: 102, False: 762]
  ------------------
 1224|    102|      TU_LOG_USBD(" Device Qualifier\r\n");
 1225|    102|      uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb();
 1226|    102|      TU_VERIFY(desc_qualifier);
  ------------------
  |  |  114|    102|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    102|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    102|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    102|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    102|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    102|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 102, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|    102|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|    102|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    102|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1227|      0|      return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier));
 1228|    102|    }
 1229|       |    // break; // unreachable
 1230|       |
 1231|     49|    default: return false;
  ------------------
  |  Branch (1231:5): [True: 49, False: 815]
  ------------------
 1232|    864|  }
 1233|    864|}
usbd.c:queue_event:
  399|  79.6k|TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, bool in_isr) {
  400|  79.6k|  TU_ASSERT(osal_queue_send(_usbd_q, event, in_isr));
  ------------------
  |  |  131|  79.6k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  79.6k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  79.6k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|  79.6k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  79.6k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  79.6k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 79.6k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  79.6k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 79.6k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  401|  79.6k|  tud_event_hook_cb(event->rhport, event->event_id, in_isr);
  402|       |  return true;
  403|  79.6k|}

fuzz.cc:_ZL8tud_taskv:
   95|  80.2k|void tud_task (void) {
   96|       |  tud_task_ext(UINT32_MAX, false);
   97|  80.2k|}

tud_control_status:
   82|    608|bool tud_control_status(uint8_t rhport, const tusb_control_request_t* request) {
   83|    608|  _ctrl_xfer.request = (*request);
   84|    608|  _ctrl_xfer.buffer = NULL;
   85|    608|  _ctrl_xfer.total_xferred = 0;
   86|    608|  _ctrl_xfer.data_len = 0;
   87|       |
   88|    608|  return status_stage_xact(rhport, request);
   89|    608|}
tud_control_xfer:
  110|  5.20k|bool tud_control_xfer(uint8_t rhport, const tusb_control_request_t* request, void* buffer, uint16_t len) {
  111|  5.20k|  _ctrl_xfer.request = (*request);
  112|  5.20k|  _ctrl_xfer.buffer = (uint8_t*) buffer;
  113|  5.20k|  _ctrl_xfer.total_xferred = 0U;
  114|  5.20k|  _ctrl_xfer.data_len = tu_min16(len, request->wLength);
  115|       |
  116|  5.20k|  if (request->wLength > 0U) {
  ------------------
  |  Branch (116:7): [True: 2.42k, False: 2.78k]
  ------------------
  117|  2.42k|    if (_ctrl_xfer.data_len > 0U) {
  ------------------
  |  Branch (117:9): [True: 2.42k, False: 0]
  ------------------
  118|  2.42k|      TU_ASSERT(buffer);
  ------------------
  |  |  131|  2.42k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  2.42k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  2.42k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|  2.42k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  2.42k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  2.42k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 2.42k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  2.42k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 2.42k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  119|  2.42k|    }
  120|  2.42k|    TU_ASSERT(data_stage_xact(rhport));
  ------------------
  |  |  131|  2.42k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  2.42k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  2.42k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|  2.42k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  2.42k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  2.42k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|  1.47k|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 1.47k]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|  1.47k|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 1.47k]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 1.47k, False: 943]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  2.42k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 943]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  121|  2.78k|  } else {
  122|  2.78k|    TU_ASSERT(status_stage_xact(rhport, request));
  ------------------
  |  |  131|  2.78k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|  2.78k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|  2.78k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|  2.78k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|  2.78k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  2.78k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|    289|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 289]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|    289|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 289]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 289, False: 2.49k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|  2.78k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 2.49k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  123|  2.78k|  }
  124|       |
  125|  3.43k|  return true;
  126|  5.20k|}
usbd_control_reset:
  136|  42.1k|void usbd_control_reset(void) {
  137|  42.1k|  tu_varclr(&_ctrl_xfer);
  ------------------
  |  |  115|  42.1k|#define tu_varclr(_var)          tu_memclr(_var, sizeof(*(_var)))
  |  |  ------------------
  |  |  |  |  114|  42.1k|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  |  |  ------------------
  ------------------
  138|  42.1k|}
usbd_control_set_complete_callback:
  141|  36.3k|void usbd_control_set_complete_callback(usbd_control_xfer_cb_t fp) {
  142|  36.3k|  _ctrl_xfer.complete_cb = fp;
  143|  36.3k|}
usbd_control_set_request:
  146|    105|void usbd_control_set_request(const tusb_control_request_t* request) {
  147|    105|  _ctrl_xfer.request = (*request);
  148|       |  _ctrl_xfer.buffer = NULL;
  149|    105|  _ctrl_xfer.total_xferred = 0;
  150|    105|  _ctrl_xfer.data_len = 0;
  151|    105|}
usbd_control.c:status_stage_xact:
   75|  3.39k|static inline bool status_stage_xact(uint8_t rhport, const tusb_control_request_t* request) {
   76|       |  // Opposite to endpoint in Data Phase
   77|  3.39k|  const uint8_t ep_addr = request->bmRequestType_bit.direction ? EDPT_CTRL_OUT : EDPT_CTRL_IN;
  ------------------
  |  Branch (77:27): [True: 25, False: 3.36k]
  ------------------
   78|  3.39k|  return usbd_edpt_xfer(rhport, ep_addr, NULL, 0, false);
   79|  3.39k|}
usbd_control.c:data_stage_xact:
   94|  2.42k|static bool data_stage_xact(uint8_t rhport) {
   95|  2.42k|  const uint16_t xact_len = tu_min16(_ctrl_xfer.data_len - _ctrl_xfer.total_xferred, CFG_TUD_ENDPOINT0_BUFSIZE);
  ------------------
  |  |  576|  2.42k|  #define CFG_TUD_ENDPOINT0_BUFSIZE  CFG_TUD_ENDPOINT0_SIZE
  |  |  ------------------
  |  |  |  |   90|  2.42k|#define CFG_TUD_ENDPOINT0_SIZE    64
  |  |  ------------------
  ------------------
   96|  2.42k|  uint8_t ep_addr = EDPT_CTRL_OUT;
   97|       |
   98|  2.42k|  if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) {
  ------------------
  |  Branch (98:7): [True: 696, False: 1.72k]
  ------------------
   99|    696|    ep_addr = EDPT_CTRL_IN;
  100|    696|    if (0u != xact_len && _ctrl_xfer.buffer != _ctrl_epbuf.buf) {
  ------------------
  |  Branch (100:9): [True: 696, False: 0]
  |  Branch (100:27): [True: 696, False: 0]
  ------------------
  101|    696|      TU_VERIFY(0 == tu_memcpy_s(_ctrl_epbuf.buf, CFG_TUD_ENDPOINT0_BUFSIZE, _ctrl_xfer.buffer, xact_len));
  ------------------
  |  |  114|    696|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    696|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  114|    696|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  111|    696|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  105|    696|  do {                                \
  |  |  |  |  |  |  |  |  |  |  106|    696|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:9): [True: 0, False: 696]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  107|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |  108|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |  109|    696|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (109:12): [Folded, False: 696]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  102|    696|    }
  103|    696|  }
  104|       |
  105|  2.42k|  return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _ctrl_epbuf.buf : NULL, xact_len, false);
  ------------------
  |  Branch (105:42): [True: 2.42k, False: 0]
  ------------------
  106|  2.42k|}

usbd.c:osal_spin_init:
   53|      1|TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) {
   54|      1|  (void) ctx;
   55|      1|}
usbd.c:osal_queue_create:
  175|      1|TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
  176|      1|  tu_fifo_clear(&qdef->ff);
  177|      1|  return (osal_queue_t) qdef;
  178|      1|}
usbd.c:osal_queue_receive:
  185|   159k|TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
  186|   159k|  (void) msec; // not used, always behave as msec = 0
  187|       |
  188|   159k|  qhdl->interrupt_set(false);
  189|   159k|  const bool success = (tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size) > 0);
  190|   159k|  qhdl->interrupt_set(true);
  191|       |
  192|   159k|  return success;
  193|   159k|}
usbd.c:osal_queue_send:
  195|  79.6k|TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) {
  196|  79.6k|  if (!in_isr) {
  ------------------
  |  Branch (196:7): [True: 26.8k, False: 52.8k]
  ------------------
  197|  26.8k|    qhdl->interrupt_set(false);
  198|  26.8k|  }
  199|       |
  200|  79.6k|  const bool success = (tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size) > 0);
  201|       |
  202|  79.6k|  if (!in_isr) {
  ------------------
  |  Branch (202:7): [True: 26.8k, False: 52.8k]
  ------------------
  203|  26.8k|    qhdl->interrupt_set(true);
  204|  26.8k|  }
  205|       |
  206|  79.6k|  return success;
  207|  79.6k|}

tusb_rhport_init:
   84|    807|bool tusb_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
   85|       |  //  backward compatible called with tusb_init(void)
   86|       |  #if defined(TUD_OPT_RHPORT) || defined(TUH_OPT_RHPORT)
   87|       |  if (rh_init == NULL) {
   88|       |    #if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT)
   89|       |    // init device stack CFG_TUSB_RHPORTx_MODE must be defined
   90|       |    const tusb_rhport_init_t dev_init = {
   91|       |      .role = TUSB_ROLE_DEVICE,
   92|       |      .speed = TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL
   93|       |    };
   94|       |    TU_ASSERT ( tud_rhport_init(TUD_OPT_RHPORT, &dev_init) );
   95|       |    _tusb_rhport_role[TUD_OPT_RHPORT] = TUSB_ROLE_DEVICE;
   96|       |    #endif
   97|       |
   98|       |    #if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT)
   99|       |    // init host stack CFG_TUSB_RHPORTx_MODE must be defined
  100|       |    const tusb_rhport_init_t host_init = {
  101|       |      .role = TUSB_ROLE_HOST,
  102|       |      .speed = TUH_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL
  103|       |    };
  104|       |    TU_ASSERT( tuh_rhport_init(TUH_OPT_RHPORT, &host_init) );
  105|       |    _tusb_rhport_role[TUH_OPT_RHPORT] = TUSB_ROLE_HOST;
  106|       |    #endif
  107|       |
  108|       |    return true;
  109|       |  }
  110|       |  #endif
  111|       |
  112|       |  // new API with explicit rhport and role
  113|    807|  TU_ASSERT(rhport < TUP_USBIP_CONTROLLER_NUM && rh_init->role != TUSB_ROLE_INVALID);
  ------------------
  |  |  131|    807|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    807|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|    807|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|    807|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|    807|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|  1.61k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 807, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:12): [True: 807, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|    807|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 807]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  114|    807|  _tusb_rhport_role[rhport] = rh_init->role;
  115|       |
  116|    807|  #if CFG_TUD_ENABLED
  117|    807|  if (rh_init->role == TUSB_ROLE_DEVICE) {
  ------------------
  |  Branch (117:7): [True: 807, False: 0]
  ------------------
  118|    807|    TU_ASSERT(tud_rhport_init(rhport, rh_init));
  ------------------
  |  |  131|    807|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  128|    807|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  131|    807|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  127|    807|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  123|    807|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  124|    807|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   73|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (73:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   96|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (96:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (124:10): [True: 0, False: 807]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  125|    807|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (125:11): [Folded, False: 807]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  119|    807|  }
  120|    807|  #endif
  121|       |
  122|       |  #if CFG_TUH_ENABLED
  123|       |  if (rh_init->role == TUSB_ROLE_HOST) {
  124|       |    TU_ASSERT(tuh_rhport_init(rhport, rh_init));
  125|       |  }
  126|       |  #endif
  127|       |
  128|    807|  return true;
  129|    807|}

dcd_init:
   49|      1|bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
   50|      1|  UNUSED(rhport);
  ------------------
  |  |   31|      1|#define UNUSED(x) (void)(x)
  ------------------
   51|      1|  UNUSED(rh_init);
  ------------------
  |  |   31|      1|#define UNUSED(x) (void)(x)
  ------------------
   52|      1|  return true;
   53|      1|}
dcd_int_handler:
   55|  80.2k|void dcd_int_handler(uint8_t rhport) {
   56|  80.2k|  assert(_fuzz_data_provider.has_value());
  ------------------
  |  Branch (56:3): [True: 80.2k, False: 0]
  ------------------
   57|       |
   58|  80.2k|  if (!state.interrupts_enabled) {
  ------------------
  |  Branch (58:7): [True: 0, False: 80.2k]
  ------------------
   59|      0|    return;
   60|      0|  }
   61|       |
   62|       |  // Choose if we want to generate a signal based on the fuzzed data.
   63|  80.2k|  if (_fuzz_data_provider->ConsumeBool()) {
  ------------------
  |  Branch (63:7): [True: 23.7k, False: 56.4k]
  ------------------
   64|       |    // Only generate bus signal events that don't carry additional union data.
   65|       |    // DCD_EVENT_XFER_COMPLETE, DCD_EVENT_SOF, and DCD_EVENT_BUS_RESET need
   66|       |    // properly initialized union fields; USBD_EVENT_FUNC_CALL is internal only.
   67|       |    // Valid bus-signal-only events: UNPLUGGED(2), SUSPEND(4), RESUME(5).
   68|  23.7k|    static const dcd_eventid_t bus_signal_events[] = {
   69|  23.7k|        DCD_EVENT_UNPLUGGED, DCD_EVENT_SUSPEND, DCD_EVENT_RESUME};
   70|  23.7k|    uint8_t idx = _fuzz_data_provider->ConsumeIntegralInRange<uint8_t>(0, 2);
   71|  23.7k|    dcd_event_bus_signal(rhport, bus_signal_events[idx],
   72|  23.7k|                         _fuzz_data_provider->ConsumeBool());
   73|  23.7k|  }
   74|       |
   75|       |  // Optionally generate a BUS_RESET event with a valid speed value.
   76|  80.2k|  if (_fuzz_data_provider->ConsumeBool()) {
  ------------------
  |  Branch (76:7): [True: 28.7k, False: 51.4k]
  ------------------
   77|  28.7k|    tusb_speed_t speed = (tusb_speed_t)_fuzz_data_provider->ConsumeIntegralInRange<uint8_t>(
   78|  28.7k|        TUSB_SPEED_FULL, TUSB_SPEED_HIGH);
   79|  28.7k|    dcd_event_bus_reset(rhport, speed, _fuzz_data_provider->ConsumeBool());
   80|  28.7k|  }
   81|       |
   82|  80.2k|  if (_fuzz_data_provider->ConsumeBool()) {
  ------------------
  |  Branch (82:7): [True: 28.7k, False: 51.5k]
  ------------------
   83|  28.7k|    constexpr size_t kSetupFrameLength = 8;
   84|  28.7k|    std::vector<uint8_t> setup =
   85|  28.7k|        _fuzz_data_provider->ConsumeBytes<uint8_t>(kSetupFrameLength);
   86|       |    // Fuzz consumer may return less than requested. If this is the case
   87|       |    // we want to make sure that at least that length is allocated and available
   88|       |    // to the signal handler.
   89|  28.7k|    if (setup.size() != kSetupFrameLength) {
  ------------------
  |  Branch (89:9): [True: 232, False: 28.4k]
  ------------------
   90|    232|      setup.resize(kSetupFrameLength);
   91|    232|    }
   92|  28.7k|    dcd_event_setup_received(rhport, setup.data(),
   93|       |                             // Identify trigger as either an interrupt or a
   94|       |                             // syncrhonous call depending on fuzz data.
   95|  28.7k|                             _fuzz_data_provider->ConsumeBool());
   96|  28.7k|  }
   97|  80.2k|}
dcd_int_enable:
   99|   186k|void dcd_int_enable(uint8_t rhport) {
  100|   186k|  state.interrupts_enabled = true;
  101|   186k|  UNUSED(rhport);
  ------------------
  |  |   31|   186k|#define UNUSED(x) (void)(x)
  ------------------
  102|   186k|  return;
  103|   186k|}
dcd_int_disable:
  105|   186k|void dcd_int_disable(uint8_t rhport) {
  106|   186k|  state.interrupts_enabled = false;
  107|   186k|  UNUSED(rhport);
  ------------------
  |  |   31|   186k|#define UNUSED(x) (void)(x)
  ------------------
  108|   186k|  return;
  109|   186k|}
dcd_set_address:
  111|    105|void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
  112|    105|  UNUSED(rhport);
  ------------------
  |  |   31|    105|#define UNUSED(x) (void)(x)
  ------------------
  113|    105|  state.address = dev_addr;
  114|       |  // Respond with status.
  115|       |  dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false);
  116|    105|  return;
  117|    105|}
dcd_edpt_xfer:
  171|  5.91k|                   uint16_t total_bytes, bool is_isr) {
  172|  5.91k|  UNUSED(rhport);
  ------------------
  |  |   31|  5.91k|#define UNUSED(x) (void)(x)
  ------------------
  173|  5.91k|  UNUSED(buffer);
  ------------------
  |  |   31|  5.91k|#define UNUSED(x) (void)(x)
  ------------------
  174|  5.91k|  UNUSED(total_bytes);
  ------------------
  |  |   31|  5.91k|#define UNUSED(x) (void)(x)
  ------------------
  175|  5.91k|  UNUSED(is_isr);
  ------------------
  |  |   31|  5.91k|#define UNUSED(x) (void)(x)
  ------------------
  176|       |
  177|  5.91k|  uint8_t const dir = tu_edpt_dir(ep_addr);
  178|       |
  179|  5.91k|  if (dir == TUSB_DIR_IN) {
  ------------------
  |  Branch (179:7): [True: 4.16k, False: 1.74k]
  ------------------
  180|  4.16k|    std::vector<uint8_t> temp =
  181|  4.16k|        _fuzz_data_provider->ConsumeBytes<uint8_t>(total_bytes);
  182|  4.16k|    std::copy(temp.begin(), temp.end(), buffer);
  183|  4.16k|  }
  184|       |  // Ignore output data as it's not useful for fuzzing without a more
  185|       |  // complex fuzzed backend. But we need to make sure it's not
  186|       |  // optimised out.
  187|  5.91k|  volatile uint8_t *dont_optimise0 = buffer;
  188|  5.91k|  volatile uint16_t dont_optimise1 = total_bytes;
  189|  5.91k|  UNUSED(dont_optimise0);
  ------------------
  |  |   31|  5.91k|#define UNUSED(x) (void)(x)
  ------------------
  190|  5.91k|  UNUSED(dont_optimise1);
  ------------------
  |  |   31|  5.91k|#define UNUSED(x) (void)(x)
  ------------------
  191|       |
  192|       |
  193|  5.91k|  return _fuzz_data_provider->ConsumeBool();
  194|  5.91k|}
dcd_edpt_stall:
  202|  44.6k|void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
  203|       |
  204|  44.6k|  UNUSED(rhport);
  ------------------
  |  |   31|  44.6k|#define UNUSED(x) (void)(x)
  ------------------
  205|  44.6k|  UNUSED(ep_addr);
  ------------------
  |  |   31|  44.6k|#define UNUSED(x) (void)(x)
  ------------------
  206|  44.6k|  return;
  207|  44.6k|}
dcd_edpt_clear_stall:
  212|     65|void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
  213|       |
  214|     65|  UNUSED(rhport);
  ------------------
  |  |   31|     65|#define UNUSED(x) (void)(x)
  ------------------
  215|     65|  UNUSED(ep_addr);
  ------------------
  |  |   31|     65|#define UNUSED(x) (void)(x)
  ------------------
  216|     65|  return;
  217|     65|}

LLVMFuzzerTestOneInput:
   44|    807|extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   45|    807|  FuzzedDataProvider provider(Data, Size);
   46|    807|  std::vector<uint8_t> callback_data = provider.ConsumeBytes<uint8_t>(
   47|    807|      provider.ConsumeIntegralInRange<size_t>(0, Size));
   48|    807|  fuzz_init(callback_data.data(), callback_data.size());
   49|    807|  tusb_rhport_init_t dev_init = {
   50|    807|    .role = TUSB_ROLE_DEVICE,
   51|    807|    .speed = TUSB_SPEED_AUTO
   52|    807|  };
   53|    807|  tusb_init(BOARD_TUD_RHPORT, &dev_init);
  ------------------
  |  |  161|    807|#define tusb_init(...)                       TU_FUNC_OPTIONAL_ARG(_tusb_init, __VA_ARGS__)
  |  |  ------------------
  |  |  |  |  131|    807|#define TU_FUNC_OPTIONAL_ARG(func, ...)   TU_XSTRCAT(func##_arg, TU_ARGS_NUM(__VA_ARGS__))(__VA_ARGS__)
  |  |  |  |  ------------------
  |  |  |  |  |  |   34|    807|#define TU_XSTRCAT(a, b)      TU_STRCAT(a, b)     ///< expand then concat
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   32|    807|#define TU_STRCAT(a, b)       a##b                ///< concat without expand
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  160|    807|#define _tusb_init_arg2(_rhport, _rh_init)   tusb_rhport_init(_rhport, _rh_init)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   54|       |
   55|  81.0k|  for (int i = 0; i < FUZZ_ITERATIONS; i++) {
  ------------------
  |  |   42|  81.0k|#define FUZZ_ITERATIONS 500
  ------------------
  |  Branch (55:19): [True: 80.9k, False: 103]
  ------------------
   56|  80.9k|    if (provider.remaining_bytes() == 0) {
  ------------------
  |  Branch (56:9): [True: 704, False: 80.2k]
  ------------------
   57|    704|      return 0;
   58|    704|    }
   59|  80.2k|    tud_int_handler(provider.ConsumeIntegral<uint8_t>());
  ------------------
  |  |  107|  80.2k|#define tud_int_handler   dcd_int_handler
  ------------------
   60|  80.2k|    tud_task(); // tinyusb device task
   61|  80.2k|  }
   62|       |
   63|    103|  return 0;
   64|    807|}

tud_descriptor_device_cb:
   46|    133|uint8_t const *tud_descriptor_device_cb(void) {
   47|    133|  tu_static tusb_desc_device_t const desc_device = {
  ------------------
  |  |   58|    133|  #define tu_static static __thread
  ------------------
   48|    133|      .bLength = sizeof(tusb_desc_device_t),
   49|    133|      .bDescriptorType = TUSB_DESC_DEVICE,
   50|    133|      .bcdUSB = USB_BCD,
  ------------------
  |  |   38|    133|#define USB_BCD 0x0200
  ------------------
   51|       |
   52|       |      // Use Interface Association Descriptor (IAD) for CDC
   53|       |      // As required by USB Specs IAD's subclass must be common class (2) and
   54|       |      // protocol must be IAD (1)
   55|    133|      .bDeviceClass = TUSB_CLASS_MISC,
   56|    133|      .bDeviceSubClass = MISC_SUBCLASS_COMMON,
   57|    133|      .bDeviceProtocol = MISC_PROTOCOL_IAD,
   58|       |
   59|    133|      .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
  ------------------
  |  |   90|    133|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
   60|       |
   61|    133|      .idVendor = USB_VID,
  ------------------
  |  |   37|    133|#define USB_VID 0xCafe
  ------------------
   62|    133|      .idProduct = USB_PID,
  ------------------
  |  |   35|    133|  (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) |          \
  |  |  ------------------
  |  |  |  |   33|    133|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    133|#define CFG_TUD_MSC              1
  |  |  |  |  ------------------
  |  |  ------------------
  |  |                 (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) |          \
  |  |  ------------------
  |  |  |  |   33|    133|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   96|    133|#define CFG_TUD_HID              0
  |  |  |  |  ------------------
  |  |  ------------------
  |  |                 (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) |          \
  |  |  ------------------
  |  |  |  |   33|    133|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   97|    133|#define CFG_TUD_MIDI             0
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   36|    133|   PID_MAP(VENDOR, 3))
  |  |  ------------------
  |  |  |  |   33|    133|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   98|    133|#define CFG_TUD_VENDOR           0
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   63|    133|      .bcdDevice = 0x0100,
   64|       |
   65|    133|      .iManufacturer = 0x01,
   66|    133|      .iProduct = 0x02,
   67|    133|      .iSerialNumber = 0x03,
   68|       |
   69|    133|      .bNumConfigurations = 0x01};
   70|       |
   71|    133|  return (uint8_t const *)&desc_device;
   72|    133|}
tud_descriptor_configuration_cb:
  161|    264|uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
  162|    264|  (void)index; // for multiple configurations
  163|       |
  164|       |#if TUD_OPT_HIGH_SPEED
  165|       |  // Although we are highspeed, host may be fullspeed.
  166|       |  return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration
  167|       |                                              : desc_fs_configuration;
  168|       |#else
  169|    264|  return desc_fs_configuration;
  170|    264|#endif
  171|    264|}
tud_descriptor_string_cb:
  192|    348|uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
  193|    348|  (void)langid;
  194|       |
  195|    348|  uint8_t chr_count;
  196|       |
  197|    348|  if (index == 0) {
  ------------------
  |  Branch (197:7): [True: 246, False: 102]
  ------------------
  198|    246|    memcpy(&_desc_str[1], string_desc_arr[0], 2);
  199|    246|    chr_count = 1;
  200|    246|  } else {
  201|       |    // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
  202|       |    // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
  203|       |
  204|    102|    if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])))
  ------------------
  |  Branch (204:9): [True: 56, False: 46]
  ------------------
  205|     56|      return NULL;
  206|       |
  207|     46|    const char *str = string_desc_arr[index];
  208|       |
  209|       |    // Cap at max char
  210|     46|    chr_count = (uint8_t)strlen(str);
  211|     46|    if (chr_count > 31)
  ------------------
  |  Branch (211:9): [True: 0, False: 46]
  ------------------
  212|      0|      chr_count = 31;
  213|       |
  214|       |    // Convert ASCII string into UTF-16
  215|    655|    for (uint8_t i = 0; i < chr_count; i++) {
  ------------------
  |  Branch (215:25): [True: 609, False: 46]
  ------------------
  216|    609|      _desc_str[1 + i] = str[i];
  217|    609|    }
  218|     46|  }
  219|       |
  220|       |  // first byte is length (including header), second byte is string type
  221|    292|  _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
  222|       |
  223|    292|  return _desc_str;
  224|    348|}

fuzz_init:
   31|    807|extern "C" int fuzz_init(const uint8_t *data, size_t size) {
   32|    807|  _fuzz_data_provider.emplace(data, size);
   33|    807|  return 0;
   34|    807|}

