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