/* @brief Start command timeout detection timer.
 */
void WiFiEngine__CommandTimeoutStart(void)
{
   int status;
   DE_TRACE_STATIC(TR_NOISE, "starting command timeout timer\n");
   status = DriverEnvironment_RegisterTimerCallback(registry.network.basic.cmdTimeout / 10,
                                                    wifiEngineState.cmd_timer_id, 
                                                    cmd_timeout_detect_cb,
                                                    1);
   if(status != DRIVERENVIRONMENT_SUCCESS) {
      DE_TRACE_STATIC(TR_NOISE, "No Cmd timeout callback registered, DE was busy\n");
   }
   WES_SET_FLAG(WES_FLAG_CMD_TIMEOUT_RUNNING);
}
/*!
 * @brief Requests to release the hic interface resource.
 *
 * @param id Identifies the user that requests the release.
 *
 * @return nothing.
 */
void wei_release_resource_hic(int id)
{
   int users;
   int thisUser;
   DE_TRACE_STATIC(TR_PS, "===========> wei_release_resource_hic\n"); 
   DE_TRACE_STRING(TR_PS_DEBUG,"State is: %s \n",state_name[state]);   
   WIFI_RESOURCE_HIC_LOCK(); 
   
   if((wifiEngineState.users & id) == 0)
   {
      /* nothing to release */
      WIFI_RESOURCE_HIC_UNLOCK();
      return;
   }
   thisUser = id;
   users = wifiEngineState.users;

   wifiEngineState.users &= ~id;

   /* trace this only while ps_enabled==TRUE */
   DE_TRACE_INT3(TR_PS, "id: %d users: %d=>%d \n",id, users,wifiEngineState.users);      

   if((id == RESOURCE_DISABLE_PS)&&(state == INTERFACE_PS_DISABLED))
   {
      /* The resource to disable power save mechansim for hic
         interface is released */
      state = INTERFACE_PS_OPEN; 
      we_ind_send(WE_IND_HIC_PS_INTERFACE_ENABLED, NULL );
   }

   if (wifiEngineState.users != 0)
   {
      /* There is someone that has requested to use the interface*/
      WIFI_RESOURCE_HIC_UNLOCK();
      return;
   }

   /* None is using the interface */
   switch(state)
   {
      case INTERFACE_PS_DISABLED:
      {;
         /* Interface has been disabled now it is time to enable it again */       
         state = INTERFACE_PS_CLOSED_WAIT;
         /* Inform firmware that ps hic interface is not used anymore */
         WiFiEngine_PsSendInterface_Down();
         state = INTERFACE_PS_CLOSED;  
      }
      break; 

      case INTERFACE_PS_OPEN:
      {
         rPowerManagementProperties *powerManagementProperties = NULL; 
         powerManagementProperties = (rPowerManagementProperties *)Registry_GetProperty(ID_powerManagement);
         
         /* Interface is temporary open - close it */   
         if(isLegacyPsNoPsPoll() && (thisUser == RESOURCE_USER_DATA_PATH) && (powerManagementProperties->psTxTrafficTimeout > 0))

         {
            /* Start a tx traffic timeout that will hold firware
               awake if more data is about to be sent */
            if(WES_TEST_FLAG(WES_FLAG_PS_TRAFFIC_TIMEOUT_RUNNING))
            {
               /* Cancel the timer so we can restart it */
               DriverEnvironment_CancelTimer(wifiEngineState.ps_traffic_timeout_timer_id);
               WES_CLEAR_FLAG(WES_FLAG_PS_TRAFFIC_TIMEOUT_RUNNING);
            }

            WIFI_RESOURCE_HIC_UNLOCK();
            wei_request_resource_hic(RESOURCE_USER_TX_TRAFFIC_TMO);
            WIFI_RESOURCE_HIC_LOCK();            
            
            if (DriverEnvironment_RegisterTimerCallback(powerManagementProperties->psTxTrafficTimeout, 
                     wifiEngineState.ps_traffic_timeout_timer_id,ps_traffic_timeout_cb,0) != 1)
            {
                DE_TRACE_STATIC(TR_SEVERE,"Failed to register timer callback\n");
                /* Skip timer and go to sleep */
                wifiEngineState.users = 0;
                wifiEngineState.dataPathState = DATA_PATH_CLOSED;
                state = INTERFACE_PS_CLOSED_WAIT;
                /* Inform firmware that ps hic interface is not used anymore */
                WiFiEngine_PsSendInterface_Down();
                state = INTERFACE_PS_CLOSED; 
            }
            else
            {
               WES_SET_FLAG(WES_FLAG_PS_TRAFFIC_TIMEOUT_RUNNING);
            }          

         }
         else
         { 
            wifiEngineState.dataPathState = DATA_PATH_CLOSED;
            state = INTERFACE_PS_CLOSED_WAIT;
            /* Inform firmware that ps hic interface is not used anymore */
            WiFiEngine_PsSendInterface_Down();
            state = INTERFACE_PS_CLOSED;
         }
      }      
      break;

      case INTERFACE_PS_CLOSED:
         DE_TRACE_STATIC(TR_PS, "State is closed no action\n"); 
      break;

      case INTERFACE_PS_OPEN_WAIT:
         DE_TRACE_STATIC(TR_PS, "Transit to OPEN state no action\n"); 
      break;         
      case INTERFACE_PS_CLOSED_WAIT:
         DE_TRACE_STATIC(TR_PS, "Transit to CLOSE state no action\n");          
      break;

      default:
         DE_TRACE_INT(TR_PS,"Unknown state is: %d \n",state);
         DE_ASSERT(FALSE);
      break;

   }

   WIFI_RESOURCE_HIC_UNLOCK();
   DE_TRACE_STRING(TR_PS_DEBUG,"State is: %s \n",state_name[state]);
   DE_TRACE_STATIC(TR_PS, "<=========== wei_release_resource_hic\n");    
}
static int ps_traffic_timeout_cb(void *data, size_t len)
{  
   rPowerManagementProperties *powerManagementProperties = NULL; 

   powerManagementProperties = (rPowerManagementProperties *)Registry_GetProperty(ID_powerManagement);
   
   DE_TRACE_STATIC(TR_PS, "====> ps_traffic_timeout_cb\n");

   if (state == INTERFACE_PS_DISABLED)
   {
      /*  power save has been disabled */
      WIFI_LOCK();
      WES_CLEAR_FLAG(WES_FLAG_PS_TRAFFIC_TIMEOUT_RUNNING);  
      WIFI_UNLOCK();
      wei_release_resource_hic(RESOURCE_USER_TX_TRAFFIC_TMO);      
      return 0;
   }
   
   if(WES_TEST_FLAG(WES_FLAG_PS_TRAFFIC_TIMEOUT_RUNNING))
   {
      WIFI_LOCK();
      WES_CLEAR_FLAG(WES_FLAG_PS_TRAFFIC_TIMEOUT_RUNNING);  
      WIFI_UNLOCK();
      if(wifiEngineState.ps_queue_cnt == 0 && wifiEngineState.ps_data_ind_received == 0)
      {
         /* No queued data and no data ind received since last timeout */
         WIFI_LOCK();
         if (wifiEngineState.dataReqPending == 0)
         {
            /* No pending data cfm - close data path */
            wifiEngineState.dataPathState = DATA_PATH_CLOSED;  
            WIFI_UNLOCK();
         }
         else
         {
            /* Let datapath continue until all cfm:s has been received */ 
            WIFI_UNLOCK();
         }
         wei_release_resource_hic(RESOURCE_USER_TX_TRAFFIC_TMO);
      }
      else
      {
         DE_TRACE_STATIC(TR_PS, "restart the timer\n");
         if (DriverEnvironment_RegisterTimerCallback(powerManagementProperties->psTxTrafficTimeout, 
                  wifiEngineState.ps_traffic_timeout_timer_id, 
                  ps_traffic_timeout_cb,0) 
               != 1)
         {
             DE_TRACE_STATIC(TR_SEVERE,"No command to callback registered, DE was busy\n");
             /* Not possible to continue - go to sleep */
             WIFI_LOCK();
             wifiEngineState.dataPathState = DATA_PATH_CLOSED; 
             WIFI_UNLOCK();
             wei_release_resource_hic(RESOURCE_USER_TX_TRAFFIC_TMO);
         }
         else
         {
            /* Wait for a new callback */
            WES_SET_FLAG(WES_FLAG_PS_TRAFFIC_TIMEOUT_RUNNING);
            wifiEngineState.ps_data_ind_received = 0;
            WiFiEngine_PsCheckQueues();
         }
         
      }
   }

   DE_TRACE_STATIC(TR_PS, "<==== ps_traffic_timeout_cb\n");   

   return 0;
}