123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711 |
- /**
- * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include "sdk_common.h"
- #if NRF_MODULE_ENABLED(NRF_CLI)
- #include <ctype.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include "nrf_cli.h"
- #include "nrf_cli_vt100.h"
- #include "app_error.h"
- #include "nrf_assert.h"
- #include "nrf_delay.h"
- #include "nrf_pwr_mgmt.h"
- #include "nrf_atomic.h"
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- #include "fnmatch.h"
- #endif
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- #if NRF_CLI_HISTORY_ELEMENT_SIZE * NRF_CLI_HISTORY_ELEMENT_COUNT == 0
- #error Not proper memory size allocated for NRF_CLI_HISTORY
- #endif
- #endif
- /* 2 == 1 char for cmd + 1 char for '\0' */
- #if NRF_CLI_CMD_BUFF_SIZE < 2
- #error too small NRF_CLI_CMD_BUFF_SIZE
- #endif
- #if NRF_CLI_PRINTF_BUFF_SIZE < 1
- #error too small NRF_CLI_PRINTF_BUFF_SIZE
- #endif
- #define NRF_CLI_HELP_CLEAR "Clear screen."
- #define NRF_CLI_HELP_COLORS "Toggle colored syntax."
- #define NRF_CLI_HELP_COLORS_OFF "Disable colored syntax."
- #define NRF_CLI_HELP_COLORS_ON "Enable colored syntax."
- #define NRF_CLI_HELP_STATISTICS "CLI statistics."
- #define NRF_CLI_HELP_STATISTICS_SHOW "Get CLI statistics for the Logger module."
- #define NRF_CLI_HELP_STATISTICS_RESET "Reset CLI statistics for the Logger module."
- #define NRF_CLI_HELP_RESIZE "Console gets terminal screen size or assumes 80 in case " \
- "the readout fails. It must be executed after each terminal " \
- "width change to ensure correct text display."
- #define NRF_CLI_HELP_RESIZE_DEFAULT "Assume 80 chars screen width and send this setting " \
- "to the terminal."
- #define NRF_CLI_HELP_HISTORY "Command history."
- #define NRF_CLI_HELP_ECHO "Toggle CLI echo."
- #define NRF_CLI_HELP_ECHO_ON "Enable CLI echo."
- #define NRF_CLI_HELP_ECHO_OFF "Disable CLI echo. Arrows and buttons: Backspace, " \
- "Delete, End, Home, Insert are not handled."
- #define NRF_CLI_HELP_CLI "Useful, not Unix-like CLI commands."
- #define NRF_CLI_MSG_SPECIFY_SUBCOMMAND "Please specify a subcommand.\r\n"
- #define NRF_CLI_MSG_UNKNOWN_PARAMETER " unknown parameter: "
- #define NRF_CLI_MSG_COMMAND_NOT_FOUND ": command not found"
- #define NRF_CLI_MSG_TAB_OVERFLOWED "Tab function: commands counter overflowed.\r\n"
- /*lint -save -esym(526,cli_command*) -esym(526,cli_sorted_cmd_ptrs*)*/
- NRF_SECTION_DEF(cli_command, nrf_cli_cmd_entry_t);
- #define CLI_DATA_SECTION_ITEM_GET(i) NRF_SECTION_ITEM_GET(cli_command, nrf_cli_cmd_entry_t, (i))
- #define CLI_DATA_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(cli_command, nrf_cli_cmd_entry_t)
- NRF_SECTION_DEF(cli_sorted_cmd_ptrs, const char *);
- /*lint -restore*/
- #define CLI_SORTED_CMD_PTRS_ITEM_GET(i) NRF_SECTION_ITEM_GET(cli_sorted_cmd_ptrs, const char *, (i))
- #define CLI_SORTED_CMD_PTRS_START_ADDR_GET NRF_SECTION_START_ADDR(cli_sorted_cmd_ptrs)
- #if defined(NRF_CLI_LOG_BACKEND) && NRF_CLI_LOG_BACKEND
- #include "nrf_log_str_formatter.h"
- #include "nrf_log_internal.h"
- #endif
- #define NRF_CLI_INIT_OPTION_PRINTER (NULL)
- #define NRF_CLI_MAX_TERMINAL_SIZE (250u)
- #define NRF_CLI_CURSOR_POSITION_BUFFER (10u) /* 10 == {esc, [, 2, 5, 0, ;, 2, 5, 0, '\0'} */
- #define NRF_CLI_DEFAULT_TERMINAL_WIDTH (80u) /* Default PuTTY width. */
- #define NRF_CLI_DEFAULT_TERMINAL_HEIGHT (24u) /* Default PuTTY height. */
- #define NRF_CLI_INITIAL_CURS_POS (1u) /* Initial cursor position is: (1, 1). */
- #define NRF_CLI_CMD_ROOT_LVL (0u)
- /* Macro to send VT100 commands. */
- #define NRF_CLI_VT100_CMD(_p_cli_, _cmd_) { \
- ASSERT(_p_cli_); \
- ASSERT(_p_cli_->p_fprintf_ctx); \
- static char const cmd[] = _cmd_; \
- nrf_fprintf(_p_cli_->p_fprintf_ctx, "%s", cmd); \
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- typedef enum
- {
- WILDCARD_CMD_ADDED,
- WILDCARD_CMD_ADDED_MISSING_SPACE,
- WILDCARD_CMD_NO_MATCH_FOUND
- } wildcard_cmd_status_t;
- #endif
- static bool cli_log_entry_process(nrf_cli_t const * p_cli, bool skip);
- static void cli_execute(nrf_cli_t const * p_cli);
- static inline void transport_buffer_flush(nrf_cli_t const * p_cli)
- {
- nrf_fprintf_buffer_flush(p_cli->p_fprintf_ctx);
- }
- static inline void cli_flag_help_set(nrf_cli_t const * p_cli)
- {
- p_cli->p_ctx->internal.flag.show_help = 1;
- }
- static inline void cli_flag_help_clear(nrf_cli_t const * p_cli)
- {
- p_cli->p_ctx->internal.flag.show_help = 0;
- }
- static inline void cli_flag_echo_set(nrf_cli_t const * p_cli)
- {
- p_cli->p_ctx->internal.flag.echo = 1;
- }
- static inline void cli_flag_echo_clear(nrf_cli_t const * p_cli)
- {
- p_cli->p_ctx->internal.flag.echo = 0;
- }
- static inline bool cli_flag_echo_is_set(nrf_cli_t const * p_cli)
- {
- return p_cli->p_ctx->internal.flag.echo == 1 ? true : false;
- }
- static inline bool cli_flag_processing_is_set(nrf_cli_t const * p_cli)
- {
- return p_cli->p_ctx->internal.flag.processing == 1 ? true : false;
- }
- static inline void receive_state_change(nrf_cli_t const * p_cli, nrf_cli_receive_t state)
- {
- p_cli->p_ctx->receive_state = state;
- }
- static inline size_t cli_strlen(char const * str)
- {
- return str == NULL ? 0 : strlen(str);
- }
- static void cli_cmd_buffer_clear(nrf_cli_t const * p_cli)
- {
- p_cli->p_ctx->cmd_buff[0] = '\0'; /* clear command buffer */
- p_cli->p_ctx->cmd_buff_pos = 0;
- p_cli->p_ctx->cmd_buff_len = 0;
- }
- /* Function returns true if cursor is at beginning of an empty line. */
- static inline bool cursor_in_empty_line(nrf_cli_t const * p_cli)
- {
- return ( (p_cli->p_ctx->cmd_buff_pos + cli_strlen(p_cli->p_name)) %
- p_cli->p_ctx->vt100_ctx.cons.terminal_wid == 0);
- }
- /* Function returns true if command length is equal to multiplicity of terminal width. */
- static inline bool full_line_cmd(nrf_cli_t const * p_cli)
- {
- return ((p_cli->p_ctx->cmd_buff_len + cli_strlen(p_cli->p_name)) %
- p_cli->p_ctx->vt100_ctx.cons.terminal_wid == 0);
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- /* Function returns true if string contains wildcard character: '?' or '*'. */
- static bool wildcard_character_exist(char * p_str)
- {
- size_t str_len = cli_strlen(p_str);
- for (size_t i = 0; i < str_len; i++)
- {
- if ((p_str[i] == '?') || (p_str[i] == '*'))
- {
- return true;
- }
- }
- return false;
- }
- #endif
- /* Function sends data stream to the CLI instance. Each time before the cli_write function is called,
- * it must be ensured that IO buffer of fprintf is flushed to avoid synchronization issues.
- * For that purpose, use function transport_buffer_flush(p_cli) */
- static void cli_write(nrf_cli_t const * p_cli,
- void const * p_data,
- size_t length,
- size_t * p_cnt)
- {
- ASSERT(p_cli && p_data);
- ASSERT(p_cli->p_iface->p_api);
- size_t offset = 0;
- size_t cnt;
- while (length)
- {
- ret_code_t ret = p_cli->p_iface->p_api->write(p_cli->p_iface,
- &((uint8_t const *)p_data)[offset],
- length,
- &cnt);
- UNUSED_VARIABLE(ret);
- ASSERT(ret == NRF_SUCCESS);
- ASSERT(length >= cnt);
- offset += cnt;
- length -= cnt;
- if (cnt == 0 && (p_cli->p_ctx->state != NRF_CLI_STATE_PANIC_MODE_ACTIVE))
- {
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- (void)task_events_wait(NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT);
- #else
- while (p_cli->p_ctx->internal.flag.tx_rdy == 0)
- {
- ;
- }
- p_cli->p_ctx->internal.flag.tx_rdy = 0;
- #endif
- }
- }
- if (p_cnt)
- {
- *p_cnt = cnt;
- }
- }
- /* Function sends 1 character to the CLI instance. */
- static inline void cli_putc(nrf_cli_t const * p_cli, char ch)
- {
- nrf_fprintf(p_cli->p_fprintf_ctx, "%c", ch);
- }
- /* Function reads data from the CLI instance. */
- static void cli_read(nrf_cli_t const * p_cli,
- void * p_data,
- size_t length,
- size_t * p_cnt)
- {
- ASSERT(p_cli && p_data);
- ASSERT(p_cli->p_iface);
- ret_code_t ret = p_cli->p_iface->p_api->read(p_cli->p_iface, p_data, length, p_cnt);
- UNUSED_VARIABLE(ret);
- }
- /* Function cmd_get shall be used to search commands. It moves the pointer pp_entry to command
- * of static command structure. If the command cannot be found, the function will set pp_entry to NULL.
- * p_command Pointer to command which will be processed (no matter the root command).
- * lvl Level of the requested command.
- * idx Index of the requested command.
- * pp_entry Pointer which points to subcommand[idx] after function execution.
- * p_st_entry Pointer to the structure where dynamic entry data can be stored.
- */
- static void cmd_get(nrf_cli_cmd_entry_t const * p_command,
- size_t lvl,
- size_t idx,
- nrf_cli_static_entry_t const ** pp_entry,
- nrf_cli_static_entry_t * p_st_entry)
- {
- ASSERT (pp_entry != NULL);
- ASSERT (p_st_entry != NULL);
- if (lvl == NRF_CLI_CMD_ROOT_LVL)
- {
- if (idx < CLI_DATA_SECTION_ITEM_COUNT)
- {
- nrf_cli_cmd_entry_t const * p_cmd = NULL;
- char const * * pp_sorted_cmds = (char const * *)CLI_SORTED_CMD_PTRS_START_ADDR_GET;
- for (size_t i = 0; i < CLI_DATA_SECTION_ITEM_COUNT; i++)
- {
- p_cmd = CLI_DATA_SECTION_ITEM_GET(i);
- if (!strcmp(pp_sorted_cmds[idx], p_cmd->u.p_static->p_syntax))
- {
- *pp_entry = p_cmd->u.p_static;
- return;
- }
- }
- }
- *pp_entry = NULL;
- return;
- }
- if (p_command == NULL)
- {
- *pp_entry = NULL;
- return;
- }
- if (p_command->is_dynamic)
- {
- p_command->u.p_dynamic_get(idx, p_st_entry);
- if (p_st_entry->p_syntax == NULL)
- {
- *pp_entry = NULL;
- }
- else
- {
- *pp_entry = p_st_entry;
- }
- }
- else
- {
- if (p_command->u.p_static[idx].p_syntax != NULL)
- {
- *pp_entry = &p_command->u.p_static[idx];
- }
- else
- {
- *pp_entry = NULL;
- }
- }
- }
- /* Function multiline_console_data_check checks the current cursor position (x, y) on terminal screen
- * based on: command length, console name length, and terminal width.
- * Example 1:
- * || - cursor
- * ----------------------------
- * |console_name $: || |
- * ----------------------------
- * => coordinates are: cur_x = 17, cur_x_end = 17,
- * cur_y = 1, cur_y_end = 1
- * Example 2:
- * ----------------------------
- * |console_name $: test command|
- * |showing |e|xample |
- * ----------------------------
- * => coordinates are: cur_x = 9, cur_x_end = 18 (cursor can be one column after 'e')
- * => cur_y = 2, cur_y_end = 2
- * Example 3:
- * ----------------------------
- * |console_name $: test command|
- * |showing e|x|ample with more |
- * |parameters |
- * ----------------------------
- * => coordinates are: cur_x = 10, cur_x_end = 11 (cursor can be one column after 's')
- * => cur_y = 2, cur_y_end = 3
- */
- static nrf_cli_multiline_cons_t const * multiline_console_data_check(nrf_cli_t const * p_cli)
- {
- nrf_cli_ctx_t * p_ctx = p_cli->p_ctx;
- nrf_cli_multiline_cons_t * p_cons = &p_cli->p_ctx->vt100_ctx.cons;
- p_cons->name_len = cli_strlen(p_cli->p_name);
- /* Current cursor position in command.
- * +1 -> because home position is (1, 1) */
- p_cons->cur_x = (p_ctx->cmd_buff_pos + p_cons->name_len) % p_cons->terminal_wid + 1;
- p_cons->cur_y = (p_ctx->cmd_buff_pos + p_cons->name_len) / p_cons->terminal_wid + 1;
- /* Extreme position when cursor is at the end of command. */
- p_cons->cur_y_end = (p_ctx->cmd_buff_len + p_cons->name_len) / p_cons->terminal_wid + 1;
- p_cons->cur_x_end = (p_ctx->cmd_buff_len + p_cons->name_len) % p_cons->terminal_wid + 1;
- return p_cons;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /* Calculates relative line number of given position in buffer */
- static uint32_t cli_line_num_with_buffer_offset_get(nrf_cli_t const * p_cli,
- nrf_cli_cmd_len_t buffer_pos)
- {
- uint32_t name_len;
- nrf_cli_multiline_cons_t *p_cons = &p_cli->p_ctx->vt100_ctx.cons;
- name_len = cli_strlen(p_cli->p_name);
- return ((buffer_pos + name_len) / p_cons->terminal_wid);
- }
- #endif
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /* Calculates column number of given position in buffer */
- static uint32_t cli_col_num_with_buffer_offset_get(nrf_cli_t const * p_cli,
- nrf_cli_cmd_len_t buffer_pos)
- {
- uint32_t name_len;
- nrf_cli_multiline_cons_t *p_cons = &p_cli->p_ctx->vt100_ctx.cons;
- name_len = cli_strlen(p_cli->p_name);
- /* columns are counted from 1 */
- return (1 + ((buffer_pos + name_len) % p_cons->terminal_wid));
- }
- #endif
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /* For the given buffer, calculates row span between position2 and position1 */
- static int32_t cli_row_span_with_buffer_offsets_get(nrf_cli_t const * p_cli,
- nrf_cli_cmd_len_t offset1,
- nrf_cli_cmd_len_t offset2)
- {
- return cli_line_num_with_buffer_offset_get(p_cli, offset2)
- - cli_line_num_with_buffer_offset_get(p_cli, offset1);
- }
- #endif
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /* For the given buffer, calculates column span between position2 and position 1 */
- static int32_t cli_column_span_with_buffer_offsets_get(nrf_cli_t const * p_cli,
- nrf_cli_cmd_len_t offset1,
- nrf_cli_cmd_len_t offset2)
- {
- return cli_col_num_with_buffer_offset_get(p_cli, offset2)
- - cli_col_num_with_buffer_offset_get(p_cli, offset1);
- }
- #endif
- /* Function sends VT100 command to clear the screen from cursor position to end of the screen. */
- static inline void cli_clear_eos(nrf_cli_t const * p_cli)
- {
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEAREOS);
- }
- /* Function sends VT100 command to save cursor position. */
- static inline void cli_cursor_save(nrf_cli_t const * p_cli)
- {
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_SAVECURSOR);
- }
- /* Function sends VT100 command to restore saved cursor position. */
- static inline void cli_cursor_restore(nrf_cli_t const * p_cli)
- {
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_RESTORECURSOR);
- }
- /* Function forcing new line - cannot be replaced with function cursor_down_move. */
- static inline void cursor_next_line_move(nrf_cli_t const * p_cli)
- {
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_NEXTLINE);
- }
- /* Function moves cursor left by n positions. */
- static inline void cursor_left_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n)
- {
- if (n > 0)
- {
- nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dD", n);
- }
- }
- /* Function moves cursor right by n positions. */
- static inline void cursor_right_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n)
- {
- if (n > 0)
- {
- nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dC", n);
- }
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /* Moves cursor horizontally by a number. Positive is right */
- static void cursor_horiz_move(nrf_cli_t const * p_cli, int32_t delta)
- {
- if (delta > 0)
- {
- cursor_right_move(p_cli, delta);
- }
- else if (delta < 0)
- {
- cursor_left_move(p_cli, -delta);
- }
- else { }
- }
- #endif
- /* Function moves cursor up by n positions. */
- static inline void cursor_up_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n)
- {
- if (n > 0)
- {
- nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dA", n);
- }
- }
- /* Function moves cursor down by n positions but it will bring no effect if cursor is in the last
- * line of terminal screen. In such case, the cursor_next_line_move function shall be invoked. */
- static inline void cursor_down_move(nrf_cli_t const * p_cli, nrf_cli_cmd_len_t n)
- {
- if (n > 0)
- {
- nrf_fprintf(p_cli->p_fprintf_ctx, "\033[%dB", n);
- }
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /* Moves cursor vertically by a number. Positive is down */
- static void cursor_vert_move(nrf_cli_t const * p_cli, int32_t delta)
- {
- if (delta > 0)
- {
- cursor_down_move(p_cli, delta);
- }
- else if (delta < 0)
- {
- cursor_up_move(p_cli, -delta);
- }
- else { }
- }
- #endif
- /* Function increments cursor position (if possible) and moves cursor to new line if necessary. */
- static void cursor_position_increment(nrf_cli_t const * p_cli)
- {
- if (p_cli->p_ctx->cmd_buff_pos >= p_cli->p_ctx->cmd_buff_len)
- {
- return; /* incrementation not possible */
- }
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- nrf_cli_cmd_len_t cur_y = p_cons->cur_y;
- ++p_cli->p_ctx->cmd_buff_pos;
- p_cons = multiline_console_data_check(p_cli);
- if (cur_y == p_cons->cur_y)
- {
- cursor_right_move(p_cli, 1);
- }
- else
- {
- cursor_next_line_move(p_cli);
- }
- }
- /* Function will move cursor back to position == cmd_buff_pos. Example usage is when cursor needs
- * to be moved back after printing some text. This function cannot be used to move cursor to new
- * location by manual change of cmd_buff_pos.*/
- static void cursor_position_synchronize(nrf_cli_t const * p_cli)
- {
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false;
- /* In case cursor reaches the bottom line of a terminal, it will be moved to the next line. */
- if (cursor_in_empty_line(p_cli) || full_line_cmd(p_cli))
- {
- cursor_next_line_move(p_cli);
- }
- if (last_line)
- {
- cursor_left_move(p_cli, p_cons->cur_x_end - p_cons->cur_x);
- }
- else
- {
- cursor_up_move(p_cli, p_cons->cur_y_end - p_cons->cur_y);
- if (p_cons->cur_x > p_cons->cur_x_end)
- {
- cursor_right_move(p_cli, p_cons->cur_x - p_cons->cur_x_end);
- }
- else
- {
- cursor_left_move(p_cli, p_cons->cur_x_end - p_cons->cur_x);
- }
- }
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /**
- * Removes the "word" to the left of the cursor:
- * - if there are spaces at the cursor position, remove all spaces to the left
- * - remove the non-spaces (word) until a space is found or a beginning of buffer
- */
- static void cli_cmd_word_remove(nrf_cli_t const * p_cli)
- {
- nrf_cli_cmd_len_t new_pos;
- nrf_cli_cmd_len_t chars_to_delete;
- int32_t row_span;
- int32_t col_span;
- /* Line must not be empty and cursor must not be at 0 to continue */
- if ((p_cli->p_ctx->cmd_buff_len == 0) || (p_cli->p_ctx->cmd_buff_pos == 0))
- {
- return;
- }
- /* start at the current position */
- new_pos = p_cli->p_ctx->cmd_buff_pos;
- chars_to_delete = 0;
- /* look back for all spaces then for non-spaces */
- while ((new_pos >= 1) && (p_cli->p_ctx->cmd_buff[new_pos - 1] == ' '))
- {
- ++chars_to_delete;
- --new_pos;
- }
- while ((new_pos >= 1) && (p_cli->p_ctx->cmd_buff[new_pos - 1] != ' '))
- {
- --new_pos;
- ++chars_to_delete;
- }
- /* calculate the new cursor */
- row_span = cli_row_span_with_buffer_offsets_get(p_cli, p_cli->p_ctx->cmd_buff_pos, new_pos);
- col_span = cli_column_span_with_buffer_offsets_get(p_cli, p_cli->p_ctx->cmd_buff_pos, new_pos);
- /* manage the buffer */
- memmove(&p_cli->p_ctx->cmd_buff[new_pos],
- &p_cli->p_ctx->cmd_buff[new_pos + chars_to_delete],
- p_cli->p_ctx->cmd_buff_len - chars_to_delete);
- p_cli->p_ctx->cmd_buff_len -= chars_to_delete;
- p_cli->p_ctx->cmd_buff_pos = new_pos;
- p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len] = '\0';
- /* update display */
- cursor_horiz_move(p_cli, col_span);
- cursor_vert_move(p_cli, row_span);
- cli_cursor_save(p_cli);
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- cli_clear_eos(p_cli);
- cli_cursor_restore(p_cli);
- }
- #endif
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY) || NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- /* Function moves cursor to begin of command position, just after console name. */
- static void cursor_home_position_move(nrf_cli_t const * p_cli)
- {
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- if ((p_cons->cur_x == p_cons->name_len + NRF_CLI_INITIAL_CURS_POS) &&
- (p_cons->cur_y == NRF_CLI_INITIAL_CURS_POS))
- {
- return; /* nothing to handle because cursor is in start position */
- }
- if (p_cons->cur_y > NRF_CLI_INITIAL_CURS_POS)
- {
- cursor_up_move(p_cli, p_cons->cur_y - NRF_CLI_INITIAL_CURS_POS);
- }
- if (p_cons->cur_x > p_cons->name_len)
- {
- cursor_left_move(p_cli, p_cons->cur_x - NRF_CLI_INITIAL_CURS_POS - p_cons->name_len);
- }
- else
- {
- cursor_right_move(p_cli, p_cons->name_len + NRF_CLI_INITIAL_CURS_POS - p_cons->cur_x);
- }
- /* align data buffer pointer with cursor position */
- p_cli->p_ctx->cmd_buff_pos = 0;
- }
- #endif
- /* Function moves cursor to end of command. */
- static void cursor_end_position_move(nrf_cli_t const * p_cli)
- {
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- if ((p_cons->cur_x == p_cons->cur_x_end) && (p_cons->cur_y == p_cons->cur_y_end))
- {
- return; /* nothing to handle because cursor is in end position */
- }
- if (p_cons->cur_y_end > p_cons->cur_y)
- {
- cursor_down_move(p_cli, p_cons->cur_y_end - p_cons->cur_y);
- }
- if (p_cons->cur_x > p_cons->cur_x_end)
- {
- cursor_left_move(p_cli, p_cons->cur_x - p_cons->cur_x_end);
- }
- else
- {
- cursor_right_move(p_cli, p_cons->cur_x_end - p_cons->cur_x);
- }
- /* align data buffer pointer with cursor position */
- p_cli->p_ctx->cmd_buff_pos = p_cli->p_ctx->cmd_buff_len;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS)
- /* Function reads cursor position from terminal. */
- static ret_code_t cursor_position_get(nrf_cli_t const * p_cli)
- {
- size_t cnt;
- uint16_t x = 0; /* horizontal position */
- uint16_t y = 0; /* vertical position */
- char c = 0;
- nrf_cli_cmd_len_t buff_idx = 0;
- /* clear temp buffer */
- memset(p_cli->p_ctx->temp_buff, 0, sizeof(p_cli->p_ctx->temp_buff));
- /* escape code asking terminal about its size */
- static char const cmd_get_terminal_size[] = "\033[6n";
- nrf_fprintf(p_cli->p_fprintf_ctx, cmd_get_terminal_size);
- /* fprintf buffer needs to be flushed to start sending prepared escape code to the terminal */
- transport_buffer_flush(p_cli);
- /* timeout for terminal response = ~1s */
- for (uint16_t i = 0; i < 1000; i++)
- {
- do
- {
- cli_read(p_cli, &c, sizeof(c), &cnt);
- if (cnt == 0)
- {
- nrf_delay_us(999);
- continue;
- }
- if ((c != NRF_CLI_VT100_ASCII_ESC) &&
- (p_cli->p_ctx->temp_buff[0] != NRF_CLI_VT100_ASCII_ESC))
- {
- continue;
- }
- if (c == 'R') /* end of response from the terminal */
- {
- p_cli->p_ctx->temp_buff[buff_idx] = '\0';
- if (p_cli->p_ctx->temp_buff[1] != '[')
- {
- p_cli->p_ctx->temp_buff[0] = 0;
- return NRF_ERROR_INVALID_DATA;
- }
- buff_idx = 2; /* index start position in the buffer where 'y' is stored */
- while (p_cli->p_ctx->temp_buff[buff_idx] != ';')
- {
- y = y * 10 + (p_cli->p_ctx->temp_buff[buff_idx++] - '0');
- if (buff_idx >= NRF_CLI_CMD_BUFF_SIZE)
- {
- return NRF_ERROR_DATA_SIZE;
- }
- }
- if (++buff_idx >= NRF_CLI_CMD_BUFF_SIZE)
- {
- return NRF_ERROR_DATA_SIZE;
- }
- while (p_cli->p_ctx->temp_buff[buff_idx] != '\0')
- {
- x = x * 10 + (p_cli->p_ctx->temp_buff[buff_idx++] - '0');
- if (buff_idx >= NRF_CLI_CMD_BUFF_SIZE)
- {
- return NRF_ERROR_DATA_SIZE;
- }
- }
- /* horizontal cursor position */
- if (x > NRF_CLI_MAX_TERMINAL_SIZE)
- {
- p_cli->p_ctx->vt100_ctx.cons.cur_x = NRF_CLI_MAX_TERMINAL_SIZE;
- }
- else
- {
- p_cli->p_ctx->vt100_ctx.cons.cur_x = (nrf_cli_cmd_len_t)x;
- }
- /* vertical cursor position */
- if (y > NRF_CLI_MAX_TERMINAL_SIZE)
- {
- p_cli->p_ctx->vt100_ctx.cons.cur_y = NRF_CLI_MAX_TERMINAL_SIZE;
- }
- else
- {
- p_cli->p_ctx->vt100_ctx.cons.cur_y = (nrf_cli_cmd_len_t)y;
- }
- p_cli->p_ctx->temp_buff[0] = 0;
- return NRF_SUCCESS;
- }
- else
- {
- p_cli->p_ctx->temp_buff[buff_idx] = c;
- }
- if (++buff_idx > NRF_CLI_CURSOR_POSITION_BUFFER - 1)
- {
- p_cli->p_ctx->temp_buff[0] = 0;
- /* data_buf[NRF_CLI_CURSOR_POSITION_BUFFER - 1] is reserved for '\0' */
- return NRF_ERROR_NO_MEM;
- }
- } while (cnt > 0);
- }
- return NRF_ERROR_TIMEOUT;
- }
- /* Function gets terminal width and height. */
- static ret_code_t terminal_size_get(nrf_cli_t const * p_cli,
- nrf_cli_cmd_len_t * p_length,
- nrf_cli_cmd_len_t * p_height)
- {
- ASSERT(p_length);
- ASSERT(p_height);
- uint16_t x;
- uint16_t y;
- if (cursor_position_get(p_cli) == NRF_SUCCESS)
- {
- x = p_cli->p_ctx->vt100_ctx.cons.cur_x;
- y = p_cli->p_ctx->vt100_ctx.cons.cur_y;
- /* assumption: terminal widht and height < 999 */
- cursor_right_move(p_cli, NRF_CLI_MAX_TERMINAL_SIZE); /* move to last column */
- cursor_down_move(p_cli, NRF_CLI_MAX_TERMINAL_SIZE); /* move to last row */
- }
- else
- {
- return NRF_ERROR_NOT_SUPPORTED;
- }
- if (cursor_position_get(p_cli) == NRF_SUCCESS)
- {
- *p_length = p_cli->p_ctx->vt100_ctx.cons.cur_x;
- *p_height = p_cli->p_ctx->vt100_ctx.cons.cur_y;
- cursor_left_move(p_cli, *p_length - x);
- cursor_up_move(p_cli, *p_height - y);
- return NRF_SUCCESS;
- }
- return NRF_ERROR_NOT_SUPPORTED;
- }
- #endif // NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS)
- #if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- static void vt100_color_set(nrf_cli_t const * p_cli, nrf_cli_vt100_color_t color)
- {
- if (color != NRF_CLI_DEFAULT)
- {
- if (p_cli->p_ctx->vt100_ctx.col.col == color)
- {
- return;
- }
- uint8_t cmd[] = NRF_CLI_VT100_COLOR(color - 1);
- p_cli->p_ctx->vt100_ctx.col.col = color;
- nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd);
- }
- else
- {
- static uint8_t const cmd[] = NRF_CLI_VT100_MODESOFF;
- p_cli->p_ctx->vt100_ctx.col.col = color;
- nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd);
- }
- }
- static void vt100_bgcolor_set(nrf_cli_t const * p_cli, nrf_cli_vt100_color_t bgcolor)
- {
- if (bgcolor != NRF_CLI_DEFAULT)
- {
- if (p_cli->p_ctx->vt100_ctx.col.bgcol == bgcolor)
- {
- return;
- }
- /* -1 because default value is first in enum */
- uint8_t cmd[] = NRF_CLI_VT100_BGCOLOR(bgcolor - 1);
- p_cli->p_ctx->vt100_ctx.col.bgcol = bgcolor;
- nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd);
- }
- }
- static inline void vt100_colors_store(nrf_cli_t const * p_cli,
- nrf_cli_vt100_colors_t * p_color)
- {
- memcpy(p_color, &p_cli->p_ctx->vt100_ctx.col, sizeof(nrf_cli_vt100_colors_t));
- }
- static void vt100_colors_restore(nrf_cli_t const * p_cli,
- nrf_cli_vt100_colors_t const * p_color)
- {
- vt100_color_set(p_cli, p_color->col);
- vt100_bgcolor_set(p_cli, p_color->bgcol);
- }
- #endif // NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- static void left_arrow_handle(nrf_cli_t const * p_cli)
- {
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- if ((p_cons->cur_x == p_cons->name_len + NRF_CLI_INITIAL_CURS_POS) &&
- (p_cons->cur_y == NRF_CLI_INITIAL_CURS_POS))
- {
- return; /* nothing to handle because cursor is in start position */
- }
- if (p_cons->cur_x == NRF_CLI_INITIAL_CURS_POS)
- { /* go to previous line */
- cursor_up_move(p_cli, 1);
- cursor_right_move(p_cli, p_cons->terminal_wid);
- --p_cli->p_ctx->cmd_buff_pos;
- }
- else
- {
- cursor_left_move(p_cli, 1);
- --p_cli->p_ctx->cmd_buff_pos;
- }
- }
- static void right_arrow_handle(nrf_cli_t const * p_cli)
- {
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- if ((p_cons->cur_x == p_cons->cur_x_end) &&
- (p_cons->cur_y == p_cons->cur_y_end))
- {
- return; /* nothing to handle because cursor is in start position */
- }
- if (p_cons->cur_x == p_cons->terminal_wid) /* go to next line */
- {
- cursor_down_move(p_cli, 1);
- cursor_left_move(p_cli, p_cons->terminal_wid);
- ++p_cli->p_ctx->cmd_buff_pos;
- }
- else
- {
- cursor_right_move(p_cli, 1);
- ++p_cli->p_ctx->cmd_buff_pos;
- }
- }
- static inline void char_insert_echo_off(nrf_cli_t const * p_cli, char data)
- {
- if (p_cli->p_ctx->cmd_buff_len >= (NRF_CLI_CMD_BUFF_SIZE - 1))
- {
- return;
- }
- p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos++] = data;
- p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos] = '\0';
- ++p_cli->p_ctx->cmd_buff_len;
- }
- static void char_insert(nrf_cli_t const * p_cli, char data)
- {
- nrf_cli_cmd_len_t diff;
- bool ins_mode = (bool)p_cli->p_ctx->internal.flag.insert_mode;
- diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos;
- if (!ins_mode)
- {
- if (p_cli->p_ctx->cmd_buff_len >= (NRF_CLI_CMD_BUFF_SIZE - 1))
- {
- return;
- }
- if (diff > 0)
- {
- memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos + 1],
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos],
- diff);
- }
- }
- else
- {
- if ((p_cli->p_ctx->cmd_buff_len >= (NRF_CLI_CMD_BUFF_SIZE - 1)) &&
- (diff == 0))
- {
- /* If cmd buffer is full, it is possible to replace chars but adding new
- is not allowed. */
- return;
- }
- }
- p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos] = data;
- if (!ins_mode)
- {
- p_cli->p_ctx->cmd_buff[++p_cli->p_ctx->cmd_buff_len] = '\0';
- }
- if (diff > 0)
- {
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false;
- /* Below if-else statement is to minimize esc codes transmission. */
- if (last_line)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- /* Move cursor one position left less in case of insert mode. */
- cursor_left_move(p_cli, diff - ins_mode);
- }
- else
- {
- /* Save the current cursor position in order to get back after fprintf function. */
- cli_cursor_save(p_cli);
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- cli_cursor_restore(p_cli);
- /* Move cursor right by one position to edit the next character. */
- cursor_right_move(p_cli, 1);
- }
- }
- else
- {
- /* New char appended at the end of buffer. */
- if (ins_mode)
- {
- p_cli->p_ctx->cmd_buff[++p_cli->p_ctx->cmd_buff_len] = '\0';
- }
- cli_putc(p_cli, data);
- }
- /* Incrementation needs to be executed before invoking function: cursor_in_empty_line. */
- ++p_cli->p_ctx->cmd_buff_pos;
- /* Forcing terminal to switch to a new line if the command is too long. */
- if (cursor_in_empty_line(p_cli))
- {
- cursor_next_line_move(p_cli);
- return;
- }
- if (full_line_cmd(p_cli))
- {
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- /* The code below will force the terminal to scroll one line down when the currently entered command
- * reaches lower right corner of the terminal screen. */
- cursor_down_move(p_cli, p_cons->cur_y_end - p_cons->cur_y - 1);
- cursor_next_line_move(p_cli);
- cursor_up_move(p_cli, p_cons->cur_y_end - p_cons->cur_y);
- cursor_right_move(p_cli, p_cons->cur_x - 1);
- return;
- }
- }
- static void char_backspace(nrf_cli_t const * p_cli)
- {
- nrf_cli_cmd_len_t diff;
- if ((p_cli->p_ctx->cmd_buff_len == 0) || (p_cli->p_ctx->cmd_buff_pos == 0))
- {
- return;
- }
- diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos;
- memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos - 1],
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos],
- diff + 1);
- --p_cli->p_ctx->cmd_buff_pos;
- --p_cli->p_ctx->cmd_buff_len;
- if (diff > 0)
- {
- cli_putc(p_cli, NRF_CLI_VT100_ASCII_BSPACE);
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false;
- if (last_line)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- cli_clear_eos(p_cli);
- cursor_left_move(p_cli, diff);
- }
- else
- {
- /* If cursor is not in last cmd line, its position needs to be saved by
- * VT100 command. */
- cli_cursor_save(p_cli);
- cli_clear_eos(p_cli);
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- cli_cursor_restore(p_cli);
- }
- }
- else
- {
- static char const cmd_bspace[] = {
- NRF_CLI_VT100_ASCII_BSPACE, ' ', NRF_CLI_VT100_ASCII_BSPACE, '\0'};
- nrf_fprintf(p_cli->p_fprintf_ctx, "%s", cmd_bspace);
- }
- }
- static void char_delete(nrf_cli_t const * p_cli)
- {
- nrf_cli_cmd_len_t diff;
- diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos;
- if (diff == 0)
- {
- return;
- }
- memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos],
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos + 1],
- diff);
- --p_cli->p_ctx->cmd_buff_len;
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- bool last_line = p_cons->cur_y == p_cons->cur_y_end ? true : false;
- /* If last line of command is edited, there is no need for saving cursor position. */
- if (last_line)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEAREOL);
- cursor_left_move(p_cli, --diff);
- }
- else
- {
- cli_cursor_save(p_cli);
- cli_clear_eos(p_cli);
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- cli_cursor_restore(p_cli);
- }
- }
- static char make_argv(size_t * p_argc, char ** pp_argv, char * p_cmd, uint8_t max_argc)
- {
- char c;
- char quote = 0;
- *p_argc = 0;
- do
- {
- c = *p_cmd;
- if (c == '\0')
- {
- break;
- }
- if (isspace((int)c))
- {
- *p_cmd++ = '\0';
- continue;
- }
- pp_argv[(*p_argc)++] = p_cmd;
- quote = 0;
- while (1)
- {
- c = *p_cmd;
- if (c == '\0')
- {
- break;
- }
- if (!quote)
- {
- switch (c)
- {
- case '\\':
- memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd));
- p_cmd += 1;
- continue;
- case '\'':
- case '\"':
- memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd));
- quote = c;
- continue;
- default:
- break;
- }
- }
- if (quote == c)
- {
- memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd));
- quote = 0;
- continue;
- }
- if (quote && c == '\\')
- {
- char t = *(p_cmd + 1);
- if (t == quote)
- {
- memmove(p_cmd, p_cmd + 1, cli_strlen(p_cmd));
- p_cmd += 1;
- continue;
- }
- if (t == '0')
- {
- uint8_t i;
- uint8_t v = 0;
- for (i = 2; i < (2 + 3); i++)
- {
- t = *(p_cmd + i);
- if (t >= '0' && t <= '7')
- {
- v = (v << 3) | (t - '0');
- }
- else
- {
- break;
- }
- }
- if (i > 2)
- {
- memmove(p_cmd, p_cmd + (i - 1), cli_strlen(p_cmd) - (i - 2));
- *p_cmd++ = v;
- continue;
- }
- }
- if (t == 'x')
- {
- uint8_t i;
- uint8_t v = 0;
- for (i = 2; i < (2 + 2); i++)
- {
- t = *(p_cmd + i);
- if (t >= '0' && t <= '9')
- {
- v = (v << 4) | (t - '0');
- }
- else if (t >= 'a' && t <= 'f')
- {
- v = (v << 4) | (t - 'a' + 10);
- }
- else if (t >= 'A' && t <= 'F')
- {
- v = (v << 4) | (t - 'A' + 10);
- }
- else
- {
- break;
- }
- }
- if (i > 2)
- {
- memmove(p_cmd, p_cmd + (i - 1), cli_strlen(p_cmd) - (i - 2));
- *p_cmd++ = v;
- continue;
- }
- }
- }
- if (!quote && isspace((int)c))
- {
- break;
- }
- p_cmd += 1;
- }
- } while (*p_argc < max_argc);
- ASSERT(*p_argc <= NRF_CLI_ARGC_MAX);
- pp_argv[*p_argc] = 0;
- return quote;
- }
- static void cli_state_set(nrf_cli_t const * p_cli, nrf_cli_state_t state)
- {
- p_cli->p_ctx->state = state;
- if (state == NRF_CLI_STATE_ACTIVE)
- {
- cli_cmd_buffer_clear(p_cli);
- nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "%s", p_cli->p_name);
- }
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- static inline void history_mode_exit(nrf_cli_t const * p_cli)
- {
- p_cli->p_ctx->p_cmd_list_element = NULL;
- }
- static void history_handle(nrf_cli_t const * p_cli, bool up)
- {
- nrf_cli_memobj_header_t header = {
- .p_prev = NULL,
- .p_next = NULL,
- .cmd_len = 0
- };
- nrf_cli_cmd_len_t current_cmd_len;
- bool skip = false;
- if (!up) /* button down */
- {
- if (p_cli->p_ctx->p_cmd_list_element == NULL)
- {
- return;
- }
- cursor_home_position_move(p_cli);
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- p_cli->p_ctx->p_cmd_list_element = header.p_next;
- current_cmd_len = p_cli->p_ctx->cmd_buff_len;
- if (p_cli->p_ctx->p_cmd_list_element == NULL)
- {
- if (cli_strlen(p_cli->p_ctx->temp_buff) > 0)
- {
- strcpy(p_cli->p_ctx->cmd_buff, p_cli->p_ctx->temp_buff);
- }
- else
- {
- p_cli->p_ctx->cmd_buff[0] = '\0';
- }
- header.cmd_len = cli_strlen(p_cli->p_ctx->cmd_buff);
- skip = true;
- }
- }
- else /* button up */
- {
- if ((p_cli->p_ctx->p_cmd_list_element == p_cli->p_ctx->p_cmd_list_tail) ||
- (p_cli->p_ctx->p_cmd_list_head == NULL))
- {
- /* Nothing to display. */
- return;
- }
- cursor_home_position_move(p_cli);
- if (p_cli->p_ctx->p_cmd_list_element == NULL)
- {
- current_cmd_len = cli_strlen(p_cli->p_ctx->cmd_buff);
- p_cli->p_ctx->p_cmd_list_element = p_cli->p_ctx->p_cmd_list_head;
- /* Save the currently entered and not executed command. */
- if (current_cmd_len > 0)
- {
- strcpy(p_cli->p_ctx->temp_buff, p_cli->p_ctx->cmd_buff);
- }
- else
- {
- p_cli->p_ctx->temp_buff[0] = '\0';
- }
- }
- else
- {
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- current_cmd_len = header.cmd_len;
- p_cli->p_ctx->p_cmd_list_element = header.p_prev;
- }
- }
- if (!skip)
- {
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_element,
- p_cli->p_ctx->cmd_buff,
- header.cmd_len + 1, /* +1 for '\0' */
- NRF_CLI_HISTORY_HEADER_SIZE);
- }
- p_cli->p_ctx->cmd_buff_pos = header.cmd_len;
- p_cli->p_ctx->cmd_buff_len = header.cmd_len;
- if (current_cmd_len > header.cmd_len)
- {
- cli_clear_eos(p_cli);
- }
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff);
- if (cursor_in_empty_line(p_cli) || full_line_cmd(p_cli))
- {
- cursor_next_line_move(p_cli);
- }
- }
- static void history_list_element_add(nrf_cli_t const * p_cli, nrf_memobj_t * p_memobj)
- {
- ASSERT(p_memobj != NULL);
- nrf_cli_memobj_header_t header;
- if (p_cli->p_ctx->p_cmd_list_head == NULL)
- {
- p_cli->p_ctx->p_cmd_list_head = p_memobj;
- p_cli->p_ctx->p_cmd_list_tail = p_memobj;
- header.p_prev = NULL;
- header.p_next = NULL;
- header.cmd_len = p_cli->p_ctx->cmd_buff_len;
- }
- else
- {
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_head,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- header.p_next = p_memobj;
- nrf_memobj_write(p_cli->p_ctx->p_cmd_list_head,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- header.p_next = NULL;
- header.p_prev = p_cli->p_ctx->p_cmd_list_head;
- header.cmd_len = p_cli->p_ctx->cmd_buff_len;
- p_cli->p_ctx->p_cmd_list_head = p_memobj;
- }
- nrf_memobj_write(p_memobj,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- nrf_memobj_write(p_memobj,
- p_cli->p_ctx->cmd_buff,
- p_cli->p_ctx->cmd_buff_len + 1, /* +1 for '\0' */
- NRF_CLI_HISTORY_HEADER_SIZE);
- }
- static void history_list_element_oldest_remove(nrf_cli_t const * p_cli)
- {
- if (p_cli->p_ctx->p_cmd_list_tail == NULL)
- {
- return; // nothing to do
- }
- nrf_cli_memobj_header_t header;
- nrf_memobj_t * p_memobj = p_cli->p_ctx->p_cmd_list_tail;
- nrf_memobj_read(p_memobj,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- p_cli->p_ctx->p_cmd_list_tail = header.p_next;
- memset(&header, 0, sizeof(nrf_cli_memobj_header_t));
- nrf_memobj_write(p_memobj, &header, NRF_CLI_HISTORY_HEADER_SIZE, 0);
- nrf_memobj_free(p_memobj);
- /* Checking if memory objects list is empty. */
- if (p_cli->p_ctx->p_cmd_list_tail == NULL)
- {
- p_cli->p_ctx->p_cmd_list_head = NULL;
- return;
- }
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_tail,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- header.p_prev = NULL;
- nrf_memobj_write(p_cli->p_ctx->p_cmd_list_tail, &header, NRF_CLI_HISTORY_HEADER_SIZE, 0);
- }
- static void history_list_free_memory(nrf_cli_t const * p_cli)
- {
- while (p_cli->p_ctx->p_cmd_list_tail != NULL)
- {
- history_list_element_oldest_remove(p_cli);
- }
- }
- static void history_save(nrf_cli_t const * p_cli)
- {
- nrf_cli_cmd_len_t cmd_new_len = cli_strlen(p_cli->p_ctx->cmd_buff);
- history_mode_exit(p_cli);
- if (cmd_new_len == 0)
- {
- return;
- }
- /* Checking if newly entered command is not duplicated with previous one. */
- if (p_cli->p_ctx->p_cmd_list_head != NULL)
- {
- nrf_cli_memobj_header_t header;
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_head,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- if (cmd_new_len == header.cmd_len)
- {
- nrf_memobj_read(p_cli->p_ctx->p_cmd_list_head,
- p_cli->p_ctx->temp_buff,
- header.cmd_len + 1, /* +1 for '\0' */
- NRF_CLI_HISTORY_HEADER_SIZE);
- if (strcmp(p_cli->p_ctx->cmd_buff, p_cli->p_ctx->temp_buff) == 0)
- {
- /* Duplicated command, nothing to save. */
- p_cli->p_ctx->temp_buff[0] = '\0';
- return;
- }
- p_cli->p_ctx->temp_buff[0] = '\0';
- }
- }
- for (size_t idx = 0; idx < NRF_CLI_HISTORY_ELEMENT_COUNT; idx++)
- {
- nrf_memobj_t * p_memobj;
- p_memobj = nrf_memobj_alloc(p_cli->p_cmd_hist_mempool,
- ((size_t)NRF_CLI_HISTORY_HEADER_SIZE + cmd_new_len + 1));
- if (p_memobj != NULL)
- {
- history_list_element_add(p_cli, p_memobj);
- return;
- }
- else
- {
- history_list_element_oldest_remove(p_cli);
- }
- }
- return;
- }
- #endif // NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- /* Function checks how many identical characters have two strings starting from the first character. */
- static nrf_cli_cmd_len_t str_similarity_check(char const * str_a, char const * str_b)
- {
- nrf_cli_cmd_len_t cnt = 0;
- while (str_a[cnt] != '\0')
- {
- if (str_a[cnt] != str_b[cnt])
- {
- return cnt;
- }
- if (++cnt == 0)
- {
- return --cnt; /* too long strings */
- }
- }
- return cnt;
- }
- static void completion_insert(nrf_cli_t const * p_cli,
- char const * p_compl,
- nrf_cli_cmd_len_t compl_len)
- {
- ASSERT (p_compl);
- nrf_cli_cmd_len_t diff = p_cli->p_ctx->cmd_buff_len - p_cli->p_ctx->cmd_buff_pos;
- if ((p_cli->p_ctx->cmd_buff_len + compl_len > NRF_CLI_CMD_BUFF_SIZE - 1) ||
- (compl_len == 0))
- {
- return;
- }
- /* Make space for completion. */
- memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos + compl_len],
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos],
- diff + 1); /* + 1 for '\0' */
- /* Insert completion. */
- memmove(&p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos],
- p_compl,
- compl_len);
- p_cli->p_ctx->cmd_buff_len = cli_strlen(p_cli->p_ctx->cmd_buff);
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s",
- &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]);
- p_cli->p_ctx->cmd_buff_pos += compl_len;
- if (cursor_in_empty_line(p_cli) || full_line_cmd(p_cli))
- {
- cursor_next_line_move(p_cli);
- }
- if (diff > 0)
- {
- cursor_position_synchronize(p_cli);
- }
- }
- static void option_print(nrf_cli_t const * p_cli,
- char const * p_option,
- nrf_cli_cmd_len_t longest_option)
- {
- static char const * tab = " ";
- /* Function initialization has been requested. */
- if (p_option == NULL)
- {
- p_cli->p_ctx->vt100_ctx.printed_cmd = 0;
- return;
- }
- longest_option += cli_strlen(tab);
- nrf_cli_cmd_len_t columns =
- (p_cli->p_ctx->vt100_ctx.cons.terminal_wid - cli_strlen(tab)) / longest_option;
- nrf_cli_cmd_len_t diff = longest_option - cli_strlen(p_option);
- if (p_cli->p_ctx->vt100_ctx.printed_cmd++ % columns == 0)
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_OPTION, "\r\n%s%s", tab, p_option);
- }
- else
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_OPTION, "%s", p_option);
- }
- cursor_right_move(p_cli, diff);
- }
- static void cli_tab_handle(nrf_cli_t const * p_cli)
- {
- size_t cmd_idx;
- size_t cmd_last = 0;
- size_t cmd_first = 0;
- size_t argc;
- char * argv[NRF_CLI_ARGC_MAX + 1]; /* +1 reserved for NULL in function make_argv */
- nrf_cli_cmd_len_t cmd_lvl = NRF_CLI_CMD_ROOT_LVL;
- nrf_cli_cmd_len_t cmd_longest = 0; /* longest matching command */
- /* Calculating the longest possible completion length. -1 for '\0'. */
- nrf_cli_cmd_len_t compl_len = (NRF_CLI_CMD_BUFF_SIZE - 1) - p_cli->p_ctx->cmd_buff_len;
- if (compl_len == 0)
- {
- return;
- }
- /* Copy command from its beginning to cursor position. */
- memcpy(p_cli->p_ctx->temp_buff,
- p_cli->p_ctx->cmd_buff,
- p_cli->p_ctx->cmd_buff_pos);
- p_cli->p_ctx->temp_buff[p_cli->p_ctx->cmd_buff_pos] = '\0';
- /* Check if the current cursor position points to the 'space' character. */
- bool space = isspace((int)p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos - 1]);
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- /* If the Tab key is pressed, "history mode" must be terminated because tab and history handlers
- are sharing the same array: temp_buff. */
- history_mode_exit(p_cli);
- #endif
- /* Create argument list. */
- (void)make_argv(&argc,
- &argv[0],
- p_cli->p_ctx->temp_buff,
- NRF_CLI_ARGC_MAX);
- nrf_cli_cmd_len_t arg_len = cli_strlen(argv[cmd_lvl]);
- /* Variable 'static_entry' is needed to handle dynamic commands. */
- nrf_cli_static_entry_t static_entry;
- nrf_cli_cmd_entry_t const * p_cmd = NULL;
- nrf_cli_static_entry_t const * p_st_cmd = NULL;
- nrf_cli_static_entry_t const * p_st_cmd_last = NULL;
- do
- {
- if ((argc == 0) ||
- (cmd_lvl >= argc - 1 + space))
- {
- if (space)
- {
- arg_len = 0;
- }
- else
- {
- arg_len = cli_strlen(argv[cmd_lvl]);
- }
- cmd_idx = 0;
- while (1)
- {
- cmd_get(p_cmd, cmd_lvl, cmd_idx++, &p_st_cmd, &static_entry);
- if (p_st_cmd == NULL)
- {
- /* No more commands available. */
- break;
- }
- if (strncmp(argv[cmd_lvl], p_st_cmd->p_syntax, arg_len) != 0)
- {
- if (p_st_cmd_last != NULL)
- {
- /* No more matches will be found as commands are sorted alphabetically. */
- break;
- }
- continue;
- }
- if (p_st_cmd_last == NULL)
- {
- cmd_first = cmd_idx - 1;
- cmd_longest = cli_strlen(p_st_cmd->p_syntax);
- if (compl_len > (cmd_longest - arg_len))
- {
- compl_len = cmd_longest - arg_len;
- }
- }
- else
- {
- nrf_cli_cmd_len_t len = cli_strlen(p_st_cmd->p_syntax);
- if (len > cmd_longest)
- {
- cmd_longest = len;
- }
- if (compl_len > 0) /* Checking if partial completion is possible */
- {
- nrf_cli_static_entry_t last_entry;
- cmd_get(p_cmd, cmd_lvl, cmd_last, &p_st_cmd_last, &last_entry);
- len = str_similarity_check(p_st_cmd->p_syntax + arg_len,
- p_st_cmd_last->p_syntax + arg_len);
- if (compl_len > len)
- {
- /* Determining the longest possible completion. */
- compl_len = len;
- }
- }
- }
- cmd_last = cmd_idx - 1;
- p_st_cmd_last = p_st_cmd;
- if (cmd_idx == 0) /* Too many possibilities */
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_WARNING, NRF_CLI_MSG_TAB_OVERFLOWED);
- break;
- }
- }
- }
- else
- {
- cmd_idx = 0;
- while (1)
- {
- cmd_get(p_cmd, cmd_lvl, cmd_idx++, &p_st_cmd, &static_entry);
- if (cmd_idx == 0)
- {
- /* No match found and commands counter overflowed. */
- nrf_cli_fprintf(p_cli, NRF_CLI_WARNING, NRF_CLI_MSG_TAB_OVERFLOWED);
- return;
- }
- if (p_st_cmd == NULL) /* No more commands available */
- {
- return;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- /* Ignore wildcard character arguments if they are "standalone". Example:
- 1. log enable info b*<tab> -> "b*" is treated as a command so no match found
- 2. log enable info b* <tab> -> "b* " is ignored, <tab> will prompt all available
- commands. */
- if (wildcard_character_exist(argv[cmd_lvl]))
- {
- break;
- }
- #endif
- /* Fuction "strcmp" is used because an exact match is required. */
- if (strcmp(argv[cmd_lvl], p_st_cmd->p_syntax) == 0)
- {
- p_cmd = p_st_cmd->p_subcmd;
- break;
- }
- }
- }
- if ((p_cmd == NULL) || (p_st_cmd == NULL))
- {
- break;
- }
- } while (++cmd_lvl < argc + space);
- if (p_st_cmd_last == NULL)
- {
- /* No match found. */
- return;
- }
- if (cmd_first == cmd_last) /* only one match found */
- {
- if (p_cmd->is_dynamic)
- {
- /* In case of dynamic entry, function cmd_get shall be called again for matching
- * command index (cmd_last). It is because static_entry is most likely appended by
- * not valid data.
- */
- cmd_get(p_cmd, cmd_lvl, cmd_last, &p_st_cmd_last, &static_entry);
- }
- if (cli_strlen(p_st_cmd_last->p_syntax) != arg_len) /* no exact match found */
- {
- completion_insert(p_cli, p_st_cmd_last->p_syntax + arg_len, compl_len);
- }
- /* Next character in the buffer is not 'space'. */
- if (!isspace((int)p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_pos]))
- {
- if (p_cli->p_ctx->internal.flag.insert_mode)
- {
- p_cli->p_ctx->internal.flag.insert_mode = 0;
- char_insert(p_cli, ' ');
- p_cli->p_ctx->internal.flag.insert_mode = 1;
- }
- else
- {
- char_insert(p_cli, ' ');
- }
- }
- else
- {
- /* case:
- | | -> cursor
- cons_name $: valid_cmd valid_sub_cmd| |argument <tab>
- */
- cursor_position_increment(p_cli);
- /* result:
- cons_name $: valid_cmd valid_sub_cmd |a|rgument
- */
- }
- return;
- }
- /* Printing all matching commands (options). */
- option_print(p_cli, NRF_CLI_INIT_OPTION_PRINTER, cmd_longest);
- for (cmd_idx = cmd_first; cmd_idx <= cmd_last; cmd_idx++)
- {
- cmd_get(p_cmd, cmd_lvl, cmd_idx, &p_st_cmd, &static_entry);
- option_print(p_cli, p_st_cmd->p_syntax, cmd_longest);
- }
- nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "\r\n%s", p_cli->p_name);
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff);
- cursor_position_synchronize(p_cli);
- completion_insert(p_cli, p_st_cmd_last->p_syntax + arg_len, compl_len);
- }
- #define NRF_CLI_ASCII_MAX_CHAR (127u)
- static inline ret_code_t ascii_filter(char const data)
- {
- return (uint8_t)data > NRF_CLI_ASCII_MAX_CHAR ? NRF_ERROR_INVALID_DATA : NRF_SUCCESS;
- }
- static void cli_state_collect(nrf_cli_t const * p_cli)
- {
- size_t count = 0;
- char data;
- while (1)
- {
- cli_read(p_cli, &data, sizeof(data), &count);
- if (count == 0)
- {
- return;
- }
- if (ascii_filter(data) != NRF_SUCCESS)
- {
- continue;
- }
- #if NRF_MODULE_ENABLED(NRF_PWR_MGMT)
- nrf_pwr_mgmt_feed();
- #endif
- switch (p_cli->p_ctx->receive_state)
- {
- case NRF_CLI_RECEIVE_DEFAULT:
- if (data == p_cli->newline_char)
- {
- if (p_cli->p_ctx->cmd_buff_len == 0)
- {
- history_mode_exit(p_cli);
- cursor_next_line_move(p_cli);
- }
- else
- {
- /* Command execution */
- cli_execute(p_cli);
- }
- cli_state_set(p_cli, NRF_CLI_STATE_ACTIVE);
- return;
- }
- switch (data)
- {
- case NRF_CLI_VT100_ASCII_ESC: /* ESCAPE */
- receive_state_change(p_cli, NRF_CLI_RECEIVE_ESC);
- break;
- case '\0':
- break;
- #if NRF_MODULE_ENABLED(NRF_CLI_METAKEYS)
- case NRF_CLI_VT100_ASCII_CTRL_A: /* CTRL + A */
- cursor_home_position_move(p_cli);
- break;
- case NRF_CLI_VT100_ASCII_CTRL_C: /* CTRL + C */
- cursor_end_position_move(p_cli);
- if (!cursor_in_empty_line(p_cli))
- {
- cursor_next_line_move(p_cli);
- }
- cli_state_set(p_cli, NRF_CLI_STATE_ACTIVE);
- break;
- case NRF_CLI_VT100_ASCII_CTRL_E: /* CTRL + E */
- cursor_end_position_move(p_cli);
- break;
- case NRF_CLI_VT100_ASCII_CTRL_L: /* CTRL + L */
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME);
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN);
- nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "%s", p_cli->p_name);
- if (cli_flag_echo_is_set(p_cli))
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff);
- cursor_position_synchronize(p_cli);
- }
- break;
- case NRF_CLI_VT100_ASCII_CTRL_U: /* CTRL + U */
- cursor_home_position_move(p_cli);
- cli_cmd_buffer_clear(p_cli);
- cli_clear_eos(p_cli);
- break;
- case NRF_CLI_VT100_ASCII_CTRL_W: /* CTRL + W */
- cli_cmd_word_remove(p_cli);
- break;
- #endif
- case '\t': /* TAB */
- if (cli_flag_echo_is_set(p_cli))
- {
- cli_tab_handle(p_cli);
- }
- break;
- case NRF_CLI_VT100_ASCII_BSPACE: /* BACKSPACE */
- if (cli_flag_echo_is_set(p_cli))
- {
- char_backspace(p_cli);
- }
- break;
- case NRF_CLI_VT100_ASCII_DEL: /* DELETE */
- if (cli_flag_echo_is_set(p_cli))
- {
- char_delete(p_cli);
- }
- break;
- default:
- if (isprint((int)data))
- {
- if (cli_flag_echo_is_set(p_cli))
- {
- char_insert(p_cli, data);
- }
- else
- {
- char_insert_echo_off(p_cli, data);
- }
- }
- break;
- }
- break;
- case NRF_CLI_RECEIVE_ESC:
- if (data == '[')
- {
- receive_state_change(p_cli, NRF_CLI_RECEIVE_ESC_SEQ);
- }
- else
- {
- receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT);
- }
- break;
- case NRF_CLI_RECEIVE_ESC_SEQ:
- receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT);
- if (!cli_flag_echo_is_set(p_cli))
- {
- return;
- }
- switch (data)
- {
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- case 'A': /* UP arrow */
- history_handle(p_cli, true);
- break;
- case 'B': /* DOWN arrow */
- history_handle(p_cli, false);
- break;
- #endif
- case 'C': /* RIGHT arrow */
- right_arrow_handle(p_cli);
- break;
- case 'D': /* LEFT arrow */
- left_arrow_handle(p_cli);
- break;
- case '4': /* END Button in ESC[n~ mode */
- receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP);
- /* fall through */
- case 'F': /* END Button in VT100 mode */
- cursor_end_position_move(p_cli);
- break;
- case '1': /* HOME Button in ESC[n~ mode */
- receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP);
- /* fall through */
- case 'H': /* HOME Button in VT100 mode */
- cursor_home_position_move(p_cli);
- break;
- case '2': /* INSERT Button in ESC[n~ mode */
- receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP);
- /* fall through */
- case 'L': /* INSERT Button in VT100 mode */
- p_cli->p_ctx->internal.flag.insert_mode ^= 1;
- break;
- case '3':/* DELETE Button in ESC[n~ mode */
- receive_state_change(p_cli, NRF_CLI_RECEIVE_TILDE_EXP);
- if (cli_flag_echo_is_set(p_cli))
- {
- char_delete(p_cli);
- }
- break;
- default:
- break;
- }
- break;
- case NRF_CLI_RECEIVE_TILDE_EXP:
- receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT);
- break;
- default:
- receive_state_change(p_cli, NRF_CLI_RECEIVE_DEFAULT);
- break;
- }
- }
- }
- /* Function remove white chars from beginning and end of command buffer. */
- static void cmd_trim(nrf_cli_t const * p_cli)
- {
- nrf_cli_cmd_len_t i = 0;
- if (p_cli->p_ctx->cmd_buff[0] == '\0') /* no command in the buffer */
- {
- return;
- }
- /* Counting white characters starting from beginning of the command. */
- while (isspace((int)p_cli->p_ctx->cmd_buff[i++]))
- {
- if (i == 0)
- {
- p_cli->p_ctx->cmd_buff[0] = '\0';
- return;
- }
- }
- /* Removing counted white characters. */
- if (--i > 0)
- {
- memmove(p_cli->p_ctx->cmd_buff,
- p_cli->p_ctx->cmd_buff + i,
- (p_cli->p_ctx->cmd_buff_len + 1) - i); /* +1 for '\0' */
- p_cli->p_ctx->cmd_buff_len = p_cli->p_ctx->cmd_buff_len - i;
- p_cli->p_ctx->cmd_buff_pos = p_cli->p_ctx->cmd_buff_len;
- }
- /* Counting white characters starting from end of command. */
- char * p_end = &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len - 1];
- i = 0;
- while (isspace((int)*p_end))
- {
- ++i;
- --p_end;
- }
- /* Removing counted white characters. */
- if (p_end != &p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len - 1])
- {
- p_cli->p_ctx->cmd_buff[p_cli->p_ctx->cmd_buff_len - i] = '\0';
- p_cli->p_ctx->cmd_buff_len = p_cli->p_ctx->cmd_buff_len - i;
- p_cli->p_ctx->cmd_buff_pos = p_cli->p_ctx->cmd_buff_len;
- }
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- static void spaces_trim(char * p_char)
- {
- nrf_cli_cmd_len_t shift = 0;
- nrf_cli_cmd_len_t len = cli_strlen(p_char);
- if (p_char == NULL)
- {
- return;
- }
- for (nrf_cli_cmd_len_t i = 0; i < len - 1; i++)
- {
- if (isspace((int)p_char[i]))
- {
- for (nrf_cli_cmd_len_t j = i + 1; j < len; j++)
- {
- if (isspace((int)p_char[j]))
- {
- shift++;
- continue;
- }
- if (shift > 0)
- {
- memmove(&p_char[i + 1], &p_char[j], len - shift + 1); // +1 for EOS
- len -= shift;
- shift = 0;
- }
- break;
- }
- }
- }
- }
- /* Adds new command and one space just before pattern */
- static bool command_to_tmp_buffer_add(nrf_cli_t const * p_cli,
- char const * p_new_cmd,
- char const * p_pattern)
- {
- nrf_cli_cmd_len_t cmd_len = cli_strlen(p_new_cmd);
- nrf_cli_cmd_len_t shift;
- char * p_cmd_source_addr;
- /* +1 for space */
- if (((size_t)p_cli->p_ctx->cmd_tmp_buff_len + cmd_len + 1) > NRF_CLI_CMD_BUFF_SIZE)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_WARNING,
- "Command buffer is too short to expand all commands matching "
- "wildcard pattern\r\n");
- return false;
- }
- p_cmd_source_addr = strstr(p_cli->p_ctx->temp_buff, p_pattern);
- if (p_cmd_source_addr == NULL)
- {
- return false;
- }
- shift = cli_strlen(p_cmd_source_addr);
- /* make place for new command: + 1 for space + 1 for EOS */
- memmove(p_cmd_source_addr + cmd_len + 1, p_cmd_source_addr, shift + 1);
- memcpy(p_cmd_source_addr, p_new_cmd, cmd_len);
- p_cmd_source_addr[cmd_len] = ' ';
- p_cli->p_ctx->cmd_tmp_buff_len += cmd_len + 1; // + 1 for space
- return true;
- }
- /* removes pattern and following space */
- static void pattern_from_tmp_buffer_remove(nrf_cli_t const * p_cli,
- char const * p_pattern)
- {
- size_t shift;
- char * p_pattern_addr = strstr(p_cli->p_ctx->temp_buff, p_pattern);
-
- nrf_cli_cmd_len_t pattern_len = cli_strlen(p_pattern);
- if (p_pattern_addr == NULL)
- {
- return;
- }
- if (p_pattern_addr > p_cli->p_ctx->temp_buff)
- {
- if (*(p_pattern_addr - 1) == ' ')
- {
- pattern_len++; /* space needs to be removed as well */
- p_pattern_addr--; /* set pointer to space */
- }
- }
- shift = cli_strlen(p_pattern_addr) - pattern_len + 1; /* +1 for EOS */
- p_cli->p_ctx->cmd_tmp_buff_len -= pattern_len;
- memmove(p_pattern_addr, p_pattern_addr + pattern_len, shift);
- }
- /**
- * @internal @brief Function for searching and adding commands matching to wildcard pattern.
- *
- * This function is internal to nrf_cli module and shall be not called directly.
- *
- * @param[in/out] p_cli Pointer to the CLI instance.
- * @param[in] p_cmd Pointer to command which will be processed
- * @param[in] cmd_lvl Command level in the command tree.
- * @param[in] p_pattern Pointer to wildcard pattern.
- * @param[out] p_counter Number of found and added commands.
- *
- * @retval WILDCARD_CMD_ADDED All matching commands added to the buffer.
- * @retval WILDCARD_CMD_ADDED_MISSING_SPACE Not all matching commands added because
- * NRF_CLI_CMD_BUFF_SIZE is too small.
- * @retval WILDCARD_CMD_NO_MATCH_FOUND No matching command found.
- */
- static wildcard_cmd_status_t commands_expand(nrf_cli_t const * p_cli,
- nrf_cli_cmd_entry_t const * p_cmd,
- size_t cmd_lvl,
- char * p_pattern,
- size_t * p_counter)
- {
- size_t cmd_idx = 0;
- size_t counter = 0;
- bool success = false;
-
- nrf_cli_static_entry_t static_entry;
- nrf_cli_static_entry_t const * p_static_entry = NULL;
- wildcard_cmd_status_t ret_val = WILDCARD_CMD_NO_MATCH_FOUND;
- do
- {
- cmd_get(p_cmd,
- cmd_lvl,
- cmd_idx++,
- &p_static_entry,
- &static_entry);
- if (p_static_entry == NULL)
- {
- break;
- }
- if (0 == fnmatch(p_pattern, p_static_entry->p_syntax, 0))
- {
- success = command_to_tmp_buffer_add(p_cli,
- p_static_entry->p_syntax,
- p_pattern);
- if (!success)
- {
- break;
- }
- counter++;
- }
- } while(cmd_idx != 0);
- if (counter > 0)
- {
- *p_counter = counter;
- pattern_from_tmp_buffer_remove(p_cli, p_pattern);
- if (success)
- {
- ret_val = WILDCARD_CMD_ADDED;
- }
- else
- {
- ret_val = WILDCARD_CMD_ADDED_MISSING_SPACE;
- }
- }
- return ret_val;
- }
- #endif // NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- /* Function is analyzing the command buffer to find matching commands. Next, it invokes the last recognized
- * command which has a handler and passes the rest of command buffer as arguments. */
- static void cli_execute(nrf_cli_t const * p_cli)
- {
- char quote;
- size_t argc;
- char * argv[NRF_CLI_ARGC_MAX + 1]; /* +1 reserved for NULL added by function make_argv */
- size_t cmd_idx; /* currently analyzed command in cmd_level */
- size_t cmd_lvl = NRF_CLI_CMD_ROOT_LVL; /* currently analyzed command level */
- size_t cmd_handler_lvl = 0; /* last command level for which a handler has been found */
- size_t cmd_handler_idx = 0; /* last command index for which a handler has been found */
- nrf_cli_cmd_entry_t const * p_cmd = NULL;
- cmd_trim(p_cli);
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- history_save(p_cli);
- #endif
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- /* Wildcard can be correctly handled under following conditions:
- - wildcard command does not have a handler
- - wildcard command is on the deepest commands level
- - other commands on the same level as wildcard command shall also not have a handler
- Algorithm:
- 1. Command buffer is copied to Temp buffer.
- 2. Algorithm goes through Command buffer to find handlers and subcommands.
- 3. If algorithm will find a wildcard character it switches to Temp buffer.
- 4. In the Temp buffer command with found wildcard character is changed into matching command(s).
- 5. Algorithm switch back to Command buffer and analyzes next command.
- 6. When all arguments are analyzed from Command buffer, Temp buffer is copied to Command buffer.
- 7. Last found handler is executed with all arguments in the Command buffer.
- */
- size_t commands_expanded = 0;
- memset(p_cli->p_ctx->temp_buff, 0, sizeof(p_cli->p_ctx->temp_buff));
- memcpy(p_cli->p_ctx->temp_buff,
- p_cli->p_ctx->cmd_buff,
- p_cli->p_ctx->cmd_buff_len);
- /* Function spaces_trim must be used instead of make_argv. At this point it is important to keep
- temp_buff as a one string. It will allow to find wildcard commands easly with strstr
- function. */
- spaces_trim(p_cli->p_ctx->temp_buff);
- p_cli->p_ctx->cmd_tmp_buff_len = cli_strlen(p_cli->p_ctx->temp_buff) + 1; // +1 for EOS
- #endif
- cursor_end_position_move(p_cli);
- if (!cursor_in_empty_line(p_cli))
- {
- cursor_next_line_move(p_cli);
- }
- /* create argument list */
- quote = make_argv(&argc,
- &argv[0],
- p_cli->p_ctx->cmd_buff,
- NRF_CLI_ARGC_MAX);
- if (!argc)
- {
- cursor_next_line_move(p_cli);
- return;
- }
- if (quote != 0)
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "not terminated: %c\r\n", quote);
- return;
- }
- /* Searching for a matching root command. */
- for (cmd_idx = 0; cmd_idx <= CLI_DATA_SECTION_ITEM_COUNT; ++cmd_idx)
- {
- if (cmd_idx >= CLI_DATA_SECTION_ITEM_COUNT)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s%s\r\n",
- argv[0],
- NRF_CLI_MSG_COMMAND_NOT_FOUND);
- return;
- }
- p_cmd = CLI_DATA_SECTION_ITEM_GET(cmd_idx);
- if (strcmp(argv[cmd_lvl], p_cmd->u.p_static->p_syntax) != 0)
- {
- continue;
- }
- break;
- }
- /* Root command shall be always static. */
- ASSERT(p_cmd->is_dynamic == false);
- /* Pointer to the deepest command level with a handler. */
- nrf_cli_cmd_entry_t const * p_cmd_low_level_entry = NULL;
- /* Memory reserved for dynamic commands. */
- nrf_cli_static_entry_t static_entry;
- nrf_cli_static_entry_t const * p_static_entry = NULL;
- nrf_cli_cmd_handler handler_cmd_lvl_0 = p_cmd->u.p_static->handler;
- if (handler_cmd_lvl_0 != NULL)
- {
- p_cli->p_ctx->p_current_stcmd = p_cmd->u.p_static;
- }
- p_cmd = p_cmd->u.p_static->p_subcmd;
- cmd_lvl++;
- cmd_idx = 0;
- while (1)
- {
- if (cmd_lvl >= argc)
- {
- break;
- }
- if (!strcmp(argv[cmd_lvl], "-h") || !strcmp(argv[cmd_lvl], "--help"))
- {
- /* Command called with help option so it makes no sense to search deeper commands. */
- cli_flag_help_set(p_cli);
- break;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- /* Wildcard character is found */
- if (wildcard_character_exist(argv[cmd_lvl]))
- {
- size_t counter = 0;
- wildcard_cmd_status_t status;
- /* Function will search commands tree for commands matching wildcard pattern stored in
- argv[cmd_lvl]. If match is found wildcard pattern will be replaced by matching
- commands in temp_buffer. If there is no space to add all matching commands function
- will add as many as possible. Next it will continue to search for next wildcard
- pattern and it will try to add matching commands. */
- status = commands_expand(p_cli, p_cmd, cmd_lvl, argv[cmd_lvl], &counter);
- if (WILDCARD_CMD_NO_MATCH_FOUND == status)
- {
- break;
- }
- commands_expanded += counter;
- cmd_lvl++;
- continue;
- }
- #endif
- cmd_get(p_cmd,
- cmd_lvl,
- cmd_idx++,
- &p_static_entry,
- &static_entry);
- if ((cmd_idx == 0) || (p_static_entry == NULL))
- {
- break;
- }
- if (strcmp(argv[cmd_lvl], p_static_entry->p_syntax) == 0)
- {
- /* checking if command has a handler */
- if (p_static_entry->handler != NULL)
- {
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- if (commands_expanded > 0)
- {
- cursor_end_position_move(p_cli);
- if (!cursor_in_empty_line(p_cli))
- {
- cursor_next_line_move(p_cli);
- }
- /* An error occured, fnmatch argument cannot be followed by argument
- * with a handler to avoid multiple function calls. */
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "Error: requested multiple function executions\r\n");
- cli_flag_help_clear(p_cli);
- return;
- }
- #endif
- /* Storing p_st_cmd->handler is not feasible for dynamic commands. Data will be
- * invalid with the next loop iteration. */
- cmd_handler_lvl = cmd_lvl;
- cmd_handler_idx = cmd_idx - 1;
- p_cmd_low_level_entry = p_cmd;
- }
- cmd_lvl++;
- cmd_idx = 0;
- p_cmd = p_static_entry->p_subcmd;
- }
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_WILDCARD)
- if (commands_expanded > 0)
- {
- /* Copy temp_buff to cmd_buff */
- memcpy(p_cli->p_ctx->cmd_buff,
- p_cli->p_ctx->temp_buff,
- p_cli->p_ctx->cmd_tmp_buff_len);
- p_cli->p_ctx->cmd_buff_len = p_cli->p_ctx->cmd_tmp_buff_len;
- /* calling make_arg function again because cmd_buffer has additional commads */
- (void)make_argv(&argc,
- &argv[0],
- p_cli->p_ctx->cmd_buff,
- NRF_CLI_ARGC_MAX);
- }
- #endif
- /* Executing the deepest found handler. */
- if (p_cmd_low_level_entry != NULL)
- {
- cmd_get(p_cmd_low_level_entry,
- cmd_handler_lvl,
- cmd_handler_idx,
- &p_static_entry,
- &static_entry);
- p_cli->p_ctx->p_current_stcmd = p_static_entry;
- p_cli->p_ctx->p_current_stcmd->handler(p_cli,
- argc - cmd_handler_lvl,
- &argv[cmd_handler_lvl]);
- }
- else if (handler_cmd_lvl_0 != NULL)
- {
- handler_cmd_lvl_0(p_cli, argc, &argv[0]);
- }
- else
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, NRF_CLI_MSG_SPECIFY_SUBCOMMAND);
- }
- cli_flag_help_clear(p_cli);
- }
- /* Function required by qsort. */
- static int string_cmp(void const * pp_a, void const * pp_b)
- {
- ASSERT(pp_a);
- ASSERT(pp_b);
- char const ** pp_str_a = (char const **)pp_a;
- char const ** pp_str_b = (char const **)pp_b;
- return strcmp(*pp_str_a, *pp_str_b);
- }
- static void cli_transport_evt_handler(nrf_cli_transport_evt_t evt_type, void * p_context)
- {
- nrf_cli_t * p_cli = (nrf_cli_t *)p_context;
- ASSERT(p_cli);
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- task_events_set(p_cli->p_ctx->task_id, evt_type == NRF_CLI_TRANSPORT_EVT_RX_RDY ?
- NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT : NRF_CLI_TRANSPORT_TX_RDY_TASK_EVT);
- #else
- if (evt_type == NRF_CLI_TRANSPORT_EVT_RX_RDY)
- {
- }
- else
- {
- /* wr done evt */
- p_cli->p_ctx->internal.flag.tx_rdy = 1;
- }
- #endif
- }
- static ret_code_t nrf_cli_instance_init(nrf_cli_t const * p_cli,
- void const * p_config,
- bool use_colors)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- ASSERT((p_cli->newline_char == '\n') || (p_cli->newline_char == '\r'));
- #if defined(NRF_CLI_LOG_BACKEND) && NRF_CLI_LOG_BACKEND
- ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_cli = p_cli;
- #endif
- ret_code_t ret = p_cli->p_iface->p_api->init(p_cli->p_iface,
- p_config,
- cli_transport_evt_handler,
- (void *)p_cli);
- if (ret != NRF_SUCCESS)
- {
- return ret;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- ASSERT(p_cli->p_cmd_hist_mempool);
- ret = nrf_memobj_pool_init(p_cli->p_cmd_hist_mempool);
- if (ret != NRF_SUCCESS)
- {
- return ret;
- }
- p_cli->p_ctx->p_cmd_list_head = NULL;
- p_cli->p_ctx->p_cmd_list_tail = NULL;
- #endif
- memset(p_cli->p_ctx, 0, sizeof(nrf_cli_ctx_t));
- p_cli->p_ctx->internal.flag.tx_rdy = 1;
- #if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- p_cli->p_ctx->internal.flag.use_colors = use_colors;
- #endif
- p_cli->p_ctx->internal.flag.echo = NRF_CLI_ECHO_STATUS;
- p_cli->p_ctx->state = NRF_CLI_STATE_INITIALIZED;
- p_cli->p_ctx->vt100_ctx.cons.terminal_wid = NRF_CLI_DEFAULT_TERMINAL_WIDTH;
- p_cli->p_ctx->vt100_ctx.cons.terminal_hei = NRF_CLI_DEFAULT_TERMINAL_HEIGHT;
- const char * * pp_sorted_cmds = (const char * *)CLI_SORTED_CMD_PTRS_START_ADDR_GET;
- for (size_t i = 0; i < CLI_DATA_SECTION_ITEM_COUNT; i++)
- {
- const nrf_cli_cmd_entry_t * cmd;
- cmd = CLI_DATA_SECTION_ITEM_GET(i);
- /* NULL syntax commands not allowed. */
- ASSERT(cmd);
- ASSERT(cmd->u.p_static->p_syntax);
- pp_sorted_cmds[i] = cmd->u.p_static->p_syntax;
- }
- if (CLI_DATA_SECTION_ITEM_COUNT > 0)
- {
- qsort(pp_sorted_cmds,
- CLI_DATA_SECTION_ITEM_COUNT,
- sizeof (char *),
- string_cmp);
- }
- return NRF_SUCCESS;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- static ret_code_t nrf_cli_instance_uninit(nrf_cli_t const * p_cli);
- void console_task(void * p_context)
- {
- nrf_cli_t * p_cli = (nrf_cli_t *)p_context;
- ret_code_t ret = nrf_cli_start(p_cli);
- APP_ERROR_CHECK(ret);
- while (1)
- {
- uint32_t evts = task_events_wait(NRF_CLI_TASK_EVTS);
- if (evts & NRF_CLI_KILL_TASK_EVT)
- {
- (void)nrf_cli_instance_uninit(p_cli);
- task_exit();
- }
- else
- {
- nrf_cli_process(p_cli);
- }
- }
- }
- #endif
- ret_code_t nrf_cli_init(nrf_cli_t const * p_cli,
- void const * p_config,
- bool use_colors,
- bool log_backend,
- nrf_log_severity_t init_lvl)
- {
- ASSERT(p_cli);
- ret_code_t err_code = nrf_cli_instance_init(p_cli, p_config, use_colors);
- #if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG)
- if ((err_code == NRF_SUCCESS) && log_backend && NRF_CLI_LOG_BACKEND)
- {
- int32_t id = nrf_log_backend_add(p_cli->p_log_backend, init_lvl);
- if (id < 0)
- {
- return NRF_ERROR_NO_MEM;
- }
- nrf_log_backend_enable(p_cli->p_log_backend);
- }
- #endif
- return err_code;
- }
- ret_code_t nrf_cli_task_create(nrf_cli_t const * p_cli)
- {
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- p_cli->p_ctx->task_id = task_create(console_task, p_cli->p_name,(void *)p_cli);
- if (p_cli->p_ctx->task_id == TASK_ID_INVALID)
- {
- return NRF_ERROR_NO_MEM;
- }
- else
- {
- return NRF_SUCCESS;
- }
- #else
- return NRF_ERROR_NOT_SUPPORTED;
- #endif
- }
- static ret_code_t nrf_cli_instance_uninit(nrf_cli_t const * p_cli)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- if (cli_flag_processing_is_set(p_cli))
- {
- return NRF_ERROR_BUSY;
- }
- #if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG)
- if (p_cli->p_log_backend != NULL)
- {
- nrf_log_backend_disable(p_cli->p_log_backend);
- nrf_log_backend_remove(p_cli->p_log_backend);
- }
- #endif
- ret_code_t ret = p_cli->p_iface->p_api->uninit(p_cli->p_iface);
- if (ret != NRF_SUCCESS)
- {
- return ret;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- history_list_free_memory(p_cli);
- #endif
- memset(p_cli->p_ctx, 0, sizeof(nrf_cli_ctx_t));
- p_cli->p_ctx->state = NRF_CLI_STATE_UNINITIALIZED;
- return NRF_SUCCESS;
- }
- ret_code_t nrf_cli_uninit(nrf_cli_t const * p_cli)
- {
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- if (cli_flag_processing_is_set(p_cli))
- {
- return NRF_ERROR_BUSY;
- }
- task_events_set(p_cli->p_ctx->task_id, NRF_CLI_KILL_TASK_EVT);
- return NRF_SUCCESS;
- #else
- return nrf_cli_instance_uninit(p_cli);
- #endif
- }
- ret_code_t nrf_cli_start(nrf_cli_t const * p_cli)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- if (p_cli->p_ctx->state != NRF_CLI_STATE_INITIALIZED)
- {
- return NRF_ERROR_INVALID_STATE;
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- void * p_context = (void *)((uint32_t)task_id_get());
- ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_context = p_context;
- #endif
- ret_code_t err_code = p_cli->p_iface->p_api->enable(p_cli->p_iface, false);
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- task_events_set(task_id_get(), NRF_CLI_TRANSPORT_RX_RDY_TASK_EVT);
- #endif
- if (err_code == NRF_SUCCESS)
- {
- #if NRF_CLI_VT100_COLORS_ENABLED
- vt100_color_set(p_cli, NRF_CLI_NORMAL);
- vt100_bgcolor_set(p_cli, NRF_CLI_VT100_COLOR_BLACK);
- #endif
- nrf_fprintf(p_cli->p_fprintf_ctx, "\r\n\n");
- cli_state_set(p_cli, NRF_CLI_STATE_ACTIVE);
- }
- return err_code;
- }
- ret_code_t nrf_cli_stop(nrf_cli_t const * p_cli)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- if (p_cli->p_ctx->state == NRF_CLI_STATE_INITIALIZED ||
- p_cli->p_ctx->state == NRF_CLI_STATE_UNINITIALIZED)
- {
- return NRF_ERROR_INVALID_STATE;
- }
- cli_state_set(p_cli, NRF_CLI_STATE_INITIALIZED);
- return NRF_SUCCESS;
- }
- void nrf_cli_process(nrf_cli_t const * p_cli)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- nrf_cli_internal_t internal;
- internal.value = 0;
- internal.flag.processing = 1;
- (void)nrf_atomic_u32_or((nrf_atomic_u32_t *)&p_cli->p_ctx->internal.value,
- internal.value);
- switch (p_cli->p_ctx->state)
- {
- case NRF_CLI_STATE_UNINITIALIZED:
- case NRF_CLI_STATE_INITIALIZED:
- /* Console initialized but not started. */
- break;
- case NRF_CLI_STATE_ACTIVE:
- {
- cli_state_collect(p_cli);
- bool log_processed = cli_log_entry_process(p_cli, false);
- if (log_processed)
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_INFO, "%s", p_cli->p_name);
- if (cli_flag_echo_is_set(p_cli))
- {
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%s", p_cli->p_ctx->cmd_buff);
- cursor_position_synchronize(p_cli);
- }
- }
- break;
- }
- default:
- break;
- }
- transport_buffer_flush(p_cli);
- internal.value = (uint32_t)0xFFFFFFFF;
- internal.flag.processing = 0;
- (void)nrf_atomic_u32_and((nrf_atomic_u32_t *)&p_cli->p_ctx->internal.value,
- internal.value);
- }
- /* Function shall be only used by the nrf_fprintf module. */
- void nrf_cli_print_stream(void const * p_user_ctx, char const * p_data, size_t data_len)
- {
- cli_write((nrf_cli_t const *)p_user_ctx,
- p_data,
- data_len,
- NULL);
- }
- void nrf_cli_fprintf(nrf_cli_t const * p_cli,
- nrf_cli_vt100_color_t color,
- char const * p_fmt,
- ...)
- {
- ASSERT(p_fmt);
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- va_list args = {0};
- va_start(args, p_fmt);
- #if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- if ((p_cli->p_ctx->internal.flag.use_colors) &&
- (color != p_cli->p_ctx->vt100_ctx.col.col))
- {
- nrf_cli_vt100_colors_t col;
- vt100_colors_store(p_cli, &col);
- vt100_color_set(p_cli, color);
- nrf_fprintf_fmt(p_cli->p_fprintf_ctx, p_fmt, &args);
- vt100_colors_restore(p_cli, &col);
- }
- else
- #endif // NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- {
- nrf_fprintf_fmt(p_cli->p_fprintf_ctx, p_fmt, &args);
- }
- va_end(args);
- }
- /* Function prints a string on terminal screen with requested margin.
- * It takes care to not divide words.
- * p_cli Pointer to CLI instance.
- * p_str Pointer to string to be printed.
- * terminal_offset Requested left margin.
- * offset_first_line Add margin to the first printed line.
- */
- static void format_offset_string_print(nrf_cli_t const * p_cli,
- char const * p_str,
- size_t terminal_offset,
- bool offset_first_line)
- {
- if (p_str == NULL)
- {
- return;
- }
- if (offset_first_line)
- {
- cursor_right_move(p_cli, terminal_offset);
- }
- size_t length;
- size_t offset = 0;
- /* Skipping whitespace. */
- while (isspace((int)*(p_str + offset)))
- {
- ++offset;
- }
- while (1)
- {
- size_t idx = 0;
- length = cli_strlen(p_str) - offset;
- if (length <= p_cli->p_ctx->vt100_ctx.cons.terminal_wid - terminal_offset)
- {
- for (idx = 0; idx < length; idx++)
- {
- if (*(p_str + offset + idx) == '\n')
- {
- transport_buffer_flush(p_cli);
- cli_write(p_cli, p_str + offset, idx, NULL);
- offset += idx + 1;
- cursor_next_line_move(p_cli);
- cursor_right_move(p_cli, terminal_offset);
- break;
- }
- }
- /* String will fit in one line. */
- nrf_fprintf(p_cli->p_fprintf_ctx, p_str + offset);
- break;
- }
- else
- {
- /* String is longer than terminal line so text needs to divide in the way
- to not divide words. */
- length = p_cli->p_ctx->vt100_ctx.cons.terminal_wid - terminal_offset;
- while (1)
- {
- /* Determining line break. */
- if (isspace((int)(*(p_str + offset + idx))))
- {
- length = idx;
- if (*(p_str + offset + idx) == '\n')
- {
- break;
- }
- }
- if ((idx + terminal_offset) >= p_cli->p_ctx->vt100_ctx.cons.terminal_wid)
- {
- /* End of line reached. */
- break;
- }
- ++idx;
- }
- /* Writing one line, fprintf IO buffer must be flushed before calling cli_write. */
- transport_buffer_flush(p_cli);
- cli_write(p_cli, p_str + offset, length, NULL);
- offset += length;
- /* Calculating text offset to ensure that next line will not begin with a space. */
- while (isspace((int)(*(p_str + offset))))
- {
- ++offset;
- }
- cursor_next_line_move(p_cli);
- cursor_right_move(p_cli, terminal_offset);
- }
- }
- cursor_next_line_move(p_cli);
- }
- void nrf_cli_help_print(nrf_cli_t const * p_cli,
- nrf_cli_getopt_option_t const * p_opt,
- size_t opt_len)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- static uint8_t const tab_len = 2;
- static char const opt_sep[] =", "; /* options separator */
- static char const help[] = "-h, --help";
- static char const cmd_sep[] = " - "; /* command separator */
- uint16_t field_width = 0;
- uint16_t longest_string = cli_strlen(help) - cli_strlen(opt_sep);
- /* Printing help string for command. */
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "%s%s",
- p_cli->p_ctx->p_current_stcmd->p_syntax,
- cmd_sep);
- field_width = cli_strlen(p_cli->p_ctx->p_current_stcmd->p_syntax) + cli_strlen(cmd_sep);
- format_offset_string_print(p_cli, p_cli->p_ctx->p_current_stcmd->p_help, field_width, false);
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Options:\r\n");
- /* Looking for the longest option string. */
- if ((opt_len > 0) && (p_opt != NULL))
- {
- for (size_t i = 0; i < opt_len; ++i)
- {
- if (cli_strlen(p_opt[i].p_optname_short) + cli_strlen(p_opt[i].p_optname)
- > longest_string)
- {
- longest_string = cli_strlen(p_opt[i].p_optname_short)
- + cli_strlen(p_opt[i].p_optname);
- }
- }
- }
- longest_string += cli_strlen(opt_sep) + tab_len;
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- " %-*s:",
- longest_string,
- help);
- /* Print help string for options (only -h and --help). */
- field_width = longest_string + tab_len + 1; /* tab_len + 1 == " " and ':' from: " %-*s:" */
- format_offset_string_print(p_cli, "Show command help.", field_width, false);
- /* Formating and printing all available options (except -h, --help). */
- if (p_opt != NULL)
- {
- for (size_t i = 0; i < opt_len; ++i)
- {
- if ((p_opt[i].p_optname_short != NULL) && (p_opt[i].p_optname != NULL))
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- " %s%s%s",
- p_opt[i].p_optname_short,
- opt_sep,
- p_opt[i].p_optname);
- field_width = longest_string + tab_len;
- cursor_right_move(p_cli,
- field_width - ( cli_strlen(p_opt[i].p_optname_short)
- + cli_strlen(p_opt[i].p_optname)
- + tab_len
- + cli_strlen(opt_sep)));
- cli_putc(p_cli, ':');
- ++field_width; /* incrementing because char ':' was already printed above */
- }
- else if (p_opt[i].p_optname_short != NULL)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- " %-*s:",
- longest_string,
- p_opt[i].p_optname_short);
- /* tab_len + 1 == " " and ':' from: " %-*s:" */
- field_width = longest_string + tab_len + 1;
- }
- else if (p_opt[i].p_optname != NULL)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- " %-*s:",
- longest_string,
- p_opt[i].p_optname);
- /* tab_len + 1 == " " and ':' from: " %-*s:" */
- field_width = longest_string + tab_len + 1;
- }
- else
- {
- /* Do nothing. */
- }
- if (p_opt[i].p_optname_help != NULL)
- {
- format_offset_string_print(p_cli, p_opt[i].p_optname_help, field_width, false);
- }
- else
- {
- cursor_next_line_move(p_cli);
- }
- }
- }
- /* Checking if there are any subcommands avilable. */
- if (p_cli->p_ctx->p_current_stcmd->p_subcmd == NULL)
- {
- return;
- }
- /* Printing formatted help of one level deeper subcommands. */
- nrf_cli_static_entry_t static_entry;
- nrf_cli_cmd_entry_t const * p_cmd = p_cli->p_ctx->p_current_stcmd->p_subcmd;
- nrf_cli_static_entry_t const * p_st_cmd = NULL;
- field_width = 0;
- longest_string = 0;
- size_t cmd_idx = 0;
- /* Searching for the longest subcommand to print. */
- while (1)
- {
- cmd_get(p_cmd, !NRF_CLI_CMD_ROOT_LVL, cmd_idx++, &p_st_cmd, &static_entry);
- if (p_st_cmd == NULL)
- {
- break;
- }
- if (cli_strlen(p_st_cmd->p_syntax) > longest_string)
- {
- longest_string = cli_strlen(p_st_cmd->p_syntax);
- }
- }
- /* Checking if there are dynamic subcommands. */
- if (cmd_idx == 1)
- {
- /* No dynamic subcommands available. */
- return;
- }
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Subcommands:\r\n");
- /* Printing subcommands and help string (if exists). */
- cmd_idx = 0;
- while (1)
- {
- cmd_get(p_cmd, !NRF_CLI_CMD_ROOT_LVL, cmd_idx++, &p_st_cmd, &static_entry);
- if (p_st_cmd == NULL)
- {
- break;
- }
- field_width = longest_string + tab_len;
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL," %-*s:", field_width, p_st_cmd->p_syntax);
- field_width += tab_len + 1; /* tab_len + 1 == " " and ':' from: " %-*s:" */
- if (p_st_cmd->p_help != NULL)
- {
- format_offset_string_print(p_cli, p_st_cmd->p_help, field_width, false);
- }
- else
- {
- cursor_next_line_move(p_cli);
- }
- }
- }
- #if NRF_CLI_LOG_BACKEND && NRF_MODULE_ENABLED(NRF_LOG)
- #define NRF_CLI_LOG_MSG_OVERFLOW_MSK ((uint32_t)7)
- static bool cli_log_entry_process(nrf_cli_t const * p_cli, bool skip)
- {
- nrf_log_entry_t entry;
- #if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- bool print_msg = false;
- #endif
- if (nrf_queue_pop(((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue, &entry) !=
- NRF_SUCCESS)
- {
- return false;
- }
- if (skip)
- {
- nrf_memobj_put(entry);
- #if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- ++p_cli->p_ctx->statistics.log_lost_cnt;
- if ((p_cli->p_ctx->statistics.log_lost_cnt & NRF_CLI_LOG_MSG_OVERFLOW_MSK) == 1)
- {
- /* Set flag to print a message after clearing the currently entered command. */
- print_msg = true;
- }
- else
- #endif
- {
- return true;
- }
- }
- {
- /* Erasing the currently displayed command and console name. */
- nrf_cli_multiline_cons_t const * p_cons = multiline_console_data_check(p_cli);
- if (p_cons->cur_y > NRF_CLI_INITIAL_CURS_POS)
- {
- cursor_up_move(p_cli, p_cons->cur_y - NRF_CLI_INITIAL_CURS_POS);
- }
- if (p_cons->cur_x > NRF_CLI_INITIAL_CURS_POS)
- {
- cursor_left_move(p_cli, p_cons->cur_x - NRF_CLI_INITIAL_CURS_POS);
- }
- cli_clear_eos(p_cli);
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- if (print_msg)
- {
- /* Print the requested string and exit function. */
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Lost logs - increase log backend queue size.\r\n");
- return true;
- }
- #endif
- /* Printing logs from the queue. */
- do
- {
- nrf_log_header_t header;
- size_t memobj_offset = 0;
- nrf_log_str_formatter_entry_params_t params;
- nrf_memobj_read(entry, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset);
- memobj_offset = HEADER_SIZE * sizeof(uint32_t);
- params.timestamp = header.timestamp;
- params.module_id = header.module_id;
- params.dropped = header.dropped;
- params.use_colors = NRF_LOG_USES_COLORS; /* Color will be provided by the console application. */
- if (header.base.generic.type == HEADER_TYPE_STD)
- {
- char const * p_log_str = (char const *)((uint32_t)header.base.std.addr);
- params.severity = (nrf_log_severity_t)header.base.std.severity;
- uint32_t nargs = header.base.std.nargs;
- uint32_t args[6];
- nrf_memobj_read(entry, args, nargs*sizeof(uint32_t), memobj_offset);
- nrf_log_std_entry_process(p_log_str,
- args,
- nargs,
- ¶ms,
- p_cli->p_fprintf_ctx);
- }
- else if (header.base.generic.type == HEADER_TYPE_HEXDUMP)
- {
- uint32_t data_len;
- uint8_t data_buf[8];
- uint32_t chunk_len;
- data_len = header.base.hexdump.len;
- params.severity = (nrf_log_severity_t)header.base.hexdump.severity;
- do
- {
- chunk_len = sizeof(data_buf) > data_len ? data_len : sizeof(data_buf);
- nrf_memobj_read(entry, data_buf, chunk_len, memobj_offset);
- memobj_offset += chunk_len;
- data_len -= chunk_len;
- nrf_log_hexdump_entry_process(data_buf, chunk_len, ¶ms, p_cli->p_fprintf_ctx);
- } while (data_len > 0);
- }
- nrf_memobj_put(entry);
- } while (nrf_queue_pop(((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue, &entry)
- == NRF_SUCCESS);
- return true;
- }
- static void nrf_log_backend_cli_put(nrf_log_backend_t const * p_backend, nrf_log_entry_t * p_msg)
- {
- nrf_cli_log_backend_t * p_backend_cli = (nrf_cli_log_backend_t *)p_backend->p_ctx;
- nrf_cli_t const * p_cli = p_backend_cli->p_cli;
- //If panic mode cannot be handled, stop handling new requests.
- if (p_cli->p_ctx->state != NRF_CLI_STATE_PANIC_MODE_INACTIVE)
- {
- bool panic_mode = (p_cli->p_ctx->state == NRF_CLI_STATE_PANIC_MODE_ACTIVE);
- //If there is no place for a new log entry, remove the oldest one.
- ret_code_t err_code = nrf_queue_push(p_backend_cli->p_queue, &p_msg);
- while (err_code != NRF_SUCCESS)
- {
- (void)cli_log_entry_process(p_cli, panic_mode ? false : true);
- err_code = nrf_queue_push(p_backend_cli->p_queue, &p_msg);
- }
- nrf_memobj_get(p_msg);
- if (panic_mode)
- {
- (void)cli_log_entry_process(p_cli, false);
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_USES_TASK_MANAGER)
- else
- {
- task_events_set((task_id_t)((uint32_t)p_backend_cli->p_context & 0x000000FF),
- NRF_CLI_LOG_PENDING_TASK_EVT);
- }
- #endif
- }
- }
- static void nrf_log_backend_cli_flush(nrf_log_backend_t const * p_backend)
- {
- nrf_cli_log_backend_t * p_backend_cli = (nrf_cli_log_backend_t *)p_backend->p_ctx;
- nrf_cli_t const * p_cli = p_backend_cli->p_cli;
- nrf_log_entry_t * p_msg;
- if (nrf_queue_pop(p_backend_cli->p_queue, &p_msg) == NRF_SUCCESS)
- {
- (void)cli_log_entry_process(p_cli, false);
- }
- UNUSED_PARAMETER(p_backend);
- }
- static void nrf_log_backend_cli_panic_set(nrf_log_backend_t const * p_backend)
- {
- nrf_cli_log_backend_t * p_backend_cli = (nrf_cli_log_backend_t *)p_backend->p_ctx;
- nrf_cli_t const * p_cli = p_backend_cli->p_cli;
- if (p_cli->p_iface->p_api->enable(p_cli->p_iface, true) == NRF_SUCCESS)
- {
- p_cli->p_ctx->state = NRF_CLI_STATE_PANIC_MODE_ACTIVE;
- }
- else
- {
- p_cli->p_ctx->state = NRF_CLI_STATE_PANIC_MODE_INACTIVE;
- }
- }
- const nrf_log_backend_api_t nrf_log_backend_cli_api = {
- .put = nrf_log_backend_cli_put,
- .flush = nrf_log_backend_cli_flush,
- .panic_set = nrf_log_backend_cli_panic_set,
- };
- #else
- static bool cli_log_entry_process(nrf_cli_t const * p_cli, bool skip)
- {
- UNUSED_PARAMETER(p_cli);
- UNUSED_PARAMETER(skip);
- return false;
- }
- #endif // NRF_CLI_LOG_BACKEND
- /* ============ built-in commands ============ */
- #if NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS)
- static bool nrf_cli_build_in_cmd_common_executed(nrf_cli_t const * p_cli,
- bool arg_cnt_nok,
- nrf_cli_getopt_option_t const * p_opt,
- size_t opt_len)
- {
- if (nrf_cli_help_requested(p_cli))
- {
- nrf_cli_help_print(p_cli, p_opt, opt_len);
- return true;
- }
- if (arg_cnt_nok)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s: wrong parameter count\r\n",
- p_cli->p_ctx->p_current_stcmd->p_syntax);
- return true;
- }
- return false;
- }
- static void nrf_cli_cmd_clear(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- UNUSED_PARAMETER(argv);
- if ((argc == 2) && (nrf_cli_help_requested(p_cli)))
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- return;
- }
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CURSORHOME);
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_CLEARSCREEN);
- }
- static void nrf_cli_cmd_cli(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- UNUSED_PARAMETER(argv);
- if ((argc == 1) || ((argc == 2) && nrf_cli_help_requested(p_cli)) )
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- return;
- }
- nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, NRF_CLI_MSG_SPECIFY_SUBCOMMAND);
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- static void nrf_cli_cmd_colors_off(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- p_cli->p_ctx->internal.flag.use_colors = 0;
- }
- static void nrf_cli_cmd_colors_on(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- p_cli->p_ctx->internal.flag.use_colors = 1;
- }
- static void nrf_cli_cmd_colors(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- if (argc == 1)
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- return;
- }
-
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 2), NULL, 0))
- {
- return;
- }
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s:%s%s\r\n",
- argv[0],
- NRF_CLI_MSG_UNKNOWN_PARAMETER,
- argv[1]);
- }
- #endif // NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- static void nrf_cli_cmd_echo(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc > 2), NULL, 0))
- {
- return;
- }
- if (argc == 2)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s:%s%s\r\n",
- argv[0],
- NRF_CLI_MSG_UNKNOWN_PARAMETER,
- argv[1]);
- return;
- }
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "Echo status: %s\r\n",
- cli_flag_echo_is_set(p_cli) ? "on" : "off");
- }
- static void nrf_cli_cmd_echo_off(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- cli_flag_echo_clear(p_cli);
- }
- static void nrf_cli_cmd_echo_on(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- cli_flag_echo_set(p_cli);
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- static void nrf_cli_cmd_history(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- size_t i = 0;
- nrf_memobj_t const * p_cmd_list = p_cli->p_ctx->p_cmd_list_tail;
- nrf_cli_memobj_header_t header;
- while (1)
- {
- if ((p_cmd_list == NULL) || (i >= NRF_CLI_HISTORY_ELEMENT_COUNT))
- {
- break;
- }
- nrf_memobj_read((nrf_memobj_t * )p_cmd_list,
- &header,
- NRF_CLI_HISTORY_HEADER_SIZE,
- 0);
- nrf_memobj_read((nrf_memobj_t * )p_cmd_list,
- p_cli->p_ctx->temp_buff,
- header.cmd_len + 1,
- NRF_CLI_HISTORY_HEADER_SIZE);
- p_cmd_list = header.p_next;
- nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "[%3d] %s\r\n", i++, p_cli->p_ctx->temp_buff);
- }
- p_cli->p_ctx->temp_buff[0] = '\0';
- }
- #endif // NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- #if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- void nrf_cli_cmd_cli_stats(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (argc == 1)
- {
- nrf_cli_help_print(p_cli, NULL, 0);
- return;
- }
- if (argc == 2)
- {
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s:%s%s\r\n",
- argv[0],
- NRF_CLI_MSG_UNKNOWN_PARAMETER,
- argv[1]);
- return;
- }
- UNUSED_RETURN_VALUE(nrf_cli_build_in_cmd_common_executed(p_cli, (argc > 2), NULL, 0));
- }
- void nrf_cli_cmd_cli_stats_show(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- nrf_queue_t const * p_queue = ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue;
- uint8_t max_util = nrf_queue_max_utilization_get(p_queue);
- uint8_t utilization = (uint8_t)(max_util * 100ul / p_queue->size);
- nrf_cli_fprintf(p_cli,
- NRF_CLI_NORMAL,
- "Lost logs: %u\r\n"
- "Max log queue utilization: %u%% [%u/%u]\r\n",
- p_cli->p_ctx->statistics.log_lost_cnt,
- utilization,
- max_util,
- p_queue->size);
- }
- void nrf_cli_cmd_cli_stats_reset(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- p_cli->p_ctx->statistics.log_lost_cnt = 0;
- nrf_queue_max_utilization_reset(
- ((nrf_cli_log_backend_t *)p_cli->p_log_backend->p_ctx)->p_queue);
- }
- #endif // NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- static void nrf_cli_cmd_resize_default(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc != 1), NULL, 0))
- {
- return;
- }
- NRF_CLI_VT100_CMD(p_cli, NRF_CLI_VT100_SETCOL_80);
- p_cli->p_ctx->vt100_ctx.cons.terminal_wid = NRF_CLI_DEFAULT_TERMINAL_WIDTH;
- p_cli->p_ctx->vt100_ctx.cons.terminal_hei = NRF_CLI_DEFAULT_TERMINAL_HEIGHT;
- }
- static void nrf_cli_cmd_resize(nrf_cli_t const * p_cli, size_t argc, char **argv)
- {
- ASSERT(p_cli);
- ASSERT(p_cli->p_ctx && p_cli->p_iface && p_cli->p_name);
- if (argc == 1)
- {
- if (terminal_size_get(p_cli,
- &p_cli->p_ctx->vt100_ctx.cons.terminal_wid,
- &p_cli->p_ctx->vt100_ctx.cons.terminal_hei) != NRF_SUCCESS)
- {
- p_cli->p_ctx->vt100_ctx.cons.terminal_wid = NRF_CLI_DEFAULT_TERMINAL_WIDTH;
- p_cli->p_ctx->vt100_ctx.cons.terminal_hei = NRF_CLI_DEFAULT_TERMINAL_HEIGHT;
- nrf_cli_fprintf(p_cli,
- NRF_CLI_WARNING,
- "No response from the terminal, assumed 80x24 screen size\r\n");
- }
- return;
- }
- if (nrf_cli_build_in_cmd_common_executed(p_cli, (argc > 2), NULL, 0))
- {
- return;
- }
- nrf_cli_fprintf(p_cli,
- NRF_CLI_ERROR,
- "%s:%s%s\r\n",
- argv[0],
- NRF_CLI_MSG_UNKNOWN_PARAMETER,
- argv[1]);
- }
- #if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_colors)
- {
- NRF_CLI_CMD(off, NULL, NRF_CLI_HELP_COLORS_OFF, nrf_cli_cmd_colors_off),
- NRF_CLI_CMD(on, NULL, NRF_CLI_HELP_COLORS_ON, nrf_cli_cmd_colors_on),
- NRF_CLI_SUBCMD_SET_END
- };
- #endif
- NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_echo)
- {
- NRF_CLI_CMD(off, NULL, NRF_CLI_HELP_ECHO_OFF, nrf_cli_cmd_echo_off),
- NRF_CLI_CMD(on, NULL, NRF_CLI_HELP_ECHO_ON, nrf_cli_cmd_echo_on),
- NRF_CLI_SUBCMD_SET_END
- };
- #if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_cli_stats)
- {
- NRF_CLI_CMD(reset, NULL, NRF_CLI_HELP_STATISTICS_RESET, nrf_cli_cmd_cli_stats_reset),
- NRF_CLI_CMD(show, NULL, NRF_CLI_HELP_STATISTICS_SHOW, nrf_cli_cmd_cli_stats_show),
- NRF_CLI_SUBCMD_SET_END
- };
- #endif // NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_cli)
- {
- #if NRF_MODULE_ENABLED(NRF_CLI_VT100_COLORS)
- NRF_CLI_CMD(colors, &m_sub_colors, NRF_CLI_HELP_COLORS, nrf_cli_cmd_colors),
- #endif
- NRF_CLI_CMD(echo, &m_sub_echo, NRF_CLI_HELP_ECHO, nrf_cli_cmd_echo),
- #if NRF_MODULE_ENABLED(NRF_CLI_STATISTICS)
- NRF_CLI_CMD(stats, &m_sub_cli_stats, NRF_CLI_HELP_STATISTICS, nrf_cli_cmd_cli_stats),
- #endif
- NRF_CLI_SUBCMD_SET_END
- };
- NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_resize)
- {
- NRF_CLI_CMD(default, NULL, NRF_CLI_HELP_RESIZE_DEFAULT, nrf_cli_cmd_resize_default),
- NRF_CLI_SUBCMD_SET_END
- };
- NRF_CLI_CMD_REGISTER(clear, NULL, NRF_CLI_HELP_CLEAR, nrf_cli_cmd_clear);
- NRF_CLI_CMD_REGISTER(cli, &m_sub_cli, NRF_CLI_HELP_CLI, nrf_cli_cmd_cli);
- #if NRF_MODULE_ENABLED(NRF_CLI_HISTORY)
- NRF_CLI_CMD_REGISTER(history, NULL, NRF_CLI_HELP_HISTORY, nrf_cli_cmd_history);
- #endif
- NRF_CLI_CMD_REGISTER(resize, &m_sub_resize, NRF_CLI_HELP_RESIZE, nrf_cli_cmd_resize);
- #endif // NRF_MODULE_ENABLED(NRF_CLI_BUILD_IN_CMDS)
- #endif // NRF_MODULE_ENABLED(NRF_CLI)
|