示例#1
0
/*!
 * \brief The MMI user-action task: in charge of launching an action requested
 * through the MMI.
 *
 */
static portTASK_FUNCTION( vSupervisorUserActionTask, pvParameters )
{
bool (*pfUserAction) (void);
bool result;

   /* Just to stop compiler warnings. */
   ( void ) pvParameters;

   for(;;)
   {
      /* 1) Suspend ourselves. */
      vTaskSuspend( NULL ); // TO KEEP
      // NOTE: the task should be resumed when it is necessary to perform a user action

      // get queue information
      if ( pdTRUE == xQueueReceive( xSUPERVISORQueue, &pfUserAction, ( portTickType ) 0 ) )
      {
        /* 2) Perform the action. */
        if (pfUserAction != NULL)
        {
          result = pfUserAction();
          if (result)
          {
            NAKED_TRACE_COM2( "User function succeed");
          }
          else
          {
            NAKED_TRACE_COM2( "User function failed");
          }
        }
      }
   }
}
示例#2
0
/*!
 * \brief Launch the "Upload CFG Files" MMI task that copies the /CFG directory
 * from the USB Mass Storage device to the Control Panel.
 *
 * \return pdTRUE
 *
 */
bool b_USBHostCopyCfg( void )
{
#if configCTRLPANEL_TRACE == 1
   eExecStatus       xRet;
#endif


   // Display User Menu Acting
   vMMI_SetUserMenuMode(eUserMenuUSBHostActing, pdFALSE);
   vTaskDelay( 3 ); // So that the supervisor task gets the focus to update the
                    // LCD screen.
   NAKED_TRACE_COM2( "Copy Config Files" );

   // Perform the task
#if configCTRLPANEL_TRACE == 1
   xRet =
#endif
   e_usbsys_cp_cfg_to_local( SYS_MODID_MMI, sMmiNavId, -1, NULL, NULL );
#if configCTRLPANEL_TRACE == 1
   if( SHELL_EXECSTATUS_KO == xRet )
      NAKED_TRACE_COM2( "Copying /CFG from USB MS device to Ctrl Panel failed.")
#endif

  // Display User Menu
  vMMI_SetUserMenuMode(eUserMenuUSBHost, pdFALSE);
  return (pdTRUE);
}
示例#3
0
/*!
 * \brief Print dev info on the trace port.
 */
void v_supervisor_trace( void )
{
#if configHEAP_INIT
#if __GNUC__
  prvCheckMallocHeap(); // Get an update of the malloc() heap highest consumption.
  NAKED_TRACE_COM2( "SUP:<%d><%d><%d>", TempoVbusOn, TempoVbusOff, pxHighestHeapAddr );
#endif
#else
  NAKED_TRACE_COM2( "SUP:<%d><%d>", TempoVbusOn, TempoVbusOff );
#endif
}
示例#4
0
/*!
 * \brief Do the required actions to leave the maintenance mode.
 *
 */
static void prv_v_leave_maintenance_mode( void )
{
#ifdef USB_ENABLE
#if USB_DEVICE_FEATURE == true
   // Release the semaphores and change the MMI user menu mode.
   prv_v_common_leave_UsbDevice_mode();

   // The actions to take to leave the maintenance mode are now done.
   bOutOfMaintenance = false;
   // We just left the USB Mass Storage device mode.
   // Special case: for com1shell, remount the local drive.
   v_com1shell_mount_local_drive();
#endif
#endif
   NAKED_TRACE_COM2( "Leaving maintenance mode");
}
示例#5
0
/*######## TEMPORARY #########################################*/
void prvCheckMallocHeap( void )
{
   portBASE_TYPE *pxMem;


   pxMem = ((portBASE_TYPE *)&__heap_end__) -1;
   while( (portBASE_TYPE *)&__heap_start__ != pxMem )
   {
      if( (portBASE_TYPE)0xA5A5A5A5 != *pxMem )
      {
         if( pxHighestHeapAddr < pxMem )
            pxHighestHeapAddr = pxMem;
         NAKED_TRACE_COM2( "worst@=%d", pxHighestHeapAddr );
         break;
      }
      else pxMem--;
   }
}
示例#6
0
/*! \brief send the static error page
 *
 *  \param pxNetCon     Input. The netconn to use to send and receive data.
 *  \param s            Input. The error code.
 *  \param extra_header Input. data to push in the error answer.
 *  \param text         Input. text to display in the error page.
 *
 */
static void prvweb_SendErrorPage(struct netconn *pxNetCon, int s, char* extra_header, const char* text )
{
portCHAR* title;
unsigned portLONG size;
portCHAR * err_data;

  err_data = (portCHAR *)pvPortMalloc(ERR_BUFFER_SIZE);
  if( NULL == err_data )
  {
    NAKED_TRACE_COM2( "prvweb_SendErrorPage(): mem alloc failed" );
    return;
  }
  /* Write the status line. */
  switch ( s )
  {
    case 400: title = "Bad Request"; break;
    case 401: title = "Unauthorized"; break;
    case 403: title = "Forbidden"; break;
    case 404: title = "Not Found"; break;
    case 408: title = "Request Timeout"; break;
    case 500: title = "Internal Error"; break;
    case 501: title = "Not Implemented"; break;
    case 503: title = "Service Unavailable"; break;
    default: title = "Something"; break;
  }
  /* add the header */
  size = prulweb_BuildHeaders(err_data, s, title, extra_header, "", "text/html");
  /* add the body */
  size += prulweb_BuildErrorBody(&err_data[size], s, title, text );
   /* add the tail */
  size += prulweb_BuildErrorTail(&err_data[size]);
  /* send the response to network */
  netconn_write(pxNetCon, err_data, size, NETCONN_COPY );
  /* free the buffer */
  vPortFree(err_data);
}
示例#7
0
/*! \brief parse the file request and send the requested file to the host
 *
 *  \param pxNetCon   Input. The netconn to use to send and receive data.
 *  \param filename   Input. The incoming filename.
 *
 */
static void prvweb_SendFile( struct netconn *pxNetCon, char* filename )
{
portLONG            size, header_size;
portLONG            fd = -1;
portCHAR            *resp_data;
unsigned portSHORT  i;
err_t               error;
pf_read_src         pfread = read;  // Set the default read to a file read.

  // NAKED_TRACE_COM2( "SendFile(): %s", filename );

  /* allocate response */
  resp_data = (portCHAR *)pvPortMalloc(webMAX_DATA_TO_SEND);

  if (resp_data != NULL)
  {
    /* add the header */
    header_size = prulweb_BuildHeaders(resp_data, 200, "OK", "", "", "text/html");

    if ((fd = open((const char *)filename, O_RDONLY)) < 0)
    {
      // Set the read function to read from the pcDefaultPage
      pfread = prv_read_default_page;
      size = x_default_page_len;
      NAKED_TRACE_COM2( "SendFile(): file not found. Default page len:%d", x_default_page_len );
    }
    else    /* get the file size */
    {
      size = fsaccess_file_get_size(fd);
    }

    /* check if file should be sent in a single frame */
    if ( size <= (webMAX_DATA_TO_SEND - header_size))
    {
      /* get the data from filesystem */
      if( pfread(fd,&resp_data[header_size],size) != size)
      {
        NAKED_TRACE_COM2( "SendFile(): short file read access error" );
        prvweb_SendErrorPage( pxNetCon, 404, filename, "Error during read access." );
        goto quit_send_page;
      }
      /* send the response to network */
      error = netconn_write(pxNetCon, resp_data, (u16_t)(header_size + size), NETCONN_COPY );
      if (error != 0)
      {
        NAKED_TRACE_COM2( "SendFile(): short file nw write error" );
        goto quit_send_page;
      }
    }
    else
    {
      /* send the header */
      error = netconn_write(pxNetCon, resp_data, header_size, NETCONN_COPY );
      if (error != 0)
      {
        NAKED_TRACE_COM2( "SendFile(): long file hdr nw write error" );
        goto quit_send_page;
      }

      /* try to send the biggest frame contained in the file */
      for (i = webNB_SECTOR_TO_SEND ; i > 0 ; i--)
      {
        /* get sectors of maximum size */
        while(size > i * FS_SIZE_OF_SECTOR)
        {
          /* get the data from filesystem */
          if( pfread(fd,resp_data, i * FS_SIZE_OF_SECTOR) !=  i * FS_SIZE_OF_SECTOR)
          {
            NAKED_TRACE_COM2( "SendFile(): long file read access error" );
            prvweb_SendErrorPage( pxNetCon, 404, filename, "Error during read access." );
            goto quit_send_page;
          }

          /* send the response to network */
          error = netconn_write(pxNetCon, resp_data, (u16_t)(i * FS_SIZE_OF_SECTOR), NETCONN_COPY );
          if (error != 0)
          {
            NAKED_TRACE_COM2( "SendFile(): long file nw write error" );
            goto quit_send_page;
          }

          size -= (i * FS_SIZE_OF_SECTOR);
        }
      }
      /* finish with the few data remaining (less than 1 sector)*/
      if ( size > 0 )
      {
        /* get the data from filesystem */
        if( pfread(fd,resp_data,size) != size)
        {
          NAKED_TRACE_COM2( "SendFile(): long file end read access error" );
          prvweb_SendErrorPage( pxNetCon, 404, filename, "Error during read access." );
          goto quit_send_page;
        }
        /* send the response to network */
        error = netconn_write(pxNetCon, resp_data, (u16_t)size, NETCONN_COPY );
        if (error != 0)
        {
          NAKED_TRACE_COM2( "SendFile(): long file end nw write error" );
          goto quit_send_page;
        }
      }
    }
  }// end if response != NULL
  else
  {
    NAKED_TRACE_COM2( "SendFile(): mem alloc failed" );
    __asm__ __volatile__ ("nop");
  }
quit_send_page:
  // vPortFree() handles the case where resp_data==NULL
  vPortFree(resp_data);
  /* close the file */
  // close() handles the case where fd is an invalid file descriptor.
  close(fd);
}
示例#8
0
文件: BasicSMTP.c 项目: Mazetti/asf
/*!
 *  \brief Task for SMTP management
 */
portTASK_FUNCTION( vBasicSMTPClient, pvParameters )
{

   struct sockaddr_in stServeurSockAddr;
   portLONG lRetval;
   portLONG lSocket = -1;
   portLONG ulResponseCode = 0;
   xMailDef * pxMail;
   int Size, SizeRead;
   portCHAR * pcRespData;
   int fd;
   portCHAR cToken[6];

   // Just to stop compiler warnings.
   ( void ) pvParameters;

   // Create the xMailsQueue capable of containing DATALOG_LOGSQUEUE_SIZE ptrs
   // to xLogDef structures.
   xMailsQueue = xQueueCreate( SMTP_MAILS_QUEUE_SIZE, sizeof( xMailDef * ) );

   // SMTP configuration.
   // Get the xCFGMutex.
   if( pdFALSE == x_supervisor_SemaphoreTake( xCFGMutex, 500 ) )
   {
      // Failed to get the CFG mutex, use the default HTTP config.
      uiSMTPPort = SMTP_PORT;
      cMailTo[0] = '\0';
      cMailFrom[0] = '\0';
      cServerName[0] = '\0';
   }
   // Mutex has been taken
   else
   {
      // get the field value for port number
      if (config_file_get_value(SMTP_CONFIG_FILE, "port" , cToken) >= 0)
      {
         sscanf(cToken, "%u", &uiSMTPPort);
      }
      // if it does not exist, use the default value
      else
      {
         uiSMTPPort = SMTP_PORT;
      }
      // try to get the mailto field
      if (config_file_get_value(SMTP_CONFIG_FILE, "mailto", cMailTo) < 0)
      {
         cMailTo[0] = '\0';
         // can't find field in config file, warn user
         NAKED_TRACE_COM2("Warning : No mailto configured !!Please fill mailto= field in %s\r\n", SMTP_CONFIG_FILE);
      }
      // try to get the mailfrom field
      if (config_file_get_value(SMTP_CONFIG_FILE, "mailfrom", cMailFrom) < 0)
      {
         cMailFrom[0] = '\0';
         // can't find field in config file, warn user
         NAKED_TRACE_COM2("Warning : No mailfrom configured !!Please fill mailfrom= field in %s\r\n", SMTP_CONFIG_FILE);
      }
      // try to get the server field
      if (config_file_get_value(SMTP_CONFIG_FILE, "server", cServerName) < 0)
      {
         cServerName[0] = '\0';
         // can't find field in config file, warn user
         NAKED_TRACE_COM2("Warning : No server name configured !! Please fill server= field in %s\r\n", SMTP_CONFIG_FILE);
      }
      // Release the xCFGMutex.
      x_supervisor_SemaphoreGive( xCFGMutex );
   }

   for(;;)
   {
      // NOTE: the task should be resumed when it is necessary to send a mail
      // Get the oldest mail from the queue.
      // NOTE: we are sure there is an item to get => no block time.
      if( pdTRUE == xQueueReceive( xMailsQueue, &pxMail, ( portTickType )1000 ) )
      {
         if (cServerName[0] == '\0')
         {
            // can't find field in config file, warn user
            NAKED_TRACE_COM2("Warning : No server name configured !! Please fill server= field in %s\r\n", SMTP_CONFIG_FILE);
         }
         else if (cMailTo[0] == '\0')
         {
            // can't find field in config file, warn user
            NAKED_TRACE_COM2("Warning : No mailto configured !!Please fill mailto= field in %s\r\n", SMTP_CONFIG_FILE);
         }
         else if (cMailFrom[0] == '\0')
         {
            // can't find field in config file, warn user
            NAKED_TRACE_COM2("Warning : No mailfrom configured !!Please fill mailfrom= field in %s\r\n", SMTP_CONFIG_FILE);
         }
         else
         {
            // Set up port
            memset(&stServeurSockAddr, 0, sizeof(stServeurSockAddr));
            stServeurSockAddr.sin_len = sizeof(stServeurSockAddr);
            stServeurSockAddr.sin_addr.s_addr = inet_addr(cServerName);
            stServeurSockAddr.sin_port = htons(uiSMTPPort);
            stServeurSockAddr.sin_family = AF_INET;

            // socket as a stream
            if ( (lSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            {
               // socket failed
               NAKED_TRACE_COM2("Socket Failed\r\n");
            }
            // connect to the server
            if(connect(lSocket,(struct sockaddr *)&stServeurSockAddr,sizeof(stServeurSockAddr)) < 0)
            {
               // connect failed
               NAKED_TRACE_COM2("Connect Failed\r\n");
            }
            else
            {
               eSMTPCurrentState = eSMTPIdle;
               while ( eSMTPCurrentState != eSMTPMailSent )
               {
                  // wait for SMTP Server answer
                  do
                  {
                     lRetval = recv(lSocket, cTempBuffer, sizeof(cTempBuffer), 0);
                  }while (lRetval <= 0);

                  cTempBuffer[3] = '\0';
                  // Get the response code from server
                  ulResponseCode = atoi(cTempBuffer);

                  switch (ulResponseCode)
                  {
                     case 220:
                     {
                        // send helo
                        send(lSocket, "HELO ", 5, 0);
                        send(lSocket, cServerName, strlen(cServerName), 0);
                        send(lSocket, "\r\n", 2, 0);
                        eSMTPCurrentState = eSMTPHeloSent;
                        break;
                     }
                     case 221:
                     {
                        // QUIT sequence has been acknowledged by server
                        if (eSMTPCurrentState == eSMTPQuitSent)
                        {
                           eSMTPCurrentState = eSMTPMailSent;
                        }
                        break;
                     }
                     case 250:
                     {
                        if (eSMTPCurrentState == eSMTPHeloSent)
                        {
                           // send MAIL FROM
                           send(lSocket, "MAIL FROM: <", 12, 0); ;
                           send(lSocket, cMailFrom, strlen(cMailFrom), 0);
                           send(lSocket, ">\r\n", 3, 0);
                           eSMTPCurrentState = eSMTPMailFromSent;
                        }
                        else if (eSMTPCurrentState == eSMTPMailFromSent)
                        {
                           // send MAIL TO
                           send(lSocket, "RCPT TO: <", 10, 0); ;
                           send(lSocket, cMailTo, strlen(cMailTo), 0);
                           send(lSocket, ">\r\n", 3, 0);
                           eSMTPCurrentState = eSMTPMailToSent;
                        }
                        else if (eSMTPCurrentState == eSMTPMailToSent)
                        {
                           // send DATA
                           send(lSocket, SMTP_DATA_STRING, 6, 0);
                           eSMTPCurrentState = eSMTPDataSent;
                        }
                        else if (eSMTPCurrentState == eSMTPContentSent)
                        {
                           // send QUIT
                           send(lSocket, SMTP_QUIT_STRING, 6, 0);
                           eSMTPCurrentState = eSMTPQuitSent;
                        }
                        break;
                     }
                     case 354:
                     {
                        if (eSMTPCurrentState == eSMTPDataSent)
                        {
                           // set Subject field
                           send(lSocket, "Subject:", 8, 0);
                           // add subject
                           send(lSocket, pxMail->Subject, strlen(pxMail->Subject), 0);
                           send(lSocket, "\r\nFROM:", 7, 0);
                           send(lSocket, cMailFrom, strlen(cMailFrom), 0);
                           send(lSocket, "\r\nTO:", 5, 0);
                           send(lSocket, cMailTo, strlen(cMailTo), 0);
                           send(lSocket, "\r\n\r\n", 4, 0);
                           // if a file has been specified, copy the content in the mail body
                           if (pxMail->File != NULL)
                           {
                              // allocate response
                              pcRespData = (portCHAR *)pvPortMalloc(SMTP_PACKET_SIZE);
                              if (pcRespData != NULL)
                              {
                                 if ((fd = open((const char *)pxMail->File, O_RDONLY)) >= 0)
                                 {
                                    Size = fsaccess_file_get_size(fd);
                                    // get sectors of maximum size
                                    while(Size > 0)
                                    {
                                       // get the data from filesystem
                                       SizeRead = read(fd, pcRespData, SMTP_PACKET_SIZE);
                                       // if error occurs during the read
                                       if (SizeRead <= 0)
                                       {
                                          // end the loop and send what has already been added
                                          break;
                                       }
                                       // sned data to the socket
                                       send(lSocket, pcRespData, SizeRead, 0);
                                       // decrease remaing size
                                       Size -= SizeRead;
                                    }
                                    // close the file
                                    close(fd);
                                    // free the buffer
                                    vPortFree(pcRespData);
                                 }
                                 else
                                 {
                                    // warn user : can't open the file
                                    NAKED_TRACE_COM2("Open file fails\r\n");
                                 }
                              }
                              else
                              {
                                 // warn user : can't malloc the file buffer
                                 NAKED_TRACE_COM2("SMTP : Malloc fails\r\n");
                              }
                           }
                           // add "<CRLF>.<CRLF>"
                           send(lSocket, SMTP_MAIL_END_STRING, 5, 0);
                           eSMTPCurrentState = eSMTPContentSent;
                        }
                        break;
                     }
                     default:
                     {
                        // unknown SMTP code
                        NAKED_TRACE_COM2("Unimplented %l SMTP response from server\r\n",ulResponseCode);
                        // break loop and reset state machine
                        eSMTPCurrentState = eSMTPMailSent;
                        break;
                     }
                  }
               }
               // close the socket
               close(lSocket);
            }
            // if the item was not posted from ISR
            if (pxMail->NeedFree == pdTRUE)
            {
               // if a file has been specified
               if ( pxMail->File != NULL )
               {
                  // free the item
                  vPortFree(pxMail->File);
               }
               // free the items
               vPortFree(pxMail->Subject);
               vPortFree(pxMail);
            }
         }
      }
   }
}
示例#9
0
/*! \brief parse the incoming request
 *         parse the HTML request and send file or execute CGI request
 *
 *  \param pxNetCon   Input. The netconn to use to send and receive data.
 *
 */
static void prvweb_ParseHTMLRequest( struct netconn *pxNetCon )
{
struct netbuf *pxRxBuffer;
portCHAR *pcRxString;
portCHAR *file;
portCHAR *path;
portCHAR *protocol;
unsigned portSHORT Length;
#if ( (LWIP_VERSION) != ((1U << 24) | (3U << 16) | (2U << 8) | (LWIP_VERSION_RC)) )
err_t    err_recv;
#endif

#if ( (LWIP_VERSION) == ((1U << 24) | (3U << 16) | (2U << 8) | (LWIP_VERSION_RC)) )
  /* We expect to immediately get data. */
  pxRxBuffer = netconn_recv( pxNetCon );
#else
  err_recv = netconn_recv( pxNetCon, &pxRxBuffer);
  if (err_recv != ERR_OK)
  {
    if (pxRxBuffer != NULL)
        goto delete_buffer;
    return;
  }
#endif

  if( pxRxBuffer != NULL )
  {
    /* Where is the data? */
    netbuf_data( pxRxBuffer, (void *) &pcRxString, &Length );
    /* Parse the first line of the request. */
    if ( pcRxString == (char*) 0 )
    {
      NAKED_TRACE_COM2( "ParseHTMLRequest(): empty request" );
      prvweb_SendErrorPage( pxNetCon, 400, "", "Wrong request : no action submitted." );
      goto delete_buffer;
    }
    /* get first occurrence of space char or \t or \n or \r */
    path = strpbrk( pcRxString, " \t\n\r" );
    if ( path == (char*) 0 )
    {
      NAKED_TRACE_COM2( "ParseHTMLRequest(): parse error" );
      prvweb_SendErrorPage( pxNetCon, 400, "", "Can't parse request." );
      goto delete_buffer;
    }
    *path++ = '\0';
    protocol = strpbrk( path, " \t\r\n" );
    *protocol++ = '\0';
    /* Is this a GET? */
    if( !strncmp( pcRxString, "GET", 3 ) )
    {
      if ( path[0] != '/' )
      {
         NAKED_TRACE_COM2( "ParseHTMLRequest(): wrong request" );
         prvweb_SendErrorPage( pxNetCon, 400, "", "Wrong request." );
         goto delete_buffer;
      }
      /* if there is a ?, this is a CGI request */
      protocol = strpbrk( path, "?" );
      if (protocol != NULL)
      {
        /* parse the CGI request */
        prvweb_ParseCGIRequest(pxNetCon, &path[1]);
        goto delete_buffer;
      }
      else
      {
        /* a file has been requested */
        file = (portCHAR *)pvPortMalloc((MAX_FILE_PATH_LENGTH * 2) + 4);
        if( NULL == file )
        {
           NAKED_TRACE_COM2( "ParseHTMLRequest(): mem alloc failed" );
           prvweb_SendErrorPage( pxNetCon, 400, "", "Memory allocation failed." );
           goto delete_buffer;
        }
        /* add web directory structure */
        sprintf(file,webSERVER_FOLDER);
        strcat(file,&(path[1]));
        /* check filename, if none, send index.htm */
        if ( file[sizeof(webSERVER_FOLDER)-1] == '\0' )
        {
          strcat(file,"index.htm");
        }
        /* go to the file transfer */
        prvweb_SendFile( pxNetCon, file );
        vPortFree(file);
      }
    }
    /* Is this a POST? */
    else if( !strncmp( pcRxString, "POST", 4 ) )
    {
      NAKED_TRACE_COM2( "ParseHTMLRequest(): POST request not supported" );
      prvweb_SendErrorPage( pxNetCon, 400, "", "POST request not supported for now." );
    }
    /* Is this a HEAD? */
    else if( !strncmp( pcRxString, "HEAD", 4 ) )
    {
      NAKED_TRACE_COM2( "ParseHTMLRequest(): HEAD request not supported" );
      prvweb_SendErrorPage( pxNetCon, 400, "", "HEAD request not supported for now." );
    }
    /* We don't handle anything else. */
    else
    {
      NAKED_TRACE_COM2( "ParseHTMLRequest(): unexpected request" );
      prvweb_SendErrorPage( pxNetCon, 400, "", "Can't parse request." );
    }
  }
  else
  {
    NAKED_TRACE_COM2( "ParseHTMLRequest(): nothing rxed" );
  }


delete_buffer: // netbuf_delete() handles the case when pxRxBuffer == NULL
  netbuf_delete( pxRxBuffer );
}
示例#10
0
/*! \brief parse the CGI request and send it to the shell
 *
 *  \param pxNetCon   Input. The netconn to use to send and receive data.
 *  \param request    Input. The incoming CGI request.
 *
 */
static void prvweb_ParseCGIRequest( struct netconn *pxNetCon, char* request )
{
portCHAR cgi_present = false, loop;
signed portCHAR * pcStringCmd;
signed portCHAR * CurrentChar;
signed portCHAR * pcStringReply;
eExecStatus       xExeStatus;
portCHAR *pcResp_data;
portLONG header_size;

  /* when entering this function, path contains :
               command.cgi?arg1=val1&arg2=val2
  it should be command arg1=val1 arg2=val2 after parsing operation */

  /* allocate command space */
  pcStringCmd = pvPortMalloc( 100 );
  if (pcStringCmd != NULL)
  {

    loop = true;
    CurrentChar = pcStringCmd;
    while (loop)
    {
      switch (*request)
      {
        case '.':
        {
          if (cgi_present == false)
          {
            cgi_present = true;
            request += strlen(".cgi");
          }
          else
          {
            *CurrentChar++ = *request++;
          }
        break;
        }
        /* move ? and & to space */
        case '?':
        case '&':
          *CurrentChar++ = ' ';
          request++;
        break;
        case '%':
          /* move %20 to space */
          if ((*(request+1) == '2') && (*(request+2) == '0'))
          {
            *CurrentChar++ = ' ';
            request += 3;
          }
          /* keep %22 */
          else if ((*(request+1) == '2') && (*(request+2) == '2'))
          {
            *CurrentChar++ = '"';
            request += 3;
          }
          /* else keep the % symbol */
          else
          {
            *CurrentChar++ = *request++;
          }
        break;
        case '\r':
        case '\n':
        case '\0':
        case ' ':
          *CurrentChar = '\0';
          loop = false;
        break;
        default:
          *CurrentChar++ = *request++;
        break;
      }
    }

    /* send command to the shell, no error control for this module */
    xExeStatus = Shell_exec(pcStringCmd, SYS_MODID_HTTP, -1, &pcStringReply);
    /* free buffer */
    vPortFree(pcStringCmd);

    if (pcStringReply != NULL)
    {
        pcResp_data = pvPortMalloc( 130 + strlen( (char *)pcStringReply ) ); // 130(header size) + sizeof( reply )
        if( NULL == pcResp_data )
        {
           if( SHELL_EXECSTATUS_OK == xExeStatus )
           {
              vPortFree(pcStringReply);
           }
           NAKED_TRACE_COM2( "ParseCGIRequest(): reply mem alloc failed" );
           // Avoid returning an error page so that the remote web browser keeps
           // on trying.
           return;
        }
        /* add the header */
        header_size = prulweb_BuildHeaders( pcResp_data, 200, "OK", "", "", "text/html");
        // Add the data.
        strcpy( pcResp_data + header_size, (char *)pcStringReply );
        if( SHELL_EXECSTATUS_OK == xExeStatus )
        {
           vPortFree(pcStringReply);
        }

        /* send the response to network */
        netconn_write(pxNetCon, pcResp_data, (u16_t)strlen( pcResp_data ), NETCONN_COPY );
        vPortFree( pcResp_data );
    }
  }
  else
  {
    NAKED_TRACE_COM2( "ParseCGIRequest(): request mem alloc failed" );
    // Avoid returning an error page so that the remote web browser keeps on trying.
  }
}
示例#11
0
/*! \brief The set time config command: set each config field value of the time module.
 *         Takes one parameter : field=value
 *
 *  \note  This function must be of the type pfShellCmd defined by the shell module.
 *
 *  \param xModId         Input. The module that is calling this function.
 *  \param FsNavId        Ignored.
 *  \param ac             Input. The argument counter. For this command, should be 1.
 *  \param av             Input. The argument vector.
 *  \param ppcStringReply Input/Output. The response string.
 *                        If Input is NULL, no response string will be output.
 *                        Else a malloc for the response string is performed here;
 *                        the caller must free this string.
 *
 *  \return the status of the command execution.
 */
eExecStatus e_cptime_cmd_set_config( eModId xModId, signed short FsNavId,
                                     int ac, signed portCHAR *av[],
                                     signed portCHAR **ppcStringReply )
{
   /* int           fd;
   eFsCmdsStatus eFsStatus; */
   struct tm     xLogDate;
   time_t        xRawDate;
   int           i;
   int           SrcIdx=0;


   // NOTE: currently the only configurable item of the time module is the
   // current time. "curtime=mm/dd/yy hh:mm:ss"

   // 1) Check the input.
   //  i) Exactly two arguments (the field and the value).
   if( 2 != ac )
   {   // Syntax error.
      if(ppcStringReply != NULL)
         *ppcStringReply = (signed portCHAR *)CPTIME_ERRMSG_SETCFG_SYNTAXERROR;
      return( SHELL_EXECSTATUS_KO );
   }

   // The field must be one of : {curtime}
   if( !strcmp("curtime", (char *)av[0]) )
   {
      // 2) Read the current time string
      sscanf( (char *)av[1], "%02d/%02d/%02d %02d:%02d:%02d",
              &(xLogDate.tm_mon), &(xLogDate.tm_mday), &(xLogDate.tm_year),
              &(xLogDate.tm_hour), &(xLogDate.tm_min), &(xLogDate.tm_sec) );
      (xLogDate.tm_mon)--; // Adjust to the logic where January index is 0.
      // WARNING: pxLogDate->tm_year == number of years since 1900.
      // We get the last 2 digits only : we suppose the year is >= 2000.
      xLogDate.tm_year += 100;
      xLogDate.tm_isdst = 0; // Daylight saving time info is not in effect.

      // Convert time broken-down representation to arithmetic representation.
      xRawDate = mktime( &xLogDate );

      if( -1 == xRawDate )
      {
         if(ppcStringReply != NULL)
            *ppcStringReply = (signed portCHAR *)CPTIME_ERRMSG_SETCFG_INVALIDDATE;
         return( SHELL_EXECSTATUS_KO );
      }
      else
      {
         NAKED_TRACE_COM2( "CPTIME:NbSchedCmd=%d", NbSchedCmd );
         // Update all cells of the scheduled commands array: cancel the schedules
         // that are in the past but keep the schedules that are still in the future.
         for( i=NbSchedCmd-1; i>=0; i-- )
         {
            if( axCmdsSched[i].xScheduledTime <= xRawDate )
            {    // This schedule is in the past => cancel it and all other cells
                 // that are further down the past.
               // NOTE: all below scheduled commands are obsolete if this one is.
               // => Cancel them too.
               SrcIdx = i+1; // Remember the last active scheduled commands index.
               for( i=0; i<SrcIdx; i++ )
               {
                  axCmdsSched[i].xScheduledTime = 0; // Mark this cell as unused.
                  NbSchedCmd--; // One scheduled cmd removed.
               }
               NAKED_TRACE_COM2( "CPTIME:NbSchedCmd=%d, SrcIdx=%d", NbSchedCmd, SrcIdx );
               break;
            }
         }

         // Shift the Scheduled Commands array down to the index 0.
         if( ( 0 != NbSchedCmd ) && ( CPTIME_MAX_NB_SCHED_CMDS > SrcIdx ) )
         {
            NAKED_TRACE_COM2( "CPTIME:Shifting array from SrcIdx=%d to 0 idx", SrcIdx );
            prv_v_ShiftScheduledCmdsArray( SrcIdx, 0 );
         }

         // Switch to new time.
         xcptime_LocalTime = xRawDate;
      }
   }
   else
   {   // Unsupported field.
      if(ppcStringReply != NULL)
         *ppcStringReply = (signed portCHAR *)CPTIME_ERRMSG_SETCFG_UNKNOWNFIELD;
      return( SHELL_EXECSTATUS_KO );
   }
   return( SHELL_EXECSTATUS_OK );


/****** CODE TO USE WHEN THERE ARE OTHER FIELDS THAN CURTIME.
   if ((fd = open(TIME_CONFIG_FILE, (O_RDWR))) >= 0)
   {
      if (config_file_set_value(fd, ac, av) != 0)
      {
         if(ppcStringReply != NULL)
         {
            *ppcStringReply = (signed portCHAR *)SHELL_ERRMSG_CONFIGERROR;
         }
         return( SHELL_EXECSTATUS_KO );
      }
      close (fd);

      return( SHELL_EXECSTATUS_OK );
   }
   else
   {
      eFsStatus = e_fscmds_CheckNavError(); // Get the fs error.
      if( ppcStringReply != NULL )
      {
         v_fscmds_GetStrMsgFromErr(eFsStatus, ppcStringReply);
      }
      return( SHELL_EXECSTATUS_KO );
   }
******/

}
示例#12
0
/*!
 * \brief Print dev info on the trace port.
 */
void v_basicweb_trace( void )
{
   NAKED_TRACE_COM2( "BASICWEB:<%d>", sCurrentNbHTTPConn );
}
示例#13
0
/*!
 * \brief Print dev info on the trace port.
 */
void v_cptime_trace( void )
{
   NAKED_TRACE_COM2( "CPTIME:<%d><%d>", NbSchedCmd, xcptime_LocalTime );
}
示例#14
0
/*!
 *  \brief The switch-to-maintenance-mode command: initiate the process to \n
 *         switch to maintenance mode.
 *         Format: maintain
 *
 *  \note  This function must be of the type pfShellCmd defined by the shell module.
 *
 *  \param xModId         Input. The module that is calling this function.
 *  \param FsNavId        Ignored.
 *  \param ac             Ignored.
 *  \param av             Ignored.
 *  \param ppcStringReply Input/Output. The response string.
 *                        If Input is NULL, no response string will be output.
 *                        Else a malloc for the response string is performed here;
 *                        the caller must free this string.
 *
 *  \return the status of the command execution.
 */
eExecStatus e_supervisor_switch_to_maintenance_mode( eModId xModId,
                              signed short FsNavId,
                              int ac, signed portCHAR *av[],
                              signed portCHAR **ppcStringReply )
{
   if( NULL != ppcStringReply )
      *ppcStringReply = NULL;

#ifdef USB_ENABLE
#if USB_DEVICE_FEATURE == true
   if( ( false == bIsInMaintenance )
       && ( 0 == u8IsMaintenanceRequired ) )
   {   // We're not in maintenance mode.
      // Initiate the process of switching to maintenance mode.
      if( 0 == u8IsMaintenanceRequired )   u8IsMaintenanceRequired++;

      // Take all maintenance mutex except the USB mutex.
      if( true == x_supervisor_SemaphoreTake( xLOGMutex, 0 ) )       u8IsMaintenanceRequired++;
#if NW_INTEGRATED_IN_CONTROL_PANEL
      if( true == x_supervisor_SemaphoreTake( xWEBMutex, 0 ) )       u8IsMaintenanceRequired++;
#endif
      if( true == x_supervisor_SemaphoreTake( xSHELLFSMutex, 0 ) )   u8IsMaintenanceRequired++;
      if( true == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) )       u8IsMaintenanceRequired++;

      // If all mutexes have been acquired, switch to maintenance mode.
      if( ( SUPERVISOR_MAINTENANCE_NBMUTEX_TOTAKE +1 ) == u8IsMaintenanceRequired )
      {
         fat_cache_flush(); // flush the FAT cache.
         nav_reset();       // Reset all file system navigators. We will mount
                            // the com1shell default drive when we'll leave the
                            // maintenance mode.
         // Switch to maintenance mode.
         xSemaphoreGive( xUSBMutex );

         // If the USB clock is frozen, unfreeze it so that we can write in the
         // USB registers.
         if(true == Is_usb_clock_frozen())
         {
           Usb_unfreeze_clock();
         }
         // If it is not akready detached, physically detach the USB device.
         if(false == Is_usb_detached())
         {
           Usb_detach();
         }
         vTaskDelay(500); // Wait 500ms
         Usb_attach();     // Reconnect the device.

         bIsInMaintenance = true;
         u8IsMaintenanceRequired = 0;
         TRACE_COM2( "Entering maintenance mode");
#ifdef MMILCD_ENABLE
         vMMI_SetUserMenuMode( eUserMenuWaitHost, pdTRUE );
#endif
      }
      // ELSE: we'll switch to maintenance mode in x_supervisor_SemaphoreGive()
      // (when the mutex(es) that we couldn't get will be released).
   }
   else
   {
      NAKED_TRACE_COM2( "Won't go to maintenance mode:"CRLF"bIsInMaintenance=%d u8CurrentUsbRole=%d u8IsMaintenanceRequired=%d", bIsInMaintenance, u8CurrentUsbRole, u8IsMaintenanceRequired );
   }
#endif
#endif

   return( SHELL_EXECSTATUS_OK );
}
示例#15
0
文件: datalog.c 项目: Mazetti/asf
/*!
 * \brief Print dev info on the trace port.
 */
void v_datalog_trace( void )
{
   NAKED_TRACE_COM2( "DATALOG:<%d><%d>", uxNbMsgsInLogsQueue, u8FreeLogIdx );
}
示例#16
0
文件: datalog.c 项目: Mazetti/asf
/*!
 * \brief Open the current log file.
 *
 * \return the file descriptor or -1 if open failed.
 */
static int prv_xopen_current_logfile( void )
{
   int       fd_current_logfile;
   struct tm *pxDate;


   // TRACE_COM2( "open logfile begin==%d", xcptime_LocalTime );

   while( 1 )
   {
      fd_current_logfile = -1; // Init to default value.

      /* Open the log file. */
      if( '\0' != *acLogFileName )
      {   // If we have an active current log file, simply open it in append mode.
         fd_current_logfile = open( acLogFileName, O_APPEND );

         // Check if the max file size has been reached.
         if( -1 != fd_current_logfile )
         {
            if( DATALOG_LOGFILE_MAXSIZE <= fsaccess_file_get_size( fd_current_logfile ) )
            {   // The current log file has reached the max size.
               // Get the current time in the "YYYYMMDDHHMMSSMS" string format.
               v_cptime_GetDateInFatStringFormat( pcTempoDate );
               // Set the file date.
               nav_file_dateset( (FS_STRING)pcTempoDate, FS_DATE_LAST_WRITE );
               close( fd_current_logfile ); // Close the file.
               *acLogFileName = '\0';       // Reset the current log file name.
               continue; // Do another loop to create/open a new file.
            }
         }
         else
         {  // The file has been removed.
            *acLogFileName = '\0'; // Reset the current log file name.
            continue;              // Do another loop to create/open a new file.
         }
      }
      else
      {   // Create a new log file.
         // Get the broken-down representation of the current date.
         pxDate = gmtime( &xcptime_LocalTime );

         // Build the filename: mmddyy_hhmm.log
         // WARNING: pxDate->tm_year == number of years since 1900.
         // For years >= 2000, we'll display the last 2 digits only.
         if( pxDate->tm_year >= 100 )
            pxDate->tm_year -= 100;

         sprintf( acLogFileName, "%s/%.2d%.2d%.2d_%.2d%.2d.log",
                  pcStringCurrentLogDirectoryName, pxDate->tm_mon +1, pxDate->tm_mday,
                  pxDate->tm_year, pxDate->tm_hour, pxDate->tm_min );

         NAKED_TRACE_COM2( "Creating log file %s", acLogFileName );

         // Create the log file only if the /LOG directory exists.
         if( true == fsaccess_IsDirPresent( (const char *)pcStringCurrentLogDirectoryName ) )
         {     // The LOG/ directory exists.
            // Create and open the file.
            // if the file already exists, then the file size is reset.
            fd_current_logfile = open( acLogFileName, (O_CREAT|O_WRONLY) );
            // previous file is closed, send a mail
            if ( *acPreviousLogFileName != '\0' )
            {
               // post alarm to SMTP task
               v_SMTP_Post(acPreviousLogFileName, acPreviousLogFileName);
            }
            strncpy(acPreviousLogFileName, acLogFileName, strlen(acLogFileName));
         }
      }
      if( -1 == fd_current_logfile )
      {   // The open failed. We're not in maintenance mode.
         // Just remove the oldest log file: TODO
         NAKED_TRACE_COM2( "Failed opening the current log file %s", acLogFileName );
         /*########### TEMPORARY #############*/
         break;
         /*###################################*/
      }
      else break;
   }

   return( fd_current_logfile );
}
示例#17
0
/*!
 * \brief Supervisor task.
 *
 * \return never
 */
static portTASK_FUNCTION( vSupervisorTask, pvParameters )
{
   portTickType xDelayLength = SUPERVISOR_DEFAULT_PERIOD;
   portTickType xLastFocusTime;
#if configHEAP_INIT == 1
#if defined(__GNUC__)
   portLONG     lCheckHeapDelay = 1;
#endif
#endif
#if configCTRLPANEL_TRACE == 1
   portLONG     lPrintTrace = 3;
#endif
   portLONG     lUpdateTimeDelay = 1;
#ifdef MMILCD_ENABLE
   portLONG     lUpdateMMITimeDelay = 1;
   portCHAR DateTime[21];
   struct tm *pxDate;
   bool ms_connected_displayed = pdFALSE;
   bool enum_connected_displayed = pdFALSE;
#endif

   /* The parameters are not used. */
   ( void )pvParameters;

#if configCTRLPANEL_TRACE == 1
   /* Initialize the dump port COM2. */
   itracedump_Init();
#endif

#ifdef MMILCD_ENABLE
   // The MMI module.
   if( pdFALSE == bMMI_start() )
   {
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }
#endif

   // Create the SHELL mutex.
   vSemaphoreCreateBinary( xSHELLFSMutex );
   if( NULL == xSHELLFSMutex )
   { // The mutex creation failed.
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }
   // Start the COM1 Shell module.
   vStartCom1Shell( mainCOMSH_TASK_PRIORITY );

   // Create the CFG mutex.
   vSemaphoreCreateBinary( xCFGMutex );
   if( NULL == xCFGMutex )
   { // The mutex creation failed.
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }

   // Start the sensor module.
   if( false == bsensor_start() )
   {
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }

#if NW_INTEGRATED_IN_CONTROL_PANEL
   // Create the Web server mutex.
   vSemaphoreCreateBinary( xWEBMutex );
   if( NULL == xWEBMutex )
   { // The mutex creation failed.
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }
   // Start network tasks.
   vStartEthernetTaskLauncher( tskIDLE_PRIORITY + 1 );
#endif

   // Create the LOG mutex.
   vSemaphoreCreateBinary( xLOGMutex );
   if( NULL == xLOGMutex )
   { // The mutex creation failed.
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }
   // Start the data logger module.
   if( false == bdatalog_start( mainDATALOG_TASK_PRIORITY ) )
   {
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }

#ifdef USB_ENABLE
#if USB_DEVICE_FEATURE == true
   // Create the USB mutex.
   vSemaphoreCreateBinary( xUSBMutex );
   if( NULL == xUSBMutex )
   { // The mutex creation failed.
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }
   // Immediately take the USB mutex. i.e. when we're a Mass Storage device,
   // we'll refuse to give r/w access to the host until a user action. This user
   // action will make the Ctrl Panel device switch to maintenance mode, in which
   // the Mass Storage USB host has r/w access to the Ctrl Panel file system.
   while( pdFALSE == x_supervisor_SemaphoreTake( xUSBMutex, 0 ) );
#endif
   // Start the USB module tasks.
   if( false == b_usbsys_start() )
   {
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }
#endif

#ifdef MMILCD_ENABLE
   // Create the supervisor queue to deal with MMI actions
   xSUPERVISORQueue = xQueueCreate( SUPERVISOR_QUEUE_SIZE, sizeof(bool *) );
   if( 0 == xSUPERVISORQueue )
   {
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }

   /* Get a File System navigator for MMI actions. */
   fsaccess_take_mutex();
   sMmiNavId = fsaccess_alloc_nav_id();
   nav_select( sMmiNavId );   // Select the navigator.
   fsaccess_give_mutex();

   /* Spawn the User Action task. */
   if( pdPASS != xTaskCreate( vSupervisorUserActionTask,
                              ( const signed portCHAR * )"MMIACT",
                              SUPERVISOR_USER_ACTION_STACK_SIZE, NULL, SUPERVISOR_USER_ACTION_TASK_PRIORITY,
                              &xSupervisorUserActionHndl ) )
   {
      vTaskDelete( xSupervisorUserActionHndl );
      // TODO: Add msg on LCD.
      // vParTestSetLED( ERROR_LED_ID, pdTRUE );
      while( 1 );
   }
#endif // #ifdef MMILCD_ENABLE

   /* We need to initialise xLastFlashTime prior to the first call to vTaskDelayUntil(). */
   xLastFocusTime = xTaskGetTickCount();

#if defined(__GNUC__)
   NAKED_TRACE_COM2( "heap start @=%d, heap end @=%d", \
                     (portBASE_TYPE *)&__heap_start__, \
                     (portBASE_TYPE *)&__heap_end__ );
#endif

   /* Enable the watchdog timer. */
   // wdt_enable( SUPERVISOR_WDT_TIMEOUT );

   for(;;)
   {
      /* Delay for the flash period then check. */
      vTaskDelayUntil( &xLastFocusTime, xDelayLength );

      // wdt_clear(); // Kick the watchdog!

      /* MMI USB management. */
#ifdef MMILCD_ENABLE
#ifdef USB_ENABLE
/*** Start of Host behaviour ***/
      // first occurrence of MS connection, Host mode
      if (ms_connected == true && ms_connected_displayed == pdFALSE)
      {
        // display connected logo
        ms_connected_displayed = pdTRUE;
        vMMI_DisplayUSBState(ms_connected_displayed);
        // Display User Menu
        vMMI_SetUserMenuMode(eUserMenuUSBHost, pdTRUE);

      }
      // first occurrence of MS disconnection, end of Host mode
      if (ms_connected == false && ms_connected_displayed == pdTRUE)
      {
        // remove connected logo
        ms_connected_displayed = pdFALSE;
        vMMI_DisplayUSBState(ms_connected_displayed);
        // clear User Menu
        vMMI_SetUserMenuMode(eUserMenuIdle, pdTRUE);
      }
/*** End of Host behaviour ***/
/*** Start of Device behaviour ***/
#if USB_DEVICE_FEATURE == true
      // first occurrence of Device connection, Device mode
      if (Is_device_enumerated() && ( enum_connected_displayed == pdFALSE ) )
      {
        if( true == bIsInMaintenance )
        {
          // display connected logo
          enum_connected_displayed = pdTRUE;
          vMMI_DisplayUSBState(enum_connected_displayed);
          // Display User Menu
          vMMI_SetUserMenuMode(eUserMenuUSBDevice, pdTRUE);
        }
      }
      // first occurrence of Device disconnection, end of Device mode
      else if (!Is_device_enumerated() && enum_connected_displayed == pdTRUE)
      {
        // remove connected logo
        enum_connected_displayed = pdFALSE;
        vMMI_DisplayUSBState(enum_connected_displayed);
        // clear User Menu
        vMMI_SetUserMenuMode(eUserMenuIdle, pdTRUE);
      }
      else
      {
        // remove connected logo => this makes the USB logo blink when the Control
        // Panel is behaving as a USB key.
        enum_connected_displayed = pdFALSE;
        vMMI_DisplayUSBState(enum_connected_displayed);
      }
/*** End of Device behaviour ***/
#endif // #if USB_DEVICE_FEATURE == true
#endif // #ifdef USB_ENABLE
#endif // #ifdef MMILCD_ENABLE

      /* update time every SUPERVISOR_DELAY_TIMEUPDATE seconds. */
      if( 0 == --lUpdateTimeDelay )
      {
         /* Update the local time. */
         lUpdateTimeDelay = SUPERVISOR_DELAY_TIMEUPDATE;
         xcptime_LocalTime++;
         // v_cptime_UpdateLocalTime();
      }

#ifdef MMILCD_ENABLE
      /* Update time displayed on the LCD. */
      if( 0 == --lUpdateMMITimeDelay)
      {
         // Get the broken-down representation of the current date.
         pxDate = gmtime( &xcptime_LocalTime );

         // WARNING: pxDate->tm_year == number of years since 1900.
         // For years >= 2000, we'll display the last 2 digits only.
         if( pxDate->tm_year >= 100 )  pxDate->tm_year -= 100;
#if DISPLAY_MMI_SECOND == 1
         sprintf( DateTime, "%02d/%02d/20%02d  %02d:%02d:%02d", pxDate->tm_mon +1, pxDate->tm_mday,
                            pxDate->tm_year, pxDate->tm_hour, pxDate->tm_min, pxDate->tm_sec );
#else
         sprintf( DateTime, "%02d/%02d/20%02d     %02d:%02d", pxDate->tm_mon +1, pxDate->tm_mday,
                            pxDate->tm_year, pxDate->tm_hour, pxDate->tm_min );
#endif
         vMMI_DisplayDateAndTime(DateTime);
         lUpdateMMITimeDelay = SUPERVISOR_DELAY_MMI_TIMEUPDATE;
      }

      // Manage MMI
      vMMI_Manage();

      // Manage MMI user action
      prv_v_manage_user_action();
#endif // #ifdef MMILCD_ENABLE

#ifdef USB_ENABLE
      if( true == bOutOfMaintenance )
      {
         prv_v_leave_maintenance_mode();
      }
#endif

      /* Execute a scheduled command if expiration date is up. */
      v_cptime_ExecuteScheduledCmd();

#if configHEAP_INIT == 1
#if defined(__GNUC__)
      /* Record the malloc() heap highest consumption every SUPERVISOR_DELAY_HEAPCHECK seconds. */
      if( 0 == --lCheckHeapDelay )
      {
         lCheckHeapDelay = SUPERVISOR_DELAY_HEAPCHECK;
         prvCheckMallocHeap();
      }
#endif
#endif

#if configCTRLPANEL_TRACE == 1
      // Display traces on USART1 every SUPERVISOR_DELAY_PRINTTASKLIST seconds.
      if( 0 == --lPrintTrace )
      {
         lPrintTrace = SUPERVISOR_DELAY_PRINTTASKLIST; // Restart the delay.
         v_syscmds_display_traces();
      }
#endif

   } // for(;;)
} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */