mscd_init:
  338|      1|void mscd_init(void) {
  339|      1|  TU_LOG_INT(CFG_TUD_MSC_LOG_LEVEL, sizeof(mscd_interface_t));
  340|      1|  tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
  ------------------
  |  |   95|      1|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  ------------------
  341|      1|}
mscd_reset:
  347|  12.7k|void mscd_reset(uint8_t rhport) {
  348|  12.7k|  (void) rhport;
  349|  12.7k|  tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
  ------------------
  |  |   95|  12.7k|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  ------------------
  350|  12.7k|}
mscd_open:
  352|    213|uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
  353|       |  // only support SCSI's BOT protocol
  354|    213|  TU_VERIFY(TUSB_CLASS_MSC    == itf_desc->bInterfaceClass &&
  ------------------
  |  |   95|    213|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    213|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   93|    213|#define TU_VERIFY_2ARGS(_cond, _ret)   TU_VERIFY_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    213|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    852|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:11): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:11): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:11): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    213|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  355|    213|            MSC_SUBCLASS_SCSI == itf_desc->bInterfaceSubClass &&
  356|    213|            MSC_PROTOCOL_BOT  == itf_desc->bInterfaceProtocol, 0);
  357|    213|  uint16_t const drv_len = sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t);
  358|    213|  TU_ASSERT(max_len >= drv_len, 0); // Max length must be at least 1 interface + 2 endpoints
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  109|    213|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  359|       |
  360|    213|  mscd_interface_t * p_msc = &_mscd_itf;
  361|    213|  p_msc->itf_num = itf_desc->bInterfaceNumber;
  362|    213|  p_msc->rhport = rhport;
  363|       |
  364|       |  // Open endpoint pair
  365|    213|  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);
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  109|    213|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|    213|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|    213|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  366|       |
  367|       |  // Prepare for Command Block Wrapper
  368|      0|  TU_ASSERT(prepare_cbw(p_msc), drv_len);
  ------------------
  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  109|      0|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  369|       |
  370|      0|  return drv_len;
  371|      0|}

tusb_fifo.c:tu_min16:
  187|  30.0k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; }
  ------------------
  |  Branch (187:89): [True: 30.0k, False: 0]
  ------------------
usbd.c:tu_min16:
  187|  3.89k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_min16 (uint16_t x, uint16_t y) { return (x < y) ? x : y; }
  ------------------
  |  Branch (187:89): [True: 3.23k, False: 659]
  ------------------
usbd.c:tu_memcpy_s:
  118|    567|TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count) {
  119|    567|  if (dest == NULL) {
  ------------------
  |  Branch (119:7): [True: 0, False: 567]
  ------------------
  120|      0|    return -1;
  121|      0|  }
  122|       |
  123|    567|  if (count == 0u) {
  ------------------
  |  Branch (123:7): [True: 0, False: 567]
  ------------------
  124|      0|    return 0;
  125|      0|  }
  126|       |
  127|    567|  if (src == NULL) {
  ------------------
  |  Branch (127:7): [True: 0, False: 567]
  ------------------
  128|      0|    return -1;
  129|      0|  }
  130|       |
  131|    567|  if (count > destsz) {
  ------------------
  |  Branch (131:7): [True: 0, False: 567]
  ------------------
  132|      0|    return -1;
  133|      0|  }
  134|       |
  135|    567|  (void) memcpy(dest, src, count);
  136|    567|  return 0;
  137|    567|}
usbd.c:tu_u16_low:
  178|  5.62k|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); }
  ------------------
  |  |   27|  5.62k|#define TU_U16_LOW(_u16)              ((uint8_t) ((uint16_t) (_u16) & 0x00ffu))
  ------------------
usbd.c:tu_desc_in_bounds:
  371|    213|TU_ATTR_ALWAYS_INLINE static inline bool tu_desc_in_bounds(const uint8_t *p_desc, const uint8_t *desc_end) {
  372|    213|  return p_desc < desc_end && tu_desc_next(p_desc) <= desc_end;
  ------------------
  |  Branch (372:10): [True: 213, False: 0]
  |  Branch (372:31): [True: 213, False: 0]
  ------------------
  373|    213|}
usbd.c:tu_desc_type:
  362|    426|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
  363|    426|  return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
  364|    426|}
usbd.c:tu_u16_high:
  177|  2.21k|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_U16_HIGH(ui16); }
  ------------------
  |  |   26|  2.21k|#define TU_U16_HIGH(_u16)             ((uint8_t) (((uint16_t) (_u16) >> 8) & 0x00ffu))
  ------------------
usbd.c:tu_unaligned_read16:
  252|    368|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void *mem) {
  253|    368|  tu_unaligned_uint16_t const *ua16 = (tu_unaligned_uint16_t const *) mem;
  254|    368|  return ua16->val;
  255|    368|}
usbd.c:tu_desc_len:
  357|    553|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
  358|    553|  return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
  359|    553|}
usbd.c:tu_desc_next:
  351|    213|TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
  352|    213|  uint8_t const* desc8 = (uint8_t const*) desc;
  353|    213|  return desc8 + desc8[DESC_OFFSET_LEN];
  354|    213|}
msc_device.c:tu_desc_next:
  351|    213|TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) {
  352|    213|  uint8_t const* desc8 = (uint8_t const*) desc;
  353|    213|  return desc8 + desc8[DESC_OFFSET_LEN];
  354|    213|}

tu_fifo_clear:
   62|      1|void tu_fifo_clear(tu_fifo_t *f) {
   63|      1|  ff_lock(f->mutex_wr);
   64|      1|  ff_lock(f->mutex_rd);
   65|       |
   66|      1|  f->rd_idx = 0;
   67|      1|  f->wr_idx = 0;
   68|       |
   69|      1|  ff_unlock(f->mutex_wr);
   70|      1|  ff_unlock(f->mutex_rd);
   71|      1|}
tu_fifo_peek_n_access_mode:
  444|  73.8k|                                    const tu_hwfifo_access_t *access_mode) {
  445|  73.8k|  uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
  446|  73.8k|  if (count == 0) {
  ------------------
  |  Branch (446:7): [True: 43.8k, False: 30.0k]
  ------------------
  447|  43.8k|    return 0; // nothing to peek
  448|  43.8k|  }
  449|       |
  450|       |  // Check overflow and correct if required
  451|  30.0k|  if (count > f->depth) {
  ------------------
  |  Branch (451:7): [True: 0, False: 30.0k]
  ------------------
  452|      0|    rd_idx = correct_read_index(f, wr_idx);
  453|      0|    count  = f->depth;
  454|      0|  }
  455|       |
  456|  30.0k|  if (count < n) {
  ------------------
  |  Branch (456:7): [True: 0, False: 30.0k]
  ------------------
  457|      0|    n = count; // limit to available count
  458|      0|  }
  459|       |
  460|  30.0k|  const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
  461|       |
  462|       |#if CFG_TUSB_FIFO_HWFIFO_API
  463|       |  if (access_mode != NULL) {
  464|       |    hwff_pull_n(f, p_buffer, n, rd_ptr, access_mode);
  465|       |  } else
  466|       |#endif
  467|  30.0k|  {
  468|  30.0k|    (void)access_mode;
  469|  30.0k|    ff_pull_n(f, p_buffer, n, rd_ptr);
  470|  30.0k|  }
  471|       |
  472|  30.0k|  return n;
  473|  73.8k|}
tu_fifo_read_n_access_mode:
  486|  73.8k|uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, const tu_hwfifo_access_t *access_mode) {
  487|  73.8k|  ff_lock(f->mutex_rd);
  488|       |
  489|       |  // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable
  490|  73.8k|  const uint16_t wr_idx = f->wr_idx;
  491|  73.8k|  n         = tu_fifo_peek_n_access_mode(f, buffer, n, wr_idx, f->rd_idx, access_mode);
  492|  73.8k|  f->rd_idx = advance_index(f->depth, f->rd_idx, n);
  493|       |
  494|  73.8k|  ff_unlock(f->mutex_rd);
  495|  73.8k|  return n;
  496|  73.8k|}
tu_fifo_write_n_access_mode:
  500|  30.0k|                                     const tu_hwfifo_access_t *access_mode) {
  501|  30.0k|  if (n == 0) {
  ------------------
  |  Branch (501:7): [True: 0, False: 30.0k]
  ------------------
  502|      0|    return 0;
  503|      0|  }
  504|       |
  505|  30.0k|  ff_lock(f->mutex_wr);
  506|       |
  507|  30.0k|  uint16_t wr_idx = f->wr_idx;
  508|  30.0k|  uint16_t rd_idx = f->rd_idx;
  509|       |
  510|  30.0k|  const uint8_t *buf8 = (const uint8_t *)data;
  511|       |
  512|  30.0k|  TU_LOG(TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u:  ", rd_idx, wr_idx,
  513|  30.0k|         tu_ff_overflow_count(f->depth, wr_idx, rd_idx), tu_ff_remaining_local(f->depth, wr_idx, rd_idx), n);
  514|       |
  515|  30.0k|  if (!f->overwritable) {
  ------------------
  |  Branch (515:7): [True: 30.0k, False: 0]
  ------------------
  516|       |    // limit up to full
  517|  30.0k|    const uint16_t remain = tu_ff_remaining_local(f->depth, wr_idx, rd_idx);
  518|  30.0k|    n                     = tu_min16(n, remain);
  519|  30.0k|  } else {
  520|       |    // In over-writable mode, fifo_write() is allowed even when fifo is full. In such case,
  521|       |    // oldest data in fifo i.e. at read pointer data will be overwritten
  522|       |    // Note: we can modify read buffer contents however we must not modify the read index itself within a write
  523|       |    // function! Since it would end up in a race condition with read functions!
  524|      0|    if (n >= f->depth) {
  ------------------
  |  Branch (524:9): [True: 0, False: 0]
  ------------------
  525|       |      // Only copy last part
  526|      0|      if (access_mode == NULL) {
  ------------------
  |  Branch (526:11): [True: 0, False: 0]
  ------------------
  527|      0|        buf8 += (n - f->depth);
  528|      0|      } else {
  529|       |        // TODO should read from hw fifo to discard data, however reading an odd number could
  530|       |        // accidentally discard data.
  531|      0|      }
  532|       |
  533|      0|      n = f->depth;
  534|       |
  535|       |      // We start writing at the read pointer's position since we fill the whole buffer
  536|      0|      wr_idx = rd_idx;
  537|      0|    } else {
  538|      0|      const uint16_t overflowable_count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx);
  539|      0|      if (overflowable_count + n >= 2 * f->depth) {
  ------------------
  |  Branch (539:11): [True: 0, False: 0]
  ------------------
  540|       |        // Double overflowed
  541|       |        // Index is bigger than the allowed range [0,2*depth)
  542|       |        // re-position write index to have a full fifo after pushed
  543|      0|        wr_idx = advance_index(f->depth, rd_idx, f->depth - n);
  544|       |
  545|       |        // TODO we should also shift out n bytes from read index since we avoid changing rd index !!
  546|       |        // However memmove() is expensive due to actual copying + wrapping consideration.
  547|       |        // Also race condition could happen anyway if read() is invoke while moving result in corrupted memory
  548|       |        // currently deliberately not implemented --> result in incorrect data read back
  549|      0|      } else {
  550|       |        // normal + single overflowed:
  551|       |        // Index is in the range of [0,2*depth) and thus detect and recoverable. Recovering is handled in read()
  552|       |        // Therefore we just increase write index
  553|       |        // we will correct (re-position) read index later on in fifo_read() function
  554|      0|      }
  555|      0|    }
  556|      0|  }
  557|       |
  558|  30.0k|  if (n) {
  ------------------
  |  Branch (558:7): [True: 30.0k, False: 0]
  ------------------
  559|  30.0k|    const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx);
  560|  30.0k|    TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr);
  561|       |
  562|       |#if CFG_TUSB_FIFO_HWFIFO_API
  563|       |    if (access_mode != NULL) {
  564|       |      hwff_push_n(f, buf8, n, wr_ptr, access_mode);
  565|       |    } else
  566|       |#endif
  567|  30.0k|    {
  568|  30.0k|      ff_push_n(f, buf8, n, wr_ptr);
  569|  30.0k|    }
  570|  30.0k|    f->wr_idx = advance_index(f->depth, wr_idx, n);
  571|       |
  572|  30.0k|    TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx);
  573|  30.0k|  }
  574|       |
  575|  30.0k|  ff_unlock(f->mutex_wr);
  576|       |
  577|  30.0k|  return n;
  578|  30.0k|}
tusb_fifo.c:idx2ptr:
  415|  60.0k|TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t idx) {
  416|       |  // Only run at most 3 times since index is limit in the range of [0..2*depth)
  417|  90.0k|  while (idx >= depth) {
  ------------------
  |  Branch (417:10): [True: 30.0k, False: 60.0k]
  ------------------
  418|  30.0k|    idx -= depth;
  419|  30.0k|  }
  420|  60.0k|  return idx;
  421|  60.0k|}
tusb_fifo.c:ff_pull_n:
  379|  30.0k|static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr) {
  380|  30.0k|  uint16_t       lin_bytes  = f->depth - rd_ptr;
  381|  30.0k|  uint16_t       wrap_bytes = n - lin_bytes; // only used if wrapped
  382|  30.0k|  const uint8_t *ff_buf     = f->buffer + rd_ptr;
  383|       |
  384|       |  // single byte access
  385|  30.0k|  if (n <= lin_bytes) {
  ------------------
  |  Branch (385:7): [True: 30.0k, False: 0]
  ------------------
  386|       |    // Linear only
  387|  30.0k|    memcpy(app_buf, ff_buf, n);
  388|  30.0k|  } else {
  389|       |    // Wrap around
  390|      0|    memcpy(app_buf, ff_buf, lin_bytes);                            // linear part
  391|      0|    memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); // wrapped part
  392|      0|  }
  393|  30.0k|}
tusb_fifo.c:advance_index:
  401|   103k|static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) {
  402|       |  // We limit the index space of p such that a correct wrap around happens
  403|       |  // Check for a wrap around or if we are in unused index space - This has to be checked first!!
  404|       |  // We are exploiting the wrap around to the correct index
  405|   103k|  uint16_t new_idx = (uint16_t)(idx + offset);
  406|   103k|  if ((idx > new_idx) || (new_idx >= 2 * depth)) {
  ------------------
  |  Branch (406:7): [True: 0, False: 103k]
  |  Branch (406:26): [True: 1.87k, False: 102k]
  ------------------
  407|  1.87k|    const uint16_t non_used_index_space = (uint16_t)(UINT16_MAX - (2 * depth - 1));
  408|  1.87k|    new_idx                             = (uint16_t)(new_idx + non_used_index_space);
  409|  1.87k|  }
  410|       |
  411|   103k|  return new_idx;
  412|   103k|}
tusb_fifo.c:ff_push_n:
  363|  30.0k|static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr) {
  364|  30.0k|  uint16_t lin_bytes  = f->depth - wr_ptr;
  365|  30.0k|  uint16_t wrap_bytes = n - lin_bytes;
  366|  30.0k|  uint8_t *ff_buf     = f->buffer + wr_ptr;
  367|       |
  368|  30.0k|  if (n <= lin_bytes) {
  ------------------
  |  Branch (368:7): [True: 30.0k, False: 0]
  ------------------
  369|       |    // Linear only case
  370|  30.0k|    memcpy(ff_buf, app_buf, n);
  371|  30.0k|  } else {
  372|       |    // Wrap around case
  373|      0|    memcpy(ff_buf, app_buf, lin_bytes);                                    // linear part
  374|      0|    memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part
  375|      0|  }
  376|  30.0k|}

tusb_fifo.c:tu_ff_overflow_count:
  243|   103k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_ff_overflow_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
  244|   103k|  const int32_t diff = (int32_t)wr_idx - (int32_t)rd_idx;
  245|   103k|  if (diff >= 0) {
  ------------------
  |  Branch (245:7): [True: 102k, False: 1.61k]
  ------------------
  246|   102k|    return (uint16_t)diff;
  247|   102k|  } else {
  248|  1.61k|    return (uint16_t)(2 * depth + diff);
  249|  1.61k|  }
  250|   103k|}
tusb_fifo.c:tu_ff_remaining_local:
  253|  30.0k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_ff_remaining_local(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) {
  254|  30.0k|  const uint16_t ovf_count = tu_ff_overflow_count(depth, wr_idx, rd_idx);
  255|  30.0k|  return (depth > ovf_count) ? (depth - ovf_count) : 0;
  ------------------
  |  Branch (255:10): [True: 30.0k, False: 0]
  ------------------
  256|  30.0k|}
usbd.c:tu_fifo_read_n:
  192|  73.8k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) {
  193|       |  return tu_fifo_read_n_access_mode(f, buffer, n, NULL);
  194|  73.8k|}
usbd.c:tu_fifo_write_n:
  205|  30.0k|TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) {
  206|       |  return tu_fifo_write_n_access_mode(f, data, n, NULL);
  207|  30.0k|}

usbd.c:tu_edpt_number:
  561|  7.80k|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_number(uint8_t addr) {
  562|  7.80k|  return (uint8_t) (addr & TUSB_EPNUM_MASK);
  563|  7.80k|}
usbd.c:tu_edpt_dir:
  556|  7.59k|TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) {
  557|  7.59k|  return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
  ------------------
  |  Branch (557:10): [True: 3.68k, False: 3.90k]
  ------------------
  558|  7.59k|}
dcd_fuzz.cc:_ZL12tu_edpt_addrhh:
  565|    207|TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) {
  566|    207|  return (uint8_t) (num | (dir == (uint8_t)TUSB_DIR_IN ? (uint8_t)TUSB_DIR_IN_MASK : 0u));
  ------------------
  |  Branch (566:28): [True: 207, False: 0]
  ------------------
  567|    207|}
dcd_fuzz.cc:_ZL11tu_edpt_dirh:
  556|  4.60k|TU_ATTR_ALWAYS_INLINE static inline tusb_dir_t tu_edpt_dir(uint8_t addr) {
  557|  4.60k|  return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT;
  ------------------
  |  Branch (557:10): [True: 3.36k, False: 1.23k]
  ------------------
  558|  4.60k|}

dcd_fuzz.cc:_ZL20dcd_event_bus_signalh13dcd_eventid_tb:
  196|  9.22k|TU_ATTR_ALWAYS_INLINE static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) {
  197|  9.22k|  dcd_event_t event;
  198|  9.22k|  event.rhport = rhport;
  199|  9.22k|  event.event_id = eid;
  200|  9.22k|  dcd_event_handler(&event, in_isr);
  201|  9.22k|}
dcd_fuzz.cc:_ZL19dcd_event_bus_reseth12tusb_speed_tb:
  204|  7.72k|TU_ATTR_ALWAYS_INLINE static inline  void dcd_event_bus_reset (uint8_t rhport, tusb_speed_t speed, bool in_isr) {
  205|  7.72k|  dcd_event_t event;
  206|  7.72k|  event.rhport = rhport;
  207|  7.72k|  event.event_id = DCD_EVENT_BUS_RESET;
  ------------------
  |  |   42|  7.72k|#define DCD_EVENT_BUS_RESET DCD_EVENT_BUS_RESET_END // backward compatibility
  ------------------
  208|  7.72k|  event.bus_reset.speed = speed;
  209|  7.72k|  dcd_event_handler(&event, in_isr);
  210|  7.72k|}
dcd_fuzz.cc:_ZL24dcd_event_setup_receivedhPKhb:
  228|  15.5k|TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) {
  229|  15.5k|  dcd_event_setup_received_tagid(rhport, setup, 0, in_isr);
  230|  15.5k|}
dcd_fuzz.cc:_ZL30dcd_event_setup_received_tagidhPKhhb:
  213|  15.5k|TU_ATTR_ALWAYS_INLINE static inline void dcd_event_setup_received_tagid(uint8_t rhport, uint8_t const * setup, uint8_t setup_tagid, bool in_isr) {
  214|  15.5k|  dcd_event_t event;
  215|  15.5k|  event.rhport = rhport;
  216|  15.5k|  event.event_id = DCD_EVENT_SETUP_RECEIVED;
  217|  15.5k|  event.setup_tagid = setup_tagid;
  218|  15.5k|  (void) memcpy(&event.setup_received, setup, sizeof(tusb_control_request_t));
  219|       |  // USB wire format is little-endian. Convert multi-byte fields to host byte order
  220|       |  // so the stack always sees correct values regardless of CPU endianness.
  221|  15.5k|  event.setup_received.wValue  = tu_le16toh(event.setup_received.wValue);
  ------------------
  |  |  253|  15.5k|  #define tu_le16toh(u16) (u16)
  ------------------
  222|  15.5k|  event.setup_received.wIndex  = tu_le16toh(event.setup_received.wIndex);
  ------------------
  |  |  253|  15.5k|  #define tu_le16toh(u16) (u16)
  ------------------
  223|  15.5k|  event.setup_received.wLength = tu_le16toh(event.setup_received.wLength);
  ------------------
  |  |  253|  15.5k|  #define tu_le16toh(u16) (u16)
  ------------------
  224|  15.5k|  dcd_event_handler(&event, in_isr);
  225|  15.5k|}

tud_event_hook_cb:
   29|  30.0k|TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
   30|  30.0k|  (void) rhport; (void) eventid; (void) in_isr;
   31|  30.0k|}
tud_descriptor_bos_cb:
   37|    231|TU_ATTR_WEAK uint8_t const* tud_descriptor_bos_cb(void) {
   38|       |  return NULL;
   39|    231|}
tud_descriptor_device_qualifier_cb:
   41|    194|TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void) {
   42|       |  return NULL;
   43|    194|}
tud_descriptor_other_speed_configuration_cb:
   45|    196|TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
   46|    196|  (void) index;
   47|       |  return NULL;
   48|    196|}
tud_umount_cb:
   53|  4.99k|TU_ATTR_WEAK void tud_umount_cb(void) {
   54|  4.99k|}
tud_suspend_cb:
   56|  1.19k|TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en) {
   57|  1.19k|  (void) remote_wakeup_en;
   58|  1.19k|}
tud_resume_cb:
   60|    556|TU_ATTR_WEAK void tud_resume_cb(void) {
   61|    556|}
tud_vendor_control_xfer_cb:
   63|    366|TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
   64|    366|  (void) rhport; (void) stage; (void) request;
   65|       |  return false;
   66|    366|}
usbd_app_driver_get_cb:
  444|      1|TU_ATTR_WEAK usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) {
  445|      1|  *driver_count = 0;
  446|       |  return NULL;
  447|      1|}
tud_inited:
  518|  44.8k|bool tud_inited(void) {
  519|  44.8k|  return _usbd_rhport != RHPORT_INVALID;
  520|  44.8k|}
tud_rhport_init:
  526|  1.01k|bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
  527|  1.01k|  if (tud_inited()) {
  ------------------
  |  Branch (527:7): [True: 1.01k, False: 1]
  ------------------
  528|  1.01k|    return true; // skip if already initialized
  529|  1.01k|  }
  530|      1|  TU_ASSERT(rh_init);
  ------------------
  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  531|       | #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
  532|       |  char const* speed_str = 0;
  533|       |  switch (rh_init->speed) {
  534|       |    case TUSB_SPEED_HIGH:
  535|       |      speed_str = "High";
  536|       |    break;
  537|       |    case TUSB_SPEED_FULL:
  538|       |      speed_str = "Full";
  539|       |    break;
  540|       |    case TUSB_SPEED_LOW:
  541|       |      speed_str = "Low";
  542|       |    break;
  543|       |    case TUSB_SPEED_AUTO:
  544|       |      speed_str = "Auto";
  545|       |    break;
  546|       |  default:
  547|       |    break;
  548|       |  }
  549|       |  TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, speed_str);
  550|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t));
  551|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t));
  552|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t));
  553|       |  TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t));
  554|       |#endif
  555|       |
  556|      1|  tu_varclr(&_usbd_dev);
  ------------------
  |  |   96|      1|#define tu_varclr(_var)          tu_memclr(_var, sizeof(*(_var)))
  |  |  ------------------
  |  |  |  |   95|      1|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  |  |  ------------------
  ------------------
  557|      1|  _usbd_queued_setup = 0;
  558|       |
  559|      1|  osal_spin_init(&_usbd_spin);
  560|       |
  561|       |#if OSAL_MUTEX_REQUIRED
  562|       |  // Init device mutex
  563|       |  _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef);
  564|       |  TU_ASSERT(_usbd_mutex);
  565|       |#endif
  566|       |
  567|       |  // Init device queue & task
  568|      1|  _usbd_q = osal_queue_create(&_usbd_qdef);
  569|      1|  TU_ASSERT(_usbd_q);
  ------------------
  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  570|       |
  571|       |  // Get application driver if available
  572|      1|  _app_driver = usbd_app_driver_get_cb(&_app_driver_count);
  573|      1|  TU_ASSERT(_app_driver_count + _builtin_driver_count <= UINT8_MAX);
  ------------------
  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  574|       |
  575|       |  // Init class drivers
  576|      2|  for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
  ------------------
  |  |  369|      2|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + _builtin_driver_count))
  ------------------
  |  Branch (576:23): [True: 1, False: 1]
  ------------------
  577|      1|    usbd_class_driver_t const* driver = get_driver(i);
  578|      1|    TU_ASSERT(driver && driver->init);
  ------------------
  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      2|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 1, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 1, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  579|      1|    TU_LOG_USBD("%s init\r\n", driver->name);
  580|      1|    driver->init();
  581|      1|  }
  582|       |
  583|      1|  _usbd_rhport = rhport;
  584|       |
  585|       |  // Init device controller driver
  586|      1|  TU_ASSERT(dcd_init(rhport, rh_init));
  ------------------
  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      1|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      1|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|      1|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      1|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      1|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      1|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  587|      1|  dcd_int_enable(rhport);
  588|       |
  589|       |  return true;
  590|      1|}
tud_task_ext:
  690|  43.8k|void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
  691|  43.8k|  (void) in_isr; // not implemented yet
  692|       |
  693|       |  // Skip if stack is not initialized
  694|  43.8k|  if (!tud_inited()) {
  ------------------
  |  Branch (694:7): [True: 0, False: 43.8k]
  ------------------
  695|      0|    return;
  696|      0|  }
  697|       |
  698|       |  // Loop until there are no more events in the queue or CFG_TUD_TASK_EVENTS_PER_RUN is reached
  699|  73.8k|  for (unsigned epr = 0;; epr++) {
  700|  73.8k|#if CFG_TUD_TASK_EVENTS_PER_RUN > 0
  701|  73.8k|    if (epr >= CFG_TUD_TASK_EVENTS_PER_RUN) {
  ------------------
  |  |  652|  73.8k|  #define CFG_TUD_TASK_EVENTS_PER_RUN  16
  ------------------
  |  Branch (701:9): [True: 0, False: 73.8k]
  ------------------
  702|      0|      TU_LOG_USBD("USBD event limit (" TU_XSTRING(CFG_TUD_TASK_EVENTS_PER_RUN) ") reached\r\n");
  703|      0|      break;
  704|      0|    }
  705|  73.8k|#endif
  706|  73.8k|    dcd_event_t event;
  707|  73.8k|    if (!osal_queue_receive(_usbd_q, &event, (_usbd_after_queue.func != NULL) ? 0 : timeout_ms)) {
  ------------------
  |  Branch (707:9): [True: 43.8k, False: 30.0k]
  |  Branch (707:46): [True: 0, False: 73.8k]
  ------------------
  708|  43.8k|      if (!run_after_queue_call()) {
  ------------------
  |  Branch (708:11): [True: 43.8k, False: 0]
  ------------------
  709|  43.8k|        return;
  710|  43.8k|      }
  711|      0|      timeout_ms = 0;
  712|      0|      continue;
  713|  43.8k|    }
  714|       |
  715|       |#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
  716|       |    if (event.event_id == DCD_EVENT_SETUP_RECEIVED) {
  717|       |      TU_LOG_USBD("\r\n"); // extra line for setup
  718|       |    }
  719|       |    TU_LOG_USBD("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED");
  720|       |#endif
  721|       |
  722|  30.0k|    switch (event.event_id) {
  723|      0|      case DCD_EVENT_BUS_RESET_START:
  ------------------
  |  Branch (723:7): [True: 0, False: 30.0k]
  ------------------
  724|      0|        TU_LOG_USBD("\r\n");
  725|      0|        usbd_reset(event.rhport);
  726|      0|        break;
  727|       |
  728|  7.72k|      case DCD_EVENT_BUS_RESET_END:
  ------------------
  |  Branch (728:7): [True: 7.72k, False: 22.2k]
  ------------------
  729|  7.72k|        TU_LOG_USBD(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]);
  730|       |        // TODO a DCD that reports both edges pays for two teardowns: track a per-rhport
  731|       |        // "start seen" flag and skip this reset, keeping it for the single-event DCDs.
  732|  7.72k|        usbd_reset(event.rhport);
  733|  7.72k|        _usbd_dev.speed = event.bus_reset.speed;
  734|  7.72k|        break;
  735|       |
  736|  4.99k|      case DCD_EVENT_UNPLUGGED:
  ------------------
  |  Branch (736:7): [True: 4.99k, False: 25.0k]
  ------------------
  737|  4.99k|        TU_LOG_USBD("\r\n");
  738|  4.99k|        usbd_reset(event.rhport);
  739|  4.99k|        tud_umount_cb();
  740|  4.99k|        break;
  741|       |
  742|  15.5k|      case DCD_EVENT_SETUP_RECEIVED:
  ------------------
  |  Branch (742:7): [True: 15.5k, False: 14.4k]
  ------------------
  743|  15.5k|        if (_usbd_queued_setup == 0) {
  ------------------
  |  Branch (743:13): [True: 3.75k, False: 11.7k]
  ------------------
  744|  3.75k|          break;
  745|  3.75k|        }
  746|  11.7k|        _usbd_queued_setup--;
  747|  11.7k|        TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8);
  748|  11.7k|        if (_usbd_queued_setup != 0) {
  ------------------
  |  Branch (748:13): [True: 0, False: 11.7k]
  ------------------
  749|      0|          TU_LOG_USBD("  Skipped since there is other SETUP in queue\r\n");
  750|      0|          break;
  751|      0|        }
  752|  11.7k|        if (!dcd_edpt0_setup_begin(event.rhport, event.setup_tagid)) {
  ------------------
  |  Branch (752:13): [True: 0, False: 11.7k]
  ------------------
  753|      0|          TU_LOG_USBD("  Skipped since DCD saw a newer SETUP or bus reset\r\n");
  754|      0|          break;
  755|      0|        }
  756|       |
  757|       |        // Mark as connected after receiving 1st setup packet.
  758|       |        // But it is easier to set it every time instead of wasting time to check then set
  759|  11.7k|        _usbd_dev.connected = 1;
  760|       |
  761|       |        // reset ep state
  762|  11.7k|        _usbd_dev.ep_status[0][TUSB_DIR_OUT] = 0;
  763|  11.7k|        _usbd_dev.ep_status[0][TUSB_DIR_IN] = 0;
  764|       |
  765|       |        // Process control request
  766|  11.7k|        if (!process_setup_received(event.rhport, &event.setup_received)) {
  ------------------
  |  Branch (766:13): [True: 8.37k, False: 3.40k]
  ------------------
  767|  8.37k|          TU_LOG_USBD("  Stall EP0\r\n");
  768|       |          // Failed -> stall both control endpoint IN and OUT
  769|  8.37k|          dcd_edpt_stall(event.rhport, TU_EP0_OUT);
  770|  8.37k|          dcd_edpt_stall(event.rhport, TU_EP0_IN);
  771|  8.37k|        }
  772|  11.7k|        break;
  773|       |
  774|      0|      case DCD_EVENT_XFER_COMPLETE: {
  ------------------
  |  Branch (774:7): [True: 0, False: 30.0k]
  ------------------
  775|       |        // Invoke the class callback associated with the endpoint address
  776|      0|        uint8_t const ep_addr = event.xfer_complete.ep_addr;
  777|      0|        uint8_t const epnum = tu_edpt_number(ep_addr);
  778|      0|        uint8_t const ep_dir = tu_edpt_dir(ep_addr);
  779|       |
  780|      0|        TU_LOG_USBD("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len);
  781|       |
  782|      0|        usbd_class_driver_t const* driver = NULL; // EP0 has no class driver
  783|      0|        if (0 != epnum) {
  ------------------
  |  Branch (783:13): [True: 0, False: 0]
  ------------------
  784|      0|          driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]);
  785|      0|          TU_ASSERT(driver,);
  ------------------
  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  109|      0|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  786|      0|        }
  787|       |
  788|       |        // Clear busy + claimed. An OUT endpoint changed to RX_PENDING, so no other task can claim and re-arm it before
  789|       |        // its buffer is consumed
  790|      0|        uint8_t const rx_pending = (0 != epnum && ep_dir == TUSB_DIR_OUT) ? TU_EDPT_STATE_RX_PENDING : 0u;
  ------------------
  |  |   34|      0|#define TU_EDPT_STATE_RX_PENDING 0x08u // OUT xfer completed, ep buffer not yet consumed by the class (#1292)
  ------------------
  |  Branch (790:37): [True: 0, False: 0]
  |  Branch (790:51): [True: 0, False: 0]
  ------------------
  791|      0|        _usbd_dev.ep_status[epnum][ep_dir] = (uint8_t) (
  792|      0|          (_usbd_dev.ep_status[epnum][ep_dir] & ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED)) | rx_pending);
  ------------------
  |  |   31|      0|#define TU_EDPT_STATE_BUSY    0x01u
  ------------------
                        (_usbd_dev.ep_status[epnum][ep_dir] & ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED)) | rx_pending);
  ------------------
  |  |   33|      0|#define TU_EDPT_STATE_CLAIMED 0x04u
  ------------------
  793|       |
  794|      0|        if (driver == NULL) {
  ------------------
  |  Branch (794:13): [True: 0, False: 0]
  ------------------
  795|       |          // Not stalled on failure: a DCD refuses an EP0 prime when a newer setup is already
  796|       |          // latched, and EP0 stalls are cleared by hardware when that setup arrives - so a stall
  797|       |          // issued here lands after the auto-clear and would stall the transfer that superseded
  798|       |          // this one. The pending setup re-drives EP0 by itself.
  799|      0|          if (!usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result,
  ------------------
  |  Branch (799:15): [True: 0, False: 0]
  ------------------
  800|      0|                                    event.xfer_complete.len)) {
  801|      0|            TU_LOG_USBD("  Control stage not continued\r\n");
  802|      0|          }
  803|      0|        } else {
  804|      0|          TU_LOG_USBD("  %s xfer callback\r\n", driver->name);
  805|      0|          driver->xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
  806|      0|        }
  807|      0|        break;
  808|      0|      }
  809|       |
  810|  1.19k|      case DCD_EVENT_SUSPEND:
  ------------------
  |  Branch (810:7): [True: 1.19k, False: 28.8k]
  ------------------
  811|       |        // NOTE: When plugging/unplugging device, the D+/D- state are unstable and
  812|       |        // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ), which result in a series of event
  813|       |        // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected
  814|  1.19k|        if (_usbd_dev.connected) {
  ------------------
  |  Branch (814:13): [True: 1.19k, False: 0]
  ------------------
  815|  1.19k|          TU_LOG_USBD(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en);
  816|  1.19k|          tud_suspend_cb(_usbd_dev.remote_wakeup_en);
  817|  1.19k|        } else {
  818|      0|          TU_LOG_USBD(" Skipped\r\n");
  819|      0|        }
  820|  1.19k|        break;
  821|       |
  822|    556|      case DCD_EVENT_RESUME:
  ------------------
  |  Branch (822:7): [True: 556, False: 29.4k]
  ------------------
  823|    556|        if (_usbd_dev.connected) {
  ------------------
  |  Branch (823:13): [True: 556, False: 0]
  ------------------
  824|    556|          TU_LOG_USBD("\r\n");
  825|    556|          tud_resume_cb();
  826|    556|        } else {
  827|      0|          TU_LOG_USBD(" Skipped\r\n");
  828|      0|        }
  829|    556|        break;
  830|       |
  831|      0|      case USBD_EVENT_FUNC_CALL:
  ------------------
  |  Branch (831:7): [True: 0, False: 30.0k]
  ------------------
  832|      0|        TU_LOG_USBD("\r\n");
  833|      0|        if (event.func_call.func != NULL) {
  ------------------
  |  Branch (833:13): [True: 0, False: 0]
  ------------------
  834|      0|          event.func_call.func(event.func_call.param);
  835|      0|        }
  836|      0|        break;
  837|       |
  838|      0|      case DCD_EVENT_SOF:
  ------------------
  |  Branch (838:7): [True: 0, False: 30.0k]
  ------------------
  839|      0|        if (tu_bit_test(_usbd_dev.sof_consumer, SOF_CONSUMER_USER)) {
  ------------------
  |  Branch (839:13): [True: 0, False: 0]
  ------------------
  840|      0|          TU_LOG_USBD("\r\n");
  841|      0|          tud_sof_cb(event.sof.frame_count);
  842|      0|        }
  843|      0|      break;
  844|       |
  845|      0|      default:
  ------------------
  |  Branch (845:7): [True: 0, False: 30.0k]
  ------------------
  846|      0|        TU_BREAKPOINT();
  ------------------
  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  ------------------
  ------------------
  847|      0|        break;
  848|  30.0k|    }
  849|       |
  850|       |    // allow to exit tud_task() if there is no event in the next run
  851|  30.0k|    timeout_ms = 0;
  852|  30.0k|  }
  853|  43.8k|}
dcd_edpt0_setup_begin:
  860|  11.7k|TU_ATTR_WEAK bool dcd_edpt0_setup_begin(uint8_t rhport, uint8_t setup_tagid) {
  861|  11.7k|  (void) rhport;
  862|  11.7k|  (void) setup_tagid;
  863|       |  return true;
  864|  11.7k|}
tud_control_status:
  906|  2.12k|bool tud_control_status(uint8_t rhport, const tusb_control_request_t* request) {
  907|       |  // _usbd_dev.ctrl_xfer fields are pre-initialized at process_setup_received entry
  908|  2.12k|  (void) request;
  909|  2.12k|  return status_stage_xact(rhport, status_stage_ep(&_usbd_dev.ctrl_xfer.request));
  910|  2.12k|}
tud_control_xfer:
  913|  2.26k|bool tud_control_xfer(uint8_t rhport, const tusb_control_request_t* request, void* buffer, uint16_t len) {
  914|       |  // _usbd_dev.ctrl_xfer.request and reset fields are pre-initialized at process_setup_received entry
  915|  2.26k|  (void) request;
  916|  2.26k|  usbd_control_xfer_t* const ctrl_xfer = &_usbd_dev.ctrl_xfer;
  917|  2.26k|  ctrl_xfer->buffer = (uint8_t*) buffer;
  918|  2.26k|  ctrl_xfer->data_len = tu_min16(len, ctrl_xfer->request.wLength);
  919|       |
  920|  2.26k|  if (ctrl_xfer->request.wLength > 0U) {
  ------------------
  |  Branch (920:7): [True: 1.63k, False: 631]
  ------------------
  921|  1.63k|    if (ctrl_xfer->data_len > 0U) {
  ------------------
  |  Branch (921:9): [True: 1.63k, False: 0]
  ------------------
  922|  1.63k|      TU_ASSERT(buffer);
  ------------------
  |  |  112|  1.63k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  1.63k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  1.63k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|  1.63k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  1.63k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  1.63k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 1.63k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  1.63k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1.63k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  923|  1.63k|    }
  924|  1.63k|    TU_VERIFY(data_stage_xact(rhport));
  ------------------
  |  |   95|  1.63k|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  1.63k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|  1.63k|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|  1.63k|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|  1.63k|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|  1.63k|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 1.06k, False: 573]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|  1.06k|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|  1.06k|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|  1.63k|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 573]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  925|  1.63k|  } else {
  926|       |    // wLength == 0: Status stage is always IN per USB 2.0 §9.3.1
  927|    631|    TU_VERIFY(status_stage_xact(rhport, TU_EP0_IN));
  ------------------
  |  |   95|    631|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    631|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    631|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    631|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    631|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    631|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 377, False: 254]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    377|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    377|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    631|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 254]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  928|    631|  }
  929|       |
  930|    827|  return true;
  931|  2.26k|}
dcd_event_handler:
 1442|  32.4k|TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) {
 1443|  32.4k|  bool send = false;
 1444|  32.4k|  switch (event->event_id) {
 1445|  4.99k|    case DCD_EVENT_UNPLUGGED:
  ------------------
  |  Branch (1445:5): [True: 4.99k, False: 27.4k]
  ------------------
 1446|  4.99k|      _usbd_dev.connected = 0;
 1447|  4.99k|      _usbd_dev.addressed = 0;
 1448|  4.99k|      _usbd_dev.cfg_num = 0;
 1449|  4.99k|      _usbd_dev.suspended = 0;
 1450|  4.99k|      send = true;
 1451|  4.99k|      break;
 1452|       |
 1453|  2.30k|    case DCD_EVENT_SUSPEND:
  ------------------
  |  Branch (1453:5): [True: 2.30k, False: 30.1k]
  ------------------
 1454|       |      // NOTE: When plugging/unplugging device, the D+/D- state are unstable and
 1455|       |      // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ).
 1456|       |      // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish
 1457|       |      // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected
 1458|  2.30k|      if (_usbd_dev.connected) {
  ------------------
  |  Branch (1458:11): [True: 1.19k, False: 1.11k]
  ------------------
 1459|  1.19k|        _usbd_dev.suspended = 1;
 1460|  1.19k|        send = true;
 1461|  1.19k|      }
 1462|  2.30k|      break;
 1463|       |
 1464|  1.92k|    case DCD_EVENT_RESUME:
  ------------------
  |  Branch (1464:5): [True: 1.92k, False: 30.5k]
  ------------------
 1465|       |      // skip event if not connected (especially required for SAMD)
 1466|  1.92k|      if (_usbd_dev.connected) {
  ------------------
  |  Branch (1466:11): [True: 556, False: 1.36k]
  ------------------
 1467|    556|        _usbd_dev.suspended = 0;
 1468|    556|        send = true;
 1469|    556|      }
 1470|  1.92k|      break;
 1471|       |
 1472|      0|    case DCD_EVENT_SOF:
  ------------------
  |  Branch (1472:5): [True: 0, False: 32.4k]
  ------------------
 1473|       |      // SOF driver handler in ISR context
 1474|      0|      for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
  ------------------
  |  |  369|      0|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + _builtin_driver_count))
  ------------------
  |  Branch (1474:27): [True: 0, False: 0]
  ------------------
 1475|      0|        usbd_class_driver_t const* driver = get_driver(i);
 1476|      0|        if (driver && driver->sof) {
  ------------------
  |  Branch (1476:13): [True: 0, False: 0]
  |  Branch (1476:23): [True: 0, False: 0]
  ------------------
 1477|      0|          driver->sof(event->rhport, event->sof.frame_count);
 1478|      0|        }
 1479|      0|      }
 1480|       |
 1481|       |      // Some MCUs after running dcd_remote_wakeup() does not have way to detect the end of remote wakeup
 1482|       |      // which last 1-15 ms. DCD can use SOF as a clear indicator that bus is back to operational
 1483|      0|      if (_usbd_dev.suspended) {
  ------------------
  |  Branch (1483:11): [True: 0, False: 0]
  ------------------
 1484|      0|        _usbd_dev.suspended = 0;
 1485|       |
 1486|      0|        dcd_event_t const event_resume = {.rhport = event->rhport, .event_id = DCD_EVENT_RESUME};
 1487|      0|        queue_event(&event_resume, in_isr);
 1488|      0|      }
 1489|       |
 1490|      0|      if (tu_bit_test(_usbd_dev.sof_consumer, SOF_CONSUMER_USER)) {
  ------------------
  |  Branch (1490:11): [True: 0, False: 0]
  ------------------
 1491|      0|        dcd_event_t const event_sof = {.rhport = event->rhport, .event_id = DCD_EVENT_SOF, .sof.frame_count = event->sof.frame_count};
 1492|      0|        queue_event(&event_sof, in_isr);
 1493|      0|      }
 1494|      0|      break;
 1495|       |
 1496|  15.5k|    case DCD_EVENT_SETUP_RECEIVED:
  ------------------
  |  Branch (1496:5): [True: 15.5k, False: 16.9k]
  ------------------
 1497|  15.5k|      _usbd_queued_setup++;
 1498|  15.5k|      send = true;
 1499|  15.5k|      break;
 1500|       |
 1501|      0|    case DCD_EVENT_XFER_COMPLETE: {
  ------------------
  |  Branch (1501:5): [True: 0, False: 32.4k]
  ------------------
 1502|       |      // Invoke the class callback associated with the endpoint address
 1503|      0|      uint8_t const ep_addr = event->xfer_complete.ep_addr;
 1504|      0|      uint8_t const epnum = tu_edpt_number(ep_addr);
 1505|      0|      uint8_t const ep_dir = tu_edpt_dir(ep_addr);
 1506|       |
 1507|      0|      send = true;
 1508|      0|      if(epnum > 0) {
  ------------------
  |  Branch (1508:10): [True: 0, False: 0]
  ------------------
 1509|      0|        usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]);
 1510|       |
 1511|      0|        if (driver && driver->xfer_isr) {
  ------------------
  |  Branch (1511:13): [True: 0, False: 0]
  |  Branch (1511:23): [True: 0, False: 0]
  ------------------
 1512|       |          // Clear busy + claimed
 1513|      0|          _usbd_dev.ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   31|      0|#define TU_EDPT_STATE_BUSY    0x01u
  ------------------
                        _usbd_dev.ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   33|      0|#define TU_EDPT_STATE_CLAIMED 0x04u
  ------------------
 1514|       |
 1515|      0|          send = !driver->xfer_isr(event->rhport, ep_addr, (xfer_result_t) event->xfer_complete.result, event->xfer_complete.len);
 1516|       |
 1517|       |          // xfer_isr() is deferred to xfer_cb(), revert busy/claimed status
 1518|      0|          if (send) {
  ------------------
  |  Branch (1518:15): [True: 0, False: 0]
  ------------------
 1519|       |            // set busy + claimed
 1520|      0|            _usbd_dev.ep_status[epnum][ep_dir] |= (TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   31|      0|#define TU_EDPT_STATE_BUSY    0x01u
  ------------------
                          _usbd_dev.ep_status[epnum][ep_dir] |= (TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   33|      0|#define TU_EDPT_STATE_CLAIMED 0x04u
  ------------------
 1521|      0|          }
 1522|      0|        }
 1523|      0|      }
 1524|      0|      break;
 1525|      0|    }
 1526|       |
 1527|  7.72k|    default:
  ------------------
  |  Branch (1527:5): [True: 7.72k, False: 24.7k]
  ------------------
 1528|  7.72k|      send = true;
 1529|  7.72k|      break;
 1530|  32.4k|  }
 1531|       |
 1532|  32.4k|  if (send && !queue_event(event, in_isr)) {
  ------------------
  |  Branch (1532:7): [True: 30.0k, False: 2.47k]
  |  Branch (1532:15): [True: 0, False: 30.0k]
  ------------------
 1533|       |    // event dropped by a full queue: undo state that would otherwise wedge permanently
 1534|      0|    if (event->event_id == DCD_EVENT_SETUP_RECEIVED) {
  ------------------
  |  Branch (1534:9): [True: 0, False: 0]
  ------------------
 1535|       |      // undo the increment, else every later SETUP is skipped as "other SETUP in queue"
 1536|       |      // and EP0 is deaf until re-init
 1537|      0|      _usbd_queued_setup--;
 1538|      0|    } else if (event->event_id == DCD_EVENT_XFER_COMPLETE) {
  ------------------
  |  Branch (1538:16): [True: 0, False: 0]
  ------------------
 1539|       |      // clear busy + claimed, else the endpoint can never be claimed or re-armed again
 1540|      0|      uint8_t const epnum = tu_edpt_number(event->xfer_complete.ep_addr);
 1541|      0|      uint8_t const ep_dir = tu_edpt_dir(event->xfer_complete.ep_addr);
 1542|      0|      _usbd_dev.ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   31|      0|#define TU_EDPT_STATE_BUSY    0x01u
  ------------------
                    _usbd_dev.ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   33|      0|#define TU_EDPT_STATE_CLAIMED 0x04u
  ------------------
 1543|      0|    }
 1544|      0|  }
 1545|  32.4k|}
usbd_int_set:
 1551|   177k|void usbd_int_set(bool enabled) {
 1552|   177k|  if (enabled) {
  ------------------
  |  Branch (1552:7): [True: 88.5k, False: 88.5k]
  ------------------
 1553|  88.5k|    dcd_int_enable(_usbd_rhport);
 1554|  88.5k|  } else {
 1555|  88.5k|    dcd_int_disable(_usbd_rhport);
 1556|  88.5k|  }
 1557|   177k|}
usbd_open_edpt_pair:
 1568|    213|                         uint8_t *ep_in) {
 1569|    213|  for (int i = 0; i < ep_count; i++) {
  ------------------
  |  Branch (1569:19): [True: 213, False: 0]
  ------------------
 1570|    213|    const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc;
 1571|       |
 1572|    213|    TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && xfer_type == desc_ep->bmAttributes.xfer);
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    426|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1573|    213|    TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|    213|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|    213|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1574|       |
 1575|      0|    if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
  ------------------
  |  Branch (1575:9): [True: 0, False: 0]
  ------------------
 1576|      0|      (*ep_in) = desc_ep->bEndpointAddress;
 1577|      0|    } else {
 1578|      0|      (*ep_out) = desc_ep->bEndpointAddress;
 1579|      0|    }
 1580|       |
 1581|      0|    p_desc = tu_desc_next(p_desc);
 1582|      0|  }
 1583|       |
 1584|      0|  return true;
 1585|    213|}
usbd_edpt_open:
 1612|    213|bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
 1613|    213|  rhport = _usbd_rhport;
 1614|       |
 1615|    213|  TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX);
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|    213|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|    213|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1616|      0|  TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t)_usbd_dev.speed));
  ------------------
  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|      0|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1617|       |
 1618|      0|  return dcd_edpt_open(rhport, desc_ep);
 1619|      0|}
usbd_edpt_xfer:
 1655|  4.39k|bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) {
 1656|  4.39k|  rhport = _usbd_rhport;
 1657|       |
 1658|  4.39k|  uint8_t const epnum = tu_edpt_number(ep_addr);
 1659|  4.39k|  uint8_t const dir = tu_edpt_dir(ep_addr);
 1660|       |
 1661|       |  // TODO skip ready() check for now since enumeration also use this API
 1662|       |  // TU_VERIFY(tud_ready());
 1663|       |
 1664|  4.39k|  TU_LOG_USBD("  Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes);
 1665|       |#if CFG_TUD_LOG_LEVEL >= 3
 1666|       |  if(dir == TUSB_DIR_IN) {
 1667|       |    TU_LOG_MEM(CFG_TUD_LOG_LEVEL, buffer, total_bytes, 2);
 1668|       |  }
 1669|       |#endif
 1670|       |
 1671|       |  // Attempt to transfer on a busy endpoint, sound like an race condition !
 1672|  4.39k|  TU_ASSERT((_usbd_dev.ep_status[epnum][dir] & TU_EDPT_STATE_BUSY) == 0);
  ------------------
  |  |  112|  4.39k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  4.39k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  4.39k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|  4.39k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  4.39k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  4.39k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 4.39k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  4.39k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 4.39k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1673|       |
 1674|       |  // Set busy first since the actual transfer can be complete before dcd_edpt_xfer()
 1675|       |  // could return and USBD task can preempt and clear the busy
 1676|  4.39k|  _usbd_dev.ep_status[epnum][dir] =
 1677|  4.39k|    (uint8_t) ((_usbd_dev.ep_status[epnum][dir] & ~TU_EDPT_STATE_RX_PENDING) | TU_EDPT_STATE_BUSY);
  ------------------
  |  |   34|  4.39k|#define TU_EDPT_STATE_RX_PENDING 0x08u // OUT xfer completed, ep buffer not yet consumed by the class (#1292)
  ------------------
                  (uint8_t) ((_usbd_dev.ep_status[epnum][dir] & ~TU_EDPT_STATE_RX_PENDING) | TU_EDPT_STATE_BUSY);
  ------------------
  |  |   31|  4.39k|#define TU_EDPT_STATE_BUSY    0x01u
  ------------------
 1678|       |
 1679|  4.39k|  if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes, is_isr)) {
  ------------------
  |  Branch (1679:7): [True: 1.71k, False: 2.67k]
  ------------------
 1680|  1.71k|    return true;
 1681|  2.67k|  } else {
 1682|       |    // Driver refused the transfer, mark endpoint as ready to allow next transfer. This is a
 1683|       |    // recoverable condition (e.g. a new setup superseding a control response), not a bug, so
 1684|       |    // do not break into the debugger - TU_BREAKPOINT() halts the CPU whenever a probe is
 1685|       |    // attached, which on a test rig is always.
 1686|  2.67k|    _usbd_dev.ep_status[epnum][dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   31|  2.67k|#define TU_EDPT_STATE_BUSY    0x01u
  ------------------
                  _usbd_dev.ep_status[epnum][dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
  ------------------
  |  |   33|  2.67k|#define TU_EDPT_STATE_CLAIMED 0x04u
  ------------------
 1687|  2.67k|    TU_LOG_USBD("FAILED\r\n");
 1688|       |    return false;
 1689|  2.67k|  }
 1690|  4.39k|}
usbd_edpt_stalled:
 1785|    793|bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) {
 1786|    793|  (void) rhport;
 1787|       |
 1788|    793|  uint8_t const epnum = tu_edpt_number(ep_addr);
 1789|    793|  uint8_t const dir = tu_edpt_dir(ep_addr);
 1790|       |
 1791|    793|  return (_usbd_dev.ep_status[epnum][dir] & TU_EDPT_STATE_STALLED) != 0;
  ------------------
  |  |   32|    793|#define TU_EDPT_STATE_STALLED 0x02u
  ------------------
 1792|    793|}
usbd.c:get_driver:
  373|  15.6k|TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8_t drvid) {
  374|  15.6k|  usbd_class_driver_t const *driver = NULL;
  375|  15.6k|  if (drvid < _app_driver_count) {
  ------------------
  |  Branch (375:7): [True: 0, False: 15.6k]
  ------------------
  376|       |    // Application drivers
  377|      0|    driver = &_app_driver[drvid];
  378|  15.6k|  } else{
  379|  15.6k|    drvid -= _app_driver_count;
  380|  15.6k|    if (_builtin_driver_count > 0 && drvid < _builtin_driver_count) {
  ------------------
  |  Branch (380:9): [True: 15.6k, Folded]
  |  Branch (380:38): [True: 12.9k, False: 2.68k]
  ------------------
  381|  12.9k|      driver = &_usbd_driver[drvid];
  382|  12.9k|    }
  383|  15.6k|  }
  384|       |
  385|  15.6k|  return driver;
  386|  15.6k|}
usbd.c:run_after_queue_call:
  663|  43.8k|static bool run_after_queue_call(void) {
  664|  43.8k|  osal_task_func_t const func = _usbd_after_queue.func;
  665|  43.8k|  if (func == NULL) {
  ------------------
  |  Branch (665:7): [True: 43.8k, False: 0]
  ------------------
  666|  43.8k|    return false;
  667|  43.8k|  }
  668|      0|  _usbd_after_queue.func = NULL;
  669|      0|  func(_usbd_after_queue.param);
  670|       |  return true;
  671|  43.8k|}
usbd.c:usbd_reset:
  651|  12.7k|static void usbd_reset(uint8_t rhport) {
  652|  12.7k|  configuration_reset(rhport);
  653|       |  // discard any pre-reset SETUP still counted: a stale count skips post-reset SETUPs
  654|  12.7k|  _usbd_queued_setup = 0;
  655|  12.7k|}
usbd.c:configuration_reset:
  639|  12.7k|static void configuration_reset(uint8_t rhport) {
  640|  25.4k|  for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
  ------------------
  |  |  369|  25.4k|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + _builtin_driver_count))
  ------------------
  |  Branch (640:23): [True: 12.7k, False: 12.7k]
  ------------------
  641|  12.7k|    usbd_class_driver_t const* driver = get_driver(i);
  642|  12.7k|    TU_ASSERT(driver,);
  ------------------
  |  |  112|  12.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  12.7k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  12.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  109|  12.7k|#define TU_ASSERT_2ARGS(_cond, _ret)   TU_ASSERT_DEFINE(_cond, _ret)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  12.7k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  12.7k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 12.7k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  12.7k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 12.7k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  643|  12.7k|    driver->reset(rhport);
  644|  12.7k|  }
  645|       |
  646|  12.7k|  tu_varclr(&_usbd_dev);
  ------------------
  |  |   96|  12.7k|#define tu_varclr(_var)          tu_memclr(_var, sizeof(*(_var)))
  |  |  ------------------
  |  |  |  |   95|  12.7k|#define tu_memclr(buffer, size)  (void) memset((buffer), 0, (size))
  |  |  ------------------
  ------------------
  647|  12.7k|  (void)memset(_usbd_dev.itf2drv, TUSB_INDEX_INVALID_8, sizeof(_usbd_dev.itf2drv)); // invalid mapping
  648|  12.7k|  (void)memset(_usbd_dev.ep2drv, TUSB_INDEX_INVALID_8, sizeof(_usbd_dev.ep2drv));   // invalid mapping
  649|  12.7k|}
usbd.c:status_stage_xact:
  884|  2.76k|TU_ATTR_ALWAYS_INLINE static inline bool status_stage_xact(uint8_t rhport, uint8_t ep_status) {
  885|  2.76k|  return usbd_edpt_xfer(rhport, ep_status, NULL, 0, false);
  886|  2.76k|}
usbd.c:status_stage_ep:
  879|  2.12k|TU_ATTR_ALWAYS_INLINE static inline uint8_t status_stage_ep(const tusb_control_request_t* request) {
  880|  2.12k|  return (request->wLength != 0 && request->bmRequestType_bit.direction) ? TU_EP0_OUT : TU_EP0_IN;
  ------------------
  |  Branch (880:11): [True: 1.28k, False: 846]
  |  Branch (880:36): [True: 169, False: 1.11k]
  ------------------
  881|  2.12k|}
usbd.c:data_stage_xact:
  890|  1.63k|static bool data_stage_xact(uint8_t rhport) {
  891|  1.63k|  usbd_control_xfer_t* const ctrl_xfer = &_usbd_dev.ctrl_xfer;
  892|  1.63k|  const uint16_t xact_len = tu_min16(ctrl_xfer->data_len - ctrl_xfer->total_xferred, CFG_TUD_ENDPOINT0_BUFSIZE);
  ------------------
  |  |  643|  1.63k|  #define CFG_TUD_ENDPOINT0_BUFSIZE  CFG_TUD_ENDPOINT0_SIZE
  |  |  ------------------
  |  |  |  |   90|  1.63k|#define CFG_TUD_ENDPOINT0_SIZE    64
  |  |  ------------------
  ------------------
  893|  1.63k|  uint8_t ep_addr = TU_EP0_OUT;
  894|       |
  895|  1.63k|  if (ctrl_xfer->request.bmRequestType_bit.direction == TUSB_DIR_IN) {
  ------------------
  |  Branch (895:7): [True: 567, False: 1.06k]
  ------------------
  896|    567|    ep_addr = TU_EP0_IN;
  897|    567|    if (0u != xact_len && ctrl_xfer->buffer != _ctrl_epbuf.buf) {
  ------------------
  |  Branch (897:9): [True: 567, False: 0]
  |  Branch (897:27): [True: 567, False: 0]
  ------------------
  898|    567|      TU_VERIFY(0 == tu_memcpy_s(_ctrl_epbuf.buf, CFG_TUD_ENDPOINT0_BUFSIZE, ctrl_xfer->buffer, xact_len));
  ------------------
  |  |   95|    567|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    567|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    567|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    567|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    567|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    567|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 0, False: 567]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    567|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 567]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  899|    567|    }
  900|    567|  }
  901|       |
  902|  1.63k|  return usbd_edpt_xfer(rhport, ep_addr, xact_len ? _ctrl_epbuf.buf : NULL, xact_len, false);
  ------------------
  |  Branch (902:42): [True: 1.63k, False: 0]
  ------------------
  903|  1.63k|}
usbd.c:process_setup_received:
 1121|  11.7k|static bool process_setup_received(uint8_t rhport, tusb_control_request_t const * p_request) {
 1122|       |  // Initialize control transfer state for this request. The request copy must be
 1123|       |  // visible to usbd_control_xfer_cb when the (asynchronous) status ZLP completes,
 1124|       |  // since the SETUP packet event has already gone out of scope by then.
 1125|  11.7k|  usbd_control_xfer_t* const ctrl_xfer = &_usbd_dev.ctrl_xfer;
 1126|  11.7k|  ctrl_xfer->request = *p_request;
 1127|  11.7k|  ctrl_xfer->buffer = NULL;
 1128|  11.7k|  ctrl_xfer->total_xferred = 0;
 1129|  11.7k|  ctrl_xfer->data_len = 0;
 1130|  11.7k|  ctrl_xfer->complete_cb = NULL;
 1131|       |
 1132|  11.7k|  p_request = &ctrl_xfer->request; // re-direct request pointer to internal copy (modifiable for hacking)
 1133|  11.7k|  TU_ASSERT(p_request->bmRequestType_bit.type < TUSB_REQ_TYPE_INVALID);
  ------------------
  |  |  112|  11.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  11.7k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  11.7k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|  11.7k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  11.7k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  11.7k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|    515|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 515]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|    515|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 515]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 515, False: 11.2k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  11.7k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 11.2k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1134|       |
 1135|       |  // Vendor request
 1136|  11.2k|  if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) {
  ------------------
  |  Branch (1136:8): [True: 366, False: 10.9k]
  ------------------
 1137|    366|    ctrl_xfer->complete_cb = tud_vendor_control_xfer_cb;
 1138|    366|    return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request);
 1139|    366|  }
 1140|       |
 1141|       |#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
 1142|       |  if (TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type && p_request->bRequest <= TUSB_REQ_SYNCH_FRAME) {
 1143|       |    TU_LOG_USBD("  %s", tu_str_std_request[p_request->bRequest]);
 1144|       |    if (TUSB_REQ_GET_DESCRIPTOR != p_request->bRequest) {
 1145|       |      TU_LOG_USBD("\r\n");
 1146|       |    }
 1147|       |  }
 1148|       |#endif
 1149|       |
 1150|  10.9k|  switch (p_request->bmRequestType_bit.recipient) { //-V2520
 1151|       |    //------------- Device Requests e.g in enumeration -------------//
 1152|  7.14k|    case TUSB_REQ_RCPT_DEVICE:
  ------------------
  |  Branch (1152:5): [True: 7.14k, False: 3.75k]
  ------------------
 1153|  7.14k|      if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) {
  ------------------
  |  Branch (1153:12): [True: 440, False: 6.70k]
  ------------------
 1154|    440|        uint8_t const itf = tu_u16_low(p_request->wIndex);
 1155|    440|        TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
  ------------------
  |  |   95|    440|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    440|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    440|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    440|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    440|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    440|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 229, False: 211]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    229|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    229|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    440|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 211]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1156|       |
 1157|    211|        usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]);
 1158|    211|        TU_VERIFY(driver);
  ------------------
  |  |   95|    211|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    211|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    211|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    211|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    211|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    211|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 211, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    211|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    211|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    211|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1159|       |
 1160|       |        // forward to class driver: "non-STD request to Interface"
 1161|      0|        return invoke_class_control(rhport, driver, p_request);
 1162|    211|      }
 1163|       |
 1164|  6.70k|      if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) {
  ------------------
  |  Branch (1164:11): [True: 0, False: 6.70k]
  ------------------
 1165|       |        // Non-standard request is not supported
 1166|      0|        TU_BREAKPOINT();
  ------------------
  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  ------------------
  ------------------
 1167|      0|        return false;
 1168|      0|      }
 1169|       |
 1170|  6.70k|      return process_std_device_request(rhport, p_request);
 1171|       |
 1172|       |    //------------- Class/Interface Specific Request -------------//
 1173|    563|    case TUSB_REQ_RCPT_INTERFACE: {
  ------------------
  |  Branch (1173:5): [True: 563, False: 10.3k]
  ------------------
 1174|    563|      uint8_t itf;
 1175|       |      #if CFG_TUD_PRINTER
 1176|       |      // Printer GET_DEVICE_ID has a weird wIndex = interface (high) | alt (low)
 1177|       |      // attempt to interpret this as a printer request if matched
 1178|       |      if (TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type &&
 1179|       |          TUSB_DIR_IN == p_request->bmRequestType_bit.direction &&
 1180|       |          TUSB_PRINTER_REQUEST_GET_DEVICE_ID == p_request->bRequest) {
 1181|       |        itf = tu_u16_high(p_request->wIndex);
 1182|       |        if (itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv)) {
 1183|       |          const usbd_class_driver_t * driver = get_driver(_usbd_dev.itf2drv[itf]);
 1184|       |          if (driver != NULL && driver->control_xfer_cb == printerd_control_xfer_cb) {
 1185|       |            if (invoke_class_control(rhport, driver, p_request)) {
 1186|       |              return true;
 1187|       |            }
 1188|       |          }
 1189|       |        }
 1190|       |      }
 1191|       |      #endif
 1192|    563|      itf = tu_u16_low(p_request->wIndex);
 1193|    563|      TU_VERIFY(itf < TU_ARRAY_SIZE(_usbd_dev.itf2drv));
  ------------------
  |  |   95|    563|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    563|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    563|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    563|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    563|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    563|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 272, False: 291]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    272|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    272|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    563|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 291]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1194|       |
 1195|    291|      usbd_class_driver_t const * driver = get_driver(_usbd_dev.itf2drv[itf]);
 1196|    291|      TU_VERIFY(driver);
  ------------------
  |  |   95|    291|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    291|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    291|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    291|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    291|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    291|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 291, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    291|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    291|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    291|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1197|       |
 1198|       |      // all requests to Interface (STD or Class) is forwarded to class driver.
 1199|       |      // notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE
 1200|      0|      if (!invoke_class_control(rhport, driver, p_request)) {
  ------------------
  |  Branch (1200:11): [True: 0, False: 0]
  ------------------
 1201|       |        // For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class
 1202|       |        // driver doesn't use alternate settings or implement this
 1203|      0|        TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type);
  ------------------
  |  |   95|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|      0|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|      0|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|      0|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|      0|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1204|       |
 1205|       |        // Clear complete callback if driver set since it can also stall the request.
 1206|      0|        ctrl_xfer->complete_cb = NULL;
 1207|       |
 1208|      0|        switch (p_request->bRequest) { //-V2520
 1209|      0|          case TUSB_REQ_GET_INTERFACE: {
  ------------------
  |  Branch (1209:11): [True: 0, False: 0]
  ------------------
 1210|      0|            uint8_t alternate = 0;
 1211|      0|            tud_control_xfer(rhport, p_request, &alternate, 1);
 1212|      0|            break;
 1213|      0|          }
 1214|       |
 1215|      0|          case TUSB_REQ_SET_INTERFACE:
  ------------------
  |  Branch (1215:11): [True: 0, False: 0]
  ------------------
 1216|       |            // A class that implements altsettings handles SET_INTERFACE itself and returns true,
 1217|       |            // so reaching here means the class does not — where only alt 0 is valid. Any non-zero
 1218|       |            // alt (unimplemented, or rejected as invalid by the class) is a Request Error (stall).
 1219|      0|            TU_VERIFY(tu_u16_low(p_request->wValue) == 0);
  ------------------
  |  |   95|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|      0|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|      0|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|      0|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|      0|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1220|      0|            tud_control_status(rhport, p_request);
 1221|      0|            break;
 1222|       |
 1223|      0|          case TUSB_REQ_GET_STATUS:
  ------------------
  |  Branch (1223:11): [True: 0, False: 0]
  ------------------
 1224|       |            // USB 2.0 9.4.5: interface GET_STATUS returns 2 reserved (zero) bytes
 1225|      0|            TU_VERIFY(process_get_status(rhport, p_request, 0x0000));
  ------------------
  |  |   95|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|      0|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|      0|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|      0|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|      0|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|      0|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|      0|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|      0|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1226|      0|            break;
 1227|       |
 1228|      0|          default: return false;
  ------------------
  |  Branch (1228:11): [True: 0, False: 0]
  ------------------
 1229|      0|        }
 1230|      0|      }
 1231|      0|      break;
 1232|      0|    }
 1233|       |
 1234|       |    //------------- Endpoint Request -------------//
 1235|  2.40k|    case TUSB_REQ_RCPT_ENDPOINT: {
  ------------------
  |  Branch (1235:5): [True: 2.40k, False: 8.49k]
  ------------------
 1236|  2.40k|      uint8_t const ep_addr = tu_u16_low(p_request->wIndex);
 1237|  2.40k|      uint8_t const ep_num  = tu_edpt_number(ep_addr);
 1238|  2.40k|      uint8_t const ep_dir  = tu_edpt_dir(ep_addr);
 1239|       |
 1240|  2.40k|      TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) );
  ------------------
  |  |  112|  2.40k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  2.40k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  2.40k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|  2.40k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  2.40k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  2.40k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|    218|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 218]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|    218|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 218]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 218, False: 2.18k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  2.40k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 2.18k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1241|  2.18k|      usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]);
 1242|       |
 1243|  2.18k|      if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) {
  ------------------
  |  Branch (1243:11): [True: 201, False: 1.98k]
  ------------------
 1244|       |        // Forward class request to its driver
 1245|    201|        TU_VERIFY(driver);
  ------------------
  |  |   95|    201|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    201|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    201|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    201|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    201|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    201|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 201, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    201|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    201|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    201|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1246|      0|        return invoke_class_control(rhport, driver, p_request);
 1247|  1.98k|      } else {
 1248|       |        // Handle STD request to endpoint
 1249|  1.98k|        switch (p_request->bRequest) { //-V2520
 1250|    793|          case TUSB_REQ_GET_STATUS:
  ------------------
  |  Branch (1250:11): [True: 793, False: 1.19k]
  ------------------
 1251|       |            // USB 2.0 9.4.5: endpoint GET_STATUS bit 0 = Halt
 1252|    793|            TU_VERIFY(process_get_status(rhport, p_request, usbd_edpt_stalled(rhport, ep_addr) ? 0x0001u : 0x0000u));
  ------------------
  |  |   95|    793|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    793|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    793|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    793|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    793|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|  1.58k|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 553, False: 240]
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:11): [True: 0, False: 793]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    553|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    553|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    793|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 240]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1253|    240|            break;
 1254|       |
 1255|    434|          case TUSB_REQ_CLEAR_FEATURE:
  ------------------
  |  Branch (1255:11): [True: 434, False: 1.55k]
  ------------------
 1256|    970|          case TUSB_REQ_SET_FEATURE: {
  ------------------
  |  Branch (1256:11): [True: 536, False: 1.44k]
  ------------------
 1257|       |            // ENDPOINT_HALT is the only endpoint feature; it exists only on a non-control endpoint
 1258|       |            // that an interface actually owns. Any other selector, the control endpoint (EP0 has no
 1259|       |            // Halt feature, USB 2.0 9.4.9), or an endpoint no driver owns is a Request Error (stall).
 1260|    970|            TU_VERIFY(TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue);
  ------------------
  |  |   95|    970|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    970|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    970|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    970|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    970|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    970|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 411, False: 559]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    411|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    411|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    970|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 559]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1261|    559|            TU_VERIFY(ep_num != 0);
  ------------------
  |  |   95|    559|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    559|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    559|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    559|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    559|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    559|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 209, False: 350]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    209|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    209|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    559|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 350]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1262|    350|            TU_VERIFY(driver != NULL);
  ------------------
  |  |   95|    350|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    350|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    350|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    350|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    350|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    350|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 350, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    350|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    350|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    350|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1263|       |
 1264|      0|            if ( TUSB_REQ_CLEAR_FEATURE == p_request->bRequest ) {
  ------------------
  |  Branch (1264:18): [True: 0, False: 0]
  ------------------
 1265|      0|              usbd_edpt_clear_stall(rhport, ep_addr);
 1266|      0|            } else {
 1267|      0|              usbd_edpt_stall(rhport, ep_addr);
 1268|      0|            }
 1269|       |
 1270|       |            // Some classes such as USBTMC need to clear/re-init their buffer on CLEAR_FEATURE.
 1271|       |            // Clear complete callback if driver set since it can also stall the request.
 1272|      0|            (void) invoke_class_control(rhport, driver, p_request);
 1273|      0|            ctrl_xfer->complete_cb = NULL;
 1274|       |
 1275|       |            // STD request must always be ACKed; skip ZLP status if driver already did that.
 1276|      0|            if (!(_usbd_dev.ep_status[0][TUSB_DIR_IN] & TU_EDPT_STATE_BUSY)) {
  ------------------
  |  |   31|      0|#define TU_EDPT_STATE_BUSY    0x01u
  ------------------
  |  Branch (1276:17): [True: 0, False: 0]
  ------------------
 1277|      0|              tud_control_status(rhport, p_request);
 1278|      0|            }
 1279|      0|          }
 1280|      0|          break;
 1281|       |
 1282|       |          // Unknown/Unsupported request
 1283|    222|          default:
  ------------------
  |  Branch (1283:11): [True: 222, False: 1.76k]
  ------------------
 1284|    222|            TU_BREAKPOINT();
  ------------------
  |  |   77|    222|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (77:40): [Folded, False: 222]
  |  |  ------------------
  ------------------
 1285|    222|            return false;
 1286|  1.98k|        }
 1287|  1.98k|      }
 1288|    240|      break;
 1289|  2.18k|    }
 1290|       |
 1291|       |    // Unknown recipient
 1292|    791|    default:
  ------------------
  |  Branch (1292:5): [True: 791, False: 10.1k]
  ------------------
 1293|    791|      TU_BREAKPOINT();
  ------------------
  |  |   77|    791|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (77:40): [Folded, False: 791]
  |  |  ------------------
  ------------------
 1294|    791|      return false;
 1295|  10.9k|  }
 1296|       |
 1297|    240|  return true;
 1298|  10.9k|}
usbd.c:process_std_device_request:
 1004|  6.70k|static bool process_std_device_request(uint8_t rhport, tusb_control_request_t const * p_request) {
 1005|  6.70k|  switch (p_request->bRequest) { //-V2520
 1006|    207|    case TUSB_REQ_SET_ADDRESS:
  ------------------
  |  Branch (1006:5): [True: 207, False: 6.49k]
  ------------------
 1007|       |      // Depending on mcu, status phase could be sent either before or after changing device address,
 1008|       |      // or even require stack to not response with status at all
 1009|       |      // Therefore DCD must take full responsibility to response and include zlp status packet if needed.
 1010|    207|      dcd_set_address(rhport, (uint8_t) p_request->wValue);
 1011|    207|      _usbd_dev.addressed = 1;
 1012|    207|      return true;
 1013|       |
 1014|    278|    case TUSB_REQ_GET_CONFIGURATION: {
  ------------------
  |  Branch (1014:5): [True: 278, False: 6.42k]
  ------------------
 1015|    278|      uint8_t cfg_num = _usbd_dev.cfg_num;
 1016|    278|      tud_control_xfer(rhport, p_request, &cfg_num, 1);
 1017|    278|      return true;
 1018|      0|    }
 1019|       |
 1020|    862|    case TUSB_REQ_SET_CONFIGURATION: {
  ------------------
  |  Branch (1020:5): [True: 862, False: 5.84k]
  ------------------
 1021|    862|      uint8_t const cfg_num = (uint8_t) p_request->wValue;
 1022|       |
 1023|       |      // Only process if new configure is different
 1024|    862|      if (_usbd_dev.cfg_num != cfg_num) {
  ------------------
  |  Branch (1024:11): [True: 213, False: 649]
  ------------------
 1025|    213|        if (_usbd_dev.cfg_num != 0) {
  ------------------
  |  Branch (1025:13): [True: 0, False: 213]
  ------------------
 1026|       |          // already configured: need to clear all endpoints and driver first
 1027|      0|          TU_LOG_USBD("  Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
 1028|       |
 1029|      0|          dcd_sof_enable(rhport, false);
 1030|      0|          dcd_edpt_close_all(rhport);
 1031|       |
 1032|       |          // close all drivers and current configured state except bus speed
 1033|      0|          const uint8_t speed = _usbd_dev.speed;
 1034|      0|          configuration_reset(rhport);
 1035|       |
 1036|      0|          _usbd_dev.speed = speed; // restore speed
 1037|      0|        }
 1038|       |
 1039|    213|        _usbd_dev.cfg_num = cfg_num;
 1040|       |
 1041|       |        // Handle the new configuration
 1042|    213|        if (cfg_num == 0) {
  ------------------
  |  Branch (1042:13): [True: 0, False: 213]
  ------------------
 1043|      0|          tud_umount_cb();
 1044|    213|        } else {
 1045|    213|          if (!process_set_config(rhport, cfg_num)) {
  ------------------
  |  Branch (1045:15): [True: 213, False: 0]
  ------------------
 1046|    213|            _usbd_dev.cfg_num = 0;
 1047|    213|            TU_ASSERT(false);
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|    213|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|    213|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 213, Folded]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1048|    213|          }
 1049|      0|          tud_mount_cb();
 1050|      0|        }
 1051|    213|      }
 1052|       |
 1053|    649|      tud_control_status(rhport, p_request);
 1054|    649|      return true;
 1055|    862|    }
 1056|       |
 1057|  2.21k|    case TUSB_REQ_GET_DESCRIPTOR:
  ------------------
  |  Branch (1057:5): [True: 2.21k, False: 4.49k]
  ------------------
 1058|  2.21k|      return process_get_descriptor(rhport, p_request);
 1059|       |
 1060|  1.06k|    case TUSB_REQ_SET_FEATURE:
  ------------------
  |  Branch (1060:5): [True: 1.06k, False: 5.64k]
  ------------------
 1061|  1.06k|      switch (p_request->wValue) { //-V2520
 1062|    823|        case TUSB_REQ_FEATURE_REMOTE_WAKEUP:
  ------------------
  |  Branch (1062:9): [True: 823, False: 241]
  ------------------
 1063|    823|          TU_LOG_USBD("    Enable Remote Wakeup\r\n");
 1064|       |          // Host may enable remote wake up before suspending especially HID device
 1065|    823|          _usbd_dev.remote_wakeup_en = 1;
 1066|    823|          tud_control_status(rhport, p_request);
 1067|    823|          return true;
 1068|       |
 1069|       |        #if CFG_TUD_TEST_MODE
 1070|       |        case TUSB_REQ_FEATURE_TEST_MODE: {
 1071|       |          // Only handle the test mode if supported and valid
 1072|       |          TU_VERIFY(0 == tu_u16_low(p_request->wIndex));
 1073|       |
 1074|       |          uint8_t const selector = tu_u16_high(p_request->wIndex);
 1075|       |          TU_VERIFY(TUSB_FEATURE_TEST_J <= selector && selector <= TUSB_FEATURE_TEST_FORCE_ENABLE);
 1076|       |
 1077|       |          _usbd_dev.ctrl_xfer.complete_cb = process_test_mode_cb;
 1078|       |          tud_control_status(rhport, p_request);
 1079|       |          return true;
 1080|       |        }
 1081|       |        #endif
 1082|       |
 1083|       |        // Stall unsupported feature selector
 1084|    241|        default: return false;
  ------------------
  |  Branch (1084:9): [True: 241, False: 823]
  ------------------
 1085|  1.06k|      }
 1086|       |
 1087|    892|    case TUSB_REQ_CLEAR_FEATURE:
  ------------------
  |  Branch (1087:5): [True: 892, False: 5.81k]
  ------------------
 1088|       |      // Only support remote wakeup for device feature
 1089|    892|      TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
  ------------------
  |  |   95|    892|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    892|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    892|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    892|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    892|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    892|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 235, False: 657]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    235|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    235|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    892|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 657]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1090|    657|      TU_LOG_USBD("    Disable Remote Wakeup\r\n");
 1091|       |
 1092|       |      // Host may disable remote wake up after resuming
 1093|    657|      _usbd_dev.remote_wakeup_en = 0;
 1094|    657|      tud_control_status(rhport, p_request);
 1095|    657|      return true;
 1096|       |
 1097|    775|    case TUSB_REQ_GET_STATUS: {
  ------------------
  |  Branch (1097:5): [True: 775, False: 5.93k]
  ------------------
 1098|       |      // Device status bit mask
 1099|       |      // - Bit 0: Self Powered TODO must invoke callback to get actual status
 1100|       |      // - Bit 1: Remote Wakeup enabled
 1101|    775|      return process_get_status(rhport, p_request, (uint16_t) _usbd_dev.dev_state_bm);
 1102|    892|    }
 1103|       |
 1104|    413|    default:
  ------------------
  |  Branch (1104:5): [True: 413, False: 6.29k]
  ------------------
 1105|    413|      TU_BREAKPOINT();
  ------------------
  |  |   77|    413|  #define TU_BREAKPOINT() do {} while (0)
  |  |  ------------------
  |  |  |  Branch (77:40): [Folded, False: 413]
  |  |  ------------------
  ------------------
 1106|       |      return false;
 1107|  6.70k|  }
 1108|  6.70k|}
usbd.c:process_set_config:
 1302|    213|static bool process_set_config(uint8_t rhport, uint8_t cfg_num) {
 1303|       |  // index is cfg_num-1
 1304|    213|  const tusb_desc_configuration_t *desc_cfg =
 1305|    213|    (const tusb_desc_configuration_t *)tud_descriptor_configuration_cb(cfg_num - 1);
 1306|    213|  TU_ASSERT(desc_cfg != NULL && desc_cfg->bDescriptorType == TUSB_DESC_CONFIGURATION);
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    426|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1307|       |
 1308|       |  // Parse configuration descriptor
 1309|    213|  _usbd_dev.self_powered = (desc_cfg->bmAttributes & TUSB_DESC_CONFIG_ATT_SELF_POWERED) ? 1u : 0u;
  ------------------
  |  Branch (1309:28): [True: 0, False: 213]
  ------------------
 1310|       |
 1311|       |  // Parse interface descriptor
 1312|    213|  const uint8_t *p_desc   = ((const uint8_t *)desc_cfg) + sizeof(tusb_desc_configuration_t);
 1313|    213|  const uint8_t *desc_end = ((const uint8_t *)desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
  ------------------
  |  |  253|    213|  #define tu_le16toh(u16) (u16)
  ------------------
 1314|       |
 1315|    213|  while (tu_desc_in_bounds(p_desc, desc_end)) {
  ------------------
  |  Branch (1315:10): [True: 213, False: 0]
  ------------------
 1316|       |    // Class will always start with Interface Association (if any) and then Interface descriptor
 1317|    213|    if (TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc)) {
  ------------------
  |  Branch (1317:9): [True: 0, False: 213]
  ------------------
 1318|      0|      p_desc = tu_desc_next(p_desc); // next to Interface
 1319|      0|      continue;
 1320|      0|    }
 1321|       |
 1322|    213|    TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc));
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1323|    213|    const tusb_desc_interface_t *desc_itf = (const tusb_desc_interface_t *)p_desc;
 1324|       |
 1325|       |    // Find driver for this interface
 1326|    213|    const uint16_t remaining_len = (uint16_t)(desc_end - p_desc);
 1327|    213|    uint8_t        drv_id;
 1328|    426|    for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) {
  ------------------
  |  |  369|    426|#define TOTAL_DRIVER_COUNT    ((uint8_t) (_app_driver_count + _builtin_driver_count))
  ------------------
  |  Branch (1328:22): [True: 213, False: 213]
  ------------------
 1329|    213|      const usbd_class_driver_t *driver = get_driver(drv_id);
 1330|    213|      TU_ASSERT(driver);
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1331|    213|      const uint16_t drv_len = driver->open(rhport, desc_itf, remaining_len);
 1332|       |
 1333|    213|      if ((sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len)) {
  ------------------
  |  Branch (1333:11): [True: 0, False: 213]
  |  Branch (1333:57): [True: 0, False: 0]
  ------------------
 1334|       |        // Open successfully
 1335|      0|        TU_LOG_USBD("  %s opened\r\n", driver->name);
 1336|       |
 1337|       |        // bind found driver to all interfaces and endpoint within drv_len
 1338|      0|        TU_ASSERT(tu_bind_driver_to_ep_itf(drv_id, _usbd_dev.ep2drv, _usbd_dev.itf2drv, CFG_TUD_INTERFACE_MAX,
  ------------------
  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|      0|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|      0|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|      0|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|      0|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|      0|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|      0|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1339|      0|                                           CFG_TUD_ENDPPOINT_MAX, p_desc, drv_len));
 1340|       |
 1341|      0|        p_desc += drv_len; // next Interface
 1342|      0|        break; // exit driver find loop
 1343|      0|      }
 1344|    213|    }
 1345|       |
 1346|       |    // Failed if there is no supported drivers
 1347|    213|    TU_ASSERT(drv_id < TOTAL_DRIVER_COUNT);
  ------------------
  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    213|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    213|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    213|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    213|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    213|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|    213|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|    213|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 213]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 213, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    213|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1348|    213|  }
 1349|       |
 1350|      0|  return true;
 1351|    213|}
usbd.c:process_get_descriptor:
 1354|  2.21k|static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request) {
 1355|  2.21k|  tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue);
 1356|  2.21k|  uint8_t const desc_index = tu_u16_low( p_request->wValue );
 1357|       |
 1358|  2.21k|  switch(desc_type) { //-V2520
 1359|    219|    case TUSB_DESC_DEVICE: {
  ------------------
  |  Branch (1359:5): [True: 219, False: 1.99k]
  ------------------
 1360|    219|      TU_LOG_USBD(" Device\r\n");
 1361|       |
 1362|    219|      void *desc_device = (void *)(uintptr_t)tud_descriptor_device_cb();
 1363|    219|      TU_ASSERT(desc_device);
  ------------------
  |  |  112|    219|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    219|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    219|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    219|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    219|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    219|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 219]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    219|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 219]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1364|       |
 1365|       |      // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has.
 1366|       |      // This only happens with the very first get device descriptor and EP0 size = 8 or 16.
 1367|    219|      if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed &&
  ------------------
  |  |   90|    219|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
  |  Branch (1367:11): [Folded, False: 219]
  |  Branch (1367:68): [True: 0, False: 0]
  ------------------
 1368|      0|          p_request->wLength > sizeof(tusb_desc_device_t)) {
  ------------------
  |  Branch (1368:11): [True: 0, False: 0]
  ------------------
 1369|       |        // Hack here: we modify the request length to prevent usbd_control response with zlp
 1370|       |        // since we are responding with 1 packet & less data than wLength.
 1371|      0|        ((tusb_control_request_t *)(uintptr_t)p_request)->wLength = CFG_TUD_ENDPOINT0_SIZE;
  ------------------
  |  |   90|      0|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
 1372|      0|        return tud_control_xfer(rhport, p_request, desc_device, CFG_TUD_ENDPOINT0_SIZE);
  ------------------
  |  |   90|      0|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
 1373|    219|      } else {
 1374|    219|        return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t));
 1375|    219|      }
 1376|    219|    }
 1377|       |    // break; // unreachable
 1378|       |
 1379|    231|    case TUSB_DESC_BOS: {
  ------------------
  |  Branch (1379:5): [True: 231, False: 1.98k]
  ------------------
 1380|    231|      TU_LOG_USBD(" BOS\r\n");
 1381|       |
 1382|       |      // requested by host if USB > 2.0 ( i.e 2.1 or 3.x )
 1383|    231|      uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb();
 1384|    231|      TU_VERIFY(desc_bos != 0);
  ------------------
  |  |   95|    231|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    231|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    231|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    231|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    231|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    231|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 231, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    231|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    231|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    231|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1385|       |
 1386|       |      // Use offsetof to avoid pointer to the odd/misaligned address
 1387|      0|      uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) );
  ------------------
  |  |  253|      0|  #define tu_le16toh(u16) (u16)
  ------------------
 1388|       |
 1389|      0|      return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len);
 1390|    231|    }
 1391|       |    // break; // unreachable
 1392|       |
 1393|    368|    case TUSB_DESC_CONFIGURATION:
  ------------------
  |  Branch (1393:5): [True: 368, False: 1.84k]
  ------------------
 1394|    564|    case TUSB_DESC_OTHER_SPEED_CONFIG: {
  ------------------
  |  Branch (1394:5): [True: 196, False: 2.01k]
  ------------------
 1395|    564|      uintptr_t desc_config;
 1396|       |
 1397|    564|      if ( desc_type == TUSB_DESC_CONFIGURATION ) {
  ------------------
  |  Branch (1397:12): [True: 368, False: 196]
  ------------------
 1398|    368|        TU_LOG_USBD(" Configuration[%u]\r\n", desc_index);
 1399|    368|        desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index);
 1400|    368|        TU_ASSERT(desc_config != 0);
  ------------------
  |  |  112|    368|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    368|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|    368|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|    368|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|    368|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|    368|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 368]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|    368|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 368]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1401|    368|      }else {
 1402|       |        // Host only request this after getting Device Qualifier descriptor
 1403|    196|        TU_LOG_USBD(" Other Speed Configuration\r\n");
 1404|    196|        desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index);
 1405|    196|        TU_VERIFY(desc_config != 0);
  ------------------
  |  |   95|    196|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    196|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    196|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    196|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    196|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    196|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 196, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    196|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    196|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    196|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1406|    196|      }
 1407|       |
 1408|       |      // Use offsetof to avoid pointer to the odd/misaligned address
 1409|    368|      uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) );
  ------------------
  |  |  253|    368|  #define tu_le16toh(u16) (u16)
  ------------------
 1410|       |
 1411|    368|      return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len);
 1412|    564|    }
 1413|       |    // break; // unreachable
 1414|       |
 1415|    771|    case TUSB_DESC_STRING: {
  ------------------
  |  Branch (1415:5): [True: 771, False: 1.44k]
  ------------------
 1416|    771|      TU_LOG_USBD(" String[%u]\r\n", desc_index);
 1417|       |
 1418|       |      // String Descriptor always uses the desc set from user
 1419|    771|      uint8_t const* desc_str = (uint8_t const*) tud_descriptor_string_cb(desc_index, p_request->wIndex);
 1420|    771|      TU_VERIFY(desc_str);
  ------------------
  |  |   95|    771|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    771|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    771|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    771|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    771|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    771|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 218, False: 553]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    218|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    218|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    771|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 553]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1421|       |
 1422|       |      // first byte of descriptor is its size
 1423|    553|      return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str));
 1424|    771|    }
 1425|       |    // break; // unreachable
 1426|       |
 1427|    194|    case TUSB_DESC_DEVICE_QUALIFIER: {
  ------------------
  |  Branch (1427:5): [True: 194, False: 2.02k]
  ------------------
 1428|    194|      TU_LOG_USBD(" Device Qualifier\r\n");
 1429|    194|      uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb();
 1430|    194|      TU_VERIFY(desc_qualifier);
  ------------------
  |  |   95|    194|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|    194|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    194|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|    194|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|    194|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|    194|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 194, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    194|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    194|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|    194|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1431|      0|      return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier));
 1432|    194|    }
 1433|       |    // break; // unreachable
 1434|       |
 1435|    235|    default: return false;
  ------------------
  |  Branch (1435:5): [True: 235, False: 1.97k]
  ------------------
 1436|  2.21k|  }
 1437|  2.21k|}
usbd.c:process_get_status:
 1114|  1.56k|static bool process_get_status(uint8_t rhport, tusb_control_request_t const * request, uint16_t status) {
 1115|  1.56k|  TU_VERIFY(request->bmRequestType_bit.direction == TUSB_DIR_IN);
  ------------------
  |  |   95|  1.56k|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  1.56k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|  1.56k|#define TU_VERIFY(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |   92|  1.56k|#define TU_VERIFY_1ARGS(_cond)         TU_VERIFY_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   86|  1.56k|  do {                                \
  |  |  |  |  |  |  |  |  |  |   87|  1.56k|    if (!(_cond)) {                   \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (87:9): [True: 722, False: 846]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |   88|    722|      return _ret;                    \
  |  |  |  |  |  |  |  |  |  |   89|    722|    }                                 \
  |  |  |  |  |  |  |  |  |  |   90|  1.56k|  } while (0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (90:12): [Folded, False: 846]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1116|    846|  return tud_control_xfer(rhport, request, &status, 2);
 1117|  1.56k|}
usbd.c:queue_event:
  416|  30.0k|TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, bool in_isr) {
  417|  30.0k|  TU_ASSERT(osal_queue_send(_usbd_q, event, in_isr));
  ------------------
  |  |  112|  30.0k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  30.0k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  30.0k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|  30.0k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  30.0k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  30.0k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 30.0k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  30.0k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 30.0k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  418|  30.0k|  tud_event_hook_cb(event->rhport, event->event_id, in_isr);
  419|       |  return true;
  420|  30.0k|}

fuzz.cc:_ZL8tud_taskv:
   76|  43.8k|void tud_task (void) {
   77|       |  tud_task_ext(UINT32_MAX, false);
   78|  43.8k|}

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

tusb_rhport_init:
   65|  1.01k|bool tusb_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
   66|       |  //  backward compatible called with tusb_init(void)
   67|       |  #if defined(TUD_OPT_RHPORT) || defined(TUH_OPT_RHPORT)
   68|       |  if (rh_init == NULL) {
   69|       |    #if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT)
   70|       |    // init device stack CFG_TUSB_RHPORTx_MODE must be defined
   71|       |    const tusb_rhport_init_t dev_init = {
   72|       |      .role = TUSB_ROLE_DEVICE,
   73|       |      .speed = TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL
   74|       |    };
   75|       |    TU_ASSERT ( tud_rhport_init(TUD_OPT_RHPORT, &dev_init) );
   76|       |    _tusb_rhport_role[TUD_OPT_RHPORT] = TUSB_ROLE_DEVICE;
   77|       |    #endif
   78|       |
   79|       |    #if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT)
   80|       |    // init host stack CFG_TUSB_RHPORTx_MODE must be defined
   81|       |    const tusb_rhport_init_t host_init = {
   82|       |      .role = TUSB_ROLE_HOST,
   83|       |      .speed = TUH_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL
   84|       |    };
   85|       |    TU_ASSERT( tuh_rhport_init(TUH_OPT_RHPORT, &host_init) );
   86|       |    _tusb_rhport_role[TUH_OPT_RHPORT] = TUSB_ROLE_HOST;
   87|       |    #endif
   88|       |
   89|       |    return true;
   90|       |  }
   91|       |  #endif
   92|       |
   93|       |  // new API with explicit rhport and role
   94|  1.01k|  TU_ASSERT(rhport < TUP_USBIP_CONTROLLER_NUM && rh_init->role != TUSB_ROLE_INVALID);
  ------------------
  |  |  112|  1.01k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  1.01k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  1.01k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|  1.01k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  1.01k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  2.03k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 1.01k, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:12): [True: 1.01k, False: 0]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  1.01k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1.01k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   95|  1.01k|  _tusb_rhport_role[rhport] = rh_init->role;
   96|       |
   97|  1.01k|  #if CFG_TUD_ENABLED
   98|  1.01k|  if (rh_init->role == TUSB_ROLE_DEVICE) {
  ------------------
  |  Branch (98:7): [True: 1.01k, False: 0]
  ------------------
   99|  1.01k|    TU_ASSERT(tud_rhport_init(rhport, rh_init));
  ------------------
  |  |  112|  1.01k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  ------------------
  |  |  |  |  112|  1.01k|#define TU_GET_3RD_ARG(arg1, arg2, arg3, ...)        arg3
  |  |  |  |  ------------------
  |  |  |  |  |  |  112|  1.01k|#define TU_ASSERT(...)                 TU_GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__)
  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  108|  1.01k|#define TU_ASSERT_1ARGS(_cond)         TU_ASSERT_DEFINE(_cond, false)
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  104|  1.01k|  do {                                                                \
  |  |  |  |  |  |  |  |  |  |  105|  1.01k|    if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   54|      0|  #define TU_MESS_FAILED() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (54:41): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |                   if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |   77|      0|  #define TU_BREAKPOINT() do {} while (0)
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  |  |  Branch (77:40): [Folded, False: 0]
  |  |  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (105:10): [True: 0, False: 1.01k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  106|  1.01k|  } while(0)
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  |  |  |  Branch (106:11): [Folded, False: 1.01k]
  |  |  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  |  |  ------------------
  |  |  |  |  |  |  ------------------
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  100|  1.01k|  }
  101|  1.01k|  #endif
  102|       |
  103|       |  #if CFG_TUH_ENABLED
  104|       |  if (rh_init->role == TUSB_ROLE_HOST) {
  105|       |    TU_ASSERT(tuh_rhport_init(rhport, rh_init));
  106|       |  }
  107|       |  #endif
  108|       |
  109|  1.01k|  return true;
  110|  1.01k|}

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|  43.8k|void dcd_int_handler(uint8_t rhport) {
   56|  43.8k|  assert(_fuzz_data_provider.has_value());
  ------------------
  |  Branch (56:3): [True: 43.8k, False: 0]
  ------------------
   57|       |
   58|  43.8k|  if (!state.interrupts_enabled) {
  ------------------
  |  Branch (58:7): [True: 0, False: 43.8k]
  ------------------
   59|      0|    return;
   60|      0|  }
   61|       |
   62|       |  // Choose if we want to generate a signal based on the fuzzed data.
   63|  43.8k|  if (_fuzz_data_provider->ConsumeBool()) {
  ------------------
  |  Branch (63:7): [True: 9.22k, False: 34.6k]
  ------------------
   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|  9.22k|    static const dcd_eventid_t bus_signal_events[] = {
   69|  9.22k|        DCD_EVENT_UNPLUGGED, DCD_EVENT_SUSPEND, DCD_EVENT_RESUME};
   70|  9.22k|    uint8_t idx = _fuzz_data_provider->ConsumeIntegralInRange<uint8_t>(0, 2);
   71|  9.22k|    dcd_event_bus_signal(rhport, bus_signal_events[idx],
   72|  9.22k|                         _fuzz_data_provider->ConsumeBool());
   73|  9.22k|  }
   74|       |
   75|       |  // Optionally generate a BUS_RESET event with a valid speed value.
   76|  43.8k|  if (_fuzz_data_provider->ConsumeBool()) {
  ------------------
  |  Branch (76:7): [True: 7.72k, False: 36.1k]
  ------------------
   77|  7.72k|    tusb_speed_t speed = (tusb_speed_t)_fuzz_data_provider->ConsumeIntegralInRange<uint8_t>(
   78|  7.72k|        TUSB_SPEED_FULL, TUSB_SPEED_HIGH);
   79|  7.72k|    dcd_event_bus_reset(rhport, speed, _fuzz_data_provider->ConsumeBool());
   80|  7.72k|  }
   81|       |
   82|  43.8k|  if (_fuzz_data_provider->ConsumeBool()) {
  ------------------
  |  Branch (82:7): [True: 15.5k, False: 28.3k]
  ------------------
   83|  15.5k|    constexpr size_t kSetupFrameLength = 8;
   84|  15.5k|    std::vector<uint8_t> setup =
   85|  15.5k|        _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|  15.5k|    if (setup.size() != kSetupFrameLength) {
  ------------------
  |  Branch (89:9): [True: 434, False: 15.1k]
  ------------------
   90|    434|      setup.resize(kSetupFrameLength);
   91|    434|    }
   92|  15.5k|    dcd_event_setup_received(rhport, setup.data(),
   93|       |                             // Identify trigger as either an interrupt or a
   94|       |                             // syncrhonous call depending on fuzz data.
   95|  15.5k|                             _fuzz_data_provider->ConsumeBool());
   96|  15.5k|  }
   97|  43.8k|}
dcd_int_enable:
   99|  88.5k|void dcd_int_enable(uint8_t rhport) {
  100|  88.5k|  state.interrupts_enabled = true;
  101|  88.5k|  UNUSED(rhport);
  ------------------
  |  |   31|  88.5k|#define UNUSED(x) (void)(x)
  ------------------
  102|  88.5k|  return;
  103|  88.5k|}
dcd_int_disable:
  105|  88.5k|void dcd_int_disable(uint8_t rhport) {
  106|  88.5k|  state.interrupts_enabled = false;
  107|  88.5k|  UNUSED(rhport);
  ------------------
  |  |   31|  88.5k|#define UNUSED(x) (void)(x)
  ------------------
  108|  88.5k|  return;
  109|  88.5k|}
dcd_set_address:
  111|    207|void dcd_set_address(uint8_t rhport, uint8_t dev_addr) {
  112|    207|  UNUSED(rhport);
  ------------------
  |  |   31|    207|#define UNUSED(x) (void)(x)
  ------------------
  113|    207|  state.address = dev_addr;
  114|       |  // Respond with status.
  115|       |  dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0, false);
  116|    207|  return;
  117|    207|}
dcd_edpt_xfer:
  171|  4.60k|                   uint16_t total_bytes, bool is_isr) {
  172|  4.60k|  UNUSED(rhport);
  ------------------
  |  |   31|  4.60k|#define UNUSED(x) (void)(x)
  ------------------
  173|  4.60k|  UNUSED(buffer);
  ------------------
  |  |   31|  4.60k|#define UNUSED(x) (void)(x)
  ------------------
  174|  4.60k|  UNUSED(total_bytes);
  ------------------
  |  |   31|  4.60k|#define UNUSED(x) (void)(x)
  ------------------
  175|  4.60k|  UNUSED(is_isr);
  ------------------
  |  |   31|  4.60k|#define UNUSED(x) (void)(x)
  ------------------
  176|       |
  177|  4.60k|  uint8_t const dir = tu_edpt_dir(ep_addr);
  178|       |
  179|  4.60k|  if (dir == TUSB_DIR_IN) {
  ------------------
  |  Branch (179:7): [True: 3.36k, False: 1.23k]
  ------------------
  180|  3.36k|    std::vector<uint8_t> temp =
  181|  3.36k|        _fuzz_data_provider->ConsumeBytes<uint8_t>(total_bytes);
  182|  3.36k|    std::copy(temp.begin(), temp.end(), buffer);
  183|  3.36k|  }
  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|  4.60k|  volatile uint8_t *dont_optimise0 = buffer;
  188|  4.60k|  volatile uint16_t dont_optimise1 = total_bytes;
  189|  4.60k|  UNUSED(dont_optimise0);
  ------------------
  |  |   31|  4.60k|#define UNUSED(x) (void)(x)
  ------------------
  190|  4.60k|  UNUSED(dont_optimise1);
  ------------------
  |  |   31|  4.60k|#define UNUSED(x) (void)(x)
  ------------------
  191|       |
  192|       |
  193|  4.60k|  return _fuzz_data_provider->ConsumeBool();
  194|  4.60k|}
dcd_edpt_stall:
  202|  16.7k|void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) {
  203|       |
  204|  16.7k|  UNUSED(rhport);
  ------------------
  |  |   31|  16.7k|#define UNUSED(x) (void)(x)
  ------------------
  205|  16.7k|  UNUSED(ep_addr);
  ------------------
  |  |   31|  16.7k|#define UNUSED(x) (void)(x)
  ------------------
  206|  16.7k|  return;
  207|  16.7k|}

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

tud_descriptor_device_cb:
   46|    219|uint8_t const *tud_descriptor_device_cb(void) {
   47|    219|  tu_static tusb_desc_device_t const desc_device = {
  ------------------
  |  |   39|    219|  #define tu_static static __thread
  ------------------
   48|    219|      .bLength = sizeof(tusb_desc_device_t),
   49|    219|      .bDescriptorType = TUSB_DESC_DEVICE,
   50|    219|      .bcdUSB = USB_BCD,
  ------------------
  |  |   38|    219|#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|    219|      .bDeviceClass = TUSB_CLASS_MISC,
   56|    219|      .bDeviceSubClass = MISC_SUBCLASS_COMMON,
   57|    219|      .bDeviceProtocol = MISC_PROTOCOL_IAD,
   58|       |
   59|    219|      .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
  ------------------
  |  |   90|    219|#define CFG_TUD_ENDPOINT0_SIZE    64
  ------------------
   60|       |
   61|    219|      .idVendor = USB_VID,
  ------------------
  |  |   37|    219|#define USB_VID 0xCafe
  ------------------
   62|    219|      .idProduct = USB_PID,
  ------------------
  |  |   35|    219|  (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) |          \
  |  |  ------------------
  |  |  |  |   33|    219|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   95|    219|#define CFG_TUD_MSC              1
  |  |  |  |  ------------------
  |  |  ------------------
  |  |                 (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) |          \
  |  |  ------------------
  |  |  |  |   33|    219|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   96|    219|#define CFG_TUD_HID              0
  |  |  |  |  ------------------
  |  |  ------------------
  |  |                 (0x4000 | PID_MAP(MSC, 0) | PID_MAP(HID, 1) | PID_MAP(MIDI, 2) |          \
  |  |  ------------------
  |  |  |  |   33|    219|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   97|    219|#define CFG_TUD_MIDI             0
  |  |  |  |  ------------------
  |  |  ------------------
  |  |   36|    219|   PID_MAP(VENDOR, 3))
  |  |  ------------------
  |  |  |  |   33|    219|#define PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
  |  |  |  |  ------------------
  |  |  |  |  |  |   98|    219|#define CFG_TUD_VENDOR           0
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
   63|    219|      .bcdDevice = 0x0100,
   64|       |
   65|    219|      .iManufacturer = 0x01,
   66|    219|      .iProduct = 0x02,
   67|    219|      .iSerialNumber = 0x03,
   68|       |
   69|    219|      .bNumConfigurations = 0x01};
   70|       |
   71|    219|  return (uint8_t const *)&desc_device;
   72|    219|}
tud_descriptor_configuration_cb:
  161|    581|uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
  162|    581|  (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|    581|  return desc_fs_configuration;
  170|    581|#endif
  171|    581|}
tud_descriptor_string_cb:
  192|    771|uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
  193|    771|  (void)langid;
  194|       |
  195|    771|  uint8_t chr_count;
  196|       |
  197|    771|  if (index == 0) {
  ------------------
  |  Branch (197:7): [True: 250, False: 521]
  ------------------
  198|    250|    memcpy(&_desc_str[1], string_desc_arr[0], 2);
  199|    250|    chr_count = 1;
  200|    521|  } 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|    521|    if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])))
  ------------------
  |  Branch (204:9): [True: 218, False: 303]
  ------------------
  205|    218|      return NULL;
  206|       |
  207|    303|    const char *str = string_desc_arr[index];
  208|       |
  209|       |    // Cap at max char
  210|    303|    chr_count = (uint8_t)strlen(str);
  211|    303|    if (chr_count > 31)
  ------------------
  |  Branch (211:9): [True: 0, False: 303]
  ------------------
  212|      0|      chr_count = 31;
  213|       |
  214|       |    // Convert ASCII string into UTF-16
  215|  4.42k|    for (uint8_t i = 0; i < chr_count; i++) {
  ------------------
  |  Branch (215:25): [True: 4.12k, False: 303]
  ------------------
  216|  4.12k|      _desc_str[1 + i] = str[i];
  217|  4.12k|    }
  218|    303|  }
  219|       |
  220|       |  // first byte is length (including header), second byte is string type
  221|    553|  _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
  222|       |
  223|    553|  return _desc_str;
  224|    771|}

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

