Setting the Link Power State

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hello,

   

I'm a little bit new to link states in USB, so please forgive my ignorance on this topic.  I'd like to set the link state to U2.  I have the following code:

   
 if (glForceLinkU2)         {             stat = CyU3PUsbGetLinkPowerState (&curState);             while ((glForceLinkU2) && (stat == CY_U3P_SUCCESS) && (curState == CyU3PUsbLPM_U0))             {                 /* Repeatedly try to go into U2 state.*/                 CyU3PUsbSetLinkPowerState (CyU3PUsbLPM_U2);                 CyU3PThreadSleep (5);                 stat = CyU3PUsbGetLinkPowerState (&curState);             }             CyU3PGpioSetValue(LED0,LED_ON);         }
   

...which is essentially the same code given in the bulkauto DMA example, except that I've added code to turn on a debug LED once the loop has finished.  Unfortunately, the loop never finishes because the link power state is never U2/is always U0.  My assumption is that I'm not doing something on the host side to allow this transition, i.e. I can't just ask the device to change to U2 if the host doesn't change something as well.  Am I correct in this assumption?  What do I have to do on both sides of the interface to get this to work?

   

Thanks!

3 Replies
RoKl_290166
Level 4
Level 4
Welcome!

Hi,

   

the host needs to allow the device to initiate a U1/U2-transition by setting U1/U2_ENABLE feature in the device using the standard-request SET_FEATURE. You can request the current values of the U1/U2_ENABLE by using the standard-request GET_STATUS. Have a look in the USB3.0 specification chapter 9.4 for more details on the standard-requests and it's definitions.

   

 

   

Best regards,

   

Robert

0 Likes
Anonymous
Not applicable

Hello,

   

I've done some more work/research on this today and I'm still running into issues.  Robert, you were correct that the function wasn't being called using the explicit SET_FEATURE call for U2_ENABLE.  I had taken one of the SDK examples and modified it for my purposes, but I'm not sure that the U2 transition actually works in the example code (I couldn't get it to work as I thought it should).  I found this in the API guide:

   

void CyU3PUsbRegisterSetupCallback ( CyU3PUSBSetupCb_t callback, CyBool_t fastEnum )

   

Register a USB setup request handler.

   

Description

   

This function is used to register a USB setup request handler with the USB driver. The fastEnum parameter specifies whether this setup handler should be used only for unknown setup requests or for all USB setup requests.

   

The example code had fastEnum set to CyTrue, which is why I couldn't initially run the code using a SET_FEATURE request.  So, I took the example cyfxlowpowertest.c and added the 'CyU3PSetPowerLink' code there.  I'm still seeing the same issue with the link state never changing from U0, even though, using debug print statements, I can see it filtering through the setup callback as expected.

   

Is there another example in the SDK that I'm missing that reproducibly forces the various states?  On the host side, I'm running Python on top of Libusb to set in the various commands, so attempt to set the link to U2, I do the following:

   

x.controlWrite(0x0,0x3,0x31,0,0,500)

   

Is that right, or am I missing something?  Like I stated before, I can see via debug messages that everything is successful until the CyU3PSetPowerLink function call.

   

Thanks,

   

Jake

0 Likes

The return code of CyU3PUsbSetLinkPowerState tells you if it tries to switch to the specfied link power mode. As already mentioned, the must have allowed the change to U1/ before U2 (enabled it). If you fake the host's permission by manually set the required flag, to pass the state check of CyU3PUsbSetLinkPowerState it will return CY_U3P_SUCCESS but won't switch to U1/U2 link power mode.

(Fake permission, based on sdk1.3.1 :

glUibDeviceInfo.usbDeviceStat |= CY_U3P_USB_DEVSTAT_U1ENABLE | CY_U3P_USB_DEVSTAT_U2ENABLE;)

As far as I can tell, you can only switch from U1/U2 mode to U0 without being asked by the host.

When and if the host wants to change to U1/U2 depends strongly on the USB-HostController driver and the host power scheme.

You can use the USB-IF Test Suite to request U2 link power mode by the host.

https://www.usb.org/usb32tools

0 Likes