/*FUNCTION*-------------------------------------------------------------------
 *
 * Function Name    : usb_otg_bus_request
 * Returned Value   : bus request message
 * Comments         : B-device requests to become Host
 *    
 *
 *END*----------------------------------------------------------------------*/
usb_status usb_otg_bus_request(usb_otg_handle handle)
{
    usb_otg_state_struct_t * usb_otg_struct_ptr = (usb_otg_state_struct_t *) handle;
    uint16_t dev_otg_status;

    if (handle == NULL)
    {
        return USBERR_ERROR;
    }

    if ((usb_otg_struct_ptr->device_state != USB_OTG_DEVSTATE_B)
    || (usb_otg_struct_ptr->sub_state != USB_OTG_SM_B_PERI_BUS_SUSP_WAIT))
    {
        return USBERR_INVALID_REQ_TYPE;
    }

    usb_otg_struct_ptr->bus_request = TRUE;

    usb_device_get_status(usb_otg_struct_ptr->dev_inst_ptr, USB_STATUS_OTG, &dev_otg_status);

    dev_otg_status |= USB_OTG_HOST_REQUEST_FLAG;

    usb_device_set_status(usb_otg_struct_ptr->dev_inst_ptr, USB_STATUS_OTG, dev_otg_status);

    return USB_OK;
}
Exemple #2
0
/**************************************************************************//*!
 *
 * @name  USB_Class_Get_Status
 *
 * @brief The funtion calls the device to send data upon recieving an IN token 
 *
 * @param handle:               handle to Identify the controller
 * @param component:            component code   
 * @param error_code:           the requested error
 * 
 * @return status       
 *         USB_OK           : When Successfull 
 *         Others           : Errors
 *
 *****************************************************************************/
usb_status USB_Class_Get_Status
(
class_handle_t handle, /* [IN] */
uint8_t component, /* [IN] component code */
uint16_t * error_code /* [OUT] the requested error */
)
{
    usb_status error = USB_OK;
    usb_class_object_struct_t* class_object_ptr = (usb_class_object_struct_t*)handle;

    if (NULL == class_object_ptr)
    {
        return USBERR_ERROR;
    }

    error = usb_device_get_status(class_object_ptr->controller_handle,
    component,error_code);

    return error;
}
/*FUNCTION*-------------------------------------------------------------------
 *
 * Function Name    : usb_otg_set_a_bus_req
 * Returned Value   : set A bus request status
 * Comments         : This function is called from the application to set/clear the 
 *                    a_bus_req parameter. This is one of the parameters that determines 
 *                    A state machine behavior.If the A device is in peripheral state 
 *                    the otg status changes to USB_OTG_HOST_REQUEST_FLAG.  
 *END*----------------------------------------------------------------------*/
usb_status usb_otg_set_a_bus_req(usb_otg_handle otg_handle, bool a_bus_req)
{
    uint16_t dev_otg_status;
    usb_otg_state_struct_t * usb_otg_struct_ptr = (usb_otg_state_struct_t *) otg_handle;
    usb_otg_status_t *otg_status = &usb_otg_struct_ptr->otg_status;
    if (otg_handle == NULL)
    {
        return USBERR_ERROR;
    }
    if (usb_otg_struct_ptr->device_state != USB_OTG_DEVSTATE_A)
    {
        return USBERR_INVALID_REQ_TYPE;
    }
    otg_status->a_bus_req = a_bus_req;
    if (usb_otg_struct_ptr->sub_state == USB_OTG_SM_A_PERIPHERAL)
    {
        usb_device_get_status(usb_otg_struct_ptr->dev_inst_ptr, USB_STATUS_OTG, &dev_otg_status);
        dev_otg_status |= USB_OTG_HOST_REQUEST_FLAG;
        usb_device_set_status(usb_otg_struct_ptr->dev_inst_ptr, USB_STATUS_OTG, dev_otg_status);
    }
    return USB_OK;
}
void MtpSuspendService(BOOL bSetup, BYTE btDirection, BYTE _USB_MEM * pbtBuffer, WORD wLength,WORD wPrivateData)
{

    USHORT uStatus;
    BOOL   bLowPowerUsbStickyBitReadResult;

    if( usb_get_current_limit() > 100 )
    {
        usb_device_get_status(USB_STATUS,&uStatus);
        if(uStatus == USB_STATE_ADDRESSED)
        {   //If we're being suspended in the addressed state, that means we've likely asked for more current than allowed by the host
            //we're going to set a sticky bit (which we'll use when we reset to determine if we've been shutdown for too much
            //current requested), and then reset the part.
            // 8/19/04 - add one bit so that we have a counter - we want to try 500mA twice before failing.
            if( ReadStickyBit((volatile _X WORD *) &HW_RTC_PERSISTENT1, HW_RTC_PERSISTANT1_LOW_POWER2_USB_BITPOS,
                              &bLowPowerUsbStickyBitReadResult) != SUCCESS )
            {
                DebugBuildAssert(FALSE); // halts only in DEBUG builds.
            }
            // if 2nd try flag is set, we've failed the 2nd time, now drop down into 100mA mode.
            if (bLowPowerUsbStickyBitReadResult)
            {
                // Clear 2nd try flag
                if ( ClearStickyBit((volatile _X WORD *)&HW_RTC_PERSISTENT1,
                                    HW_RTC_PERSISTANT1_LOW_POWER2_USB_BITPOS)  != SUCCESS)
                {
                    DebugBuildAssert(FALSE); // halts only in DEBUG build, vanishes in RETAIL build.
                }
                // Set the 100mA flag.
                if( SetStickyBit((volatile _X WORD *)&HW_RTC_PERSISTENT1, HW_RTC_PERSISTANT1_LOW_POWER_USB_BITPOS) != SUCCESS )
                {
                    DebugBuildAssert(0); // halts only if DEBUG build.
                }
            } else
            {
                //set the 2nd try sticky bit.
                if( SetStickyBit((volatile _X WORD *)&HW_RTC_PERSISTENT1, HW_RTC_PERSISTANT1_LOW_POWER2_USB_BITPOS) != SUCCESS )
                {
                    DebugBuildAssert(0); // halts only if DEBUG build.
                }
            }

            usb_device_shutdown();
            for(uStatus =0; uStatus<10000; uStatus++)
                _nop();
            //reset the part
            SystemReset();
        }
        else
        {   //DebugBuildAssert(FALSE);   //!
        }
    }

    //Turn off LRADC
    HW_BATT_CTRL.B.PWD = 1;

#ifdef DCDC_POWER_TRANSFER
    //If using hand-off code, leave the DCDC circuitry on.
    HW_VDD5V_PWR_CHARGE.B.DCANA_LP = FALSE;
    HW_DCDC_TBR.B.DCDC2_STOPCLK = FALSE;
    HW_DCDC_TBR.B.DCDC1_STOPCLK = FALSE;
#else
    //If not using hand-off code, turn off circuitry.
    HW_VDD5V_PWR_CHARGE.B.DCANA_LP = TRUE;  //Turn off some unused circuitry in the dcdc converter
    HW_DCDC_TBR.B.DCDC2_STOPCLK = TRUE;  //Turn off DCDC#2
    HW_DCDC_TBR.B.DCDC1_STOPCLK = TRUE;  //Turn off DCDC#1
#endif

    HW_DCDC_TBR.B.DCDC_ANA_BGR_BIAS = TRUE;  //Switch over to the Vbg bias voltage
    HW_REF_CTRL.B.PWRDWNS = TRUE;       // Turn down the self bias circuit
    HW_REF_CTRL.B.BIASC=1;              // drops bias currents
    HW_REF_CTRL.B.LOW_PWR=1;            // and some more.

    HW_FLCR2.B.CLKOFF = 1;                // Turns Off clock to flash module
    HW_GPFLASH_CSR0R.B.CLK_DISABLE = 1;  // Turns OFF GPFLASH

    HW_DCDC_VDDD.B.BROWNOUT_ENABLE = 0;       // Disable the brownout
    HW_DCDC_VDDD.B.VOLTAGE_LEVEL=0x0a;  //Set core to 1.34 volts

#ifdef BATTERY_CHARGE
    BatteryChargeDisableCharging(FALSE);
#endif
}
void _reentrant USBInsertionMonitorTask(void)
{
    USHORT usStatus;
    BOOL bInserted = FALSE;
    WORD i,j;
	WORD iWaitCount;

    // Check for USB disconnect
    while(1)
    {
        usb_device_get_status(USB_STATUS_CONNECTION,&usStatus);

        switch(usStatus)
        {
        case USB_CONNECTED:
            bInserted=TRUE;
            break;
        default:
            if(bInserted)//if we've been inserted, and now we're not, lets shut down
            {
//              #ifdef DEVICE_3410         // 3410 still has power when removed from usb.
              #ifdef CHKDSK
                  UsbMscCheckDiskAll();
              #endif
//              #endif
              
              // TODO - put this back in later if needed
              // Clear the display
//              ClearDisplay();
        // We need to immediately pull Write Protect low to protect the NANDs and
        // to reset the Renesas part (same line).
        HW_GPFLASH_CSR1R.B.WP0 = 0;

			  // We need to clean up any media transactions that may be hanging
              // As best we can :)
			  // stmp4770 and stmp4795, Remove drive flush on USB disconnect for NAND devices.
			  // Drive flush still necessary for MMC media, to properly close multi-writes
			  // that may be pending between SCSI commands.
              for(i=0;i<g_wUsbMscNumDevices;i++)
              {                  
                for(j=0;j<UsbMscDevice[i].wNumLunsSupported;j++)
                {
                  if(UsbMscDevice[i].Lun[j].bMediaIsRemovable == TRUE)
                  {
                    DriveFlush(UsbMscDevice[i].Lun[j].wFileSystemDriveNumber);
                  } 
                }               
              }
              
              //Do not leave.  Wait for 5V to be removed.
	          //Monitor D+/- and reset if it returns.
    	      HW_USBCSR.B.PLUGGEDIN_EN = 1;

			  iWaitCount = 0;
			  //ensure 5V Disconnect IRQ is enabled
			  SysSetIrqLevel(HW_SR_IM_L2_SETMASK);

			  while(HW_USBCSR.B.VBUSSENSE)
			  {
                  //if USB is plugged-in.  Break loop and reset to return to USBMSC.
                  if(HW_USBCSR.B.PLUGGEDIN)
                  {
                     break;
                  }


			      //wait a bit
			      SysWait(200);

				  if(iWaitCount > 10)
				  {
					 break;		// if we waited a couple secs, time to break
				  }
				  else
				  {
				  	iWaitCount++;	//increment wait count
				  }

			   }                     
			  SysWait(200);

              // Shut down
              SystemShutdown();

              // Reset the device
              SystemReset();
            }
        }
        SysWait(USB_WATCH_CALL_BACK_DELAY);
    }    
}
// Function Description: 
// Inputs:  no parameters
// Returns: no register returns
// Notes:   
void _reentrant UserInterfaceTask(void)
{
    int iTransferRate;
    WORD State=SCSI_IDLE;
    //Message Msg;
    int iDelay = HALF_SEC_UPDATE_RATE;
    int Image2Display = 0;
    BOOL bNeedToReEnable = FALSE;
    USHORT usStatus;

    SysPostMessage(5,LCD_CLEAR_RANGE,0,0,98,64);
    SysPostMessage(5,LCD_PRINT_RANGE_RSRC,0,0,ReadyImage);
    SysWait(250);

    while(1)
    {
    #ifdef BATTERY_CHARGE
        //Only charge if we're in high usb current mode. March 11 2005 addition
        if(usb_get_current_limit() <= 100) //mA
        {    BatteryChargeDisableCharging(TRUE); // until next stmp bootup
        }
        else
        {   usb_device_get_status(USB_STATUS, &usStatus);

            if(usStatus !=  USB_STATE_CONFIGURED)
            {
                if(bNeedToReEnable == FALSE)
                {   BatteryChargeDisableCharging(FALSE);
                    bNeedToReEnable = TRUE;
                }
            }
            else
            {
                if(bNeedToReEnable == TRUE)
                {   BatteryChargeEnableCharging();
                    bNeedToReEnable = FALSE;
                }    
        
                BatteryChargeStateMachine();
            }
        }
    #endif
        SysWait(UPDATE_RATE);
        if(State!= g_wActivityState )
        {
            State = g_wActivityState;
            switch(State)
            {
            case SCSI_IDLE:
                Image2Display = ReadyImage;   
                break;
            case SCSI_READING:
                Image2Display = ReadingImage;  
                break;
            case SCSI_WRITING:
                Image2Display = WritingImage; 
                break;
            }
            if (0 != Image2Display) {
                SysPostMessage(5,LCD_PRINT_RANGE_RSRC,0,0,Image2Display);
            }
        }
        iTransferRate = g_lBulkInBytes / (1+g_lLastBulkInTime-g_lFirstBulkInTime);
        SysPostMessage(7,LCD_PRINT_NUMBER,0,16,iTransferRate,5,' ');
        iTransferRate = g_lBulkOutBytes / (1+g_lLastBulkOutTime-g_lFirstBulkOutTime);
        SysPostMessage(7,LCD_PRINT_NUMBER,0,24,iTransferRate,5,' ');

        SysWait(0);
        SysPostMessage(7,LCD_PRINT_NUMBER, 0,40,g_iCommonCommands,5,' ');
        SysPostMessage(7,LCD_PRINT_NUMBER,32,40,g_iUpdaterCommands,5,' ');
        SysPostMessage(7,LCD_PRINT_NUMBER,64,40,g_iUnknownCommands,5,' ');
    }// end while(1)
}
// Function Description: 
// Inputs:  no parameters
// Returns: no register returns
// Notes:   
void _reentrant UserInterfaceTask(void)
{
    USHORT      usStatus;
    //int iTransferRate;
    WORD State=SCSI_IDLE;
    //Message Msg;
    int iDelay = HALF_SEC_UPDATE_RATE;
    BOOL bNeedToReEnable = FALSE;
    int Write_State_Persisten_Time = WRITE_STATE_PERSISTENT_TIME; 
    int i;
    
    for (i=10;i< USER_INTERFACE_STACK_SIZE;i++ )
    {   g_UserInterfaceStack[i]=0xc0ffee;
    }

    Init5VSense();

    USBLCDDisplayInit();

    SysWait(250);

    while(1)
    {
    #if (NUM_REMOVABLE_MEDIA == 1)
        // Wait until we have decided whether device is in MTP vs. MSC mode
        // Media detection uses different code for the two modes
        if(g_MtpArbitrationDone)
        {   if(MTPDetected)
            {   MtpCheckExternalMedia();
            }
            else
            {   ScsiInsertionRemovalCode();                
            }
        }
    #endif

        usb_device_get_status(USB_STATUS, &usStatus);
        if(usStatus == USB_STATE_SUSPENDED)
        {   SysWait(UPDATE_RATE);
        }
        else
        {   SysPostMessage(2,LCD_END_FRAME);
            SysWait(UPDATE_RATE);
            SysPostMessage(2,LCD_BEGIN_FRAME);
            USBLCDCheckForTransfers();
            
            if(g_bServiceDCDC)
            {   ServiceDCDC();  //Service DCDC converter
            }
        #ifdef BATTERY_CHARGE
            // For 3500 Battery Monitoring must be done only during battery charging
            // The rest of the time the system operates from USB +5V
            // and battery monitoring does not make any sense.
            // Also, battery brownout always triggered if sys operates w/ no battery.

            //Only charge if we're in high usb current mode. March 11 2005 addition
            if(usb_get_current_limit() <= 100) //mA
            {    BatteryChargeDisableCharging(TRUE); // until next stmp bootup
            }
            else
            {   if(usStatus !=  USB_STATE_CONFIGURED)
                {
                    if(bNeedToReEnable == FALSE)
                    {   BatteryChargeDisableCharging(FALSE);
                        bNeedToReEnable = TRUE;
                    }
                }
                else 
                {   if(bNeedToReEnable == TRUE)
                    {   BatteryChargeEnableCharging();
                        bNeedToReEnable = FALSE;
                    }                
                    BatteryChargeStateMachine();
                }
            }
        #endif

#if defined(BATTERY_CHARGE)            
            // I only want to update the Battery icon once per 1/2 second
            // but always check and average battery level.
            USBLCDCheckBatteryLevel();
#endif            
            if (iDelay-- <= 0)
            {
#if defined(BATTERY_CHARGE)               
                USBLCDDisplayBatteryLevel();
#endif                                
                USBLCDCheckDBStoreDirty();
                iDelay = HALF_SEC_UPDATE_RATE;
            }


            // g_wActivityState - This global is set by other code to indicate the state of the
            // system.
            // Can be set by SCSI code, or MTP code (depending on the connection)

            // Modification added for MTP/MSC system
            // In MTP/MSC, MSC uses overlays thus we need to be careful yielding to the kernel for display updates.
            // This can not be done in the middle of a multi write sequence.
            // The code was modified and uses the same technique as a monostable device. Each time scsi write is entered
            // the global g_wActivityStateMultiWrite is set to SCSI_WRITING. This will trigger the monostable for  
            // WRITE_STATE_PERSISTENT_TIME miliseconds. If a new scsi write command arrives prior WRITE_STATE_PERSISTENT_TIME
            // expires, the new scsi write command re-starts the monostable for a new full WRITE_STATE_PERSISTENT_TIME ms.
            // Once the monostable time expires without no new SCSI write commands, the state will switch to IDLE and display 
            // will return to the READY state.
            // The display task has a chance to run everytime a new SCSI write command arrives. There is no display refresh
            // during mutltiwrites. 
            if((g_wActivityStateMultiWrite == SCSI_WRITING) || (Write_State_Persisten_Time < WRITE_STATE_PERSISTENT_TIME))
            {
                if(g_wActivityStateMultiWrite == SCSI_WRITING)
                {
                    g_wActivityStateMultiWrite = SCSI_IDLE;
                    Write_State_Persisten_Time = 0;
                    
                    if(State != SCSI_WRITING)
                    {   State = SCSI_WRITING;
                        USBLCDWriting();
                    }
                }
                else
                {   Write_State_Persisten_Time += UPDATE_RATE;
                }
            }   
            else
            {
                if(State!= g_wActivityState )
                {   State = g_wActivityState;
                    switch(State)
                    {
                    case SCSI_IDLE:
                        USBLCDIdle();
                        break;
                    case SCSI_READING:
                        USBLCDReading();
                        break;
                    case SCSI_WRITING:
                        USBLCDWriting();
                        break;
                    default :
                        USBLCDIdle();
                    }
                }
            }
        } // end else !suspended

        {   USHORT usStatus;  // fixes 8777 (0 or 2 usb unplug tries out of 20 would not 
                              // boot player & mtp was still running due to rare irq loss)
            usb_device_get_status(USB_STATUS_CONNECTION,&usStatus); //we could just check the usb 5v bit instead of calling this.
            if( usStatus == USB_DISCONNECTED )
            {   // Restart the MTP device and re-enumerate
                //DebugBuildAssert(0); //During JLN verification, this hit & the reset started player. 
                StorFlush();   // flush the database first
                SystemShutdown();// we could use pragma asm to jump to the missed isr instead which resets also.
                SystemReset();
            }
        }
        
        // Update the count if it is not disabled( negative means disabled).
        if (g_StoreWatchDogCount >= 0)
        {   g_StoreWatchDogCount++;
        }
        
    } // while(1)
} // void _reentrant UserInterfaceTask(void)