#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
#include <sys/signal.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/vmodem.h"
#include "asterisk/utils.h"
Include dependency graph for chan_modem.c:
Go to the source code of this file.
Defines | |
#define | ECHO_TIMEOUT 10 |
Functions | |
static int | __unload_module (void) |
int | ast_modem_expect (struct ast_modem_pvt *p, char *result, int timeout) |
ast_channel * | ast_modem_new (struct ast_modem_pvt *i, int state) |
int | ast_modem_read_response (struct ast_modem_pvt *p, int timeout) |
int | ast_modem_send (struct ast_modem_pvt *p, char *cmd, int len) |
void | ast_modem_trim (char *s) |
AST_MUTEX_DEFINE_STATIC (monlock) | |
AST_MUTEX_DEFINE_STATIC (iflock) | |
AST_MUTEX_DEFINE_STATIC (usecnt_lock) | |
int | ast_register_modem_driver (struct ast_modem_driver *mc) |
int | ast_unregister_modem_driver (struct ast_modem_driver *mc) |
char * | description () |
Provides a description of the module. | |
static void * | do_monitor (void *data) |
static struct ast_modem_driver * | find_capability (char *ident) |
static struct ast_modem_driver * | find_driver (char *drv) |
static ast_group_t | get_group (char *s) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module () |
Initialize the module. | |
static struct ast_modem_pvt * | mkif (char *iface) |
static int | modem_answer (struct ast_channel *ast) |
static int | modem_call (struct ast_channel *ast, char *idest, int timeout) |
static int | modem_digit (struct ast_channel *ast, char digit) |
static int | modem_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | modem_hangup (struct ast_channel *ast) |
static void | modem_mini_packet (struct ast_modem_pvt *i) |
static struct ast_frame * | modem_read (struct ast_channel *) |
static struct ast_channel * | modem_request (const char *type, int format, void *data, int *cause) |
static int | modem_setup (struct ast_modem_pvt *p, int baudrate) |
static int | modem_write (struct ast_channel *ast, struct ast_frame *frame) |
static int | restart_monitor (void) |
static void | stty (struct ast_modem_pvt *p) |
int | unload_module () |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static int | baudrate = 115200 |
static const char | config [] = "modem.conf" |
static char | context [AST_MAX_EXTENSION] = "default" |
static ast_group_t | cur_group = 0 |
int | dep_warning = 0 |
static const char | desc [] = "Generic Voice Modem Driver" |
static char | dialtype = 'T' |
static struct ast_modem_driver * | drivers = NULL |
ast_dsp * | dsp = NULL |
static int | dtmfmode = MODEM_DTMF_AST |
static int | dtmfmodegen = MODEM_DTMF_AST |
static int | gmode = MODEM_MODE_IMMEDIATE |
static struct ast_modem_pvt * | iflist = NULL |
static char | incomingmsn [AST_MAX_EXTENSION] = "" |
static char | initstr [AST_MAX_INIT_STR] = "ATE0Q0" |
static char | language [MAX_LANGUAGE] = "" |
static const struct ast_channel_tech | modem_tech |
static pthread_t | monitor_thread = AST_PTHREADT_NULL |
static char | msn [AST_MAX_EXTENSION] = "" |
static char | mtype [80] = "autodetect" |
static char | outgoingmsn [AST_MAX_EXTENSION] = "" |
static int | stripmsd = 0 |
static const char | tdesc [] = "Generic Voice Modem Channel Driver" |
static const char | type [] = "Modem" |
static int | usecnt = 0 |
Definition in file chan_modem.c.
|
Definition at line 55 of file chan_modem.c. Referenced by modem_setup(). |
|
Definition at line 918 of file chan_modem.c. References ast_channel_unregister(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_modem_pvt::fd, free, LOG_WARNING, monitor_thread, ast_modem_pvt::next, and ast_modem_pvt::owner. 00919 { 00920 struct ast_modem_pvt *p, *pl; 00921 /* First, take us out of the channel loop */ 00922 ast_channel_unregister(&modem_tech); 00923 if (!ast_mutex_lock(&iflock)) { 00924 /* Hangup all interfaces if they have an owner */ 00925 p = iflist; 00926 while(p) { 00927 if (p->owner) 00928 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 00929 p = p->next; 00930 } 00931 iflist = NULL; 00932 ast_mutex_unlock(&iflock); 00933 } else { 00934 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 00935 return -1; 00936 } 00937 if (!ast_mutex_lock(&monlock)) { 00938 if (monitor_thread != AST_PTHREADT_NULL && monitor_thread != AST_PTHREADT_STOP) { 00939 pthread_cancel(monitor_thread); 00940 pthread_join(monitor_thread, NULL); 00941 } 00942 monitor_thread = AST_PTHREADT_STOP; 00943 ast_mutex_unlock(&monlock); 00944 } else { 00945 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 00946 return -1; 00947 } 00948 00949 if (!ast_mutex_lock(&iflock)) { 00950 /* Destroy all the interfaces and free their memory */ 00951 p = iflist; 00952 while(p) { 00953 /* Close the socket, assuming it's real */ 00954 if (p->fd > -1) 00955 close(p->fd); 00956 pl = p; 00957 p = p->next; 00958 /* Free associated memory */ 00959 free(pl); 00960 } 00961 iflist = NULL; 00962 ast_mutex_unlock(&iflock); 00963 } else { 00964 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 00965 return -1; 00966 } 00967 00968 return 0; 00969 }
|
|
Wait for result to occur. Return non-zero if times out or error, last response is stored in p->response Definition at line 345 of file chan_modem.c. References ast_waitfor_n_fd(), ast_modem_pvt::f, ast_modem_pvt::fd, and ast_modem_pvt::response. Referenced by aopen_answer(), aopen_break(), aopen_dialdigit(), aopen_hangup(), aopen_identify(), aopen_init(), aopen_setdev(), aopen_startrec(), bestdata_answer(), bestdata_break(), bestdata_dialdigit(), bestdata_hangup(), bestdata_identify(), bestdata_init(), bestdata_startplay(), bestdata_startrec(), i4l_answer(), i4l_break(), i4l_hangup(), i4l_init(), i4l_setdev(), i4l_startrec(), and modem_setup(). 00346 { 00347 int res = -1; 00348 timeout *= 1000; 00349 strncpy(p->response, "(No Response)", sizeof(p->response)-1); 00350 do { 00351 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL); 00352 if (res < 0) { 00353 return -1; 00354 } 00355 /* Read a response */ 00356 fgets(p->response, sizeof(p->response), p->f); 00357 if (!strncasecmp(p->response, result, strlen(result))) 00358 return 0; 00359 } while(timeout > 0); 00360 return -1; 00361 }
|
|
|
Wait for result to occur. response is stored in p->response Definition at line 296 of file chan_modem.c. References ast_waitfor_n_fd(). Referenced by aopen_break(), aopen_identify(), aopen_setdev(), bestdata_break(), bestdata_handle_escape(), bestdata_identify(), i4l_break(), i4l_setdev(), and modem_setup(). 00297 { 00298 int res = -1,c,i; 00299 timeout *= 1000; 00300 p->response[0] = 0; 00301 c = i = 0; 00302 do { 00303 res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL); 00304 if (res < 0) { 00305 strncpy(p->response, "(No Response)", sizeof(p->response)-1); 00306 return -1; 00307 } 00308 /* get no more then buffer length */ 00309 while(i < sizeof(p->response) - 1) 00310 { 00311 c = fgetc(p->f); /* get a char */ 00312 if (c < 1) /* if error */ 00313 { 00314 /* if nothing in buffer, go back into timeout stuff */ 00315 if (errno == EWOULDBLOCK) break; 00316 /* return as error */ 00317 strncpy(p->response, "(No Response)", sizeof(p->response)-1); 00318 return -1; 00319 } 00320 /* save char */ 00321 p->response[i++] = c; 00322 p->response[i] = 0; 00323 /* if end of input */ 00324 if (c == '\n') break; 00325 } 00326 if (c >= 0) /* if input terminated normally */ 00327 { 00328 /* ignore just CR/LF */ 00329 if (!strcmp(p->response,"\r\n")) 00330 { 00331 /* reset input buffer stuff */ 00332 i = 0; 00333 p->response[0] = 0; 00334 } 00335 else /* otherwise return with info in buffer */ 00336 { 00337 return 0; 00338 } 00339 } 00340 } while(timeout > 0); 00341 strncpy(p->response, "(No Response)", sizeof(p->response)-1); 00342 return -1; 00343 }
|
|
Send the command cmd (length len, or 0 if pure ascii) on modem Definition at line 272 of file chan_modem.c. References ast_modem_pvt::f. Referenced by aopen_answer(), aopen_break(), aopen_dial(), aopen_dialdigit(), aopen_handle_escape(), aopen_hangup(), aopen_identify(), aopen_init(), aopen_setdev(), aopen_startrec(), bestdata_answer(), bestdata_break(), bestdata_dial(), bestdata_dialdigit(), bestdata_handle_escape(), bestdata_hangup(), bestdata_identify(), bestdata_init(), bestdata_startplay(), bestdata_startrec(), i4l_answer(), i4l_break(), i4l_dial(), i4l_handle_escape(), i4l_hangup(), i4l_init(), i4l_setdev(), i4l_startrec(), and modem_setup(). 00273 { 00274 int i; 00275 usleep(5000); 00276 if (!len) { 00277 for(i = 0; cmd[i];) 00278 { 00279 if (fwrite(cmd + i,1,1,p->f) != 1) 00280 { 00281 if (errno == EWOULDBLOCK) continue; 00282 return -1; 00283 } 00284 i++; 00285 } 00286 tcdrain(fileno(p->f)); 00287 fprintf(p->f,"\r\n"); 00288 return 0; 00289 } else { 00290 if (fwrite(cmd, 1, len, p->f) < len) 00291 return -1; 00292 return 0; 00293 } 00294 }
|
|
Trim off trailing mess Definition at line 363 of file chan_modem.c. Referenced by aopen_identify(), aopen_read(), aopen_setdev(), bestdata_handle_escape(), bestdata_identify(), bestdata_read(), i4l_read(), i4l_setdev(), and modem_setup(). 00364 { 00365 int x; 00366 x = strlen(s) - 1; 00367 while(x >= 0) { 00368 if ((s[x] != '\r') && (s[x] != '\n') && (s[x] != ' ')) 00369 break; 00370 s[x] = '\0'; 00371 x--; 00372 } 00373 }
|
|
|
|
|
|
|
|
Register a driver Definition at line 194 of file chan_modem.c. Referenced by load_module().
|
|
Unregister a driver Definition at line 201 of file chan_modem.c. References last, and ast_modem_driver::next. Referenced by unload_module(). 00202 { 00203 struct ast_modem_driver *last = NULL, *cur; 00204 cur = drivers; 00205 while(cur) { 00206 if (cur == mc) { 00207 if (last) 00208 last->next = mc->next; 00209 else 00210 drivers = mc->next; 00211 return 0; 00212 } 00213 cur = cur->next; 00214 } 00215 return -1; 00216 }
|
|
Provides a description of the module.
Definition at line 1102 of file chan_modem.c. References desc. 01103 { 01104 return (char *) desc; 01105 }
|
|
Definition at line 611 of file chan_modem.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_select(), ast_modem_pvt::dev, ast_modem_pvt::fd, LOG_DEBUG, LOG_ERROR, LOG_WARNING, modem_mini_packet(), n, ast_modem_pvt::next, and ast_modem_pvt::owner. 00612 { 00613 fd_set rfds, efds; 00614 int n, res; 00615 struct ast_modem_pvt *i; 00616 /* This thread monitors all the frame relay interfaces which are not yet in use 00617 (and thus do not have a separate thread) indefinitely */ 00618 /* From here on out, we die whenever asked */ 00619 #if 0 00620 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 00621 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 00622 return NULL; 00623 } 00624 #endif 00625 for(;;) { 00626 /* Don't let anybody kill us right away. Nobody should lock the interface list 00627 and wait for the monitor list, but the other way around is okay. */ 00628 if (ast_mutex_lock(&monlock)) { 00629 ast_log(LOG_ERROR, "Unable to grab monitor lock\n"); 00630 return NULL; 00631 } 00632 /* Lock the interface list */ 00633 if (ast_mutex_lock(&iflock)) { 00634 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 00635 ast_mutex_unlock(&monlock); 00636 return NULL; 00637 } 00638 /* Build the stuff we're going to select on, that is the socket of every 00639 ast_modem_pvt that does not have an associated owner channel */ 00640 n = -1; 00641 FD_ZERO(&rfds); 00642 FD_ZERO(&efds); 00643 i = iflist; 00644 while(i) { 00645 if (FD_ISSET(i->fd, &rfds)) 00646 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev); 00647 if (!i->owner) { 00648 /* This needs to be watched, as it lacks an owner */ 00649 FD_SET(i->fd, &rfds); 00650 FD_SET(i->fd, &efds); 00651 if (i->fd > n) 00652 n = i->fd; 00653 } 00654 00655 i = i->next; 00656 } 00657 /* Okay, now that we know what to do, release the interface lock */ 00658 ast_mutex_unlock(&iflock); 00659 00660 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 00661 ast_mutex_unlock(&monlock); 00662 #if 0 00663 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid()); 00664 #endif 00665 /* Wait indefinitely for something to happen */ 00666 pthread_testcancel(); 00667 res = ast_select(n + 1, &rfds, NULL, &efds, NULL); 00668 pthread_testcancel(); 00669 /* Okay, select has finished. Let's see what happened. */ 00670 if (res < 1) { 00671 if ((errno != EINTR) && (errno != EAGAIN)) 00672 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno)); 00673 continue; 00674 } 00675 /* Alright, lock the interface list again, and let's look and see what has 00676 happened */ 00677 if (ast_mutex_lock(&iflock)) { 00678 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 00679 continue; 00680 } 00681 i = iflist; 00682 while(i) { 00683 if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) { 00684 if (i->owner) { 00685 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->fd, i->dev); 00686 i = i->next; 00687 continue; 00688 } 00689 modem_mini_packet(i); 00690 } 00691 i=i->next; 00692 } 00693 ast_mutex_unlock(&iflock); 00694 } 00695 /* Never reached */ 00696 return NULL; 00697 00698 }
|
|
Definition at line 157 of file chan_modem.c. References ast_modem_driver::idents, and ast_modem_driver::next. Referenced by modem_setup(). 00158 { 00159 struct ast_modem_driver *mc; 00160 int x; 00161 mc = drivers; 00162 while(mc) { 00163 for (x=0;mc->idents[x];x++) { 00164 if (!strcmp(ident, mc->idents[x])) 00165 break; 00166 } 00167 if (mc->idents[x]) 00168 break; 00169 mc = mc->next; 00170 } 00171 if (mc) { 00172 if (mc->incusecnt) 00173 mc->incusecnt(); 00174 } 00175 return mc; 00176 }
|
|
Definition at line 178 of file chan_modem.c. References ast_modem_driver::name, and ast_modem_driver::next. Referenced by modem_setup(). 00179 { 00180 struct ast_modem_driver *mc; 00181 mc = drivers; 00182 while(mc) { 00183 if (!strcasecmp(mc->name, drv)) 00184 break; 00185 mc = mc->next; 00186 } 00187 if (mc) { 00188 if (mc->incusecnt) 00189 mc->incusecnt(); 00190 } 00191 return mc; 00192 }
|
|
Definition at line 882 of file chan_modem.c. References ast_log(), ast_strdupa, copy(), group, LOG_ERROR, LOG_WARNING, and strsep(). Referenced by load_module(). 00883 { 00884 char *piece; 00885 int start, finish,x; 00886 ast_group_t group = 0; 00887 char *copy = ast_strdupa(s); 00888 char *stringp=NULL; 00889 if (!copy) { 00890 ast_log(LOG_ERROR, "Out of memory\n"); 00891 return 0; 00892 } 00893 stringp=copy; 00894 piece = strsep(&stringp, ","); 00895 while(piece) { 00896 if (sscanf(piece, "%d-%d", &start, &finish) == 2) { 00897 /* Range */ 00898 } else if (sscanf(piece, "%d", &start)) { 00899 /* Just one */ 00900 finish = start; 00901 } else { 00902 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece); 00903 return 0; 00904 } 00905 piece = strsep(&stringp, ","); 00906 00907 for (x=start;x<=finish;x++) { 00908 if ((x > 63) || (x < 0)) { 00909 ast_log(LOG_WARNING, "Ignoring invalid group %d\n", x); 00910 break; 00911 } 00912 group |= (1 << x); 00913 } 00914 } 00915 return group; 00916 }
|
|
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 1107 of file chan_modem.c. References ASTERISK_GPL_KEY. 01108 { 01109 return ASTERISK_GPL_KEY; 01110 }
|
|
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 976 of file chan_modem.c. References __unload_module(), ast_channel_register(), ast_config_destroy(), ast_config_load(), ast_load_resource(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_browse(), ast_verbose(), cfg, config, context, cur_group, dialtype, dtmfmode, dtmfmodegen, get_group(), gmode, incomingmsn, initstr, language, LOG_ERROR, LOG_WARNING, mkif(), MODEM_DTMF_AST, MODEM_DTMF_I4L, MODEM_DTMF_NONE, MODEM_MODE_IMMEDIATE, MODEM_MODE_WAIT_ANSWER, MODEM_MODE_WAIT_RING, msn, mtype, ast_variable::name, ast_variable::next, ast_modem_pvt::next, option_verbose, outgoingmsn, restart_monitor(), stripmsd, type, ast_variable::value, and VERBOSE_PREFIX_2. 00977 { 00978 struct ast_config *cfg; 00979 struct ast_variable *v; 00980 struct ast_modem_pvt *tmp; 00981 char driver[80]; 00982 cfg = ast_config_load(config); 00983 00984 /* We *must* have a config file otherwise stop immediately */ 00985 if (!cfg) { 00986 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 00987 return -1; 00988 } 00989 if (ast_mutex_lock(&iflock)) { 00990 /* It's a little silly to lock it, but we mind as well just to be sure */ 00991 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 00992 return -1; 00993 } 00994 v = ast_variable_browse(cfg, "interfaces"); 00995 while(v) { 00996 /* Create the interface list */ 00997 if (!strcasecmp(v->name, "device")) { 00998 tmp = mkif(v->value); 00999 if (tmp) { 01000 tmp->next = iflist; 01001 iflist = tmp; 01002 01003 } else { 01004 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01005 ast_config_destroy(cfg); 01006 ast_mutex_unlock(&iflock); 01007 __unload_module(); 01008 return -1; 01009 } 01010 } else if (!strcasecmp(v->name, "driver")) { 01011 snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value); 01012 if (option_verbose > 1) 01013 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver); 01014 01015 if (ast_load_resource(driver)) { 01016 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver); 01017 ast_config_destroy(cfg); 01018 ast_mutex_unlock(&iflock); 01019 __unload_module(); 01020 return -1; 01021 } 01022 } else if (!strcasecmp(v->name, "mode")) { 01023 if (!strncasecmp(v->value, "ri", 2)) 01024 gmode = MODEM_MODE_WAIT_RING; 01025 else if (!strncasecmp(v->value, "im", 2)) 01026 gmode = MODEM_MODE_IMMEDIATE; 01027 else if (!strncasecmp(v->value, "an", 2)) 01028 gmode = MODEM_MODE_WAIT_ANSWER; 01029 else 01030 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01031 } else if (!strcasecmp(v->name, "stripmsd")) { 01032 stripmsd = atoi(v->value); 01033 } else if (!strcasecmp(v->name, "type")) { 01034 strncpy(mtype, v->value, sizeof(mtype)-1); 01035 } else if (!strcasecmp(v->name, "initstr")) { 01036 strncpy(initstr, v->value, sizeof(initstr)-1); 01037 } else if (!strcasecmp(v->name, "dialtype")) { 01038 dialtype = toupper(v->value[0]); 01039 } else if (!strcasecmp(v->name, "context")) { 01040 strncpy(context, v->value, sizeof(context)-1); 01041 } else if (!strcasecmp(v->name, "msn")) { 01042 strncpy(msn, v->value, sizeof(msn)-1); 01043 } else if (!strcasecmp(v->name, "incomingmsn")) { 01044 strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1); 01045 } else if (!strcasecmp(v->name, "dtmfmode")) { 01046 char tmp[80]; 01047 char *alt; 01048 strncpy(tmp, v->value, sizeof(tmp) - 1); 01049 alt = strchr(tmp, '/'); 01050 if (!strcasecmp(tmp, "none")) 01051 dtmfmode=MODEM_DTMF_NONE; 01052 else if (!strcasecmp(tmp, "asterisk")) 01053 dtmfmode = MODEM_DTMF_AST; 01054 else if (!strcasecmp(tmp, "i4l")) 01055 dtmfmode = MODEM_DTMF_I4L; 01056 else { 01057 ast_log(LOG_WARNING, "Unknown dtmf detection mode '%s', using 'asterisk'\n", v->value); 01058 dtmfmode = MODEM_DTMF_AST; 01059 } 01060 if (alt) { 01061 if (!strcasecmp(alt, "none")) 01062 dtmfmodegen=MODEM_DTMF_NONE; 01063 else if (!strcasecmp(alt, "asterisk")) 01064 dtmfmodegen = MODEM_DTMF_AST; 01065 else if (!strcasecmp(alt, "i4l")) 01066 dtmfmodegen = MODEM_DTMF_I4L; 01067 else if (!strcasecmp(alt, "both")) 01068 dtmfmodegen = MODEM_DTMF_I4L | MODEM_DTMF_AST; 01069 else { 01070 ast_log(LOG_WARNING, "Unknown dtmf generation mode '%s', using 'asterisk'\n", v->value); 01071 dtmfmodegen = MODEM_DTMF_AST; 01072 } 01073 } else 01074 dtmfmodegen = dtmfmode; 01075 } else if (!strcasecmp(v->name, "outgoingmsn")) { 01076 strncpy(outgoingmsn, v->value, sizeof(outgoingmsn)-1); 01077 } else if (!strcasecmp(v->name, "language")) { 01078 strncpy(language, v->value, sizeof(language)-1); 01079 } else if (!strcasecmp(v->name, "group")) { 01080 cur_group = get_group(v->value); 01081 } 01082 v = v->next; 01083 } 01084 ast_mutex_unlock(&iflock); 01085 if (ast_channel_register(&modem_tech)) { 01086 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); 01087 ast_config_destroy(cfg); 01088 __unload_module(); 01089 return -1; 01090 } 01091 ast_config_destroy(cfg); 01092 /* And start the monitor for the first time */ 01093 restart_monitor(); 01094 return 0; 01095 }
|
|
Definition at line 755 of file chan_modem.c. References ast_log(), baudrate, context, cur_group, dialtype, dtmfmode, dtmfmodegen, free, gmode, incomingmsn, initstr, language, LOG_WARNING, malloc, modem_setup(), msn, outgoingmsn, stripmsd, and stty(). Referenced by load_module(). 00756 { 00757 /* Make a ast_modem_pvt structure for this interface */ 00758 struct ast_modem_pvt *tmp; 00759 #if 0 00760 int flags; 00761 #endif 00762 00763 tmp = malloc(sizeof(struct ast_modem_pvt)); 00764 if (tmp) { 00765 memset(tmp, 0, sizeof(struct ast_modem_pvt)); 00766 tmp->fd = open(iface, O_RDWR | O_NONBLOCK); 00767 if (tmp->fd < 0) { 00768 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface); 00769 free(tmp); 00770 return NULL; 00771 } 00772 strncpy(tmp->language, language, sizeof(tmp->language)-1); 00773 strncpy(tmp->msn, msn, sizeof(tmp->msn)-1); 00774 strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1); 00775 tmp->dtmfmode = dtmfmode; 00776 tmp->dtmfmodegen = dtmfmodegen; 00777 snprintf(tmp->outgoingmsn, sizeof(tmp->outgoingmsn), ",%s,", outgoingmsn); 00778 strncpy(tmp->dev, iface, sizeof(tmp->dev)-1); 00779 /* Maybe in the future we want to allow variable 00780 serial settings */ 00781 stty(tmp); 00782 tmp->f = fdopen(tmp->fd, "w+"); 00783 /* Disable buffering */ 00784 setvbuf(tmp->f, NULL, _IONBF,0); 00785 if (tmp->f < 0) { 00786 ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface); 00787 free(tmp); 00788 return NULL; 00789 } 00790 tmp->owner = NULL; 00791 tmp->ministate = 0; 00792 tmp->stripmsd = stripmsd; 00793 tmp->dialtype = dialtype; 00794 tmp->mode = gmode; 00795 tmp->group = cur_group; 00796 memset(tmp->cid_num, 0, sizeof(tmp->cid_num)); 00797 memset(tmp->cid_name, 0, sizeof(tmp->cid_name)); 00798 strncpy(tmp->context, context, sizeof(tmp->context)-1); 00799 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1); 00800 tmp->next = NULL; 00801 tmp->obuflen = 0; 00802 00803 if (modem_setup(tmp, baudrate) < 0) { 00804 ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface); 00805 free(tmp); 00806 return NULL; 00807 } 00808 } 00809 return tmp; 00810 }
|
|
Definition at line 485 of file chan_modem.c. References ast_modem_driver::answer, ast_log(), ast_setstate(), AST_STATE_UP, LOG_DEBUG, ast_modem_pvt::mc, ast_channel::name, option_debug, ast_channel::rings, and ast_channel::tech_pvt. 00486 { 00487 struct ast_modem_pvt *p; 00488 int res=0; 00489 if (option_debug) 00490 ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name); 00491 p = ast->tech_pvt; 00492 if (p->mc->answer) { 00493 res = p->mc->answer(p); 00494 } 00495 if (!res) { 00496 ast->rings = 0; 00497 ast_setstate(ast, AST_STATE_UP); 00498 } 00499 return res; 00500 }
|
|
Definition at line 218 of file chan_modem.c. References ast_log(), ast_setstate(), AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_UP, ast_waitfor(), ast_modem_driver::dial, LOG_WARNING, ast_modem_pvt::mc, MODEM_DEV_HANDSET, MODEM_DEV_TELCO_SPK, modem_read(), ast_modem_driver::setdev, ast_modem_pvt::stripmsd, and strsep(). 00219 { 00220 struct ast_modem_pvt *p; 00221 int ms = timeout; 00222 char rdest[80], *where, dstr[100] = ""; 00223 char *stringp=NULL; 00224 strncpy(rdest, idest, sizeof(rdest)-1); 00225 stringp=rdest; 00226 strsep(&stringp, ":"); 00227 where = strsep(&stringp, ":"); 00228 if (!where) { 00229 ast_log(LOG_WARNING, "Destination %s requres a real destination (device:destination)\n", idest); 00230 return -1; 00231 } 00232 p = ast->tech_pvt; 00233 strncpy(dstr, where + p->stripmsd, sizeof(dstr) - 1); 00234 /* if not a transfer or just sending tones, must be in correct state */ 00235 if (strcasecmp(rdest, "transfer") && strcasecmp(rdest,"sendtones")) { 00236 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { 00237 ast_log(LOG_WARNING, "modem_call called on %s, neither down nor reserved\n", ast->name); 00238 return -1; 00239 } 00240 } 00241 if (!strcasecmp(rdest,"transfer")) /* if a transfer, put in transfer stuff */ 00242 { 00243 snprintf(dstr, sizeof(dstr), "!,%s", where + p->stripmsd); 00244 } 00245 if (!strcasecmp(where, "handset")) { 00246 if (p->mc->setdev) 00247 if (p->mc->setdev(p, MODEM_DEV_HANDSET)) 00248 return -1; 00249 /* Should be immediately up */ 00250 ast_setstate(ast, AST_STATE_UP); 00251 } else { 00252 if (p->mc->setdev) 00253 if (p->mc->setdev(p, MODEM_DEV_TELCO_SPK)) 00254 return -1; 00255 if (p->mc->dial) 00256 p->mc->dial(p, dstr); 00257 ast_setstate(ast, AST_STATE_DIALING); 00258 while((ast->_state != AST_STATE_UP) && (ms > 0)) { 00259 ms = ast_waitfor(ast, ms); 00260 /* Just read packets and watch what happens */ 00261 if (ms > 0) { 00262 if (!modem_read(ast)) 00263 return -1; 00264 } 00265 } 00266 if (ms < 0) 00267 return -1; 00268 } 00269 return 0; 00270 }
|
|
Definition at line 145 of file chan_modem.c. References ast_log(), ast_modem_driver::dialdigit, LOG_DEBUG, ast_modem_pvt::mc, ast_channel::name, and ast_channel::tech_pvt. 00146 { 00147 struct ast_modem_pvt *p; 00148 p = ast->tech_pvt; 00149 if (p->mc->dialdigit) 00150 return p->mc->dialdigit(p, digit); 00151 ast_log(LOG_DEBUG, "Channel %s lacks digit dialing\n", ast->name); 00152 return -1; 00153 }
|
|
Definition at line 548 of file chan_modem.c. References ast_log(), LOG_WARNING, ast_modem_pvt::owner, and ast_channel::tech_pvt. 00549 { 00550 struct ast_modem_pvt *p = newchan->tech_pvt; 00551 ast_log(LOG_WARNING, "fixup called\n"); 00552 if (p->owner!=oldchan) { 00553 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n",oldchan,p->owner); 00554 return -1; 00555 } 00556 p->owner = newchan; 00557 return 0; 00558 }
|
|
Definition at line 454 of file chan_modem.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_DOWN, ast_update_use_count(), ast_verbose(), ast_modem_driver::hangup, ast_modem_driver::init, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::mc, ast_channel::name, option_debug, option_verbose, restart_monitor(), ast_channel::tech_pvt, usecnt, usecnt_lock, and VERBOSE_PREFIX_3. 00455 { 00456 struct ast_modem_pvt *p; 00457 if (option_debug) 00458 ast_log(LOG_DEBUG, "modem_hangup(%s)\n", ast->name); 00459 p = ast->tech_pvt; 00460 /* Hang up */ 00461 if (p->mc->hangup) 00462 p->mc->hangup(p); 00463 /* Re-initialize */ 00464 if (p->mc->init) 00465 p->mc->init(p); 00466 ast_setstate(ast, AST_STATE_DOWN); 00467 memset(p->cid_num, 0, sizeof(p->cid_num)); 00468 memset(p->cid_name, 0, sizeof(p->cid_name)); 00469 memset(p->dnid, 0, sizeof(p->dnid)); 00470 ((struct ast_modem_pvt *)(ast->tech_pvt))->owner = NULL; 00471 ast_mutex_lock(&usecnt_lock); 00472 usecnt--; 00473 if (usecnt < 0) 00474 ast_log(LOG_WARNING, "Usecnt < 0???\n"); 00475 ast_mutex_unlock(&usecnt_lock); 00476 ast_update_use_count(); 00477 if (option_verbose > 2) 00478 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name); 00479 ast->tech_pvt = NULL; 00480 ast_setstate(ast, AST_STATE_DOWN); 00481 restart_monitor(); 00482 return 0; 00483 }
|
|
Definition at line 599 of file chan_modem.c. References AST_CONTROL_RING, AST_FRAME_CONTROL, ast_modem_new(), AST_STATE_RING, ast_frame::frametype, ast_modem_pvt::mc, ast_modem_driver::read, and ast_frame::subclass. Referenced by do_monitor(). 00600 { 00601 struct ast_frame *fr; 00602 fr = i->mc->read(i); 00603 if (!fr) return; 00604 if (fr->frametype == AST_FRAME_CONTROL) { 00605 if (fr->subclass == AST_CONTROL_RING) { 00606 ast_modem_new(i, AST_STATE_RING); 00607 } 00608 } 00609 }
|
|
Definition at line 515 of file chan_modem.c. References ast_modem_pvt::mc, ast_modem_driver::read, and ast_channel::tech_pvt. Referenced by modem_call(). 00516 { 00517 struct ast_modem_pvt *p = ast->tech_pvt; 00518 struct ast_frame *fr=NULL; 00519 if (p->mc->read) 00520 fr = p->mc->read(p); 00521 return fr; 00522 }
|
|
Definition at line 812 of file chan_modem.c. References ast_getformatname(), ast_log(), ast_modem_new(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, dep_warning, ast_modem_pvt::dev, ast_modem_driver::formats, ast_modem_pvt::group, group, LOG_ERROR, LOG_WARNING, ast_modem_pvt::mc, ast_modem_pvt::next, ast_modem_pvt::owner, restart_monitor(), and strsep(). 00813 { 00814 int oldformat; 00815 struct ast_modem_pvt *p; 00816 struct ast_channel *tmp = NULL; 00817 char dev[80]; 00818 ast_group_t group = 0; 00819 int groupint; 00820 char *stringp=NULL; 00821 strncpy(dev, (char *)data, sizeof(dev)-1); 00822 stringp=dev; 00823 strsep(&stringp, ":"); 00824 oldformat = format; 00825 00826 if (!dep_warning) { 00827 ast_log(LOG_WARNING, "This channel driver is deprecated. Please see the UPGRADE.txt file.\n"); 00828 dep_warning = 1; 00829 } 00830 00831 if (dev[0]=='g' && isdigit(dev[1])) { 00832 /* Retrieve the group number */ 00833 if (sscanf(dev+1, "%u", &groupint) < 1) { 00834 ast_log(LOG_WARNING, "Unable to determine group from [%s]\n", (char *)data); 00835 return NULL; 00836 } 00837 group = 1 << groupint; 00838 } 00839 00840 /* Search for an unowned channel */ 00841 if (ast_mutex_lock(&iflock)) { 00842 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 00843 return NULL; 00844 } 00845 p = iflist; 00846 while(p) { 00847 if (group) { 00848 /* if it belongs to the proper group, and the format matches 00849 * and it is not in use, we found a candidate! */ 00850 if (p->group & group && 00851 p->mc->formats & format && 00852 !p->owner) { 00853 /* XXX Not quite sure that not having an owner is 00854 * sufficient evidence of beeing a free device XXX */ 00855 tmp = ast_modem_new(p, AST_STATE_DOWN); 00856 restart_monitor(); 00857 break; 00858 } 00859 } else { 00860 if (!strcmp(dev, p->dev + 5)) { 00861 if (p->mc->formats & format) { 00862 if (!p->owner) { 00863 tmp = ast_modem_new(p, AST_STATE_DOWN); 00864 restart_monitor(); 00865 break; 00866 } else 00867 ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev); 00868 } else 00869 ast_log(LOG_WARNING, "Asked for a format %s line on %s\n", ast_getformatname(format), p->dev); 00870 break; 00871 } 00872 } 00873 p = p->next; 00874 } 00875 if (!p) 00876 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev); 00877 00878 ast_mutex_unlock(&iflock); 00879 return tmp; 00880 }
|
|
Definition at line 375 of file chan_modem.c. References ast_log(), ast_modem_expect(), ast_modem_read_response(), ast_modem_send(), ast_modem_trim(), ast_verbose(), ast_modem_driver::decusecnt, ast_modem_pvt::dev, ECHO_TIMEOUT, find_capability(), find_driver(), free, ast_modem_driver::identify, ast_modem_driver::init, ast_modem_pvt::initstr, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::mc, mtype, ast_modem_driver::name, option_debug, option_verbose, ast_modem_pvt::response, and VERBOSE_PREFIX_3. Referenced by mkif(). 00376 { 00377 00378 /* Make sure there's a modem there and that it's in a reasonable 00379 mode. Set the baud rate, etc. */ 00380 char identity[256]; 00381 char *ident = NULL; 00382 char etx[2] = { 0x10, '!' }; 00383 if (option_debug) 00384 ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev); 00385 if (ast_modem_send(p, etx, 2)) { 00386 ast_log(LOG_WARNING, "Failed to send ETX?\n"); 00387 return -1; 00388 } 00389 if (ast_modem_send(p, "\r\n", 2)) { 00390 ast_log(LOG_WARNING, "Failed to send enter?\n"); 00391 return -1; 00392 } 00393 usleep(10000); 00394 /* Read any outstanding stuff */ 00395 while(!ast_modem_read_response(p, 0)); 00396 if (ast_modem_send(p, "ATZ", 0)) { 00397 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev); 00398 return -1; 00399 } 00400 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) { 00401 ast_log(LOG_WARNING, "Modem reset failed: %s\n", p->response); 00402 return -1; 00403 } 00404 if (ast_modem_send(p, p->initstr, 0)) { 00405 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev); 00406 return -1; 00407 } 00408 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) { 00409 ast_log(LOG_WARNING, "Modem initialization failed: %s\n", p->response); 00410 return -1; 00411 } 00412 if (ast_modem_send(p, "ATI3", 0)) { 00413 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev); 00414 return -1; 00415 } 00416 if (ast_modem_read_response(p, ECHO_TIMEOUT)) { 00417 ast_log(LOG_WARNING, "Modem did not provide identification\n"); 00418 return -1; 00419 } 00420 strncpy(identity, p->response, sizeof(identity)-1); 00421 ast_modem_trim(identity); 00422 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) { 00423 ast_log(LOG_WARNING, "Modem did not provide identification\n"); 00424 return -1; 00425 } 00426 if (!strcasecmp(mtype, "autodetect")) { 00427 p->mc = find_capability(identity); 00428 if (!p->mc) { 00429 ast_log(LOG_WARNING, "Unable to autodetect modem. You'll need to specify a driver in modem.conf. Please report modem identification (%s) and which driver works to markster@linux-support.net.\n", identity); 00430 return -1; 00431 } 00432 } else { 00433 p->mc = find_driver(mtype); 00434 if (!p->mc) { 00435 ast_log(LOG_WARNING, "No driver for modem type '%s'\n", mtype); 00436 return -1; 00437 } 00438 } 00439 if (p->mc->init) { 00440 if (p->mc->init(p)) { 00441 ast_log(LOG_WARNING, "Modem Initialization Failed on '%s', driver %s.\n", p->dev, p->mc->name); 00442 p->mc->decusecnt(); 00443 return -1; 00444 } 00445 } 00446 if (option_verbose > 2) { 00447 ast_verbose(VERBOSE_PREFIX_3 "Configured modem %s with driver %s (%s)\n", p->dev, p->mc->name, p->mc->identify ? (ident = p->mc->identify(p)) : "No identification"); 00448 } 00449 if (ident) 00450 free(ident); 00451 return 0; 00452 }
|
|
Definition at line 524 of file chan_modem.c. References AST_STATE_UP, ast_modem_pvt::mc, and ast_modem_driver::write. 00525 { 00526 int res=0; 00527 long flags; 00528 struct ast_modem_pvt *p = ast->tech_pvt; 00529 00530 /* Modems tend to get upset when they receive data whilst in 00531 * command mode. This makes esp. dial commands short lived. 00532 * Pauline Middelink - 2002-09-24 */ 00533 if (ast->_state != AST_STATE_UP) 00534 return 0; 00535 00536 /* Temporarily make non-blocking */ 00537 flags = fcntl(ast->fds[0], F_GETFL); 00538 fcntl(ast->fds[0], F_SETFL, flags | O_NONBLOCK); 00539 00540 if (p->mc->write) 00541 res = p->mc->write(p, frame); 00542 00543 /* Block again */ 00544 fcntl(ast->fds[0], F_SETFL, flags); 00545 return res; 00546 }
|
|
Definition at line 700 of file chan_modem.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, LOG_WARNING, and monitor_thread. 00701 { 00702 /* If we're supposed to be stopped -- stay stopped */ 00703 if (monitor_thread == AST_PTHREADT_STOP) 00704 return 0; 00705 if (ast_mutex_lock(&monlock)) { 00706 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 00707 return -1; 00708 } 00709 if (monitor_thread == pthread_self()) { 00710 ast_mutex_unlock(&monlock); 00711 ast_log(LOG_WARNING, "Cannot kill myself\n"); 00712 return -1; 00713 } 00714 if (monitor_thread != AST_PTHREADT_NULL) { 00715 pthread_kill(monitor_thread, SIGURG); 00716 pthread_join(monitor_thread, NULL); 00717 } else { 00718 /* Start a new monitor */ 00719 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) { 00720 ast_mutex_unlock(&monlock); 00721 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 00722 return -1; 00723 } 00724 } 00725 ast_mutex_unlock(&monlock); 00726 return 0; 00727 }
|
|
Definition at line 729 of file chan_modem.c. References ast_log(), ast_modem_pvt::dev, ECHO, ast_modem_pvt::fd, and LOG_WARNING. Referenced by mkif(). 00730 { 00731 struct termios mode; 00732 memset(&mode, 0, sizeof(mode)); 00733 if (tcgetattr(p->fd, &mode)) { 00734 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno)); 00735 return; 00736 } 00737 #ifndef SOLARIS 00738 cfmakeraw(&mode); 00739 #else 00740 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP 00741 |INLCR|IGNCR|ICRNL|IXON); 00742 mode.c_oflag &= ~OPOST; 00743 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); 00744 mode.c_cflag &= ~(CSIZE|PARENB); 00745 mode.c_cflag |= CS8; 00746 #endif 00747 00748 cfsetispeed(&mode, B115200); 00749 cfsetospeed(&mode, B115200); 00750 if (tcsetattr(p->fd, TCSANOW, &mode)) 00751 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno)); 00752 00753 }
|
|
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 971 of file chan_modem.c. References __unload_module(). 00972 { 00973 return __unload_module(); 00974 }
|
|
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 1097 of file chan_modem.c. References usecnt. 01098 { 01099 return usecnt; 01100 }
|
|
Definition at line 96 of file chan_modem.c. Referenced by mkif(). |
|
Definition at line 60 of file chan_modem.c. |
|
Definition at line 67 of file chan_modem.c. |
|
Definition at line 92 of file chan_modem.c. Referenced by load_module(), mkif(), mkintf(), and setup_zap(). |
|
Definition at line 115 of file chan_modem.c. Referenced by curl_exec(), cut_exec(), dundi_lookup_exec(), enumlookup_exec(), eval_exec(), get_exec(), hasvoicemail_exec(), load_moh_classes(), md5_exec(), md5check_exec(), modem_request(), put_exec(), sip_getheader(), sort_exec(), and txtcidname_exec(). |
|
Definition at line 57 of file chan_modem.c. |
|
Definition at line 61 of file chan_modem.c. Referenced by load_module(), and mkif(). |
|
Definition at line 155 of file chan_modem.c. |
|
Definition at line 86 of file chan_modem.c. Referenced by adsi_channel_restore(), adsi_load_session(), adsi_unload_session(), background_detect_exec(), conf_run(), and ss_thread(). |
|
Definition at line 82 of file chan_modem.c. |
|
Definition at line 84 of file chan_modem.c. Referenced by load_module(), and mkif(). |
|
Definition at line 62 of file chan_modem.c. Referenced by load_module(), and mkif(). |
|
Definition at line 143 of file chan_modem.c. |
|
Definition at line 79 of file chan_modem.c. Referenced by load_module(), and mkif(). |
|
Definition at line 73 of file chan_modem.c. Referenced by load_module(), and mkif(). |
|
Definition at line 70 of file chan_modem.c. |
|
Definition at line 126 of file chan_modem.c. |
|
Definition at line 111 of file chan_modem.c. |
|
Definition at line 76 of file chan_modem.c. Referenced by load_module(), and mkif(). |
|
Definition at line 65 of file chan_modem.c. Referenced by load_module(), and modem_setup(). |
|
Definition at line 89 of file chan_modem.c. Referenced by load_module(), and mkif(). |
|
Definition at line 98 of file chan_modem.c. Referenced by load_module(), mkif(), mkintf(), and setup_zap(). |
|
Definition at line 58 of file chan_modem.c. |
|
Definition at line 59 of file chan_modem.c. |
|
Definition at line 94 of file chan_modem.c. |