3737//--------------------------------------------------------------------+
3838// MACRO CONSTANT TYPEDEF
3939//--------------------------------------------------------------------+
40+ #define VS_STATE_PROBING 0 /* Configuration in progress */
41+ #define VS_STATE_COMMITTED 1 /* Ready for streaming or Streaming via bulk endpoint */
42+ #define VS_STATE_STREAMING 2 /* Streaming via isochronous endpoint */
43+
4044typedef struct {
4145 tusb_desc_interface_t std ;
4246 tusb_desc_cs_video_ctl_itf_hdr_t ctl ;
@@ -102,6 +106,7 @@ typedef struct TU_ATTR_PACKED {
102106 uint32_t offset ; /* offset for the next payload transfer */
103107 uint32_t max_payload_transfer_size ;
104108 uint8_t error_code ;/* error code */
109+ uint8_t state ; /* 0:probing 1:committed 2:streaming */
105110 /*------------- From this point, data is not cleared by bus reset -------------*/
106111 CFG_TUSB_MEM_ALIGN uint8_t ep_buf [CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE ]; /* EP transfer buffer for streaming */
107112} videod_streaming_interface_t ;
@@ -639,6 +644,17 @@ static bool _open_vc_itf(uint8_t rhport, videod_interface_t *self, uint_fast8_t
639644 return true;
640645}
641646
647+ static bool _init_vs_configuration (videod_streaming_interface_t * stm )
648+ {
649+ /* initialize streaming settings */
650+ stm -> state = VS_STATE_PROBING ;
651+ stm -> max_payload_transfer_size = 0 ;
652+ video_probe_and_commit_control_t * param =
653+ (video_probe_and_commit_control_t * )& stm -> ep_buf ;
654+ tu_memclr (param , sizeof (* param ));
655+ return _update_streaming_parameters (stm , param );
656+ }
657+
642658/** Set the alternate setting to own video streaming interface.
643659 *
644660 * @param[in,out] stm Streaming interface context.
@@ -672,43 +688,32 @@ static bool _open_vs_itf(uint8_t rhport, videod_streaming_interface_t *stm, uint
672688
673689 uint_fast8_t numeps = ((tusb_desc_interface_t const * )cur )-> bNumEndpoints ;
674690 TU_ASSERT (numeps <= TU_ARRAY_SIZE (stm -> desc .ep ));
675- stm -> desc .cur = (uint16_t ) (cur - desc ); /* Save the offset of the new settings */
676- if (!altnum ) {
677- /* initialize streaming settings */
678- stm -> max_payload_transfer_size = 0 ;
679- video_probe_and_commit_control_t * param =
680- (video_probe_and_commit_control_t * )& stm -> ep_buf ;
681- tu_memclr (param , sizeof (* param ));
682- TU_LOG2 (" done 0\n" );
683- if (!_update_streaming_parameters (stm , param ))
684- return false;
685- /* Open bulk endpoint if present. */
686- for (i = 0 , cur = tu_desc_next (cur ); i < numeps ; ++ i , cur = tu_desc_next (cur )) {
687- cur = _find_desc_ep (cur , end );
688- TU_ASSERT (cur < end );
689- tusb_desc_endpoint_t const * ep = (tusb_desc_endpoint_t const * )cur ;
690- TU_VERIFY (TUSB_XFER_BULK == ep -> bmAttributes .xfer );
691- TU_ASSERT (usbd_edpt_open (rhport , ep ));
692- stm -> desc .ep [i ] = (uint16_t )(cur - desc );
693- TU_LOG2 (" open EP%02x\n" , _desc_ep_addr (cur ));
694- }
695- return true;
691+ stm -> desc .cur = (uint16_t )(cur - desc ); /* Save the offset of the new settings */
692+ if (!altnum && (VS_STATE_COMMITTED != stm -> state )) {
693+ TU_VERIFY (_init_vs_configuration (stm ));
696694 }
697- /* Open isochronous endpoints of the new settings. */
695+ /* Open bulk or isochronous endpoints of the new settings. */
698696 for (i = 0 , cur = tu_desc_next (cur ); i < numeps ; ++ i , cur = tu_desc_next (cur )) {
699697 cur = _find_desc_ep (cur , end );
700698 TU_ASSERT (cur < end );
701699 tusb_desc_endpoint_t const * ep = (tusb_desc_endpoint_t const * )cur ;
702700 uint_fast32_t max_size = stm -> max_payload_transfer_size ;
703- if ((TUSB_XFER_ISOCHRONOUS == ep -> bmAttributes .xfer ) &&
704- (tu_edpt_packet_size (ep ) < max_size )) {
705- /* FS must be less than or equal to max packet size */
706- return false;
701+ if (altnum ) {
702+ if ((TUSB_XFER_ISOCHRONOUS == ep -> bmAttributes .xfer ) &&
703+ (tu_edpt_packet_size (ep ) < max_size )) {
704+ /* FS must be less than or equal to max packet size */
705+ return false;
706+ }
707+ } else {
708+ TU_VERIFY (TUSB_XFER_BULK == ep -> bmAttributes .xfer );
707709 }
708710 TU_ASSERT (usbd_edpt_open (rhport , ep ));
709711 stm -> desc .ep [i ] = (uint16_t ) (cur - desc );
710712 TU_LOG2 (" open EP%02x\n" , _desc_ep_addr (cur ));
711713 }
714+ if (altnum ) {
715+ stm -> state = VS_STATE_STREAMING ;
716+ }
712717 TU_LOG2 (" done\n" );
713718 return true;
714719}
@@ -921,6 +926,10 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
921926 break ;
922927
923928 case VIDEO_VS_CTL_PROBE :
929+ if (self -> state != VS_STATE_PROBING ) {
930+ self -> state = VS_STATE_PROBING ;
931+ _init_vs_configuration (self );
932+ }
924933 switch (request -> bRequest ) {
925934 case VIDEO_REQUEST_SET_CUR :
926935 if (stage == CONTROL_STAGE_SETUP ) {
@@ -992,6 +1001,10 @@ static int handle_video_stm_cs_req(uint8_t rhport, uint8_t stage,
9921001 ret = tud_video_commit_cb (self -> index_vc , self -> index_vs , param );
9931002 }
9941003 if (VIDEO_ERROR_NONE == ret ) {
1004+ self -> state = VS_STATE_COMMITTED ;
1005+ self -> buffer = NULL ;
1006+ self -> bufsize = 0 ;
1007+ self -> offset = 0 ;
9951008 /* initialize payload header */
9961009 tusb_video_payload_header_t * hdr = (tusb_video_payload_header_t * )self -> ep_buf ;
9971010 hdr -> bHeaderLength = sizeof (* hdr );
@@ -1080,6 +1093,7 @@ bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
10801093 TU_ASSERT (stm_idx < CFG_TUD_VIDEO_STREAMING );
10811094 videod_streaming_interface_t * stm = _get_instance_streaming (ctl_idx , stm_idx );
10821095 if (!stm || !stm -> desc .ep [0 ]) return false;
1096+ if (stm -> state == VS_STATE_PROBING ) return false;
10831097 return true;
10841098}
10851099
@@ -1090,6 +1104,7 @@ bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *bu
10901104 if (!buffer || !bufsize ) return false;
10911105 videod_streaming_interface_t * stm = _get_instance_streaming (ctl_idx , stm_idx );
10921106 if (!stm || !stm -> desc .ep [0 ] || stm -> buffer ) return false;
1107+ if (stm -> state == VS_STATE_PROBING ) return false;
10931108
10941109 /* Find EP address */
10951110 uint8_t const * desc = _videod_itf [stm -> index_vc ].beg ;
@@ -1185,6 +1200,7 @@ uint16_t videod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin
11851200 stm -> desc .beg = (uint16_t ) ((uintptr_t )cur - (uintptr_t )itf_desc );
11861201 cur = _next_desc_itf (cur , end );
11871202 stm -> desc .end = (uint16_t ) ((uintptr_t )cur - (uintptr_t )itf_desc );
1203+ stm -> state = VS_STATE_PROBING ;
11881204 if (0 == stm_idx && 1 == bInCollection ) {
11891205 /* If there is only one streaming interface and no alternate settings,
11901206 * host may not issue set_interface so open the streaming interface here. */
0 commit comments