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 #include <stdio.h>
00027
00028 #include <string.h>
00029 #include <stdlib.h>
00030 #include <errno.h>
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00035
00036 #include "asterisk/lock.h"
00037 #include "asterisk/vmodem.h"
00038 #include "asterisk/module.h"
00039 #include "asterisk/frame.h"
00040 #include "asterisk/logger.h"
00041 #include "asterisk/options.h"
00042
00043 #define STATE_COMMAND 0
00044 #define STATE_VOICE 1
00045
00046 #define VRA "40"
00047 #define VRN "100"
00048
00049 static char *breakcmd = "\0x10\0x03";
00050
00051 static char *desc = "A/Open (Rockwell Chipset) ITU-2 VoiceModem Driver";
00052
00053 static int usecnt;
00054 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
00055
00056 static char *aopen_idents[] = {
00057
00058 "V2.210-V90_2M_DLP",
00059 NULL
00060 };
00061
00062 static int aopen_setdev(struct ast_modem_pvt *p, int dev)
00063 {
00064 char cmd[80];
00065 if (ast_modem_send(p, "AT#VLS?", 0)) {
00066 ast_log(LOG_WARNING, "Unable to select current mode %d\n", dev);
00067 return -1;
00068 }
00069 if (ast_modem_read_response(p, 5)) {
00070 ast_log(LOG_WARNING, "Unable to select device %d\n", dev);
00071 return -1;
00072 }
00073 ast_modem_trim(p->response);
00074 strncpy(cmd, p->response, sizeof(cmd)-1);
00075 if (ast_modem_expect(p, "OK", 5)) {
00076 ast_log(LOG_WARNING, "Modem did not respond properly\n");
00077 return -1;
00078 }
00079 if (dev == atoi(cmd)) {
00080
00081
00082 return 0;
00083 }
00084 snprintf(cmd, sizeof(cmd), "AT#VLS=%d", dev);
00085 if (ast_modem_send(p, cmd, 0)) {
00086 ast_log(LOG_WARNING, "Unable to select device %d\n", dev);
00087 return -1;
00088 }
00089 if (ast_modem_read_response(p, 5)) {
00090 ast_log(LOG_WARNING, "Unable to select device %d\n", dev);
00091 return -1;
00092 }
00093 ast_modem_trim(p->response);
00094 if (strcasecmp(p->response, "VCON") && strcasecmp(p->response, "OK")) {
00095 ast_log(LOG_WARNING, "Unexpected reply: %s\n", p->response);
00096 return -1;
00097 }
00098 return 0;
00099 }
00100
00101 static int aopen_startrec(struct ast_modem_pvt *p)
00102 {
00103 if (ast_modem_send(p, "AT#VRX", 0) ||
00104 ast_modem_expect(p, "CONNECT", 5)) {
00105 ast_log(LOG_WARNING, "Unable to start recording\n");
00106 return -1;
00107 }
00108 p->ministate = STATE_VOICE;
00109 return 0;
00110 }
00111
00112 static int aopen_break(struct ast_modem_pvt *p)
00113 {
00114 if (ast_modem_send(p, "\r\n", 2)) {
00115 ast_log(LOG_WARNING, "Failed to send enter?\n");
00116 return -1;
00117 }
00118 if (ast_modem_send(p, breakcmd, 2)) {
00119 ast_log(LOG_WARNING, "Failed to break\n");
00120 return -1;
00121 }
00122 if (ast_modem_send(p, "\r\n", 2)) {
00123 ast_log(LOG_WARNING, "Failed to send enter?\n");
00124 return -1;
00125 }
00126
00127 while(!ast_modem_read_response(p, 1));
00128 if (ast_modem_send(p, "AT", 0)) {
00129
00130 ast_modem_send(p, "+++", 3);
00131 if (ast_modem_expect(p, "OK", 10)) {
00132 ast_log(LOG_WARNING, "Modem is not responding\n");
00133 return -1;
00134 }
00135 if (ast_modem_send(p, "AT", 0)) {
00136 ast_log(LOG_WARNING, "Modem is not responding\n");
00137 return -1;
00138 }
00139 }
00140 if (ast_modem_expect(p, "OK", 5)) {
00141 ast_log(LOG_WARNING, "Modem did not respond properly\n");
00142 return -1;
00143 }
00144 return 0;
00145 }
00146
00147 static int aopen_init(struct ast_modem_pvt *p)
00148 {
00149 if (option_debug)
00150 ast_log(LOG_DEBUG, "aopen_init()\n");
00151 if (aopen_break(p))
00152 return -1;
00153
00154 p->ministate = STATE_COMMAND;
00155 if (ast_modem_send(p, "AT#BDR=0", 0) ||
00156 ast_modem_expect(p, "OK", 5)) {
00157 ast_log(LOG_WARNING, "Unable to set to auto-baud\n");
00158 return -1;
00159 }
00160 if (ast_modem_send(p, "AT#CLS=8", 0) ||
00161 ast_modem_expect(p, "OK", 5)) {
00162 ast_log(LOG_WARNING, "Unable to set to voice mode\n");
00163 return -1;
00164 }
00165 if (ast_modem_send(p, "AT#VBS=8", 0) ||
00166 ast_modem_expect(p, "OK", 5)) {
00167 ast_log(LOG_WARNING, "Unable to set to 8-bit mode\n");
00168 return -1;
00169 }
00170 if (ast_modem_send(p, "AT#VSR=8000", 0) ||
00171 ast_modem_expect(p, "OK", 5)) {
00172 ast_log(LOG_WARNING, "Unable to set to 8000 Hz sampling\n");
00173 return -1;
00174 }
00175 if (ast_modem_send(p, "AT#VLS=0", 0) ||
00176 ast_modem_expect(p, "OK", 5)) {
00177 ast_log(LOG_WARNING, "Unable to set to telco interface\n");
00178 return -1;
00179 }
00180 if (ast_modem_send(p, "AT#VRA=" VRA, 0) ||
00181 ast_modem_expect(p, "OK", 5)) {
00182 ast_log(LOG_WARNING, "Unable to set to 'ringback goes away' timer\n");
00183 return -1;
00184 }
00185 if (ast_modem_send(p, "AT#VRN=" VRN, 0) ||
00186 ast_modem_expect(p, "OK", 5)) {
00187 ast_log(LOG_WARNING, "Unable to set to 'ringback never came timer'\n");
00188 return -1;
00189 }
00190 if (ast_modem_send(p, "AT#VTD=3F,3F,3F", 0) ||
00191 ast_modem_expect(p, "OK", 5)) {
00192 ast_log(LOG_WARNING, "Unable to set to tone detection\n");
00193 return -1;
00194 }
00195
00196 return 0;
00197 }
00198
00199 static struct ast_frame *aopen_handle_escape(struct ast_modem_pvt *p, char esc)
00200 {
00201
00202
00203 p->fr.frametype = AST_FRAME_NULL;
00204 p->fr.subclass = 0;
00205 p->fr.data = NULL;
00206 p->fr.datalen = 0;
00207 p->fr.samples = 0;
00208 p->fr.offset = 0;
00209 p->fr.mallocd = 0;
00210 p->fr.delivery.tv_sec = 0;
00211 p->fr.delivery.tv_usec = 0;
00212 if (esc)
00213 ast_log(LOG_DEBUG, "Escaped character '%c'\n", esc);
00214
00215 switch(esc) {
00216 case 'R':
00217 p->fr.frametype = AST_FRAME_CONTROL;
00218 p->fr.subclass = AST_CONTROL_RING;
00219 return &p->fr;
00220 case 'X':
00221 p->fr.frametype = AST_FRAME_CONTROL;
00222 p->fr.subclass = AST_CONTROL_RING;
00223 if (p->owner)
00224 ast_setstate(p->owner, AST_STATE_UP);
00225 if (aopen_startrec(p))
00226 return NULL;
00227 return &p->fr;
00228 case 'b':
00229 p->fr.frametype = AST_FRAME_CONTROL;
00230 p->fr.subclass = AST_CONTROL_BUSY;
00231 return &p->fr;
00232 case 'o':
00233 ast_log(LOG_WARNING, "Overflow on modem, flushing buffers\n");
00234 if (ast_modem_send(p, "\0x10E", 2))
00235 ast_log(LOG_WARNING, "Unable to flush buffers\n");
00236 return &p->fr;
00237 case 'u':
00238 ast_log(LOG_WARNING, "Data underrun\n");
00239
00240 case CHAR_ETX:
00241 case 'd':
00242 case 'c':
00243 case 'e':
00244 case 'a':
00245 case 'f':
00246 case 'T':
00247 case 't':
00248 case 'h':
00249 case 0:
00250
00251 return &p->fr;
00252 default:
00253 ast_log(LOG_DEBUG, "Unknown Escaped character '%c' (%d)\n", esc, esc);
00254 }
00255 return &p->fr;
00256 }
00257
00258 static struct ast_frame *aopen_read(struct ast_modem_pvt *p)
00259 {
00260 char result[256];
00261 short *b;
00262 struct ast_frame *f=NULL;
00263 int res;
00264 int x;
00265 if (p->ministate == STATE_COMMAND) {
00266
00267 fread(result, 1, 2, p->f);
00268 if (result[0] == CHAR_DLE) {
00269 return aopen_handle_escape(p, result[1]);
00270
00271 } else {
00272 if ((result[0] == '\n') || (result[0] == '\r'))
00273 return aopen_handle_escape(p, 0);
00274
00275 fgets(result + 2, sizeof(result) - 2, p->f);
00276 ast_modem_trim(result);
00277 if (!strcasecmp(result, "VCON")) {
00278
00279 if (p->mode == MODEM_MODE_IMMEDIATE)
00280 return aopen_handle_escape(p, 'X');
00281 } else
00282 if (!strcasecmp(result, "BUSY")) {
00283
00284 return aopen_handle_escape(p, 'b');
00285 } else
00286 if (!strcasecmp(result, "RING")) {
00287 return aopen_handle_escape(p, 'R');
00288 } else
00289 if (!strcasecmp(result, "NO DIALTONE")) {
00290
00291 ast_log(LOG_WARNING, "Device '%s' lacking dialtone\n", p->dev);
00292 return NULL;
00293 }
00294 ast_log(LOG_DEBUG, "Modem said '%s'\n", result);
00295 return aopen_handle_escape(p, 0);
00296 }
00297 } else {
00298
00299 b = (short *)(p->obuf + p->obuflen);
00300 while (p->obuflen/2 < 240) {
00301
00302 res = fread(result, 1, 240 - p->obuflen/2, p->f);
00303 if (res < 1) {
00304
00305 if (errno == EAGAIN)
00306 return aopen_handle_escape(p, 0);
00307 ast_log(LOG_WARNING, "Read failed: %s\n", strerror(errno));
00308 }
00309 for (x=0;x<res;x++) {
00310
00311 if (result[x] == CHAR_DLE) {
00312
00313
00314 if (f)
00315 ast_log(LOG_WARNING, "Warning: Dropped a signal frame\n");
00316 f = aopen_handle_escape(p, result[x+1]);
00317
00318
00319 if (!f)
00320 return NULL;
00321 } else {
00322
00323
00324 *(b++) = (((short)result[x]) - 127) * 0xff;
00325 p->obuflen += 2;
00326 }
00327 }
00328 if (f)
00329 break;
00330 }
00331
00332 if (f)
00333 return f;
00334
00335 p->fr.frametype = AST_FRAME_VOICE;
00336 p->fr.subclass = AST_FORMAT_SLINEAR;
00337 p->fr.samples = 240;
00338 p->fr.data = p->obuf;
00339 p->fr.datalen = p->obuflen;
00340 p->fr.mallocd = 0;
00341 p->fr.delivery.tv_sec = 0;
00342 p->fr.delivery.tv_usec = 0;
00343 p->fr.offset = AST_FRIENDLY_OFFSET;
00344 p->fr.src = __FUNCTION__;
00345 if (option_debug)
00346 ast_log(LOG_DEBUG, "aopen_read(voice frame)\n");
00347 p->obuflen = 0;
00348 return &p->fr;
00349 }
00350 return NULL;
00351 }
00352
00353 static int aopen_write(struct ast_modem_pvt *p, struct ast_frame *f)
00354 {
00355 if (option_debug)
00356 ast_log(LOG_DEBUG, "aopen_write()\n");
00357 return 0;
00358 }
00359
00360 static char *aopen_identify(struct ast_modem_pvt *p)
00361 {
00362 char identity[256];
00363 char mfr[80];
00364 char mdl[80];
00365 char rev[80];
00366 ast_modem_send(p, "AT#MDL?", 0);
00367 ast_modem_read_response(p, 5);
00368 strncpy(mdl, p->response, sizeof(mdl)-1);
00369 ast_modem_trim(mdl);
00370 ast_modem_expect(p, "OK", 5);
00371 ast_modem_send(p, "AT#MFR?", 0);
00372 ast_modem_read_response(p, 5);
00373 strncpy(mfr, p->response, sizeof(mfr)-1);
00374 ast_modem_trim(mfr);
00375 ast_modem_expect(p, "OK", 5);
00376 ast_modem_send(p, "AT#REV?", 0);
00377 ast_modem_read_response(p, 5);
00378 strncpy(rev, p->response, sizeof(rev)-1);
00379 ast_modem_trim(rev);
00380 ast_modem_expect(p, "OK", 5);
00381 snprintf(identity, sizeof(identity), "%s Model %s Revision %s", mfr, mdl, rev);
00382 return strdup(identity);
00383 }
00384
00385 static void aopen_incusecnt(void)
00386 {
00387 ast_mutex_lock(&usecnt_lock);
00388 usecnt++;
00389 ast_mutex_unlock(&usecnt_lock);
00390 ast_update_use_count();
00391 }
00392
00393 static void aopen_decusecnt(void)
00394 {
00395 ast_mutex_lock(&usecnt_lock);
00396 usecnt++;
00397 ast_mutex_unlock(&usecnt_lock);
00398 ast_update_use_count();
00399 }
00400
00401 static int aopen_answer(struct ast_modem_pvt *p)
00402 {
00403 if (ast_modem_send(p, "ATA", 0) ||
00404 ast_modem_expect(p, "VCON", 10)) {
00405 ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
00406 return -1;
00407 }
00408 return 0;
00409 }
00410
00411 static int aopen_dialdigit(struct ast_modem_pvt *p, char digit)
00412 {
00413 char cmd[80];
00414 snprintf(cmd, sizeof(cmd), "AT#VTS=%c", digit);
00415 if (ast_modem_send(p, cmd, 0) ||
00416 ast_modem_expect(p, "VCON", 10)) {
00417 ast_log(LOG_WARNING, "Unable to answer: %s", p->response);
00418 return -1;
00419 }
00420 return 0;
00421 }
00422
00423 static int aopen_dial(struct ast_modem_pvt *p, char *stuff)
00424 {
00425 char cmd[80];
00426 snprintf(cmd, sizeof(cmd), "ATD%c %s", p->dialtype,stuff);
00427 if (ast_modem_send(p, cmd, 0)) {
00428 ast_log(LOG_WARNING, "Unable to dial\n");
00429 return -1;
00430 }
00431 return 0;
00432 }
00433
00434 static int aopen_hangup(struct ast_modem_pvt *p)
00435 {
00436 if (aopen_break(p))
00437 return -1;
00438
00439 if (ast_modem_send(p, "ATH", 0) ||
00440 ast_modem_expect(p, "OK", 8)) {
00441 ast_log(LOG_WARNING, "Unable to set to data mode\n");
00442 return -1;
00443 }
00444 if (ast_modem_send(p, "AT#CLS=8", 0) ||
00445 ast_modem_expect(p, "OK", 5)) {
00446 ast_log(LOG_WARNING, "Unable to set to voice mode\n");
00447 return -1;
00448 }
00449 return 0;
00450 }
00451
00452 static struct ast_modem_driver aopen_driver =
00453 {
00454 "AOpen",
00455 aopen_idents,
00456 AST_FORMAT_SLINEAR,
00457 0,
00458 aopen_incusecnt,
00459 aopen_decusecnt,
00460 aopen_identify,
00461 aopen_init,
00462 aopen_setdev,
00463 aopen_read,
00464 aopen_write,
00465 aopen_dial,
00466 aopen_answer,
00467 aopen_hangup,
00468 aopen_startrec,
00469 NULL,
00470 NULL,
00471 NULL,
00472 NULL,
00473 aopen_dialdigit,
00474 };
00475
00476
00477
00478 int usecount(void)
00479 {
00480 return usecnt;
00481 }
00482
00483 int load_module(void)
00484 {
00485 return ast_register_modem_driver(&aopen_driver);
00486 }
00487
00488 int unload_module(void)
00489 {
00490 return ast_unregister_modem_driver(&aopen_driver);
00491 }
00492
00493 char *description()
00494 {
00495 return desc;
00496 }
00497
00498 char *key()
00499 {
00500 return ASTERISK_GPL_KEY;
00501 }