FreeCalypso > hg > tcs211-c139
diff g23m/condat/ms/src/aci/line_edit.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/g23m/condat/ms/src/aci/line_edit.c Mon Jun 01 03:24:05 2015 +0000 @@ -0,0 +1,1366 @@ +/* ++----------------------------------------------------------------------------- +| Project : +| Modul : line ++----------------------------------------------------------------------------- +| Copyright 2002 Texas Instruments Berlin, AG +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments Berlin, AG +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments Berlin, AG. ++----------------------------------------------------------------------------- +| Purpose : This modul ... ++----------------------------------------------------------------------------- +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "typedefs.h" +#include "vsi.h" +#include "pei.h" +#include "aci_mem.h" +#include "P_ACI.val" + +#include "line_edit.h" +#include "line_edit_intern.h" +#include "line_split_intern.h" + + +GLOBAL char g_ledit_echoBuf[MAX_CMD_LEN+1]; + +static T_LEDIT_SRC_MAINTAIN *rootSrc = NULL; + +/* state machine functions */ +static T_LEDIT_RSLT ledit_idle (T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_prefix_a (T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_prefix_t (T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_repeat (T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_collect (T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_run_cmd (T_LEDIT_INTERN *leditInt); +/* help functions */ +static T_LEDIT_SRC_MAINTAIN *ledit_getNewSrcMaintain (T_LEDIT_SRC_MAINTAIN *lesm); +static T_LEDIT_SRC_MAINTAIN *ledit_getSrcM (UBYTE src_id, const UBYTE *chars, USHORT len); +static T_LEDIT_SRC_MAINTAIN *ledit_getSrc (UBYTE src_id); + +static T_LEDIT_RSLT ledit_remove_src (T_LEDIT_SRC_MAINTAIN *lesm); +static T_LEDIT_RSLT ledit_check_param (const UBYTE *chars, USHORT len); +static T_LEDIT_RSLT ledit_clear_lineBuf(T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_clear_all (T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_backup (T_LEDIT_INTERN *leditInt); +static T_LEDIT_RSLT ledit_echo (T_LEDIT_INTERN *leditInt); +static void ledit_echo_clear (void); + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_set_config | ++--------------------------------------------------------------------+ + + PURPOSE : - configure CR, LF, BS chars --> similiar to S3, S4, S5 + - configure echo --> similiar to ATE echo cmds in command mode + - configure echo --> similiar to ATF echo cmds in data mode +*/ +T_LEDIT_RSLT ledit_set_config (UBYTE src_id, T_LEDIT line) +{ + T_LEDIT_SRC_MAINTAIN *lineSrcM = NULL; + UBYTE *chars = NULL; + USHORT len = 0; + + /* + * get the maintenance for this AT source or create a new one or die + */ + if ((lineSrcM = ledit_getSrcM (src_id, chars, len)) EQ NULL) + { + return (LEDIT_FAIL); + } + /* + * some checks of T_LEDIT line + */ + if (line.atE NEQ 0xFF) + { + if ((line.atE EQ TRUE) OR (line.atE EQ FALSE)) + { + lineSrcM->leditInt->lineHabit.atE = line.atE; + } + else + { + return (LEDIT_FAIL); + } + } + + if (line.S3 NEQ 0xFF) + { + if (line.S3 < 128) + { + lineSrcM->leditInt->lineHabit.S3 = line.S3; + } + else + { + return (LEDIT_FAIL); + } + } + + if (line.S4 NEQ 0xFF) + { + if (line.S4 < 128) + { + lineSrcM->leditInt->lineHabit.S4 = line.S4; + } + else + { + return (LEDIT_FAIL); + } + } + + if (line.S5 NEQ 0xFF) + { + if (line.S5 < 128) + { + lineSrcM->leditInt->lineHabit.S5 = line.S5; + } + else + { + return (LEDIT_FAIL); + } + } + + if (line.smsEnd NEQ 0xFF) + { + if (line.smsEnd < 128) + { + lineSrcM->leditInt->lineHabit.smsEnd = line.smsEnd; + } + else + { + return (LEDIT_FAIL); + } + } + + return (LEDIT_CMPL); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_ctrl | ++--------------------------------------------------------------------+ + + PURPOSE : - inform and control line edit + - in err will be error code and error message of line edit +*/ + +T_LEDIT_RSLT ledit_ctrl (UBYTE src_id, T_LEDIT_CTRL ctrl, T_LEDIT_ERR **err) +{ + T_LEDIT_SRC_MAINTAIN *lineSrcM = NULL; + + TRACE_FUNCTION ("ledit_ctrl()"); + + /* + * get the maintenance for this AT source or create a new one or die + */ + if ((lineSrcM = ledit_getSrcM (src_id, NULL, 0)) EQ NULL) + { + return (LEDIT_FAIL); + } + + switch (ctrl) + { + case LEDIT_CTRL_PROMPT: + { + ledit_echo_clear(); + strcpy (g_ledit_echoBuf,"> "); + TRACE_EVENT("ledit_ctrl(): prompt for SMS editing"); + return (LEDIT_CMPL); + } + case LEDIT_CTRL_CRLF_PROMPT: + { + ledit_echo_clear(); + /* (IRA 13, 10, 62, 32) see 07.05 */ + g_ledit_echoBuf[0] = 0x0D; /* lineSrcM->leditInt->lineHabit.S3; */ /* CR */ + g_ledit_echoBuf[1] = 0x0A; /* lineSrcM->leditInt->lineHabit.S4; */ /* LF */ + g_ledit_echoBuf[2] = 0x3E; /* '>' */ + g_ledit_echoBuf[3] = 0x20; /* ' ' */ + g_ledit_echoBuf[4] = '\0'; + TRACE_EVENT("ledit_ctrl(): default settings for line behaviour"); + return (LEDIT_CMPL); + } + case LEDIT_CTRL_CMPL: + { + TRACE_EVENT("ledit_ctrl(): reset ledit internals"); + ledit_clear_all(lineSrcM->leditInt); + return (LEDIT_CMPL); + } + case LEDIT_CTRL_REMOVE_SRC: + { + ledit_remove_src(lineSrcM); + return (LEDIT_CMPL); + } + case LEDIT_CTRL_ERROR: + { + if (err) + { + *err = &lineSrcM->leditInt->err; + } + return (LEDIT_CMPL); + } + case LEDIT_CTRL_MORE_CMDS: /* query whether there are more than one cmd */ + { + if (lineSrcM->leditInt->cmdGetIter < lineSrcM->leditInt->cmdIndex) /* check if cmdline already fully parsed */ + { + TRACE_EVENT("ledit_ctrl(): are there more commands ? Yes !"); + return (LEDIT_CMPL); + } + else + { + TRACE_EVENT("ledit_ctrl(): are there more commands ? No !"); + return (LEDIT_FAIL); + } + } + default: + { + if (*err) + { + (*err)->code = LEDIT_ERR_Unknown; + (*err)->msg = ledit_err[LEDIT_ERR_Unknown].msg; + } + return (LEDIT_FAIL); + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_get_first | ++--------------------------------------------------------------------+ + + PURPOSE : - +*/ + +T_LEDIT_RSLT ledit_get_first (UBYTE src_id, T_LEDIT_ATCMD **cmd) +{ + T_LEDIT_SRC_MAINTAIN *lesm = ledit_getSrc(src_id); + + TRACE_FUNCTION ("ledit_get_first()"); + + *cmd = NULL; /* init with no command available */ + + if (lesm EQ NULL) + { + return (LEDIT_FAIL); + } + + if (lesm->leditInt->cmdm EQ NULL) + { + return (LEDIT_FAIL); + } + + *cmd = lesm->leditInt->cmdm->cmd; + return (LEDIT_CMPL); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_get_next | ++--------------------------------------------------------------------+ + + PURPOSE : - +*/ + +T_LEDIT_RSLT ledit_get_next (UBYTE src_id, T_LEDIT_ATCMD **cmd) +{ + T_LEDIT_ATCMD_M **curCmd = NULL; + + T_LEDIT_SRC_MAINTAIN *lesm = ledit_getSrc(src_id); + + TRACE_FUNCTION ("ledit_get_next()"); + + *cmd = NULL; /* init with no command available */ + + if (lesm EQ NULL) + { + return (LEDIT_FAIL); + } + + ++(lesm->leditInt->cmdGetIter); /* 1 .. n */ + + ledit_free_cmd(lesm->leditInt); /* clear all (=previous) commands */ + lesm->leditInt->cmdm = NULL; + if (ledit_split(lesm->leditInt) EQ LEDIT_CMPL) + { + curCmd = &(lesm->leditInt->cmdm); + if (*curCmd) + { + *cmd = (*curCmd)->cmd; + return (LEDIT_CMPL); + } + } + + return (LEDIT_FAIL); /* no further command available */ +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_get_current | ++--------------------------------------------------------------------+ + + PURPOSE : - for text mode relevant functions, which have to be called twice + 1. with the destination adress + 2. with the text +*/ + +T_LEDIT_RSLT ledit_get_current (UBYTE src_id, T_LEDIT_ATCMD **cmd) +{ + T_LEDIT_SRC_MAINTAIN *lesm = ledit_getSrc(src_id); + + TRACE_FUNCTION ("ledit_get_current()"); + + *cmd = NULL; /* init with no command available */ + + if (lesm EQ NULL) + { + return (LEDIT_FAIL); + } + + if (lesm->leditInt->cmdm EQ NULL) + { + return (LEDIT_FAIL); + } + + *cmd = lesm->leditInt->cmdm->cmd; + return (LEDIT_CMPL); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_text | ++--------------------------------------------------------------------+ + + PURPOSE : - + - switch from cmd mode to text mode +*/ + +T_LEDIT_RSLT ledit_text (UBYTE src_id, const UBYTE *chars, USHORT len) +{ + T_LEDIT_SRC_MAINTAIN *lineSrcM = NULL; + char c = '\0'; + + static unsigned int beginline; /* first character position in current line */ + + TRACE_FUNCTION ("ledit_text()"); + + /* + * get the maintenance for this AT source + */ + if ((lineSrcM = ledit_getSrcM (src_id, chars, len)) EQ NULL) + { + return (LEDIT_FAIL); + } + + ledit_echo_clear (); + /* + * we use the cmdBuffer to store the text, so clean it up at first calling of this function + * in case of text sent in several chunks (this function is called again), concatenate them + * by leaving the copy iterator and the cmdBuffer untouched + * txtChunk is a binary flag + */ + if (lineSrcM->leditInt->txtChunk EQ FALSE) + { + ledit_clear_lineBuf (lineSrcM->leditInt); + lineSrcM->leditInt->txtChunk = TRUE; + beginline=0; + } + + while (lineSrcM->leditInt->srcBufIter < len) + { + c = lineSrcM->leditInt->srcBuffer[lineSrcM->leditInt->srcBufIter]; + + if (lineSrcM->leditInt->copyIter EQ MAX_CMD_LEN) /* FIXME: Should be depending to csca arround 160 */ + { + if (c EQ 0x1b) + ; + else if (c EQ lineSrcM->leditInt->lineHabit.S5) + ; + else if (c EQ lineSrcM->leditInt->lineHabit.smsEnd) + ; + else + return (LEDIT_IGNORE); + } + if (c EQ 0x1b) /* ESC */ + { + if (lineSrcM->leditInt->smsBuffer) + { + ACI_MFREE (lineSrcM->leditInt->smsBuffer); /* at first delete possible last text */ + } + lineSrcM->leditInt->smsBuffer = NULL; + lineSrcM->leditInt->txtChunk = FALSE; + return (LEDIT_ESC); /* don't generate any error message */ + } + else if (c EQ lineSrcM->leditInt->lineHabit.smsEnd) /* CTRL-Z, for all non V25.ter conform rockers */ + { + lineSrcM->leditInt->origBuffer[lineSrcM->leditInt->origBufIter++] = '\0'; /* terminate text */ + lineSrcM->leditInt->lineBuffer[lineSrcM->leditInt->copyIter++] = '\0'; /* terminate text */ + + if (lineSrcM->leditInt->smsBuffer) + { + ACI_MFREE (lineSrcM->leditInt->smsBuffer); /* at first delete possible last text */ + } + ACI_MALLOC(lineSrcM->leditInt->smsBuffer, ((lineSrcM->leditInt->copyIter+1) * sizeof(char))); + if (lineSrcM->leditInt->smsBuffer EQ NULL) + { + return (LEDIT_FAIL); + } + strcpy (lineSrcM->leditInt->smsBuffer, lineSrcM->leditInt->lineBuffer); + lineSrcM->leditInt->txtChunk = FALSE; + return (LEDIT_CMPL); + } + else if (c EQ lineSrcM->leditInt->lineHabit.S3) + { + lineSrcM->leditInt->origBuffer[lineSrcM->leditInt->origBufIter++] = 0x0a; /* add newline into SMS */ + lineSrcM->leditInt->lineBuffer[lineSrcM->leditInt->copyIter++] = 0x0a; /* add newline into SMS */ + /* + * split text, so emit promp "> " again + */ + g_ledit_echoBuf[lineSrcM->leditInt->srcBufIter] = 0x0d; /* lineSrcM->leditInt->lineHabit.S3; */ + g_ledit_echoBuf[lineSrcM->leditInt->srcBufIter+1] = 0x0a; /* lineSrcM->leditInt->lineHabit.S4; */ + g_ledit_echoBuf[lineSrcM->leditInt->srcBufIter+2] = 0x3e; /* '>' */ + g_ledit_echoBuf[lineSrcM->leditInt->srcBufIter+3] = 0x20; /* ' ' */ + beginline = lineSrcM->leditInt->copyIter; /* reset line */ + } + else if (c EQ lineSrcM->leditInt->lineHabit.S4) + { + ; /* ignore Linefeeds */ + } + else if (c EQ lineSrcM->leditInt->lineHabit.S5) /* backspace */ + { + /* + * delete last character in cmd buffer by setting iterator one step back + */ + if (lineSrcM->leditInt->copyIter > beginline) + { + --(lineSrcM->leditInt->origBufIter); + --(lineSrcM->leditInt->copyIter); + g_ledit_echoBuf[lineSrcM->leditInt->srcBufIter] = c; + return (LEDIT_COLLECT); + } + else + return (LEDIT_IGNORE); + } + else + { + lineSrcM->leditInt->origBuffer[lineSrcM->leditInt->origBufIter++] = c; /* copy character to cmd buffer */ + lineSrcM->leditInt->lineBuffer[lineSrcM->leditInt->copyIter++] = c; /* copy character to cmd buffer */ + g_ledit_echoBuf[lineSrcM->leditInt->srcBufIter] = c; + } + ++(lineSrcM->leditInt->srcBufIter); + } + return (LEDIT_COLLECT); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_get_text | ++--------------------------------------------------------------------+ + + PURPOSE : - +*/ + +T_LEDIT_RSLT ledit_get_text (UBYTE src_id, char **txt) +{ + T_LEDIT_SRC_MAINTAIN *lineSrcM = NULL; + /* + * get the maintenance for this AT source + */ + if ((lineSrcM = ledit_getSrcM (src_id, NULL, 0)) EQ NULL) + { + return (LEDIT_FAIL); + } + + if (*txt) + { + ACI_MFREE (*txt); /* free the cmd parameter part */ + } + + ACI_MALLOC (*txt, (strlen(lineSrcM->leditInt->smsBuffer)+1) * sizeof(char)); + if (*txt EQ NULL) + { + return (LEDIT_FAIL); + } + /* + * the complementary ACI_MFREE takes place in ledit_ctrl (src_params->src_id,LEDIT_CTRL_CMPL, NULL); + * which has to called for success or fail of a AT cmd line. grep in ati_cmd.c and ati_ret.c + */ + if (lineSrcM->leditInt->smsBuffer) + { + strcpy (*txt, lineSrcM->leditInt->smsBuffer); /* the parameter of the AT cmd is now the SMS text */ + } + else + { + **txt = '\0'; /* in case of 0 byte text */ + } + return (LEDIT_CMPL); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_backup | ++--------------------------------------------------------------------+ + + PURPOSE : - for possible next A/ back up the current cmd line + NOW: we shift the lineBuffer to execBuffer for execution!!! +*/ + +static T_LEDIT_RSLT ledit_backup (T_LEDIT_INTERN *leditInt) +{ + if (leditInt->execBuffer) + { + ACI_MFREE (leditInt->execBuffer); + } + + leditInt->execBuffer = leditInt->lineBuffer; + leditInt->lineBuffer = NULL; + return (LEDIT_CMPL); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_echo_clear | ++--------------------------------------------------------------------+ + + PURPOSE : - +*/ +static void ledit_echo_clear (void) +{ + memset(g_ledit_echoBuf, '\0', sizeof(g_ledit_echoBuf)); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_echo | ++--------------------------------------------------------------------+ + + PURPOSE : - for echoing put the current chars into the g_ledit_echoBuffer + but attention: + all chars before the first [aA] are ignored + the same between [aA] and [tT] + Example : "murx blah fiT + cFun = 1" will be echoed as + - ------------ + "aT + cFun = 1" +*/ +static T_LEDIT_RSLT ledit_echo (T_LEDIT_INTERN *leditInt) +{ + int i = 0; + while (g_ledit_echoBuf[i]) /* skip possible [aAtT] */ + { + ++i; + } + + while (leditInt->srcBufIterE < leditInt->len) + { + g_ledit_echoBuf[i] = leditInt->srcBuffer[leditInt->srcBufIterE]; + if (leditInt->srcBuffer[leditInt->srcBufIterE] EQ leditInt->lineHabit.S3) + { + ++i; + break; + } + ++(leditInt->srcBufIterE); + ++i; + } + + g_ledit_echoBuf[i] = '\0'; + + leditInt->srcBufIterE = 0; + + return (LEDIT_CMPL); +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_remove_src | ++--------------------------------------------------------------------+ + + PURPOSE : +*/ +static T_LEDIT_RSLT ledit_remove_src (T_LEDIT_SRC_MAINTAIN *lesm) +{ + T_LEDIT_SRC_MAINTAIN *ledSrcM = rootSrc; + T_LEDIT_SRC_MAINTAIN *tmp = rootSrc; + + if (rootSrc EQ lesm) + { + tmp = rootSrc->next; + ledit_clear_all (rootSrc->leditInt); + ACI_MFREE (rootSrc->leditInt); + rootSrc->leditInt = NULL; + rootSrc = tmp; + return (LEDIT_CMPL); + } + else + { + while(ledSrcM) + { + if (ledSrcM EQ lesm) + { + tmp->next = ledSrcM->next; + ledit_clear_all (ledSrcM->leditInt); + ACI_MFREE (ledSrcM->leditInt); + ACI_MFREE (ledSrcM); + ledSrcM = NULL; + return (LEDIT_CMPL); + } + tmp = ledSrcM; + ledSrcM = ledSrcM->next; + } + return (LEDIT_FAIL); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_getNewSrcMaintain | ++--------------------------------------------------------------------+ + + PURPOSE : +*/ +static T_LEDIT_SRC_MAINTAIN *ledit_getNewSrcMaintain (T_LEDIT_SRC_MAINTAIN *lesm) +{ + static + T_LEDIT ledit_initial = {13, 10, 8, 1, 0x1a}; + /* S3 S4 S5 E, smsEnd */ + + ACI_MALLOC(lesm, (sizeof (T_LEDIT_SRC_MAINTAIN))); + if (lesm EQ NULL) + { + return NULL; + } + lesm->next = NULL; + + ACI_MALLOC(lesm->leditInt,(sizeof (T_LEDIT_INTERN))); + if (lesm->leditInt EQ NULL) + { + ACI_MFREE (lesm); + lesm = NULL; + return NULL; + } + memset(lesm->leditInt, '\0', sizeof (T_LEDIT_INTERN)); + + lesm->leditInt->copyIter = 0; + + lesm->leditInt->srcBuffer = NULL; + lesm->leditInt->srcBufIter = 0; + + lesm->leditInt->smsBuffer = NULL; + + lesm->leditInt->lineBuffer = NULL; + lesm->leditInt->lineBufIter = 0; + + lesm->leditInt->origBuffer = NULL; + lesm->leditInt->origBufIter = 0; + + lesm->leditInt->execBuffer = NULL; + lesm->leditInt->execBufIter = 0; + + lesm->leditInt->state = ledit_idle; + lesm->leditInt->lineHabit = ledit_initial; + lesm->leditInt->err.code = LEDIT_ERR_NONE; + lesm->leditInt->err.msg = NULL; + lesm->leditInt->isStr = FALSE; + lesm->leditInt->cmdGetIter = 0; + lesm->leditInt->cmdm = NULL; + ledit_clear_all(lesm->leditInt); + + return lesm; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_getSrcM | ++--------------------------------------------------------------------+ + + PURPOSE : +*/ + +static T_LEDIT_SRC_MAINTAIN *ledit_getSrcM (UBYTE src_id, const UBYTE *chars, USHORT len) +{ + static BOOL firstCall = 1; + T_LEDIT_SRC_MAINTAIN *ledSrcM = NULL; + T_LEDIT_SRC_MAINTAIN *tmp = NULL; + + /* + * get the very first AT source maintenance + */ + if (firstCall) + { + firstCall = 0; + if ((rootSrc = ledit_getNewSrcMaintain (rootSrc)) EQ NULL) + { + return NULL; + } + rootSrc->leditInt->src_id = src_id; + rootSrc->leditInt->srcBufIterE = 0; + rootSrc->leditInt->srcBufIter = 0; + rootSrc->leditInt->srcBuffer = chars; + rootSrc->leditInt->len = len; + return rootSrc; + } + /* + * do we have a maintenance for this src_id ? + */ + ledSrcM = rootSrc; + tmp = rootSrc; + while(ledSrcM AND ledSrcM->leditInt->src_id NEQ src_id) + { + tmp = ledSrcM; + ledSrcM = ledSrcM->next; + } + if (ledSrcM EQ NULL) + { + /* + * No, this AT source called line edit for the very first time + */ + if ((ledSrcM = ledit_getNewSrcMaintain (ledSrcM)) EQ NULL) + { + return NULL; + } + tmp->next = ledSrcM; + } + + ledSrcM->leditInt->src_id = src_id; + ledSrcM->leditInt->srcBufIterE = 0; + ledSrcM->leditInt->srcBufIter = 0; + ledSrcM->leditInt->srcBuffer = chars; + ledSrcM->leditInt->len = len; + ledSrcM->leditInt->err.msg = NULL; + ledSrcM->leditInt->err.code = LEDIT_ERR_NONE; + + return ledSrcM; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_getSrc | ++--------------------------------------------------------------------+ + + PURPOSE : get an existing source maintenance +*/ + +static T_LEDIT_SRC_MAINTAIN *ledit_getSrc (UBYTE src_id) +{ + T_LEDIT_SRC_MAINTAIN *ledSrcM = NULL; + + ledSrcM = rootSrc; + + while(ledSrcM AND ledSrcM->leditInt->src_id NEQ src_id) + { + ledSrcM = ledSrcM->next; + } + if (ledSrcM EQ NULL) + { + return NULL; + } + return ledSrcM; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_check_param | ++--------------------------------------------------------------------+ + + PURPOSE : - +*/ + +static T_LEDIT_RSLT ledit_check_param (const UBYTE *chars, USHORT len) +{ + if (len EQ 0 + OR chars EQ NULL) + { + return (LEDIT_FAIL); + } + if (len > MAX_CMD_LEN) + { + return (LEDIT_FAIL); + } + return (LEDIT_CMPL); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_cmd | ++--------------------------------------------------------------------+ + + PURPOSE : - receive char, chars or complete AT-string sent by UART, bluetooth, SAT, ... + - run the state machine to build up valid AT commands +*/ + +T_LEDIT_RSLT ledit_cmd (UBYTE src_id, const UBYTE *chars, USHORT len) +{ + T_LEDIT_RSLT rv = LEDIT_COLLECT; + T_LEDIT_SRC_MAINTAIN *lineSrcM = NULL; + + TRACE_FUNCTION ("ledit_cmd()"); + + /* + * get the maintenance for this AT source or create a new one or die + */ + if ((lineSrcM = ledit_getSrcM (src_id, chars, len)) EQ NULL) + { + return (LEDIT_FAIL); + } + /* + * at first check, whether the last cmd line is already processed by ATI + * ATI will call then ledit_ctrl(src_id,LEDIT_CTRL_CMPL,NULL) + * which reset the state machine + */ + if (lineSrcM->leditInt->state EQ ledit_run_cmd) + { + /* + * ATI did not confirmed the last cmd line + */ + lineSrcM->leditInt->err.code = LEDIT_ERR_LastCmdPending; + lineSrcM->leditInt->err.msg = ledit_err[LEDIT_ERR_LastCmdPending].msg; + return (LEDIT_FAIL); + } + + /* + * the caller of ledit_cmd is responsible to echoing the passed chars back + * so clear at first the old chars from the last call of ledit_cmd + */ + ledit_echo_clear(); + + if (ledit_check_param(chars, len) EQ LEDIT_FAIL) + { + lineSrcM->leditInt->err.code = LEDIT_ERR_NoValidCommand; + lineSrcM->leditInt->err.msg = ledit_err[LEDIT_ERR_NoValidCommand].msg; + return (LEDIT_FAIL); + } + /* + * the chars of the raw source cmd line can be parsed now + * call state machine and check the return value + */ + while ((lineSrcM->leditInt->srcBufIter < len) AND ((rv EQ LEDIT_COLLECT) OR (rv EQ LEDIT_IGNORE))) + { + rv = (*lineSrcM->leditInt->state)(lineSrcM->leditInt); + if (rv EQ LEDIT_FAIL) + { + ledit_clear_all(lineSrcM->leditInt); + if (lineSrcM->leditInt->lineHabit.atE) + { + ledit_echo(lineSrcM->leditInt); + } + return rv; + } + } + /* + * the chars [aAtT] have already been put into g_ledit_echoBuf by these states + */ + if ((lineSrcM->leditInt->state NEQ ledit_prefix_a) + AND(lineSrcM->leditInt->state NEQ ledit_prefix_t)) + { + /* + * but then, put all chars after [tT] into g_ledit_echoBuf + */ + if (lineSrcM->leditInt->lineHabit.atE) + { + ledit_echo(lineSrcM->leditInt); + } + } + /* + * if ready to execute, state machine will call ledit_run_cmd() + * or in case of A/ ledit_repeat() first and then ledit_run_cmd() + */ + if (lineSrcM->leditInt->state EQ ledit_repeat) + { + rv = (*lineSrcM->leditInt->state)(lineSrcM->leditInt); + if (rv EQ LEDIT_FAIL) + { + ledit_clear_all(lineSrcM->leditInt); + TRACE_EVENT ("ledit_cmd(): ledit_repeat FAILED"); + return rv; + } + } + + if (lineSrcM->leditInt->state EQ ledit_run_cmd) + { + rv = (*lineSrcM->leditInt->state)(lineSrcM->leditInt); + if (rv EQ LEDIT_FAIL) + { + ledit_clear_all(lineSrcM->leditInt); + if (lineSrcM->leditInt->lineHabit.atE) + { + ledit_echo(lineSrcM->leditInt); + } + ledit_echo_clear(); + TRACE_EVENT ("ledit_cmd(): ledit_run_cmd FAILED"); + return rv; + } + } + TRACE_EVENT_P1 ("ledit_cmd(): returns with %d", rv); + return rv; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_idle | ++--------------------------------------------------------------------+ + + PURPOSE : - state 1 of command line parser + - start parsing of AT command line with received [aA] + - is final state with received '\0' +*/ +static T_LEDIT_RSLT ledit_idle (T_LEDIT_INTERN *leditInt) +{ + char c = leditInt->srcBuffer[leditInt->srcBufIter++]; +#ifdef _SIMULATION_ + TRACE_FUNCTION ("ledit_idle()"); +#endif + if(c EQ leditInt->lineHabit.S3) + { + return (LEDIT_OK); /* simple <CR> will emit an OK */ + } + + switch (c) + { + case 'a': + case 'A': + { + if (leditInt->lineHabit.atE) + { + g_ledit_echoBuf[0] = c; + } + leditInt->state = ledit_prefix_a; + return (LEDIT_COLLECT); + } + default: + { + TRACE_EVENT_P1("ledit_idle(): ignored character is %d", c); + return (LEDIT_IGNORE); + } + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_prefix_a | ++--------------------------------------------------------------------+ + + PURPOSE : - state 2 of command line parser + +*/ + +static void ledit_prefix_help (T_LEDIT_INTERN *leditInt, char c) +{ + if (leditInt->lineHabit.atE) + { + if ((g_ledit_echoBuf[0] EQ 'a') OR (g_ledit_echoBuf[0] EQ 'A')) + { + g_ledit_echoBuf[1] = c; + } + else + { + g_ledit_echoBuf[0] = c; + } + } +} + +static T_LEDIT_RSLT ledit_prefix_a (T_LEDIT_INTERN *leditInt) +{ + char c = leditInt->srcBuffer[leditInt->srcBufIter++]; +#ifdef _SIMULATION_ + TRACE_FUNCTION ("ledit_prefix_a()"); +#endif + if(c EQ leditInt->lineHabit.S3) + { + return (LEDIT_FAIL); /* A<CR> (or what has been set for S3) makes no sense */ + } + + switch (c) + { + case SLASH: /* '/' will not be echoed */ + { + leditInt->state = ledit_repeat; + return (LEDIT_EXCT); + } + case 't': + case 'T': + { + ledit_prefix_help (leditInt, c); + leditInt->srcBufIterE = leditInt->srcBufIter; + leditInt->state = ledit_prefix_t; + return (LEDIT_COLLECT); + } + default: + { + if(c EQ leditInt->lineHabit.S5) /* backspace */ + { + ledit_prefix_help (leditInt, c); + leditInt->state = ledit_idle; + return (LEDIT_COLLECT); /* A<S5> go back */ + } + return (LEDIT_IGNORE); + } + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_prefix_t | ++--------------------------------------------------------------------+ + + PURPOSE : - state 3 of command line parser + +*/ +static T_LEDIT_RSLT ledit_prefix_t (T_LEDIT_INTERN *leditInt) +{ + char c = leditInt->srcBuffer[leditInt->srcBufIter++]; +#ifdef _SIMULATION_ + TRACE_FUNCTION ("ledit_prefix_t()"); +#endif + if(c EQ leditInt->lineHabit.S3) + { + + if (leditInt->lineHabit.atE) + { + g_ledit_echoBuf[2] = c; + } + return (LEDIT_OK); /* AT<CR> will emit an OK */ + } + if(c EQ leditInt->lineHabit.S5) /* backspace */ + { + ledit_prefix_help (leditInt, c); + leditInt->state = ledit_prefix_a; + return (LEDIT_COLLECT); /* AT<S5> go back */ + } + leditInt->srcBufIter--; /* collect needs the first character after "AT", as well */ + leditInt->state = ledit_collect; + return (LEDIT_COLLECT); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_collect | ++--------------------------------------------------------------------+ + + PURPOSE : - state 4 of command line parser + +*/ +static T_LEDIT_RSLT ledit_repeat (T_LEDIT_INTERN *leditInt) +{ + TRACE_FUNCTION ("ledit_repeat()"); + + ++(leditInt->srcBufIter); /* to reach the end of cmd line */ + + if (leditInt->execBuffer AND leditInt->execBuffer[0]) /* is there anything to repeat? */ + { + if (leditInt->lineBuffer) /* discard current "A/" */ + { + ACI_MFREE(leditInt->lineBuffer); + leditInt->lineBuffer = NULL; + } + + if (leditInt->origBuffer) /* discard current "A/" */ + { + ACI_MFREE(leditInt->origBuffer); + leditInt->origBuffer = NULL; + } + + ledit_echo_clear (); + leditInt->state = ledit_run_cmd; + return (LEDIT_EXCT); + } + return (LEDIT_FAIL); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_collect | ++--------------------------------------------------------------------+ + + PURPOSE : - state 4 of command line parser + +*/ +static T_LEDIT_RSLT ledit_collect (T_LEDIT_INTERN *leditInt) +{ + int i = 0; + char c = leditInt->srcBuffer[leditInt->srcBufIter++]; + USHORT len = 0; +#ifdef _SIMULATION_ + TRACE_FUNCTION ("ledit_collect()"); +#endif + if (leditInt->lineBuffer EQ NULL) + { + ledit_clear_lineBuf(leditInt); + } + + while (i < leditInt->len) + { + if (leditInt->copyIter+2 EQ MAX_CMD_LEN) /* some precheck, +2 for "AT" */ + { + if (c EQ leditInt->lineHabit.S3) + ; + else if (c EQ leditInt->lineHabit.S5) + ; + else + { + ledit_prefix_help(leditInt, '\a'); + return (LEDIT_IGNORE); /* loop on all other commands if we would exceed the string */ + } + } + + if(c EQ leditInt->lineHabit.S3) + { + leditInt->origBuffer[leditInt->origBufIter] = '\0'; /* terminate cmd string */ + leditInt->lineBuffer[leditInt->copyIter] = '\0'; /* terminate cmd string */ + if (leditInt->isStr NEQ FALSE) + { + /* + * a string parameter did not end with " + * e.g: at+cpbw=1,"+491721212",145,"D2 Kundenbetreuung <--- missing closing " + */ + leditInt->err.code = LEDIT_ERR_NoValidCommand; + leditInt->err.msg = ledit_err[LEDIT_ERR_NoValidCommand].msg; + return (LEDIT_FAIL); + } + /* + * for possibly repeating backup the current cmd line + */ + ledit_backup(leditInt); + leditInt->state = ledit_run_cmd; + leditInt->origBufIter = 0; + leditInt->copyIter = 0; + return (LEDIT_EXCT); + } + else if(c EQ leditInt->lineHabit.S4) + { + ; /* ignore LF */ + } + else if(c EQ leditInt->lineHabit.S5) + { + len = leditInt->origBufIter; + if ( leditInt->origBuffer[--(len)] EQ '"' ) /* Checks if the character to be deleted is '"' */ + { + leditInt->isStr = !(leditInt->isStr); /* Toggles the variable "isStr" when '"" got deleted */ + } + if (leditInt->copyIter > 0) + { + --(leditInt->copyIter); /* delete last character in cmd buffer by setting iterator i one step back */ + } + if (leditInt->origBufIter > 0) + { + --(leditInt->origBufIter); /* delete last character in cmd buffer by setting iterator i one step back */ + } + if (leditInt->copyIter EQ 0) /* reached first character after "AT" */ + { + leditInt->state = ledit_prefix_t; /* Fall back into state 't' */ + ledit_prefix_help (leditInt, c); + leditInt->origBuffer[leditInt->origBufIter] = '\0'; /* Terminate Command !!! ACI-FIX-12036 AV2 */ + leditInt->lineBuffer[leditInt->copyIter] = '\0'; /* Terminate Command !!! ACI-FIX-12036 AV2 */ + return (LEDIT_COLLECT); /* AT<S5> go back */ + } + } + else + { + switch (c) + { + case WS: + { + if (leditInt->isStr) /* don't modify anything within string e.g.: "BlAh 1234" */ + { + leditInt->origBuffer[leditInt->origBufIter++] = c; + leditInt->lineBuffer[leditInt->copyIter++] = c; + break; + } + break; /* just to eat up white space */ + } + default: + { + if ((c > 0x20) AND (!(c & 0x80))) /* only printable chars with 7 bits */ + { + if (c EQ '"') + { + leditInt->isStr = !(leditInt->isStr); + } + leditInt->origBuffer[leditInt->origBufIter++] = c; /* copy character to cmd buffer */ + if (!(leditInt->isStr) AND c >= 'a' AND c <= 'z') + { + c -= 0x20; /* to upper */ + } + leditInt->lineBuffer[leditInt->copyIter++] = c; /* copy character to cmd buffer */ + } + } + } + } + c = leditInt->srcBuffer[leditInt->srcBufIter++]; + ++i; + if (leditInt->srcBufIter > leditInt->len) + { + break; + } + } + leditInt->origBuffer[leditInt->origBufIter] = '\0'; + leditInt->lineBuffer[leditInt->copyIter] = '\0'; /* Terminate Command !!! ACI-FIX-12036 AV2 */ + + return (LEDIT_COLLECT); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_run_cmd | ++--------------------------------------------------------------------+ + + PURPOSE : - state 5 of command line parser + +*/ +static T_LEDIT_RSLT ledit_run_cmd (T_LEDIT_INTERN *leditInt) +{ + TRACE_FUNCTION("ledit_run_cmd()"); + leditInt->cmdIndex = 1; + leditInt->cmdGetIter = 1; + ledit_free_cmd(leditInt); /* clear all (=previous) commands */ + leditInt->cmdm = NULL; + return (ledit_split (leditInt)); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_clear_cmdBuf | ++--------------------------------------------------------------------+ + + PURPOSE : - +*/ +static T_LEDIT_RSLT ledit_clear_lineBuf (T_LEDIT_INTERN *leditInt) +{ + if (leditInt->lineBuffer EQ NULL) + { + ACI_MALLOC(leditInt->lineBuffer,((MAX_CMD_LEN+1) * sizeof (char))); + } + if (leditInt->lineBuffer EQ NULL) + return (LEDIT_FAIL); + + memset(leditInt->lineBuffer, '\0',(MAX_CMD_LEN+1) * sizeof (char)); + if (leditInt->origBuffer EQ NULL) + { + ACI_MALLOC(leditInt->origBuffer,((MAX_CMD_LEN+1) * sizeof (char))); + } + if (leditInt->origBuffer EQ NULL) + return (LEDIT_FAIL); + + memset(leditInt->origBuffer, '\0',(MAX_CMD_LEN+1) * sizeof (char)); + return (LEDIT_CMPL); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_clear_all | ++--------------------------------------------------------------------+ + + PURPOSE : - +*/ +static T_LEDIT_RSLT ledit_clear_all (T_LEDIT_INTERN *leditInt) +{ + ledit_free_cmd(leditInt); /* maintained by ledit_split */ + leditInt->cmdm = NULL; + + if (leditInt->smsBuffer) + { + ACI_MFREE (leditInt->smsBuffer); + leditInt->smsBuffer = NULL; + } + + if (leditInt->lineBuffer) + { + ACI_MFREE (leditInt->lineBuffer); + leditInt->lineBuffer = NULL; + } + if (leditInt->origBuffer) + { + ACI_MFREE (leditInt->origBuffer); + leditInt->origBuffer = NULL; + } + + leditInt->txtChunk = 0; + leditInt->copyIter = 0; + leditInt->origBufIter = 0; + leditInt->lineBufIter = 0; + leditInt->execBufIter = 0; + leditInt->srcBufIter = 0; + leditInt->cmdGetIter = 0; + leditInt->cmdIndex = 0; + leditInt->isStr = FALSE; + leditInt->state = ledit_idle; /* reset to default state */ + return (LEDIT_CMPL); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-F&D (8411) MODULE : LINE_EDIT_LIB | +| STATE : code ROUTINE : ledit_trace_line | ++--------------------------------------------------------------------+ + + PURPOSE : prepare a text buffer for tracing of an AT cmd line. + a cmd line is ready for tracing after receiving of the termination + character<S3> and removing of all non necessary characters, + e.g.: white spaces and the the characters in the mAlberTO phenomenon + " m a lb er t o<S3>" is interpreted as ATO ! + the characters can come in as single chars, chunk of chars or as complete line. + the actual trace takes place with trace_cmd_line() + +*/ + +T_LEDIT_RSLT ledit_trace_line (UBYTE src_id, char *txt) +{ + T_LEDIT_SRC_MAINTAIN *lineSrcM = NULL; + /* + * get the maintenance for this AT source + */ + if ((lineSrcM = ledit_getSrcM (src_id, NULL, 0)) EQ NULL) + { + return (LEDIT_FAIL); + } + + if (lineSrcM->leditInt->execBuffer) + { + strncpy (txt, lineSrcM->leditInt->execBuffer, 77); /* limit to 77 chars, 2 are used for "AT" */ + txt[77] = '\0'; + return (LEDIT_CMPL); + } + else + { + return (LEDIT_FAIL); + } +} +