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 #include <cfg/os.h>
00054 #include <sys/timer.h>
00055 #include <dev/uart.h>
00056
00057 #include <stdlib.h>
00058 #include <string.h>
00059 #include <io.h>
00060
00061 #include <dev/chat.h>
00062
00063 u_char *chat_report;
00064
00065 #ifdef NUTDEBUG
00066
00067 static FILE *__chat_trs;
00068 static u_char __chat_trf;
00077 void NutTraceChat(FILE * stream, u_char flags)
00078 {
00079 if (stream)
00080 __chat_trs = stream;
00081 if (__chat_trs) {
00082 static prog_char dbgfmt[] = "Chat trace flags=0x%02X\n";
00083 __chat_trf = flags;
00084 fprintf_P(__chat_trs, dbgfmt, flags);
00085 } else
00086 __chat_trf = 0;
00087 }
00088
00089 #endif
00090
00091
00092
00093
00094 static char *strechr(CONST char *str, int c)
00095 {
00096 while (*str) {
00097 if (*str == '\\') {
00098 if (*++str)
00099 str++;
00100 } else if (*str == c)
00101 return (char *) str;
00102 else
00103 str++;
00104 }
00105 return 0;
00106 }
00107
00119 int NutChatExpectString(NUTCHAT * ci, char *str)
00120 {
00121 char ch;
00122 u_char m;
00123 u_char i;
00124 char *cp = str;
00125
00126 #ifdef NUTDEBUG
00127 if (__chat_trf) {
00128 static prog_char dbgfmt[] = "Expect '%s', got '";
00129 fprintf_P(__chat_trs, dbgfmt, str);
00130 }
00131 #endif
00132
00133 while (*cp) {
00134
00135
00136
00137
00138 if (_read(ci->chat_fd, &ch, 1) != 1) {
00139 #ifdef NUTDEBUG
00140 if (__chat_trf) {
00141 static prog_char dbgmsg[] = "' TIMEOUT\n";
00142 fputs_P(dbgmsg, __chat_trs);
00143 }
00144 #endif
00145 return 3;
00146 }
00147 #ifdef NUTDEBUG
00148 if (__chat_trf) {
00149 if (ch > 31 && ch < 127) {
00150 fputc(ch, __chat_trs);
00151 } else {
00152 fprintf(__chat_trs, "\\x%02X", ch);
00153 }
00154 }
00155 #endif
00156
00157
00158
00159
00160 if (ch != *cp) {
00161 cp = str;
00162 }
00163
00164
00165
00166
00167
00168 if (ch == *cp) {
00169 cp++;
00170 }
00171
00172
00173
00174
00175 for (i = 0; i < ci->chat_aborts; i++) {
00176 m = ci->chat_abomat[i];
00177 if (ch == ci->chat_abort[i][m]) {
00178 if (ci->chat_abort[i][++m] == 0) {
00179 #ifdef NUTDEBUG
00180 if (__chat_trf) {
00181 static prog_char dbgmsg[] = "' ABORT\n";
00182 fputs_P(dbgmsg, __chat_trs);
00183 }
00184 #endif
00185 return i + 4;
00186 }
00187 } else
00188 m = (ch == ci->chat_abort[i][0]);
00189 ci->chat_abomat[i] = m;
00190 }
00191
00192
00193
00194
00195 if (ci->chat_report_state > 0) {
00196 m = ci->chat_repmat;
00197 if (ci->chat_report_state == 2) {
00198 chat_report[m++] = ch;
00199 } else if (ch == ci->chat_report_search[m]) {
00200 chat_report[m++] = ch;
00201 if (ci->chat_report_search[m] == 0) {
00202 ci->chat_report_state = 2;
00203 }
00204 } else {
00205 m = (ch == ci->chat_report_search[0]);
00206 }
00207 ci->chat_repmat = m;
00208 }
00209 }
00210
00211
00212
00213
00214 if (ci->chat_report_state == 2) {
00215 m = ci->chat_repmat;
00216 while (m < CHAT_MAX_REPORT_SIZE) {
00217 if (_read(ci->chat_fd, &ch, 1) != 1 || ch < ' ') {
00218 break;
00219 }
00220 chat_report[m++] = ch;
00221
00222 #ifdef NUTDEBUG
00223 if (__chat_trf) {
00224 if (ch > 31 && ch < 127) {
00225 fputc(ch, __chat_trs);
00226 } else {
00227 fprintf(__chat_trs, "\\x%02X", ch);
00228 }
00229 }
00230 #endif
00231 }
00232 ci->chat_report_state = 0;
00233 chat_report[m] = 0;
00234 }
00235 #ifdef NUTDEBUG
00236 if (__chat_trf) {
00237 static prog_char dbgmsg[] = "'\n";
00238 fputs_P(dbgmsg, __chat_trs);
00239 }
00240 #endif
00241
00242 return 0;
00243 }
00244
00245
00246
00247
00248 static int NutChatSendString(int fd, char *str)
00249 {
00250 int rc = 0;
00251 u_char eol = 1;
00252 u_char skip;
00253 char ch;
00254
00255 #ifdef NUTDEBUG
00256 if (__chat_trf) {
00257 static prog_char dbgfmt[] = "Send '%s'\n";
00258 fprintf_P(__chat_trs, dbgfmt, str);
00259 }
00260 #endif
00261
00262
00263 _read(fd, 0, 0);
00264 while (*str && eol && rc == 0) {
00265 ch = *str++;
00266 skip = 0;
00267 if (ch == '^') {
00268 ch = *str++;
00269 ch &= 0x1f;
00270 } else if (ch == '\\') {
00271 ch = *str++;
00272 switch (ch) {
00273 case 'b':
00274 ch = '\b';
00275 break;
00276 case 'c':
00277 eol = 0;
00278 skip = 1;
00279 break;
00280 case 'd':
00281 NutSleep(1000);
00282 skip = 1;
00283 break;
00284 case 'n':
00285 ch = '\n';
00286 break;
00287 case 'N':
00288 ch = 0;
00289 break;
00290 case 'p':
00291 NutDelay(100);
00292 skip = 1;
00293 break;
00294 case 'r':
00295 ch = '\r';
00296 break;
00297 case 's':
00298 ch = ' ';
00299 break;
00300 case 't':
00301 ch = '\t';
00302 break;
00303 default:
00304 if (ch >= '0' && ch <= '7') {
00305 ch &= 0x07;
00306 if (*str >= '0' && *str <= '7') {
00307 ch <<= 3;
00308 ch |= *str++ & 0x07;
00309 if (*str >= '0' && *str <= '7') {
00310 ch <<= 3;
00311 ch |= *str++ & 0x07;
00312 }
00313 }
00314 }
00315 break;
00316 }
00317 }
00318 if (skip)
00319 skip = 0;
00320 else {
00321 NutDelay(10);
00322 if (_write(fd, &ch, 1) != 1)
00323 rc = 2;
00324 else
00325 _write(fd, 0, 0);
00326 }
00327 }
00328 if (eol && rc == 0 && _write(fd, "\r", 1) != 1)
00329 rc = 2;
00330 else
00331 _write(fd, 0, 0);
00332
00333 return rc;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 int NutChatExpect(NUTCHAT * ci, char *str)
00346 {
00347 int rc = 0;
00348 char *reply;
00349 char *subexpect;
00350
00351
00352
00353
00354 if (strcmp(str, "ABORT") == 0) {
00355 ci->chat_arg = CHAT_ARG_ABORT;
00356 return 0;
00357 }
00358 if (strcmp(str, "TIMEOUT") == 0) {
00359 ci->chat_arg = CHAT_ARG_TIMEOUT;
00360 return 0;
00361 }
00362 if (strcmp(str, "REPORT") == 0) {
00363 ci->chat_repmat = 0;
00364 ci->chat_report_state = 1;
00365 ci->chat_arg = CHAT_ARG_REPORT;
00366 return 0;
00367 }
00368
00369
00370
00371
00372 while (str) {
00373 if ((reply = strechr(str, '-')) != 0) {
00374 *reply++ = 0;
00375 if ((subexpect = strechr(reply, '-')) != 0)
00376 *subexpect++ = 0;
00377 } else
00378 subexpect = 0;
00379
00380 if ((rc = NutChatExpectString(ci, str)) != 3 || reply == 0)
00381 break;
00382 if ((rc = NutChatSendString(ci->chat_fd, reply)) != 0)
00383 break;
00384 str = subexpect;
00385 }
00386 return rc;
00387 }
00388
00401 int NutChatSend(NUTCHAT * ci, char *str)
00402 {
00403 char *cp;
00404 char ch;
00405 long lv;
00406
00407
00408
00409
00410 if (ci->chat_arg == CHAT_ARG_ABORT) {
00411 ci->chat_arg = CHAT_ARG_SEND;
00412
00413 if (ci->chat_aborts >= CHAT_MAX_ABORTS)
00414 return 1;
00415 cp = malloc(strlen(str) + 1);
00416 ci->chat_abort[ci->chat_aborts++] = cp;
00417 while (*str) {
00418 ch = *str++;
00419 if (ch == '^')
00420 *cp = *str++ & 0x1f;
00421 else if (ch == '\\') {
00422 ch = *str++;
00423 switch (ch) {
00424 case 'b':
00425 *cp++ = '\b';
00426 break;
00427 case 'n':
00428 *cp++ = '\n';
00429 break;
00430 case 'r':
00431 *cp++ = '\r';
00432 break;
00433 case 's':
00434 *cp++ = ' ';
00435 break;
00436 case 't':
00437 *cp++ = '\t';
00438 break;
00439 default:
00440 if (ch >= '0' && ch <= '7') {
00441 ch &= 0x07;
00442 if (*str >= '0' && *str <= '7') {
00443 ch <<= 3;
00444 ch |= *str++ & 0x07;
00445 if (*str >= '0' && *str <= '7') {
00446 ch <<= 3;
00447 ch |= *str++ & 0x07;
00448 }
00449 }
00450 }
00451 if (ch)
00452 *cp++ = ch;
00453 break;
00454 }
00455 } else
00456 *cp++ = ch;
00457 }
00458 *cp = 0;
00459 return 0;
00460 }
00461
00462
00463
00464
00465 if (ci->chat_arg == CHAT_ARG_TIMEOUT) {
00466 ci->chat_arg = CHAT_ARG_SEND;
00467
00468 lv = atol(str) * 1000L;
00469 if (lv <= 0)
00470 lv = CHAT_DEFAULT_TIMEOUT * 1000L;
00471
00472 _ioctl(ci->chat_fd, UART_SETREADTIMEOUT, &lv);
00473
00474 return 0;
00475 }
00476
00477
00478
00479
00480 if (ci->chat_arg == CHAT_ARG_REPORT) {
00481 ci->chat_arg = CHAT_ARG_SEND;
00482 chat_report = malloc(CHAT_MAX_REPORT_SIZE + 1);
00483 cp = malloc(strlen(str) + 1);
00484 ci->chat_report_search = cp;
00485 while (*str)
00486 *cp++ = *str++;
00487 *cp = 0;
00488
00489 return 0;
00490 }
00491
00492
00493
00494
00495 return NutChatSendString(ci->chat_fd, str);
00496 }
00497
00498
00504 NUTCHAT *NutChatCreate(int fd)
00505 {
00506 NUTCHAT *ci;
00507
00508 if ((ci = malloc(sizeof(NUTCHAT))) != 0) {
00509 memset(ci, 0, sizeof(NUTCHAT));
00510 ci->chat_fd = fd;
00511 }
00512 return ci;
00513 }
00514
00521 void NutChatDestroy(NUTCHAT * ci)
00522 {
00523 u_char i;
00524
00525 if (ci) {
00526 for (i = 0; i < ci->chat_aborts; i++)
00527 free(ci->chat_abort[i]);
00528 free(ci);
00529 }
00530 }
00531
00540 static int NutChatProc(int fd, char *script)
00541 {
00542 int rc = 0;
00543 char sendflg = 0;
00544 NUTCHAT *ci;
00545 char *arg;
00546 u_long to;
00547 u_long irto;
00548 u_long iwto;
00549
00550
00551
00552
00553 if ((ci = NutChatCreate(fd)) == 0)
00554 return 2;
00555
00556
00557
00558
00559 _ioctl(fd, UART_GETREADTIMEOUT, &irto);
00560 _ioctl(fd, UART_GETWRITETIMEOUT, &iwto);
00561 to = 45000;
00562 _ioctl(fd, UART_SETREADTIMEOUT, &to);
00563 to = 5000;
00564 _ioctl(fd, UART_SETWRITETIMEOUT, &to);
00565
00566
00567
00568
00569
00570 while (*script && rc == 0) {
00571
00572
00573
00574
00575 if (*script == ' ' || *script == '\t' || *script == '\r' || *script == '\n') {
00576 script++;
00577 continue;
00578 }
00579
00580
00581
00582
00583 if (*script == '"' || *script == '\'') {
00584 char quote = *script++;
00585
00586 arg = script;
00587 while (*script != quote) {
00588 if (*script == 0) {
00589 rc = 1;
00590 break;
00591 }
00592 if (*script++ == '\\') {
00593 if (*script)
00594 ++script;
00595 }
00596 }
00597 }
00598
00599
00600
00601
00602 else {
00603 arg = script;
00604 while (*script && *script != ' ' && *script != '\t' && *script != '\r' && *script != '\n')
00605 ++script;
00606 }
00607
00608 if (*script)
00609 *script++ = 0;
00610
00611
00612
00613
00614 if (rc == 0) {
00615 if (sendflg)
00616 rc = NutChatSend(ci, arg);
00617 else
00618 rc = NutChatExpect(ci, arg);
00619 sendflg = !sendflg;
00620 }
00621 }
00622
00623
00624
00625
00626 _ioctl(fd, UART_SETREADTIMEOUT, &irto);
00627 _ioctl(fd, UART_SETWRITETIMEOUT, &iwto);
00628
00629
00630
00631
00632 NutChatDestroy(ci);
00633
00634 return rc;
00635 }
00636
00650 int NutChat(int fd, CONST char *script)
00651 {
00652 int rc = -1;
00653 char *buf;
00654
00655
00656
00657
00658 if ((buf = malloc(strlen(script) + 1)) != 0) {
00659 strcpy(buf, script);
00660 rc = NutChatProc(fd, buf);
00661 free(buf);
00662 }
00663 return rc;
00664 }
00665
00677 #ifdef __HARVARD_ARCH__
00678 int NutChat_P(int fd, PGM_P script)
00679 {
00680 int rc = -1;
00681 char *buf;
00682
00683
00684
00685
00686 if ((buf = malloc(strlen_P(script) + 1)) != 0) {
00687 strcpy_P(buf, script);
00688 rc = NutChatProc(fd, buf);
00689 free(buf);
00690 }
00691 return rc;
00692 }
00693 #endif