00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include <cfg/os.h>
00065 #include <sys/timer.h>
00066 #include <dev/uart.h>
00067
00068 #include <stdlib.h>
00069 #include <string.h>
00070 #include <io.h>
00071 #include <memdebug.h>
00072
00073 #include <dev/chat.h>
00074
00075 uint8_t *chat_report;
00076
00077 #ifdef NUTDEBUG
00078
00079 static FILE *__chat_trs;
00080 static uint8_t __chat_trf;
00089 void NutTraceChat(FILE * stream, uint8_t flags)
00090 {
00091 if (stream)
00092 __chat_trs = stream;
00093 if (__chat_trs) {
00094 static prog_char dbgfmt[] = "Chat trace flags=0x%02X\n";
00095 __chat_trf = flags;
00096 fprintf_P(__chat_trs, dbgfmt, flags);
00097 } else
00098 __chat_trf = 0;
00099 }
00100
00101 #endif
00102
00103
00104
00105
00106 static char *strechr(CONST char *str, int c)
00107 {
00108 while (*str) {
00109 if (*str == '\\') {
00110 if (*++str)
00111 str++;
00112 } else if (*str == c)
00113 return (char *) str;
00114 else
00115 str++;
00116 }
00117 return 0;
00118 }
00119
00131 int NutChatExpectString(NUTCHAT * ci, char *str)
00132 {
00133 char ch;
00134 uint8_t m;
00135 uint8_t i;
00136 char *cp = str;
00137
00138 #ifdef NUTDEBUG
00139 if (__chat_trf) {
00140 static prog_char dbgfmt[] = "Expect '%s', got '";
00141 fprintf_P(__chat_trs, dbgfmt, str);
00142 }
00143 #endif
00144
00145 while (*cp) {
00146
00147
00148
00149
00150 if (_read(ci->chat_fd, &ch, 1) != 1) {
00151 #ifdef NUTDEBUG
00152 if (__chat_trf) {
00153 static prog_char dbgmsg[] = "' TIMEOUT\n";
00154 fputs_P(dbgmsg, __chat_trs);
00155 }
00156 #endif
00157 return 3;
00158 }
00159 #ifdef NUTDEBUG
00160 if (__chat_trf) {
00161 if (ch > 31 && ch < 127) {
00162 fputc(ch, __chat_trs);
00163 } else {
00164 fprintf(__chat_trs, "\\x%02X", ch);
00165 }
00166 }
00167 #endif
00168
00169
00170
00171
00172 if (ch != *cp) {
00173 cp = str;
00174 }
00175
00176
00177
00178
00179
00180 if (ch == *cp) {
00181 cp++;
00182 }
00183
00184
00185
00186
00187 for (i = 0; i < ci->chat_aborts; i++) {
00188 m = ci->chat_abomat[i];
00189 if (ch == ci->chat_abort[i][m]) {
00190 if (ci->chat_abort[i][++m] == 0) {
00191 #ifdef NUTDEBUG
00192 if (__chat_trf) {
00193 static prog_char dbgmsg[] = "' ABORT\n";
00194 fputs_P(dbgmsg, __chat_trs);
00195 }
00196 #endif
00197 return i + 4;
00198 }
00199 } else
00200 m = (ch == ci->chat_abort[i][0]);
00201 ci->chat_abomat[i] = m;
00202 }
00203
00204
00205
00206
00207 if (ci->chat_report_state > 0) {
00208 m = ci->chat_repmat;
00209 if (ci->chat_report_state == 2) {
00210 chat_report[m++] = ch;
00211 } else if (ch == ci->chat_report_search[m]) {
00212 chat_report[m++] = ch;
00213 if (ci->chat_report_search[m] == 0) {
00214 ci->chat_report_state = 2;
00215 }
00216 } else {
00217 m = (ch == ci->chat_report_search[0]);
00218 }
00219 ci->chat_repmat = m;
00220 }
00221 }
00222
00223
00224
00225
00226 if (ci->chat_report_state == 2) {
00227 m = ci->chat_repmat;
00228 while (m < CHAT_MAX_REPORT_SIZE) {
00229 if (_read(ci->chat_fd, &ch, 1) != 1 || ch < ' ') {
00230 break;
00231 }
00232 chat_report[m++] = ch;
00233
00234 #ifdef NUTDEBUG
00235 if (__chat_trf) {
00236 if (ch > 31 && ch < 127) {
00237 fputc(ch, __chat_trs);
00238 } else {
00239 fprintf(__chat_trs, "\\x%02X", ch);
00240 }
00241 }
00242 #endif
00243 }
00244 ci->chat_report_state = 0;
00245 chat_report[m] = 0;
00246 }
00247 #ifdef NUTDEBUG
00248 if (__chat_trf) {
00249 static prog_char dbgmsg[] = "'\n";
00250 fputs_P(dbgmsg, __chat_trs);
00251 }
00252 #endif
00253
00254 return 0;
00255 }
00256
00257
00258
00259
00260 static int NutChatSendString(int fd, char *str)
00261 {
00262 int rc = 0;
00263 uint8_t eol = 1;
00264 uint8_t skip;
00265 char ch;
00266
00267 #ifdef NUTDEBUG
00268 if (__chat_trf) {
00269 static prog_char dbgfmt[] = "Send '%s'\n";
00270 fprintf_P(__chat_trs, dbgfmt, str);
00271 }
00272 #endif
00273
00274
00275 _read(fd, 0, 0);
00276 while (*str && eol && rc == 0) {
00277 ch = *str++;
00278 skip = 0;
00279 if (ch == '^') {
00280 ch = *str++;
00281 ch &= 0x1f;
00282 } else if (ch == '\\') {
00283 ch = *str++;
00284 switch (ch) {
00285 case 'b':
00286 ch = '\b';
00287 break;
00288 case 'c':
00289 eol = 0;
00290 skip = 1;
00291 break;
00292 case 'd':
00293 NutSleep(1000);
00294 skip = 1;
00295 break;
00296 case 'n':
00297 ch = '\n';
00298 break;
00299 case 'N':
00300 ch = 0;
00301 break;
00302 case 'p':
00303 NutDelay(100);
00304 skip = 1;
00305 break;
00306 case 'r':
00307 ch = '\r';
00308 break;
00309 case 's':
00310 ch = ' ';
00311 break;
00312 case 't':
00313 ch = '\t';
00314 break;
00315 default:
00316 if (ch >= '0' && ch <= '7') {
00317 ch &= 0x07;
00318 if (*str >= '0' && *str <= '7') {
00319 ch <<= 3;
00320 ch |= *str++ & 0x07;
00321 if (*str >= '0' && *str <= '7') {
00322 ch <<= 3;
00323 ch |= *str++ & 0x07;
00324 }
00325 }
00326 }
00327 break;
00328 }
00329 }
00330 if (skip)
00331 skip = 0;
00332 else {
00333 NutDelay(10);
00334 if (_write(fd, &ch, 1) != 1)
00335 rc = 2;
00336 else
00337 _write(fd, 0, 0);
00338 }
00339 }
00340 if (eol && rc == 0 && _write(fd, "\r", 1) != 1)
00341 rc = 2;
00342 else
00343 _write(fd, 0, 0);
00344
00345 return rc;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 int NutChatExpect(NUTCHAT * ci, char *str)
00358 {
00359 int rc = 0;
00360 char *reply;
00361 char *subexpect;
00362
00363
00364
00365
00366 if (strcmp(str, "ABORT") == 0) {
00367 ci->chat_arg = CHAT_ARG_ABORT;
00368 return 0;
00369 }
00370 if (strcmp(str, "TIMEOUT") == 0) {
00371 ci->chat_arg = CHAT_ARG_TIMEOUT;
00372 return 0;
00373 }
00374 if (strcmp(str, "REPORT") == 0) {
00375 ci->chat_repmat = 0;
00376 ci->chat_report_state = 1;
00377 ci->chat_arg = CHAT_ARG_REPORT;
00378 return 0;
00379 }
00380
00381
00382
00383
00384 while (str) {
00385 if ((reply = strechr(str, '-')) != 0) {
00386 *reply++ = 0;
00387 if ((subexpect = strechr(reply, '-')) != 0)
00388 *subexpect++ = 0;
00389 } else
00390 subexpect = 0;
00391
00392 if ((rc = NutChatExpectString(ci, str)) != 3 || reply == 0)
00393 break;
00394 if ((rc = NutChatSendString(ci->chat_fd, reply)) != 0)
00395 break;
00396 str = subexpect;
00397 }
00398 return rc;
00399 }
00400
00413 int NutChatSend(NUTCHAT * ci, char *str)
00414 {
00415 char *cp;
00416 char ch;
00417 long lv;
00418
00419
00420
00421
00422 if (ci->chat_arg == CHAT_ARG_ABORT) {
00423 ci->chat_arg = CHAT_ARG_SEND;
00424
00425 if (ci->chat_aborts >= CHAT_MAX_ABORTS)
00426 return 1;
00427 cp = malloc(strlen(str) + 1);
00428 ci->chat_abort[ci->chat_aborts++] = cp;
00429 while (*str) {
00430 ch = *str++;
00431 if (ch == '^')
00432 *cp = *str++ & 0x1f;
00433 else if (ch == '\\') {
00434 ch = *str++;
00435 switch (ch) {
00436 case 'b':
00437 *cp++ = '\b';
00438 break;
00439 case 'n':
00440 *cp++ = '\n';
00441 break;
00442 case 'r':
00443 *cp++ = '\r';
00444 break;
00445 case 's':
00446 *cp++ = ' ';
00447 break;
00448 case 't':
00449 *cp++ = '\t';
00450 break;
00451 default:
00452 if (ch >= '0' && ch <= '7') {
00453 ch &= 0x07;
00454 if (*str >= '0' && *str <= '7') {
00455 ch <<= 3;
00456 ch |= *str++ & 0x07;
00457 if (*str >= '0' && *str <= '7') {
00458 ch <<= 3;
00459 ch |= *str++ & 0x07;
00460 }
00461 }
00462 }
00463 if (ch)
00464 *cp++ = ch;
00465 break;
00466 }
00467 } else
00468 *cp++ = ch;
00469 }
00470 *cp = 0;
00471 return 0;
00472 }
00473
00474
00475
00476
00477 if (ci->chat_arg == CHAT_ARG_TIMEOUT) {
00478 ci->chat_arg = CHAT_ARG_SEND;
00479
00480 lv = atol(str) * 1000L;
00481 if (lv <= 0)
00482 lv = CHAT_DEFAULT_TIMEOUT * 1000L;
00483
00484 _ioctl(ci->chat_fd, UART_SETREADTIMEOUT, &lv);
00485
00486 return 0;
00487 }
00488
00489
00490
00491
00492 if (ci->chat_arg == CHAT_ARG_REPORT) {
00493 ci->chat_arg = CHAT_ARG_SEND;
00494 chat_report = malloc(CHAT_MAX_REPORT_SIZE + 1);
00495 cp = malloc(strlen(str) + 1);
00496 ci->chat_report_search = cp;
00497 while (*str)
00498 *cp++ = *str++;
00499 *cp = 0;
00500
00501 return 0;
00502 }
00503
00504
00505
00506
00507 return NutChatSendString(ci->chat_fd, str);
00508 }
00509
00510
00516 NUTCHAT *NutChatCreate(int fd)
00517 {
00518 NUTCHAT *ci;
00519
00520 if ((ci = malloc(sizeof(NUTCHAT))) != 0) {
00521 memset(ci, 0, sizeof(NUTCHAT));
00522 ci->chat_fd = fd;
00523 }
00524 return ci;
00525 }
00526
00533 void NutChatDestroy(NUTCHAT * ci)
00534 {
00535 uint8_t i;
00536
00537 if (ci) {
00538 for (i = 0; i < ci->chat_aborts; i++)
00539 free(ci->chat_abort[i]);
00540 free(ci);
00541 }
00542 }
00543
00552 static int NutChatProc(int fd, char *script)
00553 {
00554 int rc = 0;
00555 char sendflg = 0;
00556 NUTCHAT *ci;
00557 char *arg;
00558 uint32_t to;
00559 uint32_t irto;
00560 uint32_t iwto;
00561
00562
00563
00564
00565 if ((ci = NutChatCreate(fd)) == 0)
00566 return 2;
00567
00568
00569
00570
00571 _ioctl(fd, UART_GETREADTIMEOUT, &irto);
00572 _ioctl(fd, UART_GETWRITETIMEOUT, &iwto);
00573 to = 45000;
00574 _ioctl(fd, UART_SETREADTIMEOUT, &to);
00575 to = 5000;
00576 _ioctl(fd, UART_SETWRITETIMEOUT, &to);
00577
00578
00579
00580
00581
00582 while (*script && rc == 0) {
00583
00584
00585
00586
00587 if (*script == ' ' || *script == '\t' || *script == '\r' || *script == '\n') {
00588 script++;
00589 continue;
00590 }
00591
00592
00593
00594
00595 if (*script == '"' || *script == '\'') {
00596 char quote = *script++;
00597
00598 arg = script;
00599 while (*script != quote) {
00600 if (*script == 0) {
00601 rc = 1;
00602 break;
00603 }
00604 if (*script++ == '\\') {
00605 if (*script)
00606 ++script;
00607 }
00608 }
00609 }
00610
00611
00612
00613
00614 else {
00615 arg = script;
00616 while (*script && *script != ' ' && *script != '\t' && *script != '\r' && *script != '\n')
00617 ++script;
00618 }
00619
00620 if (*script)
00621 *script++ = 0;
00622
00623
00624
00625
00626 if (rc == 0) {
00627 if (sendflg)
00628 rc = NutChatSend(ci, arg);
00629 else
00630 rc = NutChatExpect(ci, arg);
00631 sendflg = !sendflg;
00632 }
00633 }
00634
00635
00636
00637
00638 _ioctl(fd, UART_SETREADTIMEOUT, &irto);
00639 _ioctl(fd, UART_SETWRITETIMEOUT, &iwto);
00640
00641
00642
00643
00644 NutChatDestroy(ci);
00645
00646 return rc;
00647 }
00648
00662 int NutChat(int fd, CONST char *script)
00663 {
00664 int rc = -1;
00665 char *buf;
00666
00667
00668
00669
00670 if ((buf = strdup(script)) != NULL) {
00671 rc = NutChatProc(fd, buf);
00672 free(buf);
00673 }
00674 return rc;
00675 }
00676
00688 #ifdef __HARVARD_ARCH__
00689 int NutChat_P(int fd, PGM_P script)
00690 {
00691 int rc = -1;
00692 char *buf;
00693
00694
00695
00696
00697 if ((buf = malloc(strlen_P(script) + 1)) != 0) {
00698 strcpy_P(buf, script);
00699 rc = NutChatProc(fd, buf);
00700 free(buf);
00701 }
00702 return rc;
00703 }
00704 #endif