cancel
Showing results for 
Search instead for 
Did you mean: 

Please help me !! Problems with IsocReceiveData

linh nguyen
Associate II
Posted on May 26, 2017 at 10:59

I am developing a UVC Host FULL Speed Driver in Kit STM32F4 Discovery .

I brought up Webcam and it streaming data.

But when I receive data from

Isochronos Endpoint

My source :

USBH_IsocReceiveData(phost,imgBuffer,EpOutSize,pipe_out_uvc);

 uint32_t time_count = phost->Timer;

while (1){

   URB_Status = USBH_LL_GetURBState(phost,pipe_out_uvc);

   if (USBH_URB_DONE == URB_Status && phost->Timer-time_count > tbInterval_stream){

      time_count = phost->Timer;

      uint32_t

Xfer_

len =USBH_LL_GetLastXferSize (phost, pipe_out_uvc);

      if(

Xfer_len

){

         USBH_UsrLog('[DEBUG]==========>header size : %d',*imgBuffer);   

      }

   }

}

I received event

USBH_URB_DONE

but

Xfer_len always 

equal 0 and nothing in

imgBuffer

.

Please help me fix my problem. Thanks you so much !!!

I using lib usb in STM32Cube FW_F4 V1.16.0

#usb #isochronos-endpoint #isochronos #isocreceivedata #stm32f4-discovery
12 REPLIES 12
dirk.frerichs
Associate II
Posted on August 15, 2017 at 10:15

show your complete initialisation...

probe get

probe set

commit set

set interface ( with correct alternate setting !! )

why are you using while() loop?

you can use the original example code from ST to usw several states.

    switch (pVideo->StreamState){

        case VIDEO_STREAM_PROBE_SET:        

            break;

       

        case VIDEO_STREAM_PROBE_GET:

            break;

        case VIDEO_STREAM_COMMIT_SET:

            break;

        case VIDEO_STREAM_SET_INTERFACE:

            break;

        case VIDEO_STREAM_START:

            USBH_IsocReceiveData( phost ,

                DMA_USBH_Buffer ,

                pVideo->EpVideoStream.wMaxPacketSize ,

                pVideo->EpVideoStream.bPipe );

            pVideo->StreamState         = VIDEO_STREAM_PLAY;

            osMessagePut ( phost->os_event, USBH_CLASS_EVENT ,pVideo->EpVideoStream.bInterval);

            break;

        case VIDEO_STREAM_PLAY:

            if((phost->Timer-pVideo->EpVideoStream.wTimer) >= pVideo->EpVideoStream.bInterval){

                pVideo->EpVideoStream.wTimer = phost->Timer;

                USBH_URBStateTypeDef urb_state =  USBH_LL_GetURBState(phost , pVideo->EpVideoStream.bPipe);

                switch( urb_state ){

                    case USBH_URB_DONE:

                        HandleReceivedFrame(     phost,

                                                pVideo ,

                                                DMA_USBH_Buffer,

                                                USBH_LL_GetLastXferSize(phost, pVideo->EpVideoStream.bPipe ));

                        USBH_IsocReceiveData( phost ,

                            DMA_USBH_Buffer,

                            pVideo->EpVideoStream.wMaxPacketSize,

                            pVideo->EpVideoStream.bPipe );

                        break;

                    case USBH_URB_IDLE:

                    case USBH_URB_NOTREADY:

                    case USBH_URB_NYET:

                    case USBH_URB_ERROR:

                    case USBH_URB_STALL:

                    default:

                        break;

                }

            }else{

                osMessagePut ( phost->os_event, USBH_CLASS_EVENT,  pVideo->EpVideoStream.bInterval );

             }

            break;

        default:

            break;

    }

if alternate settings and interface is correct, then you receive data from camera.

Posted on July 03, 2018 at 22:18

Hey! I am in a similar situation, I am writing a UVC class driver for a STM32F769 Discovery board. I'm doing the stream negociation in this way : probe set -> probe get -> commit set. I then set an alternate interface for the video streaming interface and up to there everything works just fine. I've checked the values returned in the probe get phase and they are coherent. The LED on the webcam turns on (which seems to be a good indicator that the webcam is recording) but when I perform a 

USBH_IsocReceiveData() the value returned by 

USBH_LL_GetURBState is always USBH_URB_IDLE. This leads me to think that the webcam is not outputting video data. Do you have any idea on how I could make some progress on this ? 

What does the DMA_USBH_Buffer parameter mean in the USBH_IsocReceiveData() function ? 

I attached the code of my class driver. The stream negotiation is done in the USBH_CAM_NegociateRequests() function

the USBH_CAM_Process() function is the main state machine of the driver and the USBH_IsocReceiveData is done there. 

Also by reverse engineering the webcam with an USB protocol analyser I noticed that the Windows driver managed the stream in a completely different way (using the vendor specific extension units) would it be possible to access the probe and commit controls? Does a webcam have to implement these controls (probe commit) to be compliant to the UVC class? 

You seem to know your way around this and I would be really grateful if you could provide me with some info. 

Best regards

Colin Cina

Attached code : 

=============

USBH_StatusTypeDef USBH_CAM_NegociateRequests(USBH_HandleTypeDef* phost, CAM_HandleTypeDef* CAM_Handle)

{

USBH_StatusTypeDef testStatus = USBH_BUSY;

USBH_StatusTypeDef status = USBH_BUSY;

switch(CAM_Handle->streamNeg_state)

{

case CAM_REQ_STREAM_INIT:

CAM_Handle->streamNeg_state = CAM_REQ_SET_PROBE;

break;

case CAM_REQ_SET_PROBE:

initProbeSet(&(CAM_Handle->probeSet));

CAM_Handle->streamNeg_state = CAM_REQ_SET_PROBE_WAIT;

break;

case CAM_REQ_SET_PROBE_WAIT:

//SET_CUR request [probe] with the probe control data structure

if(USBH_CSRequest(phost, USB_REQ_SET_CUR, VS_PROBE_CONTROL, VS_INTERFACE) == USBH_OK)

{

CAM_Handle->streamNeg_state = CAM_REQ_GET_PROBE;

}

break;

case CAM_REQ_GET_PROBE:

//GET_CUR request [probe] -> store the probe control data received

if(USBH_CSRequest(phost, USB_REQ_GET_CUR, VS_PROBE_CONTROL, VS_INTERFACE) == USBH_OK)

{

CAM_Handle->streamNeg_state = CAM_REQ_SET_COMMIT;

}

break;

case CAM_REQ_SET_COMMIT:

//SET_CUR request [commit] with the data read back from the GET_CUR request

//Compare the two videoProbe data structure and set the definitive version to the probe commit terminal

memcpy(CAM_Handle->probeSet.data, phost->device.Data, 26);

CAM_Handle->streamNeg_state = CAM_REQ_SET_COMMIT_WAIT;

break;

case CAM_REQ_SET_COMMIT_WAIT:

testStatus = USBH_CSRequest(phost, USB_REQ_SET_CUR, VS_COMMIT_CONTROL, VS_INTERFACE);

if(testStatus == USBH_OK)

{

CAM_Handle->streamNeg_state = CAM_REQ_SET_INTERFACE;

}

break;

case CAM_REQ_SET_INTERFACE:

//select an aternate setting for the interface based on the MaxPayloadTransferSize received in the GET_CUR

CAM_Handle->stream_altSetting = setAppropriateInterface(phost, CAM_Handle->probeSet.params.dwMaxPayloadTransferSize);

CAM_Handle->stream_interface = USBH_FindInterfaceIndex(phost, 0x01, CAM_Handle->stream_altSetting); //1 stands for the video streaming interface number

if(CAM_Handle->stream_interface != 0xFF)

{

if(USBH_SelectInterface(phost, CAM_Handle->stream_interface) == USBH_OK)

{

CAM_Handle->streamNeg_state = CAM_REQ_SET_INTERFACE_WAIT;

}

}

break;

case CAM_REQ_SET_INTERFACE_WAIT:

if(USBH_SetInterface(phost, 0x01, CAM_Handle->stream_altSetting) == USBH_OK)

{

//allow the host process state machine to move on the the HOST_CLASS state from where the bgnd function is gonna be called

status = USBH_OK;

CAM_Handle->ctl_state = CAM_REQ_IDLE;

}

break;

default:

break;

}

   return status;

}

USBH_StatusTypeDef USBH_CAM_Process(USBH_HandleTypeDef *phost)

{

USBH_StatusTypeDef status = USBH_OK;

USBH_URBStateTypeDef urbStatus = USBH_URB_IDLE;

CAM_HandleTypeDef *CAM_Handle = (CAM_HandleTypeDef *) phost->pActiveClass->pData;

switch (CAM_Handle->state)

{

case CAM_INIT:

CAM_Handle->state = CAM_CONFIG;

break;

case CAM_IDLE:

break;

case CAM_CONFIG:

if(configureDevice(phost, CAM_Handle) == USBH_OK)

{

CAM_Handle->state = CAM_IDLE;

}

break;

case CAM_POLL:

if(USBH_LL_GetURBState(phost , CAM_Handle->interruptPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */

{

/* Issue Clear Feature on interrupt IN endpoint */

if(USBH_ClrFeature(phost, CAM_Handle->interruptEp_addr) == USBH_OK)

{

/* Change state to issue next IN token */

CAM_Handle->state = CAM_HANDLE_INT;

}

}

break;

case CAM_HANDLE_INT:

if(USBH_InterruptReceiveData(phost, CAM_Handle->interruptDataBuffer, CAM_Handle->interruptLength, CAM_Handle->interruptPipe) == USBH_OK){

CAM_Handle->state = CAM_CONFIG;

}

break;

case CAM_GET_STREAM_START:

if((phost->Timer & 1) == 0)

{

CAM_Handle->timer = phost->Timer;

CAM_Handle->state = CAM_GET_STREAM;

USBH_IsocReceiveData(phost, CAM_Handle->pImgData, CAM_Handle->streamLength, CAM_Handle->streamPipe);

}

break;

case CAM_GET_STREAM:

urbStatus = USBH_LL_GetURBState(phost, CAM_Handle->streamPipe);

if((urbStatus == USBH_URB_DONE) && (( phost->Timer - CAM_Handle->timer) >= CAM_Handle->streamPoll))

{

uint32_t rx_size = USBH_LL_GetLastXferSize(phost, CAM_Handle->streamPipe);

CAM_Handle->timer = phost->Timer;

CAM_Handle->state = CAM_IDLE;

}

break;

case CAM_ERROR:

break;

default:

break;

}

return status;

}
dirk.frerichs
Associate II
Posted on July 04, 2018 at 08:52

hi 

i had some trouble in the past with isochronous transfer.

the original library doesn't support this mode.

https://community.st.com/0D50X00009XkdyKSAR

 

did you fix it?

try this first.

uint8_t             DMA_USBH_Buffer[ USB_MAX_ENDPOINT_SIZE] ;

//this is the data receive buffer

Posted on July 06, 2018 at 17:19

Hi ! 

Thanks for your response, it was indeed helpful. I am able to retrieve what seems to be the header of an MJEPG video frame now that the HAL_HCD_IN_IRQHandler takes also isochronous endpoints into account. However I am only able to make one transfer, after that the URB status remains to USBH_URB_IDLE because somehow the conditons to get to the 

else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC)

{

   ...

   else if((hhcd->hc[chnum].ep_type == EP_TYPE_INTR)||

   (hhcd->hc[chnum].ep_type == EP_TYPE_ISOC )) 

   {

      ...

   }

}

If I am right about this video frame header being transmitted, it indicates an end of frame. Could that mean that the webcam has no more data to transmit? I forgot to mention that I am currently NOT working with an RTOS 

Posted on July 06, 2018 at 17:23

I guess that doesn't change the behavior of the program, but I took your example of the process state machine ( where the isocReceiveData() calls are made) 

Kind regards 

Colin Cina

PS : this comment belongs with the one above but something went wrong and I couln't editi it. 

Posted on July 08, 2018 at 08:40

Colin,

There is another bug in stm32f7xx_hal_hcd.c shown below diff lines.

--- Src_org/stm32f7xx_hal_hcd.c 2018-03-23 12:48:34.000000000 +0900

+++ Src/stm32f7xx_hal_hcd.c 2018-06-04 13:41:21.000000000 +0900

@@ -423,7 +423,11 @@ HAL_StatusTypeDef HAL_HCD_HC_SubmitReque

    

break;

  

case EP_TYPE_ISOC:

+ ♯ if 0

    

hhcd->hc[ch_num].data_pid = HC_PID_DATA0;

+ ♯ else

+

   

hhcd->hc[ch_num].data_pid = HC_PID_DATA2;

+ ♯ endif

    

break;

  

}

@@ -883,6 +887,15 @@ static void HCD_HC_IN_IRQHandler

 

(HCD_

      

hhcd->hc[chnum].urb_state = URB_DONE;

      

HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);

    

}

+ ♯ if 0

+ ♯ else

+

   

else if(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC)

+

   

{

+

     

USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;

+

     

hhcd->hc[chnum].urb_state = URB_DONE;

+

     

HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);

+

   

}

+ ♯ endif

    

hhcd->hc[chnum].toggle_in ^= 1;

  

}

HAL_HCD_HC_SubmitRequest() always uses DATA0 as data_pid. It means

it can send only one transaction within a micro frame.

Normally, UVC camera needs to send large 

amount

 of data and requires

multiples (two or three) transactions per micro frame.

Check your web camera stream endpoint and use DATA1 or DATA2 data_pid instead.

Toshiharu

dirk.frerichs
Associate II
Posted on July 11, 2018 at 08:16

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6vr&d=%2Fa%2F0X0000000byA%2FbhLevVxGYn6_lxHQNFFsRpaT3rc7NDvlAXfWGu4mFEI&asPdf=false
dirk.frerichs
Associate II
Posted on July 12, 2018 at 15:34

no, SOF is not in use !!

USBH_ClassTypeDef VIDEO_Class = {

        'VIDEO',

        VC_CLASS,

        USBH_VIDEO_InterfaceInit,

        USBH_VIDEO_InterfaceDeInit,

        USBH_VIDEO_ClassRequest,

        USBH_VIDEO_Process,

        USBH_VIDEO_SOFProcess

};

the ISR creates a Event for USBH_VIDEO_Process function.

ISO streams don't use handshake or controlframes btw HALT or STALL 

you must react as fast as possible to free the DMA buffer

btw i'm using USB HS peripherials in FULL Speed mode... 

USBH_StatusTypeDef  USBH_LL_Init (USBH_HandleTypeDef *phost)

{

  /* Init USB_IP */

  if (phost->id == HOST_HS) {

  /* Link The driver to the stack */

  hhcd_USB_OTG_HS.pData = phost;

  phost->pData = &hhcd_USB_OTG_HS;

  hhcd_USB_OTG_HS.Instance                     = USB_OTG_HS;

  hhcd_USB_OTG_HS.Init.Host_channels         = 12;

  hhcd_USB_OTG_HS.Init.speed                 = HCD_SPEED_FULL;

  hhcd_USB_OTG_HS.Init.dma_enable             = ENABLE;

  hhcd_USB_OTG_HS.Init.phy_itface             = USB_OTG_EMBEDDED_PHY;

because  you cant use USB FS peripherials with DMA mode!!

Posted on July 12, 2018 at 14:41

Hey thanks a lot for the example! I noticed that you don't make use of the SOF process call back in order to schedule the

USBH_IsocReceiveData requests. Isn't that mandatory ? I'm asking this because that's how I intend to do it but I notice that after a while the SOF interrupt do not happen any more and I'm not sure what the cause is. 

Edit : Appart from that SOF issue, I am receiving Image data from the webcam with the correct settings.

Kind regards 

Colin Cina