#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/vmodem.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
Include dependency graph for chan_modem_aopen.c:
Go to the source code of this file.
Defines | |
#define | STATE_COMMAND 0 |
#define | STATE_VOICE 1 |
#define | VRA "40" |
#define | VRN "100" |
Functions | |
static int | aopen_answer (struct ast_modem_pvt *p) |
static int | aopen_break (struct ast_modem_pvt *p) |
static void | aopen_decusecnt (void) |
static int | aopen_dial (struct ast_modem_pvt *p, char *stuff) |
static int | aopen_dialdigit (struct ast_modem_pvt *p, char digit) |
static struct ast_frame * | aopen_handle_escape (struct ast_modem_pvt *p, char esc) |
static int | aopen_hangup (struct ast_modem_pvt *p) |
static char * | aopen_identify (struct ast_modem_pvt *p) |
static void | aopen_incusecnt (void) |
static int | aopen_init (struct ast_modem_pvt *p) |
static struct ast_frame * | aopen_read (struct ast_modem_pvt *p) |
static int | aopen_setdev (struct ast_modem_pvt *p, int dev) |
static int | aopen_startrec (struct ast_modem_pvt *p) |
static int | aopen_write (struct ast_modem_pvt *p, struct ast_frame *f) |
AST_MUTEX_DEFINE_STATIC (usecnt_lock) | |
char * | description () |
Provides a description of the module. | |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static struct ast_modem_driver | aopen_driver |
static char * | aopen_idents [] |
static char * | breakcmd = "\0x10\0x03" |
static char * | desc = "A/Open (Rockwell Chipset) ITU-2 VoiceModem Driver" |
static int | usecnt |
|
Definition at line 43 of file chan_modem_aopen.c. Referenced by aopen_init(), aopen_read(), bestdata_break(), bestdata_dial(), bestdata_dialdigit(), bestdata_init(), bestdata_read(), bestdata_startplay(), bestdata_startrec(), i4l_init(), and i4l_read(). |
|
Definition at line 44 of file chan_modem_aopen.c. Referenced by aopen_startrec(), bestdata_startrec(), i4l_answer(), i4l_dialdigit(), and i4l_startrec(). |
|
Definition at line 46 of file chan_modem_aopen.c. Referenced by aopen_init(), and bestdata_init(). |
|
Definition at line 47 of file chan_modem_aopen.c. Referenced by aopen_init(), and bestdata_init(). |
|
Definition at line 401 of file chan_modem_aopen.c. References ast_log(), ast_modem_expect(), ast_modem_send(), LOG_WARNING, and ast_modem_pvt::response. 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 }
|
|
Definition at line 112 of file chan_modem_aopen.c. References ast_log(), ast_modem_expect(), ast_modem_read_response(), ast_modem_send(), and LOG_WARNING. Referenced by aopen_hangup(), and aopen_init(). 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 /* Read any outstanding junk */ 00127 while(!ast_modem_read_response(p, 1)); 00128 if (ast_modem_send(p, "AT", 0)) { 00129 /* Modem might be stuck in some weird mode, try to get it out */ 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 }
|
|
Definition at line 393 of file chan_modem_aopen.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), and usecnt_lock. 00394 { 00395 ast_mutex_lock(&usecnt_lock); 00396 usecnt++; 00397 ast_mutex_unlock(&usecnt_lock); 00398 ast_update_use_count(); 00399 }
|
|
Definition at line 423 of file chan_modem_aopen.c. References ast_log(), ast_modem_send(), ast_modem_pvt::dialtype, and LOG_WARNING. 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 }
|
|
Definition at line 411 of file chan_modem_aopen.c. References ast_log(), ast_modem_expect(), ast_modem_send(), LOG_WARNING, and ast_modem_pvt::response. 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 }
|
|
Definition at line 199 of file chan_modem_aopen.c. References aopen_startrec(), AST_CONTROL_BUSY, AST_CONTROL_RING, AST_FRAME_CONTROL, AST_FRAME_NULL, ast_log(), ast_modem_send(), ast_setstate(), AST_STATE_UP, CHAR_ETX, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_modem_pvt::fr, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, ast_modem_pvt::owner, ast_frame::samples, and ast_frame::subclass. Referenced by aopen_read(). 00200 { 00201 /* Handle escaped characters -- but sometimes we call it directly as 00202 a quick way to cause known responses */ 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': /* Pseudo ring */ 00217 p->fr.frametype = AST_FRAME_CONTROL; 00218 p->fr.subclass = AST_CONTROL_RING; 00219 return &p->fr; 00220 case 'X': /* Pseudo connect */ 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': /* Busy signal */ 00229 p->fr.frametype = AST_FRAME_CONTROL; 00230 p->fr.subclass = AST_CONTROL_BUSY; 00231 return &p->fr; 00232 case 'o': /* Overrun */ 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': /* Underrun */ 00238 ast_log(LOG_WARNING, "Data underrun\n"); 00239 /* Fall Through */ 00240 case CHAR_ETX: /* End Transmission */ 00241 case 'd': /* Dialtone */ 00242 case 'c': /* Calling Tone */ 00243 case 'e': /* European version */ 00244 case 'a': /* Answer Tone */ 00245 case 'f': /* Bell Answer Tone */ 00246 case 'T': /* Timing mark */ 00247 case 't': /* Handset off hook */ 00248 case 'h': /* Handset hungup */ 00249 case 0: /* Pseudo signal */ 00250 /* Ignore */ 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 }
|
|
Definition at line 434 of file chan_modem_aopen.c. References aopen_break(), ast_log(), ast_modem_expect(), ast_modem_send(), and LOG_WARNING. 00435 { 00436 if (aopen_break(p)) 00437 return -1; 00438 /* Hangup by switching to data, then back to voice */ 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 }
|
|
Definition at line 360 of file chan_modem_aopen.c. References ast_modem_expect(), ast_modem_read_response(), ast_modem_send(), ast_modem_trim(), ast_modem_pvt::response, and strdup. 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 }
|
|
Definition at line 385 of file chan_modem_aopen.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_update_use_count(), and usecnt_lock. 00386 { 00387 ast_mutex_lock(&usecnt_lock); 00388 usecnt++; 00389 ast_mutex_unlock(&usecnt_lock); 00390 ast_update_use_count(); 00391 }
|
|
Definition at line 147 of file chan_modem_aopen.c. References aopen_break(), ast_log(), ast_modem_expect(), ast_modem_send(), LOG_DEBUG, LOG_WARNING, ast_modem_pvt::ministate, option_debug, STATE_COMMAND, VRA, and VRN. 00148 { 00149 if (option_debug) 00150 ast_log(LOG_DEBUG, "aopen_init()\n"); 00151 if (aopen_break(p)) 00152 return -1; 00153 /* Force into command mode */ 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 }
|
|
Definition at line 258 of file chan_modem_aopen.c. References aopen_handle_escape(), ast_log(), ast_modem_trim(), CHAR_DLE, ast_modem_pvt::dev, ast_modem_pvt::f, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::ministate, ast_modem_pvt::mode, MODEM_MODE_IMMEDIATE, ast_modem_pvt::obuf, ast_modem_pvt::obuflen, result, and STATE_COMMAND. 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 /* Read the first two bytes, first, in case it's a control message */ 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 /* Read the rest of the line */ 00275 fgets(result + 2, sizeof(result) - 2, p->f); 00276 ast_modem_trim(result); 00277 if (!strcasecmp(result, "VCON")) { 00278 /* If we're in immediate mode, reply now */ 00279 if (p->mode == MODEM_MODE_IMMEDIATE) 00280 return aopen_handle_escape(p, 'X'); 00281 } else 00282 if (!strcasecmp(result, "BUSY")) { 00283 /* Same as a busy signal */ 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 /* There's no dialtone, so the line isn't working */ 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 /* We have to be more efficient in voice mode */ 00299 b = (short *)(p->obuf + p->obuflen); 00300 while (p->obuflen/2 < 240) { 00301 /* Read ahead the full amount */ 00302 res = fread(result, 1, 240 - p->obuflen/2, p->f); 00303 if (res < 1) { 00304 /* If there's nothing there, just continue on */ 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 /* Process all the bytes that we've read */ 00311 if (result[x] == CHAR_DLE) { 00312 /* We assume there is no more than one signal frame among our 00313 data. */ 00314 if (f) 00315 ast_log(LOG_WARNING, "Warning: Dropped a signal frame\n"); 00316 f = aopen_handle_escape(p, result[x+1]); 00317 /* If aopen_handle_escape says NULL, say it now, doesn't matter 00318 what else is there, the connection is dead. */ 00319 if (!f) 00320 return NULL; 00321 } else { 00322 /* Generate a 16-bit signed linear value from our 00323 unsigned 8-bit value */ 00324 *(b++) = (((short)result[x]) - 127) * 0xff; 00325 p->obuflen += 2; 00326 } 00327 } 00328 if (f) 00329 break; 00330 } 00331 /* If we have a control frame, return it now */ 00332 if (f) 00333 return f; 00334 /* If we get here, we have a complete voice frame */ 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 }
|
|
Definition at line 62 of file chan_modem_aopen.c. References ast_log(), ast_modem_expect(), ast_modem_read_response(), ast_modem_send(), ast_modem_trim(), LOG_WARNING, and ast_modem_pvt::response. 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 /* We're already in the right mode, don't bother changing for fear of 00081 hanging up */ 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 }
|
|
Definition at line 101 of file chan_modem_aopen.c. References ast_log(), ast_modem_expect(), ast_modem_send(), LOG_WARNING, ast_modem_pvt::ministate, and STATE_VOICE. Referenced by aopen_handle_escape(). 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 }
|
|
Definition at line 353 of file chan_modem_aopen.c. References ast_log(), LOG_DEBUG, and option_debug. 00354 { 00355 if (option_debug) 00356 ast_log(LOG_DEBUG, "aopen_write()\n"); 00357 return 0; 00358 }
|
|
|
|
Provides a description of the module.
Definition at line 493 of file chan_modem_aopen.c. 00494 { 00495 return desc; 00496 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 498 of file chan_modem_aopen.c. References ASTERISK_GPL_KEY. 00499 { 00500 return ASTERISK_GPL_KEY; 00501 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 483 of file chan_modem_aopen.c. References aopen_driver, and ast_register_modem_driver(). 00484 { 00485 return ast_register_modem_driver(&aopen_driver); 00486 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 488 of file chan_modem_aopen.c. References aopen_driver, and ast_unregister_modem_driver(). 00489 { 00490 return ast_unregister_modem_driver(&aopen_driver); 00491 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 478 of file chan_modem_aopen.c. 00479 { 00480 return usecnt; 00481 }
|
|
Definition at line 452 of file chan_modem_aopen.c. Referenced by load_module(), and unload_module(). |
|
Initial value: {
"V2.210-V90_2M_DLP",
NULL
}
Definition at line 56 of file chan_modem_aopen.c. |
|
Definition at line 49 of file chan_modem_aopen.c. |
|
Definition at line 51 of file chan_modem_aopen.c. |
|
Definition at line 53 of file chan_modem_aopen.c. |