#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 924 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, iflist, LOG_WARNING, modem_tech, ast_modem_pvt::next, and ast_modem_pvt::owner. 00925 { 00926 struct ast_modem_pvt *p, *pl; 00927 /* First, take us out of the channel loop */ 00928 ast_channel_unregister(&modem_tech); 00929 if (!ast_mutex_lock(&iflock)) { 00930 /* Hangup all interfaces if they have an owner */ 00931 p = iflist; 00932 while(p) { 00933 if (p->owner) 00934 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 00935 p = p->next; 00936 } 00937 iflist = NULL; 00938 ast_mutex_unlock(&iflock); 00939 } else { 00940 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 00941 return -1; 00942 } 00943 if (!ast_mutex_lock(&monlock)) { 00944 if (monitor_thread != AST_PTHREADT_NULL && monitor_thread != AST_PTHREADT_STOP) { 00945 pthread_cancel(monitor_thread); 00946 pthread_join(monitor_thread, NULL); 00947 } 00948 monitor_thread = AST_PTHREADT_STOP; 00949 ast_mutex_unlock(&monlock); 00950 } else { 00951 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 00952 return -1; 00953 } 00954 00955 if (!ast_mutex_lock(&iflock)) { 00956 /* Destroy all the interfaces and free their memory */ 00957 p = iflist; 00958 while(p) { 00959 /* Close the socket, assuming it's real */ 00960 if (p->fd > -1) 00961 close(p->fd); 00962 pl = p; 00963 p = p->next; 00964 /* Free associated memory */ 00965 free(pl); 00966 } 00967 iflist = NULL; 00968 ast_mutex_unlock(&iflock); 00969 } else { 00970 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 00971 return -1; 00972 } 00973 00974 return 0; 00975 }
|
|
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 0 00358 fprintf(stderr, "Modem said: %s", p->response); 00359 #endif 00360 if (!strncasecmp(p->response, result, strlen(result))) 00361 return 0; 00362 } while(timeout > 0); 00363 return -1; 00364 }
|
|
|
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(), ast_modem_pvt::f, ast_modem_pvt::fd, and ast_modem_pvt::response. 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_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 366 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(). 00367 { 00368 int x; 00369 x = strlen(s) - 1; 00370 while(x >= 0) { 00371 if ((s[x] != '\r') && (s[x] != '\n') && (s[x] != ' ')) 00372 break; 00373 s[x] = '\0'; 00374 x--; 00375 } 00376 }
|
|
|
|
|
|
|
|
Register a driver Definition at line 194 of file chan_modem.c. References drivers, and ast_modem_driver::next. Referenced by load_module().
|
|
Unregister a driver Definition at line 201 of file chan_modem.c. References drivers, 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 1108 of file chan_modem.c. 01109 { 01110 return (char *) desc; 01111 }
|
|
Definition at line 617 of file chan_modem.c. References ast_log(), ast_mutex_lock(), LOG_ERROR, LOG_WARNING, and n. 00618 { 00619 fd_set rfds, efds; 00620 int n, res; 00621 struct ast_modem_pvt *i; 00622 /* This thread monitors all the frame relay interfaces which are not yet in use 00623 (and thus do not have a separate thread) indefinitely */ 00624 /* From here on out, we die whenever asked */ 00625 #if 0 00626 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) { 00627 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n"); 00628 return NULL; 00629 } 00630 #endif 00631 for(;;) { 00632 /* Don't let anybody kill us right away. Nobody should lock the interface list 00633 and wait for the monitor list, but the other way around is okay. */ 00634 if (ast_mutex_lock(&monlock)) { 00635 ast_log(LOG_ERROR, "Unable to grab monitor lock\n"); 00636 return NULL; 00637 } 00638 /* Lock the interface list */ 00639 if (ast_mutex_lock(&iflock)) { 00640 ast_log(LOG_ERROR, "Unable to grab interface lock\n"); 00641 ast_mutex_unlock(&monlock); 00642 return NULL; 00643 } 00644 /* Build the stuff we're going to select on, that is the socket of every 00645 ast_modem_pvt that does not have an associated owner channel */ 00646 n = -1; 00647 FD_ZERO(&rfds); 00648 FD_ZERO(&efds); 00649 i = iflist; 00650 while(i) { 00651 if (FD_ISSET(i->fd, &rfds)) 00652 ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev); 00653 if (!i->owner) { 00654 /* This needs to be watched, as it lacks an owner */ 00655 FD_SET(i->fd, &rfds); 00656 FD_SET(i->fd, &efds); 00657 if (i->fd > n) 00658 n = i->fd; 00659 } 00660 00661 i = i->next; 00662 } 00663 /* Okay, now that we know what to do, release the interface lock */ 00664 ast_mutex_unlock(&iflock); 00665 00666 /* And from now on, we're okay to be killed, so release the monitor lock as well */ 00667 ast_mutex_unlock(&monlock); 00668 #if 0 00669 ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid()); 00670 #endif 00671 /* Wait indefinitely for something to happen */ 00672 pthread_testcancel(); 00673 res = ast_select(n + 1, &rfds, NULL, &efds, NULL); 00674 pthread_testcancel(); 00675 /* Okay, select has finished. Let's see what happened. */ 00676 if (res < 1) { 00677 if ((errno != EINTR) && (errno != EAGAIN)) 00678 ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno)); 00679 continue; 00680 } 00681 /* Alright, lock the interface list again, and let's look and see what has 00682 happened */ 00683 if (ast_mutex_lock(&iflock)) { 00684 ast_log(LOG_WARNING, "Unable to lock the interface list\n"); 00685 continue; 00686 } 00687 i = iflist; 00688 while(i) { 00689 if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) { 00690 if (i->owner) { 00691 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d, %s)...\n", i->fd, i->dev); 00692 i = i->next; 00693 continue; 00694 } 00695 modem_mini_packet(i); 00696 } 00697 i=i->next; 00698 } 00699 ast_mutex_unlock(&iflock); 00700 } 00701 /* Never reached */ 00702 return NULL; 00703 00704 }
|
|
Definition at line 157 of file chan_modem.c. References drivers, 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 drivers, ast_modem_driver::incusecnt, 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 888 of file chan_modem.c. References ast_log(), ast_strdupa, copy(), group, LOG_ERROR, LOG_WARNING, and strsep(). Referenced by load_module(). 00889 { 00890 char *piece; 00891 int start, finish,x; 00892 ast_group_t group = 0; 00893 char *copy = ast_strdupa(s); 00894 char *stringp=NULL; 00895 if (!copy) { 00896 ast_log(LOG_ERROR, "Out of memory\n"); 00897 return 0; 00898 } 00899 stringp=copy; 00900 piece = strsep(&stringp, ","); 00901 while(piece) { 00902 if (sscanf(piece, "%d-%d", &start, &finish) == 2) { 00903 /* Range */ 00904 } else if (sscanf(piece, "%d", &start)) { 00905 /* Just one */ 00906 finish = start; 00907 } else { 00908 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'. Using '0'\n", s,piece); 00909 return 0; 00910 } 00911 piece = strsep(&stringp, ","); 00912 00913 for (x=start;x<=finish;x++) { 00914 if ((x > 63) || (x < 0)) { 00915 ast_log(LOG_WARNING, "Ignoring invalid group %d\n", x); 00916 break; 00917 } 00918 group |= (1 << x); 00919 } 00920 } 00921 return group; 00922 }
|
|
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 1113 of file chan_modem.c. References ASTERISK_GPL_KEY. 01114 { 01115 return ASTERISK_GPL_KEY; 01116 }
|
|
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 982 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, get_group(), iflist, 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, modem_tech, ast_variable::name, ast_variable::next, ast_modem_pvt::next, option_verbose, restart_monitor(), ast_variable::value, and VERBOSE_PREFIX_2. 00983 { 00984 struct ast_config *cfg; 00985 struct ast_variable *v; 00986 struct ast_modem_pvt *tmp; 00987 char driver[80]; 00988 cfg = ast_config_load(config); 00989 00990 /* We *must* have a config file otherwise stop immediately */ 00991 if (!cfg) { 00992 ast_log(LOG_ERROR, "Unable to load config %s\n", config); 00993 return -1; 00994 } 00995 if (ast_mutex_lock(&iflock)) { 00996 /* It's a little silly to lock it, but we mind as well just to be sure */ 00997 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 00998 return -1; 00999 } 01000 v = ast_variable_browse(cfg, "interfaces"); 01001 while(v) { 01002 /* Create the interface list */ 01003 if (!strcasecmp(v->name, "device")) { 01004 tmp = mkif(v->value); 01005 if (tmp) { 01006 tmp->next = iflist; 01007 iflist = tmp; 01008 01009 } else { 01010 ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value); 01011 ast_config_destroy(cfg); 01012 ast_mutex_unlock(&iflock); 01013 __unload_module(); 01014 return -1; 01015 } 01016 } else if (!strcasecmp(v->name, "driver")) { 01017 snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value); 01018 if (option_verbose > 1) 01019 ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver); 01020 01021 if (ast_load_resource(driver)) { 01022 ast_log(LOG_ERROR, "Failed to load driver %s\n", driver); 01023 ast_config_destroy(cfg); 01024 ast_mutex_unlock(&iflock); 01025 __unload_module(); 01026 return -1; 01027 } 01028 } else if (!strcasecmp(v->name, "mode")) { 01029 if (!strncasecmp(v->value, "ri", 2)) 01030 gmode = MODEM_MODE_WAIT_RING; 01031 else if (!strncasecmp(v->value, "im", 2)) 01032 gmode = MODEM_MODE_IMMEDIATE; 01033 else if (!strncasecmp(v->value, "an", 2)) 01034 gmode = MODEM_MODE_WAIT_ANSWER; 01035 else 01036 ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value); 01037 } else if (!strcasecmp(v->name, "stripmsd")) { 01038 stripmsd = atoi(v->value); 01039 } else if (!strcasecmp(v->name, "type")) { 01040 strncpy(mtype, v->value, sizeof(mtype)-1); 01041 } else if (!strcasecmp(v->name, "initstr")) { 01042 strncpy(initstr, v->value, sizeof(initstr)-1); 01043 } else if (!strcasecmp(v->name, "dialtype")) { 01044 dialtype = toupper(v->value[0]); 01045 } else if (!strcasecmp(v->name, "context")) { 01046 strncpy(context, v->value, sizeof(context)-1); 01047 } else if (!strcasecmp(v->name, "msn")) { 01048 strncpy(msn, v->value, sizeof(msn)-1); 01049 } else if (!strcasecmp(v->name, "incomingmsn")) { 01050 strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1); 01051 } else if (!strcasecmp(v->name, "dtmfmode")) { 01052 char tmp[80]; 01053 char *alt; 01054 strncpy(tmp, v->value, sizeof(tmp) - 1); 01055 alt = strchr(tmp, '/'); 01056 if (!strcasecmp(tmp, "none")) 01057 dtmfmode=MODEM_DTMF_NONE; 01058 else if (!strcasecmp(tmp, "asterisk")) 01059 dtmfmode = MODEM_DTMF_AST; 01060 else if (!strcasecmp(tmp, "i4l")) 01061 dtmfmode = MODEM_DTMF_I4L; 01062 else { 01063 ast_log(LOG_WARNING, "Unknown dtmf detection mode '%s', using 'asterisk'\n", v->value); 01064 dtmfmode = MODEM_DTMF_AST; 01065 } 01066 if (alt) { 01067 if (!strcasecmp(alt, "none")) 01068 dtmfmodegen=MODEM_DTMF_NONE; 01069 else if (!strcasecmp(alt, "asterisk")) 01070 dtmfmodegen = MODEM_DTMF_AST; 01071 else if (!strcasecmp(alt, "i4l")) 01072 dtmfmodegen = MODEM_DTMF_I4L; 01073 else if (!strcasecmp(alt, "both")) 01074 dtmfmodegen = MODEM_DTMF_I4L | MODEM_DTMF_AST; 01075 else { 01076 ast_log(LOG_WARNING, "Unknown dtmf generation mode '%s', using 'asterisk'\n", v->value); 01077 dtmfmodegen = MODEM_DTMF_AST; 01078 } 01079 } else 01080 dtmfmodegen = dtmfmode; 01081 } else if (!strcasecmp(v->name, "outgoingmsn")) { 01082 strncpy(outgoingmsn, v->value, sizeof(outgoingmsn)-1); 01083 } else if (!strcasecmp(v->name, "language")) { 01084 strncpy(language, v->value, sizeof(language)-1); 01085 } else if (!strcasecmp(v->name, "group")) { 01086 cur_group = get_group(v->value); 01087 } 01088 v = v->next; 01089 } 01090 ast_mutex_unlock(&iflock); 01091 if (ast_channel_register(&modem_tech)) { 01092 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); 01093 ast_config_destroy(cfg); 01094 __unload_module(); 01095 return -1; 01096 } 01097 ast_config_destroy(cfg); 01098 /* And start the monitor for the first time */ 01099 restart_monitor(); 01100 return 0; 01101 }
|
|
Definition at line 761 of file chan_modem.c. References ast_log(), free, LOG_WARNING, malloc, modem_setup(), and stty(). Referenced by load_module(). 00762 { 00763 /* Make a ast_modem_pvt structure for this interface */ 00764 struct ast_modem_pvt *tmp; 00765 #if 0 00766 int flags; 00767 #endif 00768 00769 tmp = malloc(sizeof(struct ast_modem_pvt)); 00770 if (tmp) { 00771 memset(tmp, 0, sizeof(struct ast_modem_pvt)); 00772 tmp->fd = open(iface, O_RDWR | O_NONBLOCK); 00773 if (tmp->fd < 0) { 00774 ast_log(LOG_WARNING, "Unable to open '%s'\n", iface); 00775 free(tmp); 00776 return NULL; 00777 } 00778 strncpy(tmp->language, language, sizeof(tmp->language)-1); 00779 strncpy(tmp->msn, msn, sizeof(tmp->msn)-1); 00780 strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1); 00781 tmp->dtmfmode = dtmfmode; 00782 tmp->dtmfmodegen = dtmfmodegen; 00783 snprintf(tmp->outgoingmsn, sizeof(tmp->outgoingmsn), ",%s,", outgoingmsn); 00784 strncpy(tmp->dev, iface, sizeof(tmp->dev)-1); 00785 /* Maybe in the future we want to allow variable 00786 serial settings */ 00787 stty(tmp); 00788 tmp->f = fdopen(tmp->fd, "w+"); 00789 /* Disable buffering */ 00790 setvbuf(tmp->f, NULL, _IONBF,0); 00791 if (tmp->f < 0) { 00792 ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface); 00793 free(tmp); 00794 return NULL; 00795 } 00796 tmp->owner = NULL; 00797 tmp->ministate = 0; 00798 tmp->stripmsd = stripmsd; 00799 tmp->dialtype = dialtype; 00800 tmp->mode = gmode; 00801 tmp->group = cur_group; 00802 memset(tmp->cid_num, 0, sizeof(tmp->cid_num)); 00803 memset(tmp->cid_name, 0, sizeof(tmp->cid_name)); 00804 strncpy(tmp->context, context, sizeof(tmp->context)-1); 00805 strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1); 00806 tmp->next = NULL; 00807 tmp->obuflen = 0; 00808 00809 if (modem_setup(tmp, baudrate) < 0) { 00810 ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface); 00811 free(tmp); 00812 return NULL; 00813 } 00814 } 00815 return tmp; 00816 }
|
|
Definition at line 488 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. 00489 { 00490 struct ast_modem_pvt *p; 00491 int res=0; 00492 if (option_debug) 00493 ast_log(LOG_DEBUG, "modem_answer(%s)\n", ast->name); 00494 p = ast->tech_pvt; 00495 if (p->mc->answer) { 00496 res = p->mc->answer(p); 00497 } 00498 if (!res) { 00499 ast->rings = 0; 00500 ast_setstate(ast, AST_STATE_UP); 00501 } 00502 return res; 00503 }
|
|
Definition at line 218 of file chan_modem.c. References ast_channel::_state, 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_channel::name, ast_modem_driver::setdev, ast_modem_pvt::stripmsd, strsep(), and ast_channel::tech_pvt. 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 551 of file chan_modem.c. References ast_log(), LOG_WARNING, ast_modem_pvt::owner, and ast_channel::tech_pvt. 00552 { 00553 struct ast_modem_pvt *p = newchan->tech_pvt; 00554 ast_log(LOG_WARNING, "fixup called\n"); 00555 if (p->owner!=oldchan) { 00556 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n",oldchan,p->owner); 00557 return -1; 00558 } 00559 p->owner = newchan; 00560 return 0; 00561 }
|
|
|
Definition at line 605 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. 00606 { 00607 struct ast_frame *fr; 00608 fr = i->mc->read(i); 00609 if (!fr) return; 00610 if (fr->frametype == AST_FRAME_CONTROL) { 00611 if (fr->subclass == AST_CONTROL_RING) { 00612 ast_modem_new(i, AST_STATE_RING); 00613 } 00614 } 00615 }
|
|
Definition at line 518 of file chan_modem.c. References ast_modem_pvt::mc, ast_modem_driver::read, and ast_channel::tech_pvt. Referenced by modem_call(). 00519 { 00520 struct ast_modem_pvt *p = ast->tech_pvt; 00521 struct ast_frame *fr=NULL; 00522 if (p->mc->read) 00523 fr = p->mc->read(p); 00524 return fr; 00525 }
|
|
Definition at line 818 of file chan_modem.c. References ast_getformatname(), ast_log(), ast_modem_new(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, ast_modem_pvt::dev, ast_modem_driver::formats, ast_modem_pvt::group, group, iflist, LOG_ERROR, LOG_WARNING, ast_modem_pvt::mc, ast_modem_pvt::next, ast_modem_pvt::owner, restart_monitor(), and strsep(). 00819 { 00820 int oldformat; 00821 struct ast_modem_pvt *p; 00822 struct ast_channel *tmp = NULL; 00823 char dev[80]; 00824 ast_group_t group = 0; 00825 int groupint; 00826 char *stringp=NULL; 00827 strncpy(dev, (char *)data, sizeof(dev)-1); 00828 stringp=dev; 00829 strsep(&stringp, ":"); 00830 oldformat = format; 00831 00832 if (!dep_warning) { 00833 ast_log(LOG_WARNING, "This channel driver is deprecated. Please see the UPGRADE.txt file.\n"); 00834 dep_warning = 1; 00835 } 00836 00837 if (dev[0]=='g' && isdigit(dev[1])) { 00838 /* Retrieve the group number */ 00839 if (sscanf(dev+1, "%u", &groupint) < 1) { 00840 ast_log(LOG_WARNING, "Unable to determine group from [%s]\n", (char *)data); 00841 return NULL; 00842 } 00843 group = 1 << groupint; 00844 } 00845 00846 /* Search for an unowned channel */ 00847 if (ast_mutex_lock(&iflock)) { 00848 ast_log(LOG_ERROR, "Unable to lock interface list???\n"); 00849 return NULL; 00850 } 00851 p = iflist; 00852 while(p) { 00853 if (group) { 00854 /* if it belongs to the proper group, and the format matches 00855 * and it is not in use, we found a candidate! */ 00856 if (p->group & group && 00857 p->mc->formats & format && 00858 !p->owner) { 00859 /* XXX Not quite sure that not having an owner is 00860 * sufficient evidence of beeing a free device XXX */ 00861 tmp = ast_modem_new(p, AST_STATE_DOWN); 00862 restart_monitor(); 00863 break; 00864 } 00865 } else { 00866 if (!strcmp(dev, p->dev + 5)) { 00867 if (p->mc->formats & format) { 00868 if (!p->owner) { 00869 tmp = ast_modem_new(p, AST_STATE_DOWN); 00870 restart_monitor(); 00871 break; 00872 } else 00873 ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev); 00874 } else 00875 ast_log(LOG_WARNING, "Asked for a format %s line on %s\n", ast_getformatname(format), p->dev); 00876 break; 00877 } 00878 } 00879 p = p->next; 00880 } 00881 if (!p) 00882 ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev); 00883 00884 ast_mutex_unlock(&iflock); 00885 return tmp; 00886 }
|
|
Definition at line 378 of file chan_modem.c. References ast_log(), ast_modem_expect(), ast_modem_read_response(), ast_modem_send(), ast_modem_trim(), ast_modem_driver::decusecnt, ast_modem_pvt::dev, ECHO_TIMEOUT, find_capability(), find_driver(), ast_modem_driver::init, ast_modem_pvt::initstr, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::mc, ast_modem_driver::name, option_debug, and ast_modem_pvt::response. Referenced by mkif(). 00379 { 00380 00381 /* Make sure there's a modem there and that it's in a reasonable 00382 mode. Set the baud rate, etc. */ 00383 char identity[256]; 00384 char *ident = NULL; 00385 char etx[2] = { 0x10, '!' }; 00386 if (option_debug) 00387 ast_log(LOG_DEBUG, "Setting up modem %s\n", p->dev); 00388 if (ast_modem_send(p, etx, 2)) { 00389 ast_log(LOG_WARNING, "Failed to send ETX?\n"); 00390 return -1; 00391 } 00392 if (ast_modem_send(p, "\r\n", 2)) { 00393 ast_log(LOG_WARNING, "Failed to send enter?\n"); 00394 return -1; 00395 } 00396 usleep(10000); 00397 /* Read any outstanding stuff */ 00398 while(!ast_modem_read_response(p, 0)); 00399 if (ast_modem_send(p, "ATZ", 0)) { 00400 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev); 00401 return -1; 00402 } 00403 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) { 00404 ast_log(LOG_WARNING, "Modem reset failed: %s\n", p->response); 00405 return -1; 00406 } 00407 if (ast_modem_send(p, p->initstr, 0)) { 00408 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev); 00409 return -1; 00410 } 00411 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) { 00412 ast_log(LOG_WARNING, "Modem initialization failed: %s\n", p->response); 00413 return -1; 00414 } 00415 if (ast_modem_send(p, "ATI3", 0)) { 00416 ast_log(LOG_WARNING, "Modem not responding on %s\n", p->dev); 00417 return -1; 00418 } 00419 if (ast_modem_read_response(p, ECHO_TIMEOUT)) { 00420 ast_log(LOG_WARNING, "Modem did not provide identification\n"); 00421 return -1; 00422 } 00423 strncpy(identity, p->response, sizeof(identity)-1); 00424 ast_modem_trim(identity); 00425 if (ast_modem_expect(p, "OK", ECHO_TIMEOUT)) { 00426 ast_log(LOG_WARNING, "Modem did not provide identification\n"); 00427 return -1; 00428 } 00429 if (!strcasecmp(mtype, "autodetect")) { 00430 p->mc = find_capability(identity); 00431 if (!p->mc) { 00432 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); 00433 return -1; 00434 } 00435 } else { 00436 p->mc = find_driver(mtype); 00437 if (!p->mc) { 00438 ast_log(LOG_WARNING, "No driver for modem type '%s'\n", mtype); 00439 return -1; 00440 } 00441 } 00442 if (p->mc->init) { 00443 if (p->mc->init(p)) { 00444 ast_log(LOG_WARNING, "Modem Initialization Failed on '%s', driver %s.\n", p->dev, p->mc->name); 00445 p->mc->decusecnt(); 00446 return -1; 00447 } 00448 } 00449 if (option_verbose > 2) { 00450 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"); 00451 } 00452 if (ident) 00453 free(ident); 00454 return 0; 00455 }
|
|
Definition at line 527 of file chan_modem.c. References ast_channel::_state, AST_STATE_UP, ast_channel::fds, ast_modem_pvt::mc, ast_channel::tech_pvt, and ast_modem_driver::write. 00528 { 00529 int res=0; 00530 long flags; 00531 struct ast_modem_pvt *p = ast->tech_pvt; 00532 00533 /* Modems tend to get upset when they receive data whilst in 00534 * command mode. This makes esp. dial commands short lived. 00535 * Pauline Middelink - 2002-09-24 */ 00536 if (ast->_state != AST_STATE_UP) 00537 return 0; 00538 00539 /* Temporarily make non-blocking */ 00540 flags = fcntl(ast->fds[0], F_GETFL); 00541 fcntl(ast->fds[0], F_SETFL, flags | O_NONBLOCK); 00542 00543 if (p->mc->write) 00544 res = p->mc->write(p, frame); 00545 00546 /* Block again */ 00547 fcntl(ast->fds[0], F_SETFL, flags); 00548 return res; 00549 }
|
|
Definition at line 706 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, and LOG_WARNING. 00707 { 00708 /* If we're supposed to be stopped -- stay stopped */ 00709 if (monitor_thread == AST_PTHREADT_STOP) 00710 return 0; 00711 if (ast_mutex_lock(&monlock)) { 00712 ast_log(LOG_WARNING, "Unable to lock monitor\n"); 00713 return -1; 00714 } 00715 if (monitor_thread == pthread_self()) { 00716 ast_mutex_unlock(&monlock); 00717 ast_log(LOG_WARNING, "Cannot kill myself\n"); 00718 return -1; 00719 } 00720 if (monitor_thread != AST_PTHREADT_NULL) { 00721 pthread_kill(monitor_thread, SIGURG); 00722 pthread_join(monitor_thread, NULL); 00723 } else { 00724 /* Start a new monitor */ 00725 if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) { 00726 ast_mutex_unlock(&monlock); 00727 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 00728 return -1; 00729 } 00730 } 00731 ast_mutex_unlock(&monlock); 00732 return 0; 00733 }
|
|
Definition at line 735 of file chan_modem.c. References ast_log(), ast_modem_pvt::dev, ECHO, ast_modem_pvt::fd, and LOG_WARNING. Referenced by mkif(). 00736 { 00737 struct termios mode; 00738 memset(&mode, 0, sizeof(mode)); 00739 if (tcgetattr(p->fd, &mode)) { 00740 ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno)); 00741 return; 00742 } 00743 #ifndef SOLARIS 00744 cfmakeraw(&mode); 00745 #else 00746 mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP 00747 |INLCR|IGNCR|ICRNL|IXON); 00748 mode.c_oflag &= ~OPOST; 00749 mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); 00750 mode.c_cflag &= ~(CSIZE|PARENB); 00751 mode.c_cflag |= CS8; 00752 #endif 00753 00754 cfsetispeed(&mode, B115200); 00755 cfsetospeed(&mode, B115200); 00756 if (tcsetattr(p->fd, TCSANOW, &mode)) 00757 ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno)); 00758 00759 }
|
|
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 977 of file chan_modem.c. References __unload_module(). 00978 { 00979 return __unload_module(); 00980 }
|
|
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 1103 of file chan_modem.c. 01104 { 01105 return usecnt; 01106 }
|
|
Definition at line 96 of file chan_modem.c. |
|
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. |
|
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(), 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. |
|
Definition at line 155 of file chan_modem.c. Referenced by ast_register_modem_driver(), ast_unregister_modem_driver(), find_capability(), and find_driver(). |
|
|
Definition at line 82 of file chan_modem.c. |
|
Definition at line 84 of file chan_modem.c. |
|
Definition at line 62 of file chan_modem.c. |
|
Definition at line 143 of file chan_modem.c. |
|
Definition at line 79 of file chan_modem.c. |
|
Definition at line 73 of file chan_modem.c. |
|
Definition at line 70 of file chan_modem.c. |
|
Definition at line 126 of file chan_modem.c. Referenced by __unload_module(), ast_modem_new(), and load_module(). |
|
Definition at line 111 of file chan_modem.c. |
|
Definition at line 76 of file chan_modem.c. |
|
Definition at line 65 of file chan_modem.c. |
|
Definition at line 89 of file chan_modem.c. |
|
Definition at line 98 of file chan_modem.c. |
|
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. |