/*! * \brief Init the push button 3 sensor. * * \return true upon success, false if error. */ bool b_pushb3_init ( void ) { portCHAR token[6]; // Get the xCFGMutex. if( pdTRUE == x_supervisor_SemaphoreTake( xCFGMutex, 20 ) ) { // get the field if (config_file_get_value(SENSOR_PB3_CONFIG_FILE, "alarm" , token) >= 0) { // update value if (!strcmp(token, "on")) { bAlarm3 = pdTRUE; } } // Release the xCFGMutex. x_supervisor_SemaphoreGive( xCFGMutex ); } /* configure push button to produce IT on input change */ gpio_enable_pin_interrupt(PB3_POSITION , GPIO_PIN_CHANGE); /* Disable all interrupts */ Disable_global_interrupt(); /* register push button 3 handler on level 3 */ INTC_register_interrupt( (__int_handler)&vpushb_ISR, AVR32_GPIO_IRQ_0 + (PB3_POSITION/8), AVR32_INTC_INT3); /* Enable all interrupts */ Enable_global_interrupt(); return (true); }
//! //! @brief USB Command Block Wrapper (CBW) management //! //! This function decodes the CBW command and stores the SCSI command. //! static void usb_mass_storage_cbw(void) { bool cbw_error; Usb_reset_endpoint_fifo_access(EP_MS_OUT); //! Check if dCBWSignature is correct cbw_error = (Usb_read_endpoint_data(EP_MS_OUT, 32) != *(U32 *)&"USBC"); //! Store CBW Tag to be repeated in CSW dCBWTag = Usb_read_endpoint_data(EP_MS_OUT, 32); g_scsi_data_remaining = Usb_read_endpoint_data(EP_MS_OUT, 32); g_scsi_data_remaining = usb_format_usb_to_mcu_data(32, g_scsi_data_remaining); //! if (bmCBWFlags.bit7 == 1) {direction = IN;} if (Usb_read_endpoint_data(EP_MS_OUT, 8)) { ms_endpoint = EP_MS_IN; if (cbw_error) { Usb_ack_out_received_free(EP_MS_OUT); Usb_enable_stall_handshake(EP_MS_IN); return; } } else { ms_endpoint = EP_MS_OUT; if (cbw_error) { Usb_enable_stall_handshake(EP_MS_OUT); Usb_ack_out_received_free(EP_MS_OUT); return; } } usb_LUN = Usb_read_endpoint_data(EP_MS_OUT, 8); if (!ms_multiple_drive) { usb_LUN = get_cur_lun(); } //! Dummy CBWCBLength read Usb_read_endpoint_data(EP_MS_OUT, 8); //! Store scsi_command usb_read_ep_rxpacket(EP_MS_OUT, g_scsi_command, sizeof(g_scsi_command), NULL); Usb_ack_out_received_free(EP_MS_OUT); // Take the USB Mutex(i.e. we're allowed to perform a ms cmd). /* if( ( pdFALSE == ( xGiveUsbMutex = x_supervisor_SemaphoreTake( xUSBMutex, 0 ) ) ) || ( !scsi_decode_command() && g_scsi_data_remaining ) ) */ if( ( pdFALSE == (xGiveUsbMutex = x_supervisor_SemaphoreTake( xUSBMutex, 0 ) ) ) || ( !scsi_decode_command() && g_scsi_data_remaining ) ) { Usb_enable_stall_handshake(ms_endpoint); } }
/*! * \brief The log-to-file task. * */ static portTASK_FUNCTION( vLogToFileTask, pvParameters ) { int fd_current_logfile; /* Just to stop compiler warnings. */ ( void ) pvParameters; xDataLogStatus = SYS_STATUS_RUNNING; /* Init the current log file name. */ *acLogFileName = '\0'; *acPreviousLogFileName = '\0'; for(;;) { /* 1) Suspend ourselves. */ vTaskSuspend( NULL ); // TO KEEP // NOTE: the task should be resumed when it is necessary to log the data // to the current log file, i.e.: // (*) if the xLogQueue is 75% full, // OR // (*) if the vDataLog_FlushLogs() has been called. // Take the data logger system mutex. if( false == x_supervisor_SemaphoreTake( xLOGMutex, 0 ) ) // 0 == Do not wait for the mutex. { // Pop the oldest logs from the logs queue so that the Control Panel // can still do logs acquisition. prv_vsave_logs( -1 ); continue; } /* 2) Log the data into the current log file. */ // 2a) Open the current log file. fd_current_logfile = prv_xopen_current_logfile(); /* if( -1 == fd_current_logfile ) { // Should never happen (cf prv_xopen_current_logfile() final implem.) continue; } */ // Although the open should not fail, if it happens(!!!), prv_vsave_logs() // will correctly handle the (-1) value by just poping the oldest logs from // the logs queue. // 2b) Move each item of the queue to the log file then close the file. prv_vsave_logs(fd_current_logfile); // Release the data logger system mutex. x_supervisor_SemaphoreGive( xLOGMutex ); } }
/*! * \brief Init the temperature channel. * * \return true upon success, false if error. */ bool b_temperature_init ( void ) { portCHAR token[6]; portCHAR * unit; // Get the xCFGMutex. if( pdTRUE == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) ) { // get the field if (config_file_get_value(SENSOR_TEMP_CONFIG_FILE, "alarm" , token) >= 0) { // update value if (!strcmp(token, "on")) { b_temp_alarm = pdTRUE; } } if (config_file_get_value(SENSOR_TEMP_CONFIG_FILE, "min" , token) >= 0) { unit = strpbrk(token , "C"); if (unit != NULL) { *unit = '\0'; } l_temp_min = atol(token); } if (config_file_get_value(SENSOR_TEMP_CONFIG_FILE, "max" , token) >= 0) { unit = strpbrk(token , "C"); if (unit != NULL) { *unit = '\0'; } l_temp_max = atol(token); } if (config_file_get_value(SENSOR_TEMP_CONFIG_FILE, "lograte" , token) >= 0) { ul_temp_lograte = atoi(token); } // Release the xCFGMutex. x_supervisor_SemaphoreGive( xCFGMutex ); } /* enable pin for sensor */ gpio_enable_module_pin( ADC_TEMPERATURE_PIN , ADC_TEMPERATURE_FUNCTION ); return (true); }
/*! * \brief Init the potentiometer channel. * * \return true upon success, false if error. */ bool b_potentiometer_init ( void ) { portCHAR token[6]; portCHAR * percent; // Get the xCFGMutex. if( pdTRUE == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) ) { // get the field if (config_file_get_value(SENSOR_POT_CONFIG_FILE, "alarm" , token) >= 0) { // update value if (!strcmp(token, "on")) { b_pot_alarm = pdTRUE; } } if (config_file_get_value(SENSOR_POT_CONFIG_FILE, "min" , token) >= 0) { percent = strpbrk(token , "%"); if (percent != NULL) { *percent = '\0'; } sscanf(token, "%u", &ul_pot_min); } if (config_file_get_value(SENSOR_POT_CONFIG_FILE, "max" , token) >= 0) { percent = strpbrk(token , "%"); if (percent != NULL) { *percent = '\0'; } sscanf(token, "%u", &ul_pot_max); } if (config_file_get_value(SENSOR_POT_CONFIG_FILE, "lograte" , token) >= 0) { sscanf(token, "%u", &ul_pot_lograte); } // Release the xCFGMutex. x_supervisor_SemaphoreGive( xCFGMutex ); } /* enable pin for sensor */ gpio_enable_module_pin( ADC_POTENTIOMETER_PIN , ADC_POTENTIOMETER_FUNCTION ); return (true); }
/*! * \brief Init the joystick sensor. * * \return true upon success, false if error. */ bool b_joystick_init ( void ) { portCHAR token[6]; // Get the xCFGMutex. if( pdTRUE == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) ) { // get the field if (config_file_get_value(SENSOR_JS_CONFIG_FILE, "alarm" , token) >= 0) { // update value if (!strcmp(token, "on")) { bAlarm = pdTRUE; } } // Release the xCFGMutex. x_supervisor_SemaphoreGive( xCFGMutex ); } /* configure joystick up to produce IT on all state change */ gpio_enable_pin_interrupt(GPIO_JOYSTICK_UP , GPIO_PIN_CHANGE); /* configure joystick down to produce IT on all state change */ gpio_enable_pin_interrupt(GPIO_JOYSTICK_DOWN , GPIO_PIN_CHANGE); /* configure joystick right to produce IT on all state change */ gpio_enable_pin_interrupt(GPIO_JOYSTICK_RIGHT , GPIO_PIN_CHANGE); /* configure joystick left to produce IT on all state change */ gpio_enable_pin_interrupt(GPIO_JOYSTICK_LEFT , GPIO_PIN_CHANGE); /* configure joystick press to produce IT on all state change */ gpio_enable_pin_interrupt(GPIO_JOYSTICK_PUSH , GPIO_PIN_CHANGE); /* Disable all interrupts */ Disable_global_interrupt(); /* register joystick handler on level 3 */ INTC_register_interrupt( (__int_handler)&vjoystick_ISR, AVR32_GPIO_IRQ_0 + (GPIO_JOYSTICK_UP/8), AVR32_INTC_INT3); INTC_register_interrupt( (__int_handler)&vjoystick_ISR, AVR32_GPIO_IRQ_0 + (GPIO_JOYSTICK_PUSH/8), AVR32_INTC_INT3); /* Enable all interrupts */ Enable_global_interrupt(); return (true); }
/*! \brief WEB server main task * check for incoming connection and process it * */ portTASK_FUNCTION( vBasicWEBServer, pvParameters ) { struct netconn *pxHTTPListener, *pxNewConnection; portCHAR token[6]; portSHORT TaskIdx; portLONG err_count; /* initialize current nb connection */ sCurrentNbHTTPConn = 0; vSemaphoreCreateBinary( xMutexNbHTTPConn ); x_default_page_len = strlen( pcDefaultPage ); /* HTTP configuration. */ // Get the xCFGMutex. if( pdFALSE == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) ) { // Failed to get the CFG mutex, use the default HTTP config. webHttpPort = webHTTP_PORT; } // Mutex has been taken else { // get the field value for port number if (config_file_get_value(HTTP_CONFIG_FILE, "port" , token) >= 0) { sscanf(token, "%u", &webHttpPort); } // if it does not exist, use the default value else { webHttpPort = webHTTP_PORT; } // Release the xCFGMutex. x_supervisor_SemaphoreGive( xCFGMutex ); } // Create a new tcp connection handle pxHTTPListener = netconn_new( NETCONN_TCP ); netconn_bind(pxHTTPListener, NULL, webHttpPort ); netconn_listen( pxHTTPListener ); // Loop forever for( ;; ) { #if ( (LWIP_VERSION) == ((1U << 24) | (3U << 16) | (2U << 8) | (LWIP_VERSION_RC)) ) /* Wait for a first connection. */ pxNewConnection = netconn_accept(pxHTTPListener); #else while(netconn_accept(pxHTTPListener, &pxNewConnection) != ERR_OK) { vTaskDelay( webSHORT_DELAY ); } #endif if(pxNewConnection != NULL) { /* read the nb of connection, no need to use Mutex */ while( webHTTP_NB_CONN == sCurrentNbHTTPConn ) { vTaskDelay( webSHORT_DELAY ); } // Take the xWEBMutex if there are no active connections. if( 0 == sCurrentNbHTTPConn ) { if( pdFALSE == x_supervisor_SemaphoreTake( xWEBMutex, 0 ) ) { prvweb_SendErrorPage( pxNewConnection, 503, "", "AVR32 UC3 Web server under maintenance." ); // Close the connection. vTaskDelay( 50 ); err_count = 4; while( netconn_close( pxNewConnection ) != ERR_OK ) { if (--err_count == 0) break; vTaskDelay( webSHORT_DELAY ); } err_count = 4; while( netconn_delete( pxNewConnection ) != ERR_OK ) { if (--err_count == 0) break; vTaskDelay( webSHORT_DELAY ); } continue; } } // Find an available spot in the tTaskHandle[] array. // We're sure to find one because sCurrentNbHTTPConn < webHTTP_NB_CONN. TaskIdx = 0; while( NULL != tTaskHandle[TaskIdx] ) TaskIdx++; while( xSemaphoreTake(xMutexNbHTTPConn , portMAX_DELAY ) != pdTRUE ); sCurrentNbHTTPConn++; // Release the mutex. xSemaphoreGive( xMutexNbHTTPConn ); // TRACE_COM2( "nb http conn:%d",sCurrentNbHTTPConn ); if( xTaskCreate( prvweb_ProcessSingleConnection, ( signed portCHAR * )"WCONN", webHTTP_CONNECTION_STACK_SIZE, pxNewConnection, webHTTP_CONNECTION_PRIORITY, &tTaskHandle[TaskIdx] ) != pdPASS) { TRACE_COM2( "xTaskCreate() alloc error" ); /* delete connection */ err_count = 4; while( netconn_close( pxNewConnection ) != ERR_OK ) { if (--err_count == 0) break; vTaskDelay( webSHORT_DELAY ); } err_count = 4; while( netconn_delete( pxNewConnection ) != ERR_OK ) { if (--err_count == 0) break; vTaskDelay( webSHORT_DELAY ); } while( xSemaphoreTake(xMutexNbHTTPConn , portMAX_DELAY ) != pdTRUE ); sCurrentNbHTTPConn--; // Release the xWEBMutex if there are no active connections. if( 0 == sCurrentNbHTTPConn ) { x_supervisor_SemaphoreGive( xWEBMutex ); } // Release the mutex. xSemaphoreGive( xMutexNbHTTPConn ); }// end if task not created }// end if new connection }// end infinite loop }
/*! * \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 ); }
/*! * \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. */
/*! * \brief a command line executor. * * \param pcStringCmd Input. The cmd line to execute. NULL-terminated string. * Format: cmd [arg] [arg=val], with 6 (arg,val) maximum. * WARNING: this string will be modified. * \param xModId Input. The module that is calling this exe function. * \param FsNavId Input. The file system navigator id to use if the cmd * is a file system command. * \param ppcStringReply Output. The caller must free this string (by calling vportFree()) * only if it is non-NULL and the returned status is OK. * * \return the status of the command execution. */ eExecStatus Shell_exec( signed portCHAR *pcStringCmd, eModId xModId, signed short FsNavId, signed portCHAR **ppcStringReply) { eCmdStatus xCmdStatus; portBASE_TYPE ac; signed portCHAR *av[SHELL_MAX_NBTOKEN]; portBASE_TYPE CmdIdx; int i; eExecStatus xRet; // 1) Identify the command and tokenize the rest of the command line. xCmdStatus = prvCmdIdentify_Tokenize( pcStringCmd, xModId, &ac, av, &CmdIdx ); if(SHELL_CMDSTATUS_NOTFOUND == xCmdStatus) { // Command not found. if(ppcStringReply != NULL) { *ppcStringReply = (signed portCHAR *)SHELL_MSG_CMDNOTFOUND; } return(SHELL_EXECSTATUS_KO); } else if(SHELL_CMDSTATUS_PERMISSIONDENIED == xCmdStatus) { // Permission denied. if(ppcStringReply != NULL) { *ppcStringReply = (signed portCHAR *)SHELL_MSG_PERMISSIONDENIED; } return(SHELL_EXECSTATUS_KO); } /* Get the SHELLFS mutex for File system access. */ // We put this check here to reduce the code footprint (normally it should be // in each fs cmd function). if( ( CmdIdx >= SHELL_FS_FIRSTCMDIDX ) && ( CmdIdx <= SHELL_FS_LASTCMDIDX ) ) { if( pdFALSE == x_supervisor_SemaphoreTake( xSHELLFSMutex, 0 ) ) { // Failed to get the SHELLFS mutex. if(ppcStringReply != NULL) { *ppcStringReply = (signed portCHAR *)SHELL_ERRMSG_MAINTENANCEMODE; } return(SHELL_EXECSTATUS_KO); } } /* Special case for the !! command. Only for the SYS_MODID_COM1SHELL module, cf. a_cmd_registration[]. */ if( 0 == CmdIdx ) // !! command { CmdIdx = PrevCmdIdx; // Execute the previous cmd. if( -1 == CmdIdx ) { // No previous command. if(ppcStringReply != NULL) { *ppcStringReply = (signed portCHAR *)SHELL_MSG_NOHISTORY; } return(SHELL_EXECSTATUS_KO); } ac = PrevCmdAc; // NOTE: we take a shortcut here: we suppose the caller // keeps the same pcStringCmd from one call to another. for(i=0; i<ac; i++) av[i] = PrevCmdAv[i]; } else { PrevCmdIdx = CmdIdx; // Save the cmd (used by the !! cmd). PrevCmdAc = ac; for(i=0; i<ac; i++) PrevCmdAv[i] = av[i]; } // 2) Execute the command. if(ppcStringReply != NULL) *ppcStringReply = NULL; xRet = a_cmd_registration[CmdIdx].pf_exec_cmd( xModId, FsNavId, ac, av, ppcStringReply ); /* Release the SHELLFS mutex. */ if( ( CmdIdx >= SHELL_FS_FIRSTCMDIDX ) && ( CmdIdx <= SHELL_FS_LASTCMDIDX ) ) { x_supervisor_SemaphoreGive( xSHELLFSMutex ); } return( xRet ); }
/*! * \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); } } } } }