WIZlib Library API  ver 1.0
WIZlib Library API User Menual
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
atcmd.c
Go to the documentation of this file.
1 
12 //#define FILE_LOG_SILENCE
13 #include "appmod/atcmd/atcmd.h"
14 #include "appmod/atcmd/cmdrun.h"
15 
16 #define CMD_CLEAR() { \
17  atci.tcmd.op[0] = atci.tcmd.sign = atci.tcmd.arg1[0] = atci.tcmd.arg2[0] = 0; \
18  atci.tcmd.arg3[0] = atci.tcmd.arg4[0] = atci.tcmd.arg5[0] = atci.tcmd.arg6[0] = 0; \
19 }
20 #define RESP_CR(type_v) do{CMD_CLEAR(); cmd_resp(type_v, VAL_NONE); return;}while(0)
21 #define RESP_CDR(type_v, dgt_v) do{ \
22  CMD_CLEAR(); sprintf((char*)atci.tcmd.arg1, "%d", dgt_v); \
23  cmd_resp(type_v, VAL_NONE); return; \
24 }while(0)
25 
26 #define CMP_CHAR_2(str_p, c1_v, c2_v) \
27  (str_p[1] != 0 || ((str_p[0]=toupper(str_p[0]))!=c1_v && str_p[0]!=c2_v))
28 #define CMP_CHAR_3(str_p, c1_v, c2_v, c3_v) \
29  (str_p[1] != 0 || ((str_p[0]=toupper(str_p[0]))!=c1_v && str_p[0]!=c2_v && str_p[0]!=c3_v))
30 #define CHK_DGT_RANGE(str_p, snum_v, minval_v, maxval_v) \
31  ((snum_v=atoi((char*)str_p))>maxval_v || snum_v<minval_v)
32 #define CHK_ARG_LEN(arg_p, maxlen_v, ret_v) { \
33  if(maxlen_v == 0) { \
34  if(arg_p[0] != 0) RESP_CDR(RET_WRONG_ARG, ret_v); \
35  } else if(strlen((char*)arg_p) > maxlen_v) RESP_CDR(RET_WRONG_ARG, ret_v); \
36 }
37 
38 static void cmd_set_prev(uint8 buflen);
39 static int8 cmd_divide(int8 *buf);
40 static void cmd_assign(void);
41 static void hdl_nset(void);
42 static void hdl_nstat(void);
43 static void hdl_nmac(void);
44 static void hdl_nopen(void);
45 static void hdl_ncls(void);
46 static void hdl_nsend(void);
47 static void hdl_nrecv(void);
48 static void hdl_nsock(void);
49 static void hdl_nopt(void);
50 #if 0 // for wlan
51 static void hdl_wset(void);
52 static void hdl_wstat(void);
53 static void hdl_wscan(void);
54 static void hdl_wjoin(void);
55 static void hdl_wleave(void);
56 static void hdl_wsec(void);
57 static void hdl_wwps(void);
58 #endif
59 static void hdl_mset(void);
60 static void hdl_mstat(void);
61 static void hdl_mevt(void);
62 static void hdl_musart(void);
63 static void hdl_mspi(void);
64 static void hdl_mprof(void);
65 static void hdl_mrst(void);
66 static void hdl_fdhcpd(void);
67 static void hdl_fdns(void);
68 static void hdl_fping(void);
69 static void hdl_fgpio(void);
70 static void hdl_eset(void);
71 static void hdl_estat(void);
72 
73 
74 #define ATCMD_BUF_SIZE 100
75 #define PREVBUF_MAX_SIZE 250
76 #define PREVBUF_MAX_NUM 10
77 #define PREVBUF_LAST (PREVBUF_MAX_NUM-1)
78 #define CMD_SIGN_NONE 0
79 #define CMD_SIGN_QUEST 1
80 #define CMD_SIGN_INDIV 2
81 #define CMD_SIGN_EQUAL 3
82 
83 static int8 termbuf[ATCMD_BUF_SIZE];
84 static int8 *prevbuf[PREVBUF_MAX_NUM];
85 static uint8 previdx = 0, prevcnt = 0;
86 static int16 prevlen = 0;
87 
88 struct atc_info atci;
89 
90 
96 void atc_init(void)
97 {
98  int8 i;
99 
100  memset(termbuf, 0, ATCMD_BUF_SIZE);
101  for(i=0; i<PREVBUF_MAX_NUM; i++) prevbuf[i] = NULL;
102  atci.sendsock = VAL_NONE;
103  atci.echo = VAL_ENABLE;
104  atci.poll = POLL_MODE_SEMI;
105 
106  sockwatch_open(1, atc_async_cb); // 1~7 번 소켓을 atc에 할당
107  sockwatch_open(2, atc_async_cb);
108  sockwatch_open(3, atc_async_cb);
109  sockwatch_open(4, atc_async_cb);
110  sockwatch_open(5, atc_async_cb);
111  sockwatch_open(6, atc_async_cb);
112  sockwatch_open(7, atc_async_cb);
113 
114  printf("\r\n\r\n\r\n[W,0]\r\n");
115 
116  // ToDo
117 
118  printf("[S,0]\r\n");
119 }
120 
126 void atc_run(void)
127 {
128  int8 i, ret, recv_char;
129  static int8 curidx = -1, curcnt = 0;
130  static uint8 buflen = 0;
131  //static bool prompt = TRUE;
132 
133  recv_char = (int8)getchar_nonblk();
134  if(recv_char == RET_NOK) return; // 입력 값 없는 경우 printf("RECV: 0x%x\r\n", recv_char);
135 
136  if(atci.sendsock != VAL_NONE)
137  {
138  //if(atci.sendsock == VAL_INVALID) { // send fail등으로 더 받을 필요가 없더라도 정해진 size는 입력이 들어올 것으로 가정
139  // if(++atci.worklen >= atci.sendlen) {
140  // atci.sendsock = VAL_NONE; // 그냥 카운트만 하고 버림
141  // cmd_resp(ret, VAL_NONE); // 마지막으로 실패 응답하고 나감
142  // }
143  // return;
144  //}
145 
146  atci.sendbuf[atci.worklen++] = recv_char;
147  if(atci.worklen >= atci.sendlen) { // 입력이 완료되면
148  act_nsend(atci.sendsock, atci.sendbuf, atci.worklen, atci.sendip, &atci.sendport);
149  atci.sendsock = VAL_NONE;
150  }
151  return;
152  }
153  //if(prompt == FALSE) {
154  // prompt = TRUE;
155  // PUTCHAR('>');
156  //}
157 
158  if(isgraph(recv_char) == 0) // 제어 문자 처리
159  { //printf("ctrl\r\n");
160  switch(recv_char) {
161  case 0x0d: // CR(\r)
162  break; // do nothing
163  case 0x0a: // LF(\n) printf("<ENT>");
164  if(atci.echo) printf("\r\n");
165  termbuf[buflen] = 0;
166  curidx = -1;
167  curcnt = 0;
168  //prompt = FALSE;
169  break;
170  case 0x08: // BS printf("<BS>\r\n");
171  if(buflen != 0) {
172  buflen--;
173  termbuf[buflen] = 0;
174  if(atci.echo) printf("\b \b");
175  }
176  break;
177  case 0x1b: // ESC printf("<ESC>\r\n");
178  Delay_ms(5); // For receiving rest key. (this is for the users using terminal, so little delay doesn't matter)
179  {
180  int8 sec_char = (int8)getchar_nonblk();
181  int8 trd_char = (int8)getchar_nonblk(); //printf("s(%x),t(%x)", sec_char, trd_char);
182  if(sec_char == '[') {
183  switch(trd_char) {
184  case 'A': //printf("<U>\r\n");
185  if(curcnt >= prevcnt) break; // 최대 히스토리 수를 넘기면 break
186  if(curidx == -1) curidx = previdx; // 처음 누르는 경우 현제 idx값 지정
187  for(i=0; i<buflen; i++) if(atci.echo) PUTCHAR('\b'); // 입력화면 삭제
188  for(i=0; i<buflen; i++) if(atci.echo) PUTCHAR(' '); // 입력화면 삭제
189  for(i=0; i<buflen; i++) if(atci.echo) PUTCHAR('\b'); // 입력화면 삭제
190  if(curidx == 0) curidx = PREVBUF_LAST; // 직전 값 지정
191  else curidx--;
192  curcnt++; //printf("##%d, %d$$\r\n", curidx, prevlen);Delay_ms(5);printf("##%s$$\r\n", prevbuf[curidx]);Delay_ms(5);
193  if(prevbuf[curidx]) {
194  buflen = strlen((char*)prevbuf[curidx]);
195  strcpy((char*)termbuf, (char*)prevbuf[curidx]);
196  } else CRITICAL_ERR("prevbuf NULL");
197  if(atci.echo) printf("%s", termbuf);
198  break;
199  case 'B': //printf("<D>\r\n");
200  if(curcnt <= 0) break; // 처음이면 break
201  for(i=0; i<buflen; i++) if(atci.echo) PUTCHAR('\b'); // 입력화면 삭제
202  for(i=0; i<buflen; i++) if(atci.echo) PUTCHAR(' '); // 입력화면 삭제
203  for(i=0; i<buflen; i++) if(atci.echo) PUTCHAR('\b'); // 입력화면 삭제
204  if(curidx == PREVBUF_LAST) curidx = 0; // 다음 값 지정
205  else curidx++;
206  curcnt--; //printf("##%d, %d$$\r\n", curidx, prevlen);Delay_ms(5);printf("##%s$$\r\n", prevbuf[curidx]);Delay_ms(5);
207  if(curcnt == 0) {
208  buflen = 0;
209  } else if(prevbuf[curidx]) {
210  buflen = strlen((char*)prevbuf[curidx]);
211  strcpy((char*)termbuf, (char*)prevbuf[curidx]);
212  if(atci.echo) printf("%s", termbuf);
213  } else CRITICAL_ERR("prevbuf NULL");
214  break;
215  case 'C': break;//printf("<R>\r\n"); break;
216  case 'D': break;//printf("<L>\r\n"); break;
217  }
218  }
219  }
220  break;
221  //case 0x20:
222  // break;
223  //case 0x7f: //printf("<DEL>\r\n");
224  // memset(termbuf, 0, CMD_BUF_SIZE);
225  // buflen = 0; //printf("DEL: cur(%d), mfunc(%c), depth(%d)\r\n", mi.cur, mtree[mi.cur-1].mfunc==NULL?'N':'Y', depth);
226  // printf("\r\n");
227  // break;
228  //case 0x1b: //printf("<ESC>\r\n");
229  // break;
230  }
231 
232  }
233  else if(buflen < ATCMD_BUF_SIZE-1) // -1 이유 : 0 이 하나 필요하므로
234  {
235  termbuf[buflen++] = (uint8)recv_char; //termbuf[buflen] = 0;
236  if(atci.echo) PUTCHAR(recv_char); //printf(" termbuf(%c, %s)\r\n", recv_char, termbuf);
237  }//else { printf("input buffer stuffed\r\n"); }
238 
239  if(recv_char != 0x0a || buflen == 0) return; //LOGA("Command: %d, %s\r\n", buflen, termbuf);
240 
241  cmd_set_prev(buflen);
242  buflen = 0;
243 
244  CMD_CLEAR();
245  ret = cmd_divide(termbuf);
246  if(ret == RET_OK) {
247  cmd_assign();
248  } else if(ret != RET_DONE) {
249  cmd_resp(ret, VAL_NONE);
250  }
251 }
252 
253 static void cmd_set_prev(uint8 buflen)
254 {
255  int8 idx;
256 
257  while(prevcnt >= PREVBUF_MAX_NUM || (prevcnt && prevlen+buflen > PREVBUF_MAX_SIZE-1)) {
258  idx = (previdx + PREVBUF_MAX_NUM - prevcnt) % PREVBUF_MAX_NUM; // oldest index
259  if(prevbuf[idx]) {
260  prevlen -= strlen((char*)prevbuf[idx]) + 1;
261  free(prevbuf[idx]);
262  prevcnt--;
263  } else CRITICAL_ERR("ring buf 1");
264  }
265 
266  prevbuf[previdx] = malloc(buflen+1);
267 
268  while(prevcnt && prevbuf[previdx] == NULL) {
269  idx = (previdx + PREVBUF_MAX_NUM - prevcnt) % PREVBUF_MAX_NUM; // oldest index
270  if(prevbuf[idx]) {
271  prevlen -= strlen((char*)prevbuf[idx]) + 1;
272  free(prevbuf[idx]);
273  prevcnt--;
274  prevbuf[previdx] = malloc(buflen+1);
275  } else CRITICAL_ERR("ring buf 2");
276  }
277 
278  if(prevbuf[previdx] == NULL) CRITICAL_ERR("malloc fail"); // 만약 실패해도 걍 하고 싶으면 수정
279  else {
280  strcpy((char*)prevbuf[previdx], (char*)termbuf); //printf("$$%s## was set\r\n", prevbuf[previdx]);
281  if(previdx == PREVBUF_LAST) previdx = 0;
282  else previdx++;
283  prevcnt++;
284  prevlen += buflen + 1;
285  }
286 }
287 
288 static int8 cmd_divide(int8 *buf)
289 {
290  int8 ret, *split, *noteptr, *tmpptr = buf; //printf("cmd_divide 1 \r\n");
291 
292  if(strchr((char*)tmpptr, '=')) atci.tcmd.sign = CMD_SIGN_EQUAL;
293  else if(strchr((char*)tmpptr, '?')) atci.tcmd.sign = CMD_SIGN_QUEST;
294  else if(strchr((char*)tmpptr, '-')) atci.tcmd.sign = CMD_SIGN_INDIV;
295 
296  split = strsep(&tmpptr, "=-?");
297  if(split != NULL)
298  {
299  for (noteptr = split; *noteptr; noteptr++) *noteptr = toupper(*noteptr);
300  if(strlen((char*)split) > OP_SIZE+3-1 ||
301  split[0] != 'A' || split[1] != 'T' || split[2] != '+')
302  {
303  if(split[0] == 'A' && split[1] == 'T' && split[2] == 0) { // Just 'AT' input
304  if(atci.tcmd.sign == CMD_SIGN_QUEST) {
305  if(prevcnt < 2) printf("[D,,0]\r\n");
306  else {
307  uint8 idx = previdx;
308  if(previdx < 2) idx += PREVBUF_MAX_NUM - 2; //printf("==%d,%d==", previdx, idx);}
309  else idx -= 2; //printf("++%d,%d++", previdx, idx);}printf("--%d--", idx);Delay_ms(5);
310  printf("[D,,%d]\r\n%s\r\n", strlen((char*)prevbuf[idx]), prevbuf[idx]);
311  }
312  }
313  else if(atci.tcmd.sign == CMD_SIGN_NONE) printf("[S]\r\n");
314  else return RET_WRONG_SIGN;
315  return RET_DONE;
316  } else {
317  strcpy((char*)atci.tcmd.op, (char*)split);
318  }
319  } else {
320  strcpy((char*)atci.tcmd.op, (char*)&split[3]);
321  }
322  }
323  else return RET_WRONG_OP; //printf("first splite is NULL\r\n");
324 
325 #define ARG_PARSE(arg_v, size_v, dgt_v) \
326 { \
327  split = strsep(&tmpptr, ","); \
328  if(split != NULL) { \
329  if(strlen((char*)split) > size_v-1) { \
330  ret = RET_WRONG_ARG; \
331  CMD_CLEAR(); \
332  sprintf((char*)atci.tcmd.arg1, "%d", dgt_v); \
333  goto FAIL_END; \
334  } else strcpy((char*)arg_v, (char*)split); \
335  } else goto OK_END; \
336 } \
337 
338  ARG_PARSE(atci.tcmd.arg1, ARG_1_SIZE, 1);
339  ARG_PARSE(atci.tcmd.arg2, ARG_2_SIZE, 2);
340  ARG_PARSE(atci.tcmd.arg3, ARG_3_SIZE, 3);
341  ARG_PARSE(atci.tcmd.arg4, ARG_4_SIZE, 4);
342  ARG_PARSE(atci.tcmd.arg5, ARG_5_SIZE, 5);
343  ARG_PARSE(atci.tcmd.arg6, ARG_6_SIZE, 6);
344  if(*tmpptr != 0) {
345  ret = RET_WRONG_ARG;
346  CMD_CLEAR();
347  goto FAIL_END;
348  } //DBGA("Debug: (%s)", tmpptr); 최대 arg넘게 들어온 것 확인용 - Strict Param 정책
349 
350 OK_END:
351  ret = RET_OK;
352 FAIL_END:
353  DBGA("[%s] S(%d),OP(%s),A1(%s),A2(%s),A3(%s),A4(%s),A5(%s),A6(%s)",
354  ret==RET_OK?"OK":"ERR", atci.tcmd.sign, atci.tcmd.op?atci.tcmd.op:"<N>", atci.tcmd.arg1?atci.tcmd.arg1:"<N>",
355  atci.tcmd.arg2?atci.tcmd.arg2:"<N>", atci.tcmd.arg3?atci.tcmd.arg3:"<N>", atci.tcmd.arg4?atci.tcmd.arg4:"<N>",
356  atci.tcmd.arg5?atci.tcmd.arg5:"<N>", atci.tcmd.arg6?atci.tcmd.arg6:"<N>");
357  return ret;
358 }
359 
360 static void cmd_assign(void)
361 {
362 #define CMD_NOT_FOUND() do{CMD_CLEAR(); cmd_resp(RET_WRONG_OP, VAL_NONE);}while(0)
363 
364  if(atci.tcmd.op[0] == 'N') // Network Group
365  {
366  if(strcmp((char*)&atci.tcmd.op[1], "SET")==0) hdl_nset();
367  else if(strcmp((char*)&atci.tcmd.op[1], "STAT")==0) hdl_nstat();
368  else if(strcmp((char*)&atci.tcmd.op[1], "MAC")==0) hdl_nmac();
369  else if(strcmp((char*)&atci.tcmd.op[1], "OPEN")==0) hdl_nopen();
370  else if(strcmp((char*)&atci.tcmd.op[1], "CLS")==0) hdl_ncls();
371  else if(strcmp((char*)&atci.tcmd.op[1], "SEND")==0) hdl_nsend();
372  else if(strcmp((char*)&atci.tcmd.op[1], "RECV")==0) hdl_nrecv();
373  else if(strcmp((char*)&atci.tcmd.op[1], "SOCK")==0) hdl_nsock();
374  else if(strcmp((char*)&atci.tcmd.op[1], "OPT")==0) hdl_nopt();
375  else CMD_NOT_FOUND();
376  }
377 #if 0
378  else if(atci.tcmd.op[0] == 'W') // WiFi Group
379  {
380  if(strcmp((char*)&atci.tcmd.op[1], "SET")==0) hdl_wset();
381  else if(strcmp((char*)&atci.tcmd.op[1], "STAT")==0) hdl_wstat();
382  else if(strcmp((char*)&atci.tcmd.op[1], "SCAN")==0) hdl_wscan();
383  else if(strcmp((char*)&atci.tcmd.op[1], "JOIN")==0) hdl_wjoin();
384  else if(strcmp((char*)&atci.tcmd.op[1], "LEAVE")==0) hdl_wleave();
385  else if(strcmp((char*)&atci.tcmd.op[1], "SEC")==0) hdl_wsec();
386  else if(strcmp((char*)&atci.tcmd.op[1], "WPS")==0) hdl_wwps();
387  else CMD_NOT_FOUND();
388  }
389 #endif
390  else if(atci.tcmd.op[0] == 'M') // Manage Group
391  {
392  if(strcmp((char*)&atci.tcmd.op[1], "SET")==0) hdl_mset();
393  else if(strcmp((char*)&atci.tcmd.op[1], "STAT")==0) hdl_mstat();
394  else if(strcmp((char*)&atci.tcmd.op[1], "EVT")==0) hdl_mevt();
395  else if(strcmp((char*)&atci.tcmd.op[1], "USART")==0) hdl_musart();
396  else if(strcmp((char*)&atci.tcmd.op[1], "SPI")==0) hdl_mspi();
397  else if(strcmp((char*)&atci.tcmd.op[1], "PROF")==0) hdl_mprof();
398  else if(strcmp((char*)&atci.tcmd.op[1], "RST")==0) hdl_mrst();
399  else CMD_NOT_FOUND();
400  }
401  else if(atci.tcmd.op[0] == 'F') // Extra Func Group
402  {
403  if(strcmp((char*)&atci.tcmd.op[1], "DHCPD")==0) hdl_fdhcpd();
404  else if(strcmp((char*)&atci.tcmd.op[1], "DNS")==0) hdl_fdns();
405  else if(strcmp((char*)&atci.tcmd.op[1], "PING")==0) hdl_fping();
406  else if(strcmp((char*)&atci.tcmd.op[1], "GPIO")==0) hdl_fgpio();
407  else CMD_NOT_FOUND();
408  }
409  else if(atci.tcmd.op[0] == 'E') // Ethernet Group
410  {
411  if(strcmp((char*)&atci.tcmd.op[1], "SET")==0) hdl_eset();
412  else if(strcmp((char*)&atci.tcmd.op[1], "STAT")==0) hdl_estat();
413  else CMD_NOT_FOUND();
414  }
415  else CMD_NOT_FOUND();
416 }
417 
418 void cmd_resp_dump(int8 idval, int8 *dump)
419 {
420  uint16 len = dump!=NULL?strlen((char*)dump):0;
421 
422  if(len == 0) {
423  if(idval == VAL_NONE) printf("[D,,0]\r\n");
424  else printf("[D,%d,0]\r\n", idval);
425  } else {
426  if(idval == VAL_NONE) printf("[D,,%d]\r\n%s\r\n", len, dump);
427  else printf("[D,%d,%d]\r\n%s\r\n", idval, len, dump);
428  DBG("going to free");
429  MEM_FREE(dump);
430  DBG("free done");
431  }
432 }
433 
434 void cmd_resp(int8 retval, int8 idval)
435 {
436  uint8 cnt, len, idx = 0;
437 
438  DBGA("ret(%d), id(%d)", retval, idval);
439  cnt = (atci.tcmd.arg1[0] != 0) + (atci.tcmd.arg2[0] != 0) + (atci.tcmd.arg3[0] != 0) +
440  (atci.tcmd.arg4[0] != 0) + (atci.tcmd.arg5[0] != 0) + (atci.tcmd.arg6[0] != 0);
441 #define MAKE_RESP(item_v, size_v) \
442 { \
443  if(item_v[0] != 0) { \
444  termbuf[idx++] = ','; \
445  len = strlen((char*)item_v); \
446  if(len > size_v-1) CRITICAL_ERR("resp buf overflow"); \
447  memcpy((char*)&termbuf[idx], (char*)item_v, len); \
448  idx += len; \
449  cnt--; \
450  } else if(cnt) { \
451  termbuf[idx++] = ','; \
452  } \
453 }//printf("MakeResp-(%s)(%d)", item_v, len);
454  termbuf[idx++] = '[';
455  if(retval >= RET_OK) {
456  if(retval == RET_OK) termbuf[idx++] = 'S';
457  else if(retval == RET_OK_DUMP) CRITICAL_ERR("use cmd_resp_dump for dump");
458  else if(retval == RET_ASYNC) termbuf[idx++] = 'W';
459  else if(retval == RET_RECV) termbuf[idx++] = 'R';
460  else CRITICAL_ERRA("undefined return value (%d)", retval);
461 
462  if(idval != VAL_NONE) {
463  termbuf[idx++] = ',';
464  //snprintf((char*)tbuf, TBUF_SIZE, "%d", idval);
465  //len = strlen((char*)tbuf);
466  //strcpy((char*)&termbuf[idx], (char*)tbuf);
467  sprintf((char*)&termbuf[idx], "%d", idval);
468  len = digit_length(idval, 10);
469  idx += len;
470  } else if(cnt) termbuf[idx++] = ',';
471  } else {
472  termbuf[idx++] = 'F';
473  termbuf[idx++] = ',';
474  if(idval != VAL_NONE) {
475  //snprintf((char*)tbuf, TBUF_SIZE, "%d", idval);
476  //len = strlen((char*)tbuf);
477  //strcpy((char*)&termbuf[idx], (char*)tbuf);
478  sprintf((char*)&termbuf[idx], "%d", idval);
479  len = digit_length(idval, 10);
480  idx += len;
481  }
482  termbuf[idx++] = ',';
483 #define CMD_SWT_DEF(errval_v) termbuf[idx++] = errval_v; break;
484 #define CMD_SWT_EXT(base_v, errval_v) termbuf[idx++]=base_v;termbuf[idx++] = errval_v; break;
485  switch(retval) {
486  case RET_UNSPECIFIED: CMD_SWT_DEF(ERRVAL_UNSPECIFIED);
487  case RET_WRONG_OP: CMD_SWT_DEF(ERRVAL_WRONG_OP);
488  case RET_WRONG_SIGN: CMD_SWT_DEF(ERRVAL_WRONG_SIGN);
489  case RET_WRONG_ARG: CMD_SWT_DEF(ERRVAL_WRONG_ARG);
490  case RET_RANGE_OUT: CMD_SWT_DEF(ERRVAL_RANGE_OUT);
491  case RET_DISABLED: CMD_SWT_DEF(ERRVAL_DISABLED);
492  case RET_NOT_ALLOWED: CMD_SWT_DEF(ERRVAL_NOT_ALLOWED);
493  case RET_BUSY: CMD_SWT_DEF(ERRVAL_BUSY);
494  case RET_TIMEOUT: CMD_SWT_DEF(ERRVAL_TIMEOUT);
495  case RET_NO_SOCK: CMD_SWT_EXT('1', ERRVAL_NO_SOCK);
496  case RET_SOCK_CLS: CMD_SWT_EXT('1', ERRVAL_SOCK_CLS);
497  case RET_USING_PORT: CMD_SWT_EXT('1', ERRVAL_USING_PORT);
498  case RET_NOT_CONN: CMD_SWT_EXT('1', ERRVAL_NOT_CONN);
499  case RET_WRONG_ADDR: CMD_SWT_EXT('1', ERRVAL_WRONG_ADDR);
500  case RET_NO_DATA: CMD_SWT_EXT('1', ERRVAL_NO_DATA);
501  case RET_NO_FREEMEM: CMD_SWT_EXT('2', ERRVAL_NO_FREEMEM);
502  default:termbuf[idx++] = '0';break;
503  }
504  }
505  MAKE_RESP(atci.tcmd.arg1, ARG_1_SIZE);
506  MAKE_RESP(atci.tcmd.arg2, ARG_2_SIZE);
507  MAKE_RESP(atci.tcmd.arg3, ARG_3_SIZE);
508  MAKE_RESP(atci.tcmd.arg4, ARG_4_SIZE);
509  MAKE_RESP(atci.tcmd.arg5, ARG_5_SIZE);
510  MAKE_RESP(atci.tcmd.arg6, ARG_6_SIZE);
511  termbuf[idx++] = ']';
512  termbuf[idx++] = 0;
513  printf("%s\r\n", termbuf); // print basic response
514 }
515 
516 static void hdl_nset(void)
517 {
518  int8 mode, num = -1;
519  uint8 ip[4];
520 
521  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_QUEST; // x는 ?로 치환
522  if(atci.tcmd.sign == CMD_SIGN_QUEST)
523  {
524  if(atci.tcmd.arg1[0] != 0) {
525  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
526  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, 1, 6)) RESP_CDR(RET_RANGE_OUT, 1);
527  }
528  CMD_CLEAR();
529  act_nset_q(num);
530  }
531  else if(atci.tcmd.sign == CMD_SIGN_INDIV)
532  {
533  if(atci.tcmd.arg1[0] != 0) {
534  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
535  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, 1, 6)) RESP_CDR(RET_RANGE_OUT, 1);
536  if(num == 1) {
537  if(CMP_CHAR_2(atci.tcmd.arg2, 'D', 'S')) RESP_CDR(RET_WRONG_ARG, 2);
538  mode = atci.tcmd.arg2[0];
539  CMD_CLEAR();
540  act_nset_a(mode, NULL, NULL, NULL, NULL, NULL);
541  } else {
542  if(ip_check(atci.tcmd.arg2, ip) != RET_OK) RESP_CDR(RET_WRONG_ARG, 2);
543  CMD_CLEAR();
544  switch(num) {
545  case 2: act_nset_a(0, ip, NULL, NULL, NULL, NULL); return;
546  case 3: act_nset_a(0, NULL, ip, NULL, NULL, NULL); return;
547  case 4: act_nset_a(0, NULL, NULL, ip, NULL, NULL); return;
548  case 5: act_nset_a(0, NULL, NULL, NULL, ip, NULL); return;
549  case 6: act_nset_a(0, NULL, NULL, NULL, NULL, ip); return;
550  default: CRITICAL_ERR("nset wrong num");
551  }
552  }
553  } else RESP_CDR(RET_WRONG_ARG, 1);
554  }
555  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
556  {
557  uint8 sn[4], gw[4], dns1[4], dns2[4], *ptr[5];
558  num = 0;
559  if(atci.tcmd.arg1[0] != 0) {
560  if(CMP_CHAR_2(atci.tcmd.arg1, 'D', 'S')) RESP_CDR(RET_WRONG_ARG, 1);
561  else num++;
562  }
563 
564 #define NSET_ARG_SET(arg_p, addr_p, idx_v, ret_v) \
565 if(arg_p[0] != 0) { \
566  num++; \
567  if(ip_check(arg_p, addr_p) != RET_OK) RESP_CDR(RET_WRONG_ARG, ret_v); \
568  ptr[idx_v] = addr_p; \
569 } else ptr[idx_v] = NULL
570 
571  NSET_ARG_SET(atci.tcmd.arg2, ip, 0, 2);
572  NSET_ARG_SET(atci.tcmd.arg3, sn, 1, 3);
573  NSET_ARG_SET(atci.tcmd.arg4, gw, 2, 4);
574  NSET_ARG_SET(atci.tcmd.arg5, dns1, 3, 5);
575  NSET_ARG_SET(atci.tcmd.arg6, dns2, 4, 6);
576  if(num == 0) RESP_CR(RET_NOT_ALLOWED);
577  mode = atci.tcmd.arg1[0];
578  CMD_CLEAR();
579  act_nset_a(mode, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
580  }
581  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
582 }
583 
584 static void hdl_nstat(void)
585 {
586  int8 num = -1;
587 
588  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_QUEST;
589  if(atci.tcmd.sign == CMD_SIGN_QUEST)
590  {
591  if(atci.tcmd.arg1[0] != 0) {
592  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
593  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, 1, 6)) RESP_CDR(RET_RANGE_OUT, 1);
594  }
595  CMD_CLEAR();
596  act_nstat(num);
597  }
598  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
599  else if(atci.tcmd.sign == CMD_SIGN_EQUAL) RESP_CR(RET_WRONG_SIGN);
600  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
601 }
602 
603 static void hdl_nmac(void)
604 {
605  int8 num = -1;
606  uint8 mac[6];
607 
608  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_QUEST;
609  if(atci.tcmd.sign == CMD_SIGN_QUEST)
610  {
611  if(atci.tcmd.arg1[0] != 0) {
612  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
613  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, 1, 1)) RESP_CDR(RET_RANGE_OUT, 1);
614  }
615  CMD_CLEAR();
616  act_nmac_q();
617  }
618  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
619  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
620  {
621  if(mac_check(atci.tcmd.arg1, mac) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
622  CMD_CLEAR();
623  act_nmac_a(mac);
624  }
625  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
626 }
627 
628 static void hdl_nopen(void)
629 {
630  int8 type=0;
631  uint8 DstIP[4], *dip = NULL;
632  uint16 SrcPort, DstPort = 0;
633 
634  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_QUEST;
635  if(atci.tcmd.sign == CMD_SIGN_QUEST)
636  {
637  CMD_CLEAR();
638  act_nopen_q();
639  }
640  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
641  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
642  {
643  if(CMP_CHAR_3(atci.tcmd.arg1, 'S', 'C', 'U')) RESP_CDR(RET_WRONG_ARG, 1);
644  if(port_check(atci.tcmd.arg2, &SrcPort) != RET_OK) RESP_CDR(RET_WRONG_ARG, 2);
645 
646  if(atci.tcmd.arg1[0] == 'C') {
647  if(ip_check(atci.tcmd.arg3, DstIP) != RET_OK) RESP_CDR(RET_WRONG_ARG, 3);
648  if(port_check(atci.tcmd.arg4, &DstPort) != RET_OK) RESP_CDR(RET_WRONG_ARG, 4);
649  dip = DstIP;
650  } else if(atci.tcmd.arg1[0] == 'U') {
651  if(atci.tcmd.arg3[0] != 0 && atci.tcmd.arg4[0] != 0) {
652  if(ip_check(atci.tcmd.arg3, DstIP) != RET_OK) RESP_CDR(RET_WRONG_ARG, 3);
653  if(port_check(atci.tcmd.arg4, &DstPort) != RET_OK) RESP_CDR(RET_WRONG_ARG, 4);
654  dip = DstIP;
655  } else {
656  CHK_ARG_LEN(atci.tcmd.arg3, 0, 3);
657  CHK_ARG_LEN(atci.tcmd.arg4, 0, 4);
658  }
659  } else { // 'S' 무시정책이냐 아니면 전부 확인 정책이냐
660  CHK_ARG_LEN(atci.tcmd.arg3, 0, 3);
661  CHK_ARG_LEN(atci.tcmd.arg4, 0, 4);
662  }
663 
664  CHK_ARG_LEN(atci.tcmd.arg5, 0, 5);
665  type = atci.tcmd.arg1[0];
666  CMD_CLEAR();
667  act_nopen_a(type, SrcPort, dip, DstPort);
668  }
669  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
670 }
671 
672 static void hdl_ncls(void)
673 {
674  int8 num = -1;
675 
676  if(atci.tcmd.sign == CMD_SIGN_NONE) RESP_CR(RET_WRONG_SIGN);
677  if(atci.tcmd.sign == CMD_SIGN_QUEST) RESP_CR(RET_WRONG_SIGN);
678  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
679  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
680  {
681  if(atci.tcmd.arg1[0] != 0) {
682  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
683  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, ATC_SOCK_NUM_START, ATC_SOCK_NUM_END))
684  RESP_CDR(RET_RANGE_OUT, 1);
685  }
686  CMD_CLEAR();
687  act_ncls(num);
688  }
689  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
690 }
691 
692 static void hdl_nsend(void)
693 {
694  int8 num = -1;
695  int32 ret;
696  uint8 *dip = NULL;
697  uint16 *dport = NULL;
698 
699  if(atci.tcmd.sign == CMD_SIGN_NONE) RESP_CR(RET_WRONG_SIGN);
700  if(atci.tcmd.sign == CMD_SIGN_QUEST) RESP_CR(RET_WRONG_SIGN);
701  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
702  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
703  {
704  if(atci.tcmd.arg1[0] != 0) {
705  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
706  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, ATC_SOCK_NUM_START, ATC_SOCK_NUM_END))
707  RESP_CDR(RET_RANGE_OUT, 1);
708  }
709  if(str_check(isdigit, atci.tcmd.arg2) != RET_OK ||
710  (atci.sendlen = atoi((char*)atci.tcmd.arg2)) < 1 ||
711  atci.sendlen > WORK_BUF_SIZE) RESP_CDR(RET_RANGE_OUT, 2);
712 
713  if(atci.tcmd.arg3[0]) {
714  if(ip_check(atci.tcmd.arg3, atci.sendip) == RET_OK) dip = atci.sendip;
715  else RESP_CDR(RET_WRONG_ARG, 3);
716  }
717  if(atci.tcmd.arg4[0]) {
718  if(port_check(atci.tcmd.arg4, &atci.sendport)==RET_OK) dport = &atci.sendport;
719  else RESP_CDR(RET_WRONG_ARG, 4);
720  }
721 
722  CHK_ARG_LEN(atci.tcmd.arg5, 0, 5);
723  CHK_ARG_LEN(atci.tcmd.arg6, 0, 6);
724  CMD_CLEAR();
725  ret = act_nsend_chk(num, &atci.sendlen, dip, dport);
726  if(ret != RET_OK) return;
727 
728  atci.sendsock = num; // 유효성 검사가 완료되면 SEND모드로 전환
729  atci.worklen = 0;
730  cmd_resp(RET_ASYNC, num);
731  }
732  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
733 }
734 
735 static void hdl_nrecv(void)
736 {
737  int8 num = VAL_NONE;
738  int32 maxlen;
739 
740  if(atci.poll == POLL_MODE_NONE) RESP_CR(RET_DISABLED);
741  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_EQUAL;
742  if(atci.tcmd.sign == CMD_SIGN_QUEST) RESP_CR(RET_WRONG_SIGN);
743  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
744  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
745  {
746  if(atci.tcmd.arg1[0] != 0) {
747  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
748  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, ATC_SOCK_NUM_START, ATC_SOCK_NUM_END))
749  RESP_CDR(RET_RANGE_OUT, 1);
750  }
751  if(atci.tcmd.arg2[0] == 0) maxlen = WORK_BUF_SIZE; // 사이즈 지정안되면 최대값으로 지정
752  else if(str_check(isdigit, atci.tcmd.arg2) != RET_OK) RESP_CDR(RET_WRONG_ARG, 2);
753  else if((maxlen = atoi((char*)atci.tcmd.arg2)) < 1 || maxlen > WORK_BUF_SIZE)
754  RESP_CDR(RET_RANGE_OUT, 2);
755  CMD_CLEAR();
756  act_nrecv(num, maxlen);
757  }
758  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
759 }
760 
761 static void hdl_nsock(void)
762 {
763 
764  int8 num = -1;
765 
766  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_QUEST;
767  if(atci.tcmd.sign == CMD_SIGN_QUEST)
768  {
769  CMD_CLEAR();
770  act_nsock(VAL_NONE);
771  }
772  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
773  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
774  {
775  if(atci.tcmd.arg1[0] != 0) {
776  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
777  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, ATC_SOCK_NUM_START, ATC_SOCK_NUM_END))
778  RESP_CDR(RET_RANGE_OUT, 1);
779  }
780  CMD_CLEAR();
781  act_nsock(num);
782  }
783  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
784 }
785 
786 static void hdl_nopt(void)
787 {
788  CMD_CLEAR();
789  RESP_CR(RET_NOT_ALLOWED);
790 }
791 #if 0
792 static void hdl_wset(void)
793 {
794 
795 }
796 
797 static void hdl_wstat(void)
798 {
799 
800 }
801 
802 static void hdl_wscan(void)
803 {
804 
805 }
806 
807 static void hdl_wjoin(void)
808 {
809 
810 }
811 
812 static void hdl_wleave(void)
813 {
814 
815 }
816 
817 static void hdl_wsec(void)
818 {
819 
820 }
821 
822 static void hdl_wwps(void)
823 {
824 
825 }
826 #endif
827 static void hdl_mset(void)
828 {
829  int8 echo, poll, num = -1; //, mode, country
830 
831  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_QUEST; // [?] 구현
832  if(atci.tcmd.sign == CMD_SIGN_QUEST)
833  {
834  if(atci.tcmd.arg1[0] != 0) {
835  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
836  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, 1, 4)) RESP_CDR(RET_RANGE_OUT, 1);
837  }
838  CMD_CLEAR();
839  act_mset_q(num);
840  }
841  else if(atci.tcmd.sign == CMD_SIGN_INDIV)
842  {
843  if(atci.tcmd.arg1[0] != 0) {
844  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
845  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, 1, 4)) RESP_CDR(RET_RANGE_OUT, 1);
846  if(num == 1) {
847  if(CMP_CHAR_2(atci.tcmd.arg2, 'E', 'D')) RESP_CDR(RET_WRONG_ARG, 2);
848  echo = atci.tcmd.arg2[0];
849  CMD_CLEAR();
850  act_mset_a(echo, 0, 0, 0);
851  } else if(num == 2) {
852  RESP_CDR(RET_NOT_ALLOWED, 2); // 아직 정해진 것 없음
853  } else if(num == 3) {
854  if(CMP_CHAR_3(atci.tcmd.arg2, 'F', 'S', 'D')) RESP_CDR(RET_WRONG_ARG, 2);
855  poll = atci.tcmd.arg2[0];
856  CMD_CLEAR();
857  act_mset_a(0, 0, poll, 0);
858  } else RESP_CDR(RET_NOT_ALLOWED, 2); // 국가 설정 아직 구현안함
859  } else RESP_CDR(RET_WRONG_ARG, 1);
860  }
861  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
862  {
863  num = 0;
864  if(atci.tcmd.arg1[0] != 0) {
865  num++;
866  if(CMP_CHAR_2(atci.tcmd.arg1, 'E', 'D')) RESP_CDR(RET_WRONG_ARG, 1);
867  }
868  if(atci.tcmd.arg3[0] != 0) {
869  num++;
870  if(CMP_CHAR_3(atci.tcmd.arg3, 'F', 'S', 'D')) RESP_CDR(RET_WRONG_ARG, 3);
871  }
872  // arg 2, 4 는 일단 무시
873  if(num == 0) RESP_CR(RET_NOT_ALLOWED);
874  echo = atci.tcmd.arg1[0];
875  poll = atci.tcmd.arg3[0];
876  CMD_CLEAR();
877  act_mset_a(echo, 0, poll, 0);
878  }
879  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
880 }
881 
882 static void hdl_mstat(void)
883 {
884  int8 num = -1;
885 
886  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_QUEST;
887  if(atci.tcmd.sign == CMD_SIGN_QUEST)
888  {
889  if(atci.tcmd.arg1[0] != 0) {
890  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
891  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, 1, 1)) RESP_CDR(RET_RANGE_OUT, 1);
892  }
893  CMD_CLEAR();
894  act_mstat();
895  }
896  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
897  else if(atci.tcmd.sign == CMD_SIGN_EQUAL) RESP_CR(RET_WRONG_SIGN);
898  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
899 }
900 
901 static void hdl_mevt(void)
902 {
903  int8 num = -1;
904 
905  if(atci.poll != POLL_MODE_FULL) RESP_CR(RET_DISABLED);
906  if(atci.tcmd.sign == CMD_SIGN_NONE) atci.tcmd.sign = CMD_SIGN_EQUAL;
907  if(atci.tcmd.sign == CMD_SIGN_QUEST)
908  {
909  CMD_CLEAR();
910  act_mevt_q();
911  }
912  else if(atci.tcmd.sign == CMD_SIGN_INDIV) RESP_CR(RET_WRONG_SIGN);
913  else if(atci.tcmd.sign == CMD_SIGN_EQUAL)
914  {
915  if(atci.tcmd.arg1[0] != 0) {
916  if(str_check(isdigit, atci.tcmd.arg1) != RET_OK) RESP_CDR(RET_WRONG_ARG, 1);
917  if(CHK_DGT_RANGE(atci.tcmd.arg1, num, ATC_SOCK_NUM_START, ATC_SOCK_NUM_END))
918  RESP_CDR(RET_RANGE_OUT, 1);
919  }
920  CMD_CLEAR();
921  act_mevt_a(num);
922  }
923  else CRITICAL_ERRA("wrong sign(%d)", atci.tcmd.sign);
924 }
925 
926 static void hdl_musart(void)
927 {
928  RESP_CR(RET_NOT_ALLOWED);
929 }
930 
931 static void hdl_mspi(void)
932 {
933  RESP_CR(RET_NOT_ALLOWED);
934 }
935 
936 static void hdl_mprof(void)
937 {
938  RESP_CR(RET_NOT_ALLOWED);
939 }
940 
941 static void hdl_mrst(void)
942 {
943  CMD_CLEAR();
944  cmd_resp(RET_OK, VAL_NONE);
945  NVIC_SystemReset();
946 }
947 
948 static void hdl_fdhcpd(void)
949 {
950  RESP_CR(RET_NOT_ALLOWED);
951 }
952 
953 static void hdl_fdns(void)
954 {
955  RESP_CR(RET_NOT_ALLOWED);
956 }
957 
958 static void hdl_fping(void)
959 {
960  RESP_CR(RET_NOT_ALLOWED);
961 }
962 
963 static void hdl_fgpio(void)
964 {
965  RESP_CR(RET_NOT_ALLOWED);
966 }
967 
968 static void hdl_eset(void)
969 {
970  RESP_CR(RET_NOT_ALLOWED);
971 }
972 
973 static void hdl_estat(void)
974 {
975  RESP_CR(RET_NOT_ALLOWED);
976 }
977 
978 
979 
980 
981 
982 
983 
984 
985 
986 
987 
988 
989 
990