Dropping VBus

This functionality is for On-The-Go (OTG)-enabled devices only.

The USB control application on a Symbian platform phone that supports USB host/OTG services (and is acting as an A-device) has exclusive responsibility for dropping VBus. No other application on the device can initiate a VBus drop.

Purpose

An OTG A-device is responsible for providing power on VBus for as long as this is appropriate (in other words, whenever the bus is in use), regardless of whether the A-device is acting as the host or the peripheral. The USB Manager includes functionality that enables the USB control application to power up VBus (see Controlling when the phone is the USB host).

The USB Manager also contains functionality that enables the USB control application on an A-device to power down VBus. VBus needs to be powered down whenever USB is not is use, because this saves power and extends battery life.

This document tells you how to use the USB Manager's functionality for powering down VBus.

Using the USB Manager to power down VBus

Basic Procedure

The high-level steps involved in powering down VBus are shown here:

  1. Find out whether the bus connection is idle.

  2. Start an idle timer.

  3. Drop VBus.

Dropping VBus

To drop VBus, do the following in your USB control application:

  1. Find out whether the bus connection is idle (see Monitoring whether the phone's bus connection is idle or busy).

    RProperty otgConnectionIdleProp;           //Create a bus connection property object
                                               //Attach to it
    User::LeaveIfError(otgConnectionIdleProp.Attach(KUidUsbManCategory, KUsbOtgConnectionIdleProperty));
    TRequestStatus status;
    otgConnectionIdleProp.Subscribe(status); //Subscribe for notification of the next status change
    User::WaitForRequest(status);
    TInt val;
    TInt okToDropVBus = otgConnectionIdleProp.Get(val); 

    Note: After detecting that the bus connection is idle, you might more realistically want to start an idle timer (by using an active object of the CTimer class) instead of dropping VBus immediately. This is important because the idle state might be a transitory one. If you do implement a timer, then, when you are deciding how long to allow as the idle time, remember that keeping the connection alive uses battery power but that taking the connection down (by dropping VBus) too early potentially inconveniences the phone's user (by requiring him or her to re-activate USB services after only short periods of inactivity). It is for you to decide how best to compromise between the need to save battery power and the need for a positive user experience of one feature (USB connectivity) of the Symbian phone.

  2. If the bus connection is not idle, then do nothing; if it is idle, then drop VBus (in other words, relinquish control of VBus and power it down) by calling RUsb::BusDrop():

    if (!okToDropVBus)
       {  
          break; 
       }
    else
       {
        err = usb.BusDrop();
        if (err != KErrNone)
           {
             // Handle error 
             // If this is an A-device and you have received an error back after
             // calling RUsb::BusDrop(), then VBus is already down.
    
            if (err == KErrUsbOtgBadState)
                {
                // Handle error
                // If this is an A-device and you receive this error, it means 
                // that there is a hardware problem caused by a B-device drawing
                // too much current. To restore the A-device to an idle state 
                // you must now run RUsb::BusClearError(). 
    
                // If this is a B-device the error message is because
                // the device has no control of VBus (and so cannot drop it).
                err = usb.BusClearError();
                if (err != KErrNone)
                    {
                    // If you receive an error after running RUsb::BusClearError()
                    // here, it is either because the device is a B-device (and
                    // therefore should not be trying to control VBus), or it indicates 
                    // an Out of Memory condition (in which case the error returned 
                    // is KErrNoMemory).
                    }
                }
           }    
       }          

Note: The sample code above includes information about restoring USB services on an A-device after a B-device has been drawing too much power from it. When this happens, the A-device is unable to maintain the necessary voltage on VBus, and the low-level OTG stack will automatically drop VBus to prevent damage to the A-device. In the code above, if this has happened, then VBus will already be down when RUsb::BusDrop() is called, and an error condition therefore exists that makes further USB connectivity impossible. To restore USB connectivity, you need to call RUsb::BusClearError(). This restores the A-device to an A-idle state from which it can pass to a host state again when required (see The OTG state transitions). You must also display a message telling the phone's user to remove the offending device from the phone.