Пример #1
0
//----------------------------------------------------------------------------------------------
static void _micoNotify_WiFi_Scan_OK (ScanResult_adv *pApList, mico_Context_t * const inContext)
{
  (void)inContext;

  queue_msg_t msg;
  msg.L = gL;
  msg.source = onWIFI | 0x10;
  msg.para1 = pApList->ApNum;
  msg.para2 = wifi_scan_succeed;
  msg.para4 = NULL;

  if (pApList->ApNum > 0) {
    msg.para3 = (uint8_t*)malloc(sizeof(_ApList)*pApList->ApNum);
    if (msg.para3 != NULL) {
      memcpy((_ApList*)msg.para3, pApList->ApList, sizeof(_ApList)*pApList->ApNum);
    }
    else msg.para3 = NULL;
  }
  else msg.para3 = NULL;

  if (wifi_scan_succeed != LUA_NOREF) {
    mico_rtos_push_to_queue( &os_queue, &msg, 0);
  }
  else {
    _WiFi_Scan_OK(gL, msg.para1, (_ApList*)msg.para3, wifi_scanned_print);
    free(msg.para3);
    msg.para3 = NULL;
  }
  wifi_scanned = 1;
}
Пример #2
0
static void timed_event_handler( void* arg )
{
    mico_timed_event_t* event_object = (mico_timed_event_t*) arg;
    mico_event_message_t message;

    message.function = event_object->function;
    message.arg = event_object->arg;

    mico_rtos_push_to_queue( &event_object->thread->event_queue, &message, MICO_NO_WAIT );
}
Пример #3
0
OSStatus mico_rtos_send_asynchronous_event( mico_worker_thread_t* worker_thread, event_handler_t function, void* arg )
{
    mico_event_message_t message;

    if( worker_thread->thread == NULL )
        return kNotInitializedErr;

    message.function = function;
    message.arg = arg;

    return mico_rtos_push_to_queue( &worker_thread->event_queue, &message, MICO_NO_WAIT );
}
Пример #4
0
// == Timer interrupt handler =======
static void _tmr_handler( void* arg )
{
  unsigned id = (unsigned)arg;
  if(id<NUM_TMR)
  {
    queue_msg_t msg;
    msg.L = gL;
    msg.source = onTMR;
    //msg.para1 = tmr_cb_ref[id];
    msg.para2 = tmr_cb_ref[id];
    mico_rtos_push_to_queue( &os_queue, &msg,0);
  }
}
Пример #5
0
//------------------------------------------------------------------------------------------
static void _micoNotify_WifiStatusHandler(WiFiEvent event, mico_Context_t * const inContext)
{
  (void)inContext;
  
  queue_msg_t msg;
  msg.L = gL;
  msg.source = onWIFI;
  msg.para3 = NULL;
  msg.para4 = NULL;
  
  switch (event) {
    case NOTIFY_STATION_UP:
      wifi_sta_started = 1;
      if (wifi_status_changed_STA != LUA_NOREF) {
        msg.para1 = 0;
        msg.para2 = wifi_status_changed_STA;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
      break;
    case NOTIFY_STATION_DOWN:
      wifi_sta_started = 0;
      if (wifi_status_changed_STA != LUA_NOREF) {
        msg.para1 = 1;
        msg.para2 = wifi_status_changed_STA;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
      break;
    case NOTIFY_AP_UP:
      wifi_ap_started = 1;
      if (wifi_status_changed_AP != LUA_NOREF) {
        msg.para1 = 2;
        msg.para2 = wifi_status_changed_AP;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
      break;
    case NOTIFY_AP_DOWN:
      wifi_ap_started = 0;
      if (wifi_status_changed_AP != LUA_NOREF) {
        msg.para1 = 3;
        msg.para2 = wifi_status_changed_AP;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
      break;
    default:
      if (wifi_status_changed_AP != LUA_NOREF) {
        msg.para1 = 4;
        msg.para2 = wifi_status_changed_AP;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
      if (wifi_status_changed_STA != LUA_NOREF) {
        msg.para1 = 4;
        msg.para2 = wifi_status_changed_STA;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
      break;
  }
}
Пример #6
0
OSStatus SysComSendMsg(SysComMsg *msg)
{
    OSStatus err = kUnknownErr;
    
    mico_rtos_lock_mutex(&SysComMutex);
    
    err = mico_rtos_push_to_queue(&SysComQueue[msg->receiver], &msg, 0);
    if(err != kNoErr) {
        SysCom_ERR("SysComSend: msg(addr: 0x%08X) push to SysComQueue[%d] failed with err(%d)", (addP_t)msg, msg->receiver, err);
    }
    else {
        SysCom_DBG("SysComSend: msg(addr: 0x%08X) push to SysComQueue[%d] successfully", (addP_t)msg, msg->receiver);
    }
    
    mico_rtos_unlock_mutex(&SysComMutex);
    
    return err;
}
Пример #7
0
OSStatus sppUartCommandProcess(uint8_t *inBuf, int inLen, app_context_t * const inContext)
{
  spp_log_trace();
  OSStatus err = kNoErr;
  int i;
  mico_queue_t* p_queue=NULL;
  socket_msg_t *real_msg;

  for(i=0; i < MAX_QUEUE_NUM; i++) {
    p_queue = inContext->appStatus.socket_out_queue[i];
    if(p_queue  != NULL ){
      break;
    }
  }
  if (p_queue == NULL)
    return kNoErr;
  
  if (MAX_SOCK_MSG_LEN < sockmsg_len)
    return kNoMemoryErr;
  real_msg = (socket_msg_t*)malloc(sizeof(socket_msg_t) - 1 + inLen);

  if (real_msg == NULL)
    return kNoMemoryErr;
  sockmsg_len += (sizeof(socket_msg_t) - 1 + inLen);
  real_msg->len = inLen;
  memcpy(real_msg->data, inBuf, inLen);
  real_msg->ref = 0;
  
  mico_rtos_lock_mutex(&inContext->appStatus.queue_mtx);
  socket_msg_take(real_msg);
  for(i=0; i < MAX_QUEUE_NUM; i++) {
    p_queue = inContext->appStatus.socket_out_queue[i];
    if(p_queue  != NULL ){
      socket_msg_take(real_msg);
      if (kNoErr != mico_rtos_push_to_queue(p_queue, &real_msg, 0)) {
        socket_msg_free(real_msg);
    }
  }
  }        
  socket_msg_free(real_msg);
  mico_rtos_unlock_mutex(&inContext->appStatus.queue_mtx);
  return err;
}
OSStatus AaSysComSend(void* msg_ptr)
{
    if(msg_ptr == NULL) {
        AaSysLogPrint(LOGLEVEL_ERR, "msg_ptr is NULL");
        return kParamErr;
    }
    
    SMsgInternalHeader header;
    SMsgHeader* msg = (SMsgHeader*)msg_ptr;

    if(msg->sender >= MsgQueue_MAX || msg->target >= MsgQueue_MAX) {
        AaSysLogPrint(LOGLEVEL_ERR, "sender 0x%02x or receiver 0x%02x failed", 
                msg->sender, msg->target);
        return kParamErr;
    }

    if(msg->msg_id >= API_MESSAGE_ID_MAX) {
        AaSysLogPrint(LOGLEVEL_ERR, "message id 0x%04x failed", msg->msg_id);
        return kParamErr;
    }

    header.msg_id = msg->msg_id;
    header.target = msg->target;
    header.sender = msg->sender;
    header.body_size = sizeof(SMsgHeader) + msg->pl_size;
    header.body = msg_ptr;

    if(kNoErr != mico_rtos_push_to_queue(&msg_queue[header.target], &header, MICO_WAIT_FOREVER)) {
        AaSysLogPrint(LOGLEVEL_ERR, "message 0x%04x send failed", header.msg_id);

        if(msg_ptr != NULL) free(msg_ptr);
        return kInProgressErr;
    }

    AaSysLogPrint(LOGLEVEL_DBG, "message(0x%04x) have been sent from %s to %s", 
            header.msg_id, 
            AaSysComPrintThreadName(header.sender), 
            AaSysComPrintThreadName(header.target));

    return kNoErr;
}
Пример #9
0
//===================================
static int queue_push( lua_State* L )
{
  if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION)
  {
    lua_pushvalue(L, 1);  // copy argument (func) to the top of stack
    gL = L;
    queue_msg_t msg;
    msg.L = gL;
    msg.source = USER;
    
    if (lua_type(L, 2) == LUA_TNUMBER) msg.para1 = luaL_checkinteger( L, 2 );
    else msg.para1 = -9999;

    msg.para2 = luaL_ref(L, LUA_REGISTRYINDEX);
    mico_rtos_push_to_queue( &os_queue, &msg, 0);
    l_message( NULL, "pushed");
  }
  else
    return luaL_error( L, "callback function needed" );

  
  return 0;
}
Пример #10
0
// handle cloud msg here, for example: send to USART or echo to cloud
OSStatus MicoFogCloudCloudMsgProcess(mico_Context_t* context, 
                                     const char* topic, const unsigned int topicLen,
                                     unsigned char *inBuf, unsigned int inBufLen)
{
  fogcloud_log_trace();
  OSStatus err = kUnknownErr;
  uint32_t real_msg_len = 0;

  // push msg into queue
  fogcloud_msg_t *real_msg;
  fogcloud_msg_t *p_tem_msg = NULL;  // msg pointer
  
  real_msg_len = sizeof(fogcloud_msg_t) + topicLen + inBufLen;
  if(FOGCLOUD_TOTAL_BUF_LENGTH < (total_recv_buf_len + real_msg_len)){
    return kNoMemoryErr;
  }
  real_msg = (fogcloud_msg_t*)malloc(real_msg_len);
  if (real_msg == NULL){
    return kNoMemoryErr;
  }
  total_recv_buf_len += real_msg_len;
  
	memset(real_msg, '\0', sizeof(real_msg));
  real_msg->topic_len = topicLen;
  real_msg->data_len = inBufLen;
  memcpy(real_msg->data, topic, topicLen);
  memcpy(real_msg->data + topicLen, inBuf, inBufLen);
  //memcpy(real_msg->data + topicLen + inBufLen, '\0', 1);
  
  if(NULL != msg_recv_queue){
    mico_rtos_lock_mutex(&msg_recv_queue_mutex);
    if(mico_rtos_is_queue_full(&msg_recv_queue)){
      fogcloud_log("WARNGING: FogCloud msg overrun, abandon old messages!");
      err = mico_rtos_pop_from_queue(&msg_recv_queue, &p_tem_msg, 0);  // just pop old msg pointer from queue 
      if(kNoErr == err){
        if(NULL != p_tem_msg){  // delete msg, free msg memory
          free(p_tem_msg);
          p_tem_msg = NULL;
        }
      }
      else{
        mico_rtos_unlock_mutex(&msg_recv_queue_mutex);
        fogcloud_log("WARNGING: FogCloud msg overrun, abandon current message!");
        if(NULL != real_msg){  // queue full, new msg abandoned
          free(real_msg);
          real_msg = NULL;
        }
        return kOverrunErr;
      }
    }
    // insert a msg into recv queue
    if (kNoErr != mico_rtos_push_to_queue(&msg_recv_queue, &real_msg, 0)) {  // just push msg pointer in queue
      free(real_msg);
      real_msg = NULL;
      err = kWriteErr;
    }
    else{
      err = kNoErr;
    }
    mico_rtos_unlock_mutex(&msg_recv_queue_mutex);
  }
  else{
    if(NULL != real_msg){
      free(real_msg);
      real_msg = NULL;
    }
    return kNotInitializedErr;
  }
  
  return err;
}
Пример #11
0
/**
  * @brief  USBH_MSC_BOT_Process
  *         The function handle the BOT protocol.
  * @param  phost: Host handle
  * @param  lun: Logical Unit Number
  * @retval USBH Status
  */
USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
{
    USBH_StatusTypeDef   status = USBH_BUSY;
    USBH_StatusTypeDef   error  = USBH_BUSY;
    BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED;
    USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
    MSC_HandleTypeDef *MSC_Handle =  phost->pActiveClass->pData;
    uint8_t toggle = 0;
    uint16_t USBH_URB = USBH_URB_EVENT;

    switch (MSC_Handle->hbot.state)
    {
    case BOT_SEND_CBW:
        MSC_Handle->hbot.cbw.field.LUN = lun;
        MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT;
        USBH_BulkSendData (phost,
                           MSC_Handle->hbot.cbw.data,
                           BOT_CBW_LENGTH,
                           MSC_Handle->OutPipe,
                           1);

        break;

    case BOT_SEND_CBW_WAIT:

        URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);

        if(URB_Status == USBH_URB_DONE)
        {
            if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 )
            {
                /* If there is Data Transfer Stage */
                if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H)
                {
                    /* Data Direction is IN */
                    MSC_Handle->hbot.state = BOT_DATA_IN;
                }
                else
                {
                    /* Data Direction is OUT */
                    MSC_Handle->hbot.state = BOT_DATA_OUT;
                }
            }

            else
            {   /* If there is NO Data Transfer Stage */
                MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
            }
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif

        }
        else if(URB_Status == USBH_URB_NOTREADY)
        {
            /* Re-send CBW */
            MSC_Handle->hbot.state = BOT_SEND_CBW;
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }
        else if(URB_Status == USBH_URB_STALL)
        {
            MSC_Handle->hbot.state  = BOT_ERROR_OUT;
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }
        break;

    case BOT_DATA_IN:
        /* Send first packet */
        USBH_BulkReceiveData (phost,
                              MSC_Handle->hbot.pbuf,
                              MSC_Handle->InEpSize ,
                              MSC_Handle->InPipe);

        MSC_Handle->hbot.state  = BOT_DATA_IN_WAIT;

        break;

    case BOT_DATA_IN_WAIT:

        URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);

        if(URB_Status == USBH_URB_DONE)
        {
            /* Adjudt Data pointer and data length */
            if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize)
            {
                MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize;
                MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize;
            }
            else
            {
                MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
            }

            /* More Data To be Received */
            if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
            {
                /* Send next packet */
                USBH_BulkReceiveData (phost,
                                      MSC_Handle->hbot.pbuf,
                                      MSC_Handle->InEpSize ,
                                      MSC_Handle->InPipe);

            }
            else
            {
                /* If value was 0, and successful transfer, then change the state */
                MSC_Handle->hbot.state  = BOT_RECEIVE_CSW;
#if (USBH_USE_OS == 1)
                mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
            }
        }
        else if(URB_Status == USBH_URB_STALL)
        {
            /* This is Data IN Stage STALL Condition */
            MSC_Handle->hbot.state  = BOT_ERROR_IN;

            /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
            6.7.2 Host expects to receive data from the device
            3. On a STALL condition receiving data, then:
            The host shall accept the data received.
            The host shall clear the Bulk-In pipe.
            4. The host shall attempt to receive a CSW.*/

#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }
        break;

    case BOT_DATA_OUT:

        USBH_BulkSendData (phost,
                           MSC_Handle->hbot.pbuf,
                           MSC_Handle->OutEpSize ,
                           MSC_Handle->OutPipe,
                           1);


        MSC_Handle->hbot.state  = BOT_DATA_OUT_WAIT;
        break;

    case BOT_DATA_OUT_WAIT:
        URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);

        if(URB_Status == USBH_URB_DONE)
        {
            /* Adjudt Data pointer and data length */
            if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize)
            {
                MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize;
                MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize;
            }
            else
            {
                MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
            }

            /* More Data To be Sent */
            if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
            {
                USBH_BulkSendData (phost,
                                   MSC_Handle->hbot.pbuf,
                                   MSC_Handle->OutEpSize ,
                                   MSC_Handle->OutPipe,
                                   1);
            }
            else
            {
                /* If value was 0, and successful transfer, then change the state */
                MSC_Handle->hbot.state  = BOT_RECEIVE_CSW;
            }
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }

        else if(URB_Status == USBH_URB_NOTREADY)
        {
            /* Re-send same data */
            MSC_Handle->hbot.state  = BOT_DATA_OUT;
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }

        else if(URB_Status == USBH_URB_STALL)
        {
            MSC_Handle->hbot.state  = BOT_ERROR_OUT;

            /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
            6.7.3 Ho - Host expects to send data to the device
            3. On a STALL condition sending data, then:
            " The host shall clear the Bulk-Out pipe.
            4. The host shall attempt to receive a CSW.
            */
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }
        break;

    case BOT_RECEIVE_CSW:

        USBH_BulkReceiveData (phost,
                              MSC_Handle->hbot.csw.data,
                              BOT_CSW_LENGTH ,
                              MSC_Handle->InPipe);

        MSC_Handle->hbot.state  = BOT_RECEIVE_CSW_WAIT;
        break;

    case BOT_RECEIVE_CSW_WAIT:

        URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe);

        /* Decode CSW */
        if(URB_Status == USBH_URB_DONE)
        {
            MSC_Handle->hbot.state = BOT_SEND_CBW;
            MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;
            CSW_Status = USBH_MSC_DecodeCSW(phost);

            if(CSW_Status == BOT_CSW_CMD_PASSED)
            {
                status = USBH_OK;
            }
            else
            {
                status = USBH_FAIL;
            }
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }
        else if(URB_Status == USBH_URB_STALL)
        {
            MSC_Handle->hbot.state  = BOT_ERROR_IN;
#if (USBH_USE_OS == 1)
            mico_rtos_push_to_queue((mico_queue_t *) &(phost->os_event), &USBH_URB, 0 );
#endif
        }
        break;

    case BOT_ERROR_IN:
        error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN);

        if (error == USBH_OK)
        {
            MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
        }
        else if (error == USBH_UNRECOVERED_ERROR)
        {
            /* This means that there is a STALL Error limit, Do Reset Recovery */
            MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
        }
        break;

    case BOT_ERROR_OUT:
        error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT);

        if ( error == USBH_OK)
        {

            toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe);
            USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle);
            USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0);
            MSC_Handle->hbot.state = BOT_ERROR_IN;
        }
        else if (error == USBH_UNRECOVERED_ERROR)
        {
            MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
        }
        break;


    case BOT_UNRECOVERED_ERROR:
        status = USBH_MSC_BOT_REQ_Reset(phost);
        if ( status == USBH_OK)
        {
            MSC_Handle->hbot.state = BOT_SEND_CBW;
        }
        break;

    default:
        break;
    }
    return status;
}
Пример #12
0
// ======= FTP thread handler =========
static void _thread_ftp(void*inContext)
{
  (void)inContext;

  fd_set readset, wrset;
  struct timeval_t t_val;
  int k;
  uint32_t timeout = 0;
  uint8_t recv_tmo = 0;

  t_val.tv_sec = 0;
  t_val.tv_usec = 5000;

  timeout = mico_get_time();
  ftp_log("\r\n[FTP trd] FTP THREAD STARTED\r\n");
  
  // *** First we have to get IP address and connect the cmd socket
  char pIPstr[16]={0};
  int err;
  k = 3;
  do {
    err = gethostbyname((char *)pDomain4Dns, (uint8_t *)pIPstr, 16);
    if (err != kNoErr) {
      k--;
      mico_thread_msleep(50);
    }
  }while ((err != kNoErr) && (k > 0));
  
  if ((err == kNoErr) && (ftpCmdSocket != NULL)) {
    ftpCmdSocket->addr.s_ip = inet_addr(pIPstr);
    ftpCmdSocket->clientFlag = NO_ACTION;

    free(pDomain4Dns);
    pDomain4Dns=NULL;

    // Connect socket!
    char ip[17];
    memset(ip, 0x00, 17);
    inet_ntoa(ip, ftpCmdSocket->addr.s_ip);
    ftp_log("[FTP cmd] Got IP: %s, connecting...\r\n", ip);

    struct sockaddr_t *paddr = &(ftpCmdSocket->addr);
    int slen = sizeof(ftpCmdSocket->addr);
    // _micoNotify will be called if connected
    connect(ftpCmdSocket->socket, paddr, slen);
  }
  else {
    ftp_log("[FTP dns] Get IP error\r\n");
    goto terminate;
  }

  if (recvBuf == NULL) {
    recvBuf = malloc(MAX_RECV_LEN+4);
    memset(recvBuf, 0, MAX_RECV_LEN+4);
  }
  recvLen = 0;

  // ===========================================================================
  // Main Thread loop
  while (1) {
    mico_thread_msleep(5);
        
    if (ftpCmdSocket == NULL) goto terminate;

    if ( ((mico_get_time() - timeout) > MAX_FTP_TIMEOUT) ||
         (((mico_get_time() - timeout) > 8000) && (!(status & FTP_LOGGED))) ) {
      // ** TIMEOUT **
      ftp_log("[FTP trd] Timeout\r\n");
      timeout = mico_get_time();
      
      if ((status & FTP_LOGGED))
        ftpCmdSocket->clientFlag = REQ_ACTION_QUIT;
      else
        ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT;
    }

    // ========== stage #1, Check cmd socket action requests ===================
    
    //REQ_ACTION_DISCONNECT
    if (ftpCmdSocket->clientFlag == REQ_ACTION_DISCONNECT) {
      ftpCmdSocket->clientFlag = NO_ACTION;
      
      closeDataSocket();
      
      ftp_log("[FTP cmd] Socket disconnected\r\n");
      if (ftpCmdSocket->disconnect_cb != LUA_NOREF) {
        queue_msg_t msg;
        msg.L = gL;
        msg.source = onFTP;
        msg.para1 = 0;
        msg.para2 = ftpCmdSocket->disconnect_cb;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
      closeCmdSocket(0);
      continue;
    }
    //REQ_ACTION_QUIT
    if (ftpCmdSocket->clientFlag == REQ_ACTION_QUIT) {
      if ((status & FTP_LOGGED)) {
        ftpCmdSocket->clientFlag = NO_ACTION;
        ftp_log("[FTP cmd] Quit command\r\n");
        if (_send("QUIT\r\n", 6) <= 0) {
          ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT;
        }
      }
      else ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT;
      continue;
    }

    if (!(status & FTP_CONNECTED)) continue;
    //--------------------------------------

    //REQ_ACTION_LIST, REQ_ACTION_RECV, REQ_ACTION_SEND
    else if ((ftpCmdSocket->clientFlag == REQ_ACTION_LIST) ||
             (ftpCmdSocket->clientFlag == REQ_ACTION_RECV) ||
             (ftpCmdSocket->clientFlag == REQ_ACTION_SEND)) {
      ftpCmdSocket->clientLastFlag = ftpCmdSocket->clientFlag;
      ftpCmdSocket->clientFlag = NO_ACTION;

      _send("PASV\r\n", 6);
    }
    //REQ_ACTION_DOLIST
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_DOLIST) {
      ftpCmdSocket->clientFlag = NO_ACTION;

      int res;
      if (ftpfile != NULL) {
        char tmps[100];
        if (list_type == 1) sprintf(tmps,"NLST %s\r\n", ftpfile);
        else sprintf(tmps,"LIST %s\r\n", ftpfile);
        res = _send(&tmps[0], strlen(ftpfile)+7);
        free(ftpfile);
        ftpfile = NULL;
      }
      else {
        if (list_type == 1) res = _send("NLST\r\n", 6);
        else res = _send("LIST\r\n", 6);
      }
      if (res > 0) status |= FTP_LISTING;
      else {
        ftp_log("[FTP cmd] LIST command failed.\r\n");
      }
    }
    //REQ_ACTION_DORECV
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_DORECV) {
      ftpCmdSocket->clientFlag = NO_ACTION;

      char tmps[100];
      sprintf(tmps,"RETR %s\r\n", ftpfile);
      int res = _send(&tmps[0], strlen(ftpfile)+7);
      if (res > 0) {
        status |= FTP_RECEIVING;
        file_status = 0;
      }
      else {
        ftp_log("[FTP cmd] RETR command failed.\r\n");
        file_status = -4;
      }
    }
    //REQ_ACTION_DOSEND
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_DOSEND) {
      ftpCmdSocket->clientFlag = NO_ACTION;

      char tmps[100];
      if ((send_type & SEND_APPEND)) sprintf(tmps,"APPE %s\r\n", ftpfile);
      else sprintf(tmps,"STOR %s\r\n", ftpfile);
      int res = _send(&tmps[0], strlen(ftpfile)+7);
      if (res > 0) {
        file_status = 0;
      }
      else {
        ftp_log("[FTP cmd] STOR/APPE command failed.\r\n");
        file_status = -4;
      }
    }
    //REQ_ACTION_CHDIR
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_CHDIR) {
      ftpCmdSocket->clientFlag = NO_ACTION;

      if (ftpfile != NULL) {
        char tmps[100];
        sprintf(tmps,"CWD %s\r\n", ftpfile);
        _send(&tmps[0], strlen(ftpfile)+6);
        free(ftpfile);
        ftpfile = NULL;
      }
      else {
        _send("PWD\r\n", 5);
      }
    }
    //REQ_ACTION_LOGGED
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_LOGGED) {
      ftpCmdSocket->clientFlag=NO_ACTION;
      if (ftpCmdSocket->logon_cb != LUA_NOREF) {
        queue_msg_t msg;
        msg.L = gL;
        msg.source = onFTP;
        msg.para1 = 1;
        msg.para3 = NULL;
        msg.para2 = ftpCmdSocket->logon_cb;
        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
    }
    //REQ_ACTION_LIST_RECEIVED
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_LIST_RECEIVED) {
      ftpCmdSocket->clientFlag=NO_ACTION;
      if (ftpCmdSocket->list_cb != LUA_NOREF) {
        queue_msg_t msg;
        msg.L = gL;
        msg.source = onFTP;
        msg.para1 = recvDataLen;
        msg.para2 = ftpCmdSocket->list_cb;
        msg.para3 = (uint8_t*)malloc(recvDataLen+4);
        if (msg.para3 != NULL) memcpy((char*)msg.para3, recvDataBuf, recvDataLen);

        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
    }
    //REQ_ACTION_RECEIVED
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_RECEIVED) {
      ftpCmdSocket->clientFlag=NO_ACTION;
      if (ftpCmdSocket->received_cb != LUA_NOREF) {
        queue_msg_t msg;
        msg.L = gL;
        msg.source = onFTP;
        msg.para1 = file_status;
        msg.para3 = NULL;
        if (recv_type == RECV_TOSTRING) {
          msg.para3 = (uint8_t*)malloc(recvDataLen+4);
          if (msg.para3 != NULL) memcpy((char*)msg.para3, recvDataBuf, recvDataLen);
        }
        msg.para2 = ftpCmdSocket->received_cb;

        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
    }
    //REQ_ACTION_SENT
    else if (ftpCmdSocket->clientFlag == REQ_ACTION_SENT) {
      ftpCmdSocket->clientFlag=NO_ACTION;
      if (ftpCmdSocket->sent_cb != LUA_NOREF) {
        queue_msg_t msg;
        msg.L = gL;
        msg.source = onFTP;
        msg.para1 = file_status;
        msg.para3 = NULL;
        msg.para2 = ftpCmdSocket->sent_cb;

        mico_rtos_push_to_queue( &os_queue, &msg, 0);
      }
    }

    // ========== stage 2, check data send =====================================
    if ((ftpDataSocket != NULL) && ((status & FTP_SENDING))) {
      FD_ZERO(&wrset);
      FD_SET(ftpDataSocket->socket, &wrset);
      // check socket state
      select(ftpDataSocket->socket+1, NULL, &wrset, NULL, &t_val);
      
      if (FD_ISSET(ftpDataSocket->socket, &wrset)) {
        int err;
        if ((send_type & SEND_STRING)) err = _sendString();
        else err = _sendFile();
        if (err != 0) {
          closeDataSocket();
          // close file;
          if (file_fd != FILE_NOT_OPENED) {
            SPIFFS_close(&fs,file_fd);
            file_fd = FILE_NOT_OPENED;
            ftp_log("\r\n[FTP dta] Data file closed\r\n");
          }
          data_done = 1;
          status &= ~FTP_SENDING;
          ftpCmdSocket->clientFlag = REQ_ACTION_SENT;
        }
        continue;
      }
    }

    // ========== stage 3, check receive&disconnect ============================
    FD_ZERO(&readset);
    // ** select sockets to monitor for receive or disconnect
    int maxfd = ftpCmdSocket->socket;
    FD_SET(ftpCmdSocket->socket, &readset);
    if ( (ftpDataSocket != NULL) && ((status & FTP_DATACONNECTED)) ) {
      if (ftpDataSocket->socket > maxfd) maxfd = ftpDataSocket->socket;
      FD_SET(ftpDataSocket->socket, &readset);
    }
    // ** check sockets state
    select(maxfd+1, &readset, NULL, NULL, &t_val);

    // ** Check COMMAND socket
    if (FD_ISSET(ftpCmdSocket->socket, &readset)) {
      // read received data to buffer
      int rcv_len;
      if ((MAX_RECV_LEN-recvLen) > 1) {
        rcv_len = recv(ftpCmdSocket->socket, (recvBuf+recvLen), MAX_RECV_LEN-recvLen-1, 0);
      }
      else { // buffer full, ignore received bytes
        char tmpb[16];
        rcv_len = recv(ftpCmdSocket->socket, &tmpb[0], 16, 0);
      }
      
      if (rcv_len <= 0) { // failed
        ftp_log("\r\n[FTP cmd] Disconnect!\r\n");
        ftpCmdSocket->clientFlag = REQ_ACTION_DISCONNECT;
        continue;
      }
      
      recvLen += rcv_len;
      _checkCmdResponse(); // leave only the last line in buffer
      timeout = mico_get_time();
      recv_tmo = 0;
    }

    // ** Check DATA socket
    if ( (ftpDataSocket != NULL) && ((status & FTP_DATACONNECTED)) ) {
      if (FD_ISSET(ftpDataSocket->socket, &readset)) {
        // read received data to buffer
        int rcv_len = recv(ftpDataSocket->socket, (recvDataBuf+recvDataLen), max_recv_datalen-recvDataLen-1, 0);

        if (rcv_len <= 0) { // failed
          if (!(status & (FTP_RECEIVING | FTP_LISTING))) {
            ftp_log("\r\n[FTP dta] Disconnect!\r\n");
            closeDataSocket();
            file_status = -9;
            data_done = 1;
          }
          continue;
        }
        else {
          if ((status & FTP_RECEIVING) && (recv_type == RECV_TOFILE)) {
            // === write received data to file ===
            recvDataLen = rcv_len;
            _saveData(0);
            recvDataLen = 0;
          }
          else if ((status & FTP_LISTING) || ((status & FTP_RECEIVING) && (recv_type == RECV_TOSTRING))) {
            if ((recvDataLen + rcv_len) < (max_recv_datalen-16)) recvDataLen += rcv_len;
            else recvDataLen = max_recv_datalen-16;
            *(recvDataBuf + recvDataLen) = '\0';
          }
        }
        timeout = mico_get_time();
        recv_tmo = 0;
      }
    }

    // ===== nothing received ==================================================
    recv_tmo++;
    if (recv_tmo < 10) continue;
    
    recv_tmo = 0;

    // == Check if something was received from Command socket ==
    if (recvLen > 0) {
      // == Analize response ===
      response();
      recvLen = 0;
      memset(recvBuf, 0, MAX_RECV_LEN);
    }

    // == Check if Data socket was receiving ==
    if ((status & (FTP_RECEIVING | FTP_LISTING))) {
      // Finish all operattions on data socket
      if ((status & FTP_RECEIVING) && (recv_type == RECV_TOFILE)) {
        _saveData(1);
        recvDataLen = 0;
      }
      else {
        if ((status & FTP_RECEIVING) && (recv_type == RECV_TOSTRING)) {
          file_status = recvDataLen;
        }
        ftp_log("[FTP dta] Data received (%d)\r\n", recvDataLen);
      }
      
      if ((status & FTP_LISTING)) {
        status &= ~FTP_LISTING;
        ftpCmdSocket->clientFlag = REQ_ACTION_LIST_RECEIVED;
      }
      if ((status & FTP_RECEIVING)) {
        status &= ~FTP_RECEIVING;
        ftpCmdSocket->clientFlag = REQ_ACTION_RECEIVED;
      }

      // Close data socket
      closeDataSocket();
      data_done = 1;
    }
  } // while

terminate:
  _ftp_deinit(0);
  ftp_log("\r\n[FTP trd] FTP THREAD TERMINATED\r\n");
  ftp_thread_is_started = false;
  mico_rtos_delete_thread( NULL );
}