/** * Purges Tasks where this component is scheduler or schedulee from the TaskQueue. */ void purgeTasks (void *comp) { #ifdef MULTI_MONKS pthread_mutex_lock(&task_mutex); #endif Task *T = taskQueue; Task **temp = &taskQueue; uint8_t i = 0; while(T != NULL) { if(T->schedulee == comp || T->scheduler == comp) { Log(LOG_SCHEDULER, "[pT] id %x\n", T->identifier); i ++; *temp = T->next; returnMessage((Message *) T->context); taskCompleted(T); T = *temp; } else { temp = &(T->next); T = T->next; } } #ifdef MULTI_MONKS pthread_mutex_unlock(&task_mutex); #endif }
void SerialUI::exit(bool terminate_gui) { #ifdef SUI_ENABLE_MODES if (mode() == SUIMode_Program) { if (terminate_gui) println_P(terminate_gui_prog); println_P(end_of_tx_str); // ensure we always restart in "user" mode... setMode(SUIMode_User); } else #endif { returnMessage(goodbye); } user_present = false; user_presence_last_interaction_ms = 0; // go back to top level menu, in case we re-enter SUI later... current_menu = &top_lev_menu; }
char * Menu::mallocReadKey() { #ifdef SUI_INCLUDE_EXTRA_SAFETYCHECKS if (max_key_len < 1) { return NULL; } #endif #ifdef SUI_DYNAMIC_MEMORY_ALLOCATION_ENABLE // we'll need--at most--a container that is the size of our largest key for the menu char * akey = (char*) malloc(sizeof(char) * (max_key_len + 2)); #else char * akey = key_staticstr; #endif #ifdef SUI_INCLUDE_DEBUG SUI_MENU_DEBUG_OUTPUT("Post read key allocation") sui_driver->showFreeRAM(); #endif if (!akey) { #ifdef SUI_SERIALUI_ECHO_WARNINGS returnMessage(error_cantalloc_key); #endif return NULL; } MENUMEMSET(akey, 0, max_key_len + 2); uint8_t numRead = sui_driver->readBytesToEOL(akey, max_key_len + 1); if (!numRead) { MENUFREE(akey); return NULL; } // make sure we don't include any return/newlines in our key uint8_t num_nonEOL = 0; for (uint8_t i = 0; i < numRead; i++) { if (akey[i] == '\r' || akey[i] == '\n') { akey[i] = 0; } else { num_nonEOL ++; } } if (num_nonEOL) { // we had some valid, non-EOL, chars. return akey; } // no non-EOL MENUFREE(akey); return NULL; }
void Menu::init(SerialUI * suidrv, PGM_P name, uint8_t num_items_hint, Menu * parent) { sui_driver = suidrv; menu_name = name; parent_menu = parent; num_menu_items = 0; #ifdef SUI_DYNAMIC_MEMORY_ALLOCATION_ENABLE max_menu_items = 0; #else max_menu_items = SUI_STATIC_MEMORY_NUM_ITEMS_MAXIMUM; #endif expand_list_amount = SUI_MENU_EXPANDITEMLIST_AMOUNT_DEFAULT; item_list = NULL; // set our max_key_len to hold *at least* // the available built-in commands if (max_key_len < 1) { // max_key_len is now a class-level var, so // we only need to do this once. It will // eventually hold the max key length for the // largest key in the whole menu system. #ifdef SUI_ENABLE_MODES max_key_len = strlen_P(key_mode_program); #else max_key_len = strlen_P(help_key); if (strlen_P(exit_key) > max_key_len) { max_key_len = strlen_P(exit_key); } #endif } #ifdef SUI_INCLUDE_EXTRA_SAFETYCHECKS if (strlen_P(menu_name) > SUI_MENU_PROGMEM_STRING_ABS_MAXLEN) { returnMessage(PSTR(SUI_ERRORMSG_MENUNAME_TOOLONG)); } #endif #ifdef SUI_INCLUDE_DEBUG if (parent_menu) { // can't start doing output before SerialUI is initialized // so we only do this stuff for sub-menus SUI_MENU_DEBUG_OUTPUT("Initializing Menu "); showName(); sui_driver->println(" "); } #endif expandItemList(num_items_hint); }
bool Menu::addCommand(PGM_P key_str, MenuCommand_Callback callback, PGM_P help_str) { MenuItem itm(key_str, help_str, NULL, callback); #ifdef SUI_INCLUDE_EXTRA_SAFETYCHECKS if (itm.key_size > SUI_MENU_PROGMEM_STRING_ABS_MAXLEN) { returnMessage(PSTR(SUI_ERRORMSG_MENUITEM_KEY_TOOLONG)); } if (help_str && strlen_P(help_str) > SUI_MENU_PROGMEM_STRING_ABS_MAXLEN) { sui_driver->println_P(help_str); returnMessage(PSTR(SUI_ERRORMSG_MENUITEM_HELP_TOOLONG)); } #endif return addMenuItem(&itm); }
void executeTasks () { Task *toExecute = retrieveTask(); Log(LOG_SCHEDINTF, "[executeTasks] Start\n"); while(toExecute != NULL) { Log(LOG_SCHEDINTF, "[executeTasks] Executing a task\n"); toExecute->function(toExecute->schedulee, toExecute->context, toExecute->scheduler); returnMessage(toExecute->context); taskCompleted(toExecute); Log(LOG_SCHEDINTF, "[executeTasks] Task execution done\n"); toExecute = retrieveTask(); } Log(LOG_SCHEDINTF, "[executeTasks] End\n"); }
Menu * Menu::subMenu(PGM_P key_str, PGM_P help_str) { #ifdef SUI_DYNAMIC_MEMORY_ALLOCATION_ENABLE // dynamic memory is enabled, so we malloc a pointer to fresh // memory, and keep a reference to this block within the // MenuItem: Menu * sub_men = (Menu*) malloc(sizeof(Menu)); #else // we'll just use the next available sub-menu slot if (submenu_static_idx >= SUI_STATIC_MEMORY_NUM_SUBMENUS_TOTAL_MAXIMUM) return NULL; Menu * sub_men = &(submenu_staticlist[submenu_static_idx]); submenu_static_idx++; #endif if (!sub_men) { SUI_MENU_DEBUG_OUTPUT("Submenu creation fail"); #ifdef SUI_SERIALUI_ECHO_WARNINGS returnMessage(error_cantalloc_submenu); #endif return NULL; } sub_men->init(sui_driver, key_str, 0, this); MenuItem itm(key_str, help_str, sub_men, NULL); if (!addMenuItem(&itm)) { MENUFREE(sub_men); return NULL; } #ifdef SUI_INCLUDE_DEBUG SUI_MENU_DEBUG_OUTPUT("Added submenu"); sui_driver->showFreeRAM(); #endif return sub_men; }
string MasterSettings::getCurrentMOTDFromFile(const string &filename) const { string defaultMessage = "Welcome to Bitfighter!"; FILE *f = fopen(filename.c_str(), "r"); if(!f) { logprintf(LogConsumer::LogError, "Unable to open MOTD file \"%s\" -- using default MOTD.", filename.c_str()); return defaultMessage; } char message[MOTD_LEN]; bool ok = fgets(message, MOTD_LEN, f); fclose(f); if(!ok) return defaultMessage; string returnMessage(message); trim_right_in_place(returnMessage, "\n"); // Remove any trailing new lines return returnMessage; }
Menu * Menu::handleRequest() { #ifdef SUI_INCLUDE_EXTRA_SAFETYCHECKS if (!num_menu_items) { #ifdef SUI_SERIALUI_ECHO_WARNINGS returnMessage(error_nomenuitems); #endif // error! return this; } #endif char * key_entered = mallocReadKey(); if (!key_entered) { // nothing entered sui_driver->println(' '); return this; } #ifdef SUI_SERIALUI_ECHO_ON // echo if (sui_driver->echoCommands()) { #ifdef SUI_ENABLE_MODES if (sui_driver->mode() == SUIMode_User) #endif { sui_driver->println(key_entered); } } #endif MenuItem * itm = itemForKey(key_entered); if (itm) { // get rid of our malloc'ed key MENUFREE(key_entered); if (itm->command) { SUI_MENU_DEBUG_OUTPUT("Running command"); (itm->command)(); return this; } #ifdef SUI_MENU_ENABLE_SUBMENUS else if (itm->subMenu) { SUI_MENU_DEBUG_OUTPUT("Entering submenu"); itm->subMenu->enter(); return itm->subMenu; } #endif // get here, we have a problem. // error return this; } // not found... #ifdef SUI_MENU_ENABLE_SUBMENUS if (parent_menu && strncmp_P(key_entered, up_key, strlen_P(up_key)) == 0) { // get rid of our malloc'ed key SUI_MENU_DEBUG_OUTPUT("Going up a level"); MENUFREE(key_entered); return upLevel(); } #endif if (strncmp_P(key_entered, help_key, strlen_P(help_key)) == 0) { SUI_MENU_DEBUG_OUTPUT("Help request"); // get rid of our malloc'ed key MENUFREE(key_entered); showHelp(); return this; } if ( ( parent_menu == NULL) && strncmp_P(key_entered, exit_key, strlen_P(exit_key)) == 0) { // get rid of our malloc'ed key SUI_MENU_DEBUG_OUTPUT("Exit request"); MENUFREE(key_entered); return NULL; } #ifdef SUI_ENABLE_MODES // check for program mode command... if (strncmp_P(key_entered, key_mode_program, strlen_P(key_mode_program)) == 0) { SUI_MENU_DEBUG_OUTPUT("Entering program mode"); sui_driver->setMode(SUIMode_Program); MENUFREE(key_entered); char sepChar[2]; sepChar[0] = SUI_SERIALUI_PROG_STR_SEP_CHAR; sepChar[1] = '\0'; char outBuf[SUI_SERIALUI_PROGMEM_STRING_ABS_MAXLEN]; outBuf[0] = '\0'; strcat(outBuf, sepChar); strcat_P(outBuf, prog_mode_info_VERSION); strcat(outBuf, sepChar); #ifdef SUI_MENU_ENABLE_SUBMENUS strcat_P(outBuf, up_key); #else strcat(outBuf, "X"); #endif /* SUI_MENU_ENABLE_SUBMENUS */ strcat(outBuf, sepChar); strcat_P(outBuf, exit_key); strcat(outBuf, sepChar); strcat_P(outBuf, error_generic); strcat(outBuf, sepChar); strcat_P(outBuf, prog_mode_info_helpkey); strcat(outBuf, sepChar); strcat_P(outBuf, help_key_prog_commandprefix); strcat(outBuf, sepChar); strcat_P(outBuf, help_key_prog_submenuprefix); strcat(outBuf, sepChar); strcat_P(outBuf, help_sep_prog); strcat(outBuf, sepChar); strcat_P(outBuf, prog_mode_info_moreprompt_string); strcat(outBuf, sepChar); strcat_P(outBuf, prog_mode_info_moreprompt_num); strcat(outBuf, sepChar); strcat(outBuf, SUI_SERIALUI_PROMPT); strcat(outBuf, sepChar); strcat_P(outBuf, prog_mode_info_EOT); strcat(outBuf, sepChar); #ifdef SUI_ENABLE_STREAMPROMPTING strcat_P(outBuf, prog_mode_info_moreprompt_stream); strcat(outBuf, sepChar); #endif strcat_P(outBuf, prog_mode_terminate_gui); strcat(outBuf, sepChar); sui_driver->print(strlen(outBuf) + 1, DEC); sui_driver->println(outBuf); return this; } if (strncmp_P(key_entered, key_mode_user, strlen_P(key_mode_user)) == 0) { SUI_MENU_DEBUG_OUTPUT("Entering 'user' mode"); sui_driver->setMode(SUIMode_User); MENUFREE(key_entered); return this; } #endif /* SUI_ENABLE_MODES */ if (strncmp_P(key_entered, key_ping_command, strlen_P(key_ping_command)) == 0) { MENUFREE(key_entered); pingRespond(); return this; } // get rid of our malloc'ed key unknownCommand(key_entered); MENUFREE(key_entered); return this; }
void Menu::enter() { SUI_MENU_DEBUG_OUTPUT("Entering menu"); returnMessage(menu_name); }
bool Menu::expandItemList(uint8_t by_amount) { #ifdef SUI_DYNAMIC_MEMORY_ALLOCATION_ENABLE // using dynamic memory allocations int menuitm_size = sizeof(MenuItem); MenuItem * new_list = NULL; if (!by_amount) { // set optional param to default value by_amount = expand_list_amount; } if (item_list) { // we've already got a list in hand... we want to expand it a bit new_list = (MenuItem*) realloc(item_list, menuitm_size * (num_menu_items + by_amount)); #ifdef SUI_INCLUDE_DEBUG if (parent_menu) { // can't start doing output before SerialUI is initialized // so we only do this stuff for sub-menus SUI_MENU_DEBUG_OUTPUT("Dynamically expanding list of menu items for "); showName(); sui_driver->println(" "); sui_driver->showFreeRAM(); } #endif } else { // no list yet, malloc one please: new_list = (MenuItem*) malloc(menuitm_size * by_amount); #ifdef SUI_INCLUDE_DEBUG if (parent_menu) { // can't start doing output before SerialUI is initialized // so we only do this stuff for sub-menus SUI_MENU_DEBUG_OUTPUT("Allocating list of menu items for "); showName(); sui_driver->println(" "); sui_driver->showFreeRAM(); } #endif } if (new_list != NULL) { // we gots a new list, huzzah. // make note of our new space... max_menu_items += by_amount; // zero the newly allocated memory MENUMEMSET(&(new_list[num_menu_items]), 0, menuitm_size * by_amount); // keep that pointer item_list = new_list; // success! return true; } // abject failure... #ifdef SUI_SERIALUI_ECHO_WARNINGS returnMessage(error_cantalloc_menuitem); #endif #endif // either there was an error, or we aren't using // dynamic memory allocations... in both cases: return false; }
/* The send command function. Waits for numResults number of reply messages */ ptr_GSM_msg GSM::sendCommand(string c, int numResults) { /* Smart pointer object with message */ ptr_GSM_msg returnMessage(new GSMMessage); /* Exit if the module is off */ if (!powerOn) { returnMessage->addMessage("PowerOff"); return returnMessage; } /* Add message to send queue */ GSMMessage toSend(c,1); sendQueue.put(&toSend); /* Wait for reply */ mRespWaiting.lock(); int me = respWaiting; me %= respLength; respWaiting+=numResults; mRespWaiting.unlock(); int rxed = 0; /* Start timeout */ timeout = false; timeoutTimer.start(TIMEOUT*1000); /* Get reply messages. RX thread will set replyFor to our value and then we will get message from queue */ while (rxed < numResults) { /* Timed out so exit */ if (timeout) { for (int i = rxed; i < numResults; i++) { returnMessage->addMessage("TIMEOUT"); } mRespWaiting.lock(); respWaiting -= (numResults - rxed); mRespWaiting.unlock(); break; } /* See if message is recieved for us */ mRespWaiting.lock(); if (replyFor == me) { /* If it is, get from queue */ rxed++; me++; me%=respLength; osEvent e = sendCommandReplyQueue.get(); if (e.status == osEventMessage) { /* Add the message to our return message */ string* m = ((string*) e.value.p); returnMessage->addMessage(*m); /* If an error on GSM module then rest of expected results will not be coming */ if ((*m).find("ERROR") != string::npos) { //Clear remaining requests because of error. for (int i = rxed; i < numResults; i++) { returnMessage->addMessage("ERR_CLEARED"); } mRespWaiting.lock(); respWaiting -= (numResults - rxed); mRespWaiting.unlock(); rxed = numResults; } /* Delete receieved message */ delete m; } timeout = false; timeoutTimer.start(TIMEOUT * 1000); } else { Thread::wait(10); } mRespWaiting.unlock(); } /* Recieved all messages */ mRespWaiting.lock(); if (respWaiting == 0) { replyFor = -1; } waitingForReply = false; mRespWaiting.unlock(); /* And send message back to function, unblocking */ return returnMessage; }