Sun Aug 6 15:06:10 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

chan_modem.c File Reference

A/Open ITU-56/2 Voice Modem Driver (Rockwell, IS-101, and others). More...

#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_channelast_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_driverfind_capability (char *ident)
static struct ast_modem_driverfind_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_pvtmkif (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_framemodem_read (struct ast_channel *)
static struct ast_channelmodem_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_driverdrivers = NULL
ast_dspdsp = NULL
static int dtmfmode = MODEM_DTMF_AST
static int dtmfmodegen = MODEM_DTMF_AST
static int gmode = MODEM_MODE_IMMEDIATE
static struct ast_modem_pvtiflist = 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


Detailed Description

A/Open ITU-56/2 Voice Modem Driver (Rockwell, IS-101, and others).

Definition in file chan_modem.c.


Define Documentation

#define ECHO_TIMEOUT   10
 

Definition at line 55 of file chan_modem.c.

Referenced by modem_setup().


Function Documentation

static int __unload_module void   )  [static]
 

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 }

int ast_modem_expect struct ast_modem_pvt p,
char *  result,
int  timeout
 

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 }

struct ast_channel* ast_modem_new struct ast_modem_pvt i,
int  state
 

Used by modem drivers to start up the PBX on a RING

Definition at line 560 of file chan_modem.c.

References ast_channel_alloc(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_set_callerid(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, ast_strlen_zero(), ast_update_use_count(), ast_modem_pvt::cid_name, ast_modem_pvt::cid_num, ast_modem_pvt::context, ast_channel::context, ast_modem_pvt::dev, ast_modem_pvt::dnid, ast_channel::exten, ast_modem_pvt::fd, ast_channel::fds, ast_modem_driver::formats, ast_channel::language, ast_modem_pvt::language, LOG_WARNING, ast_modem_pvt::mc, ast_modem_driver::name, ast_channel::name, ast_channel::nativeformats, ast_modem_pvt::owner, ast_channel::rings, ast_channel::tech, ast_channel::tech_pvt, type, ast_channel::type, usecnt, and usecnt_lock.

Referenced by modem_mini_packet(), and modem_request().

00561 {
00562    struct ast_channel *tmp;
00563    tmp = ast_channel_alloc(1);
00564    if (tmp) {
00565       tmp->tech = &modem_tech;
00566       snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
00567       tmp->type = type;
00568       tmp->fds[0] = i->fd;
00569       tmp->nativeformats = i->mc->formats;
00570       ast_setstate(tmp, state);
00571       if (state == AST_STATE_RING)
00572          tmp->rings = 1;
00573       tmp->tech_pvt = i;
00574       strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
00575 
00576       ast_set_callerid(tmp, i->cid_num, i->cid_name, i->cid_num);
00577 
00578       if (!ast_strlen_zero(i->language))
00579          strncpy(tmp->language,i->language, sizeof(tmp->language)-1);
00580       if (!ast_strlen_zero(i->dnid))
00581          strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
00582       i->owner = tmp;
00583       ast_mutex_lock(&usecnt_lock);
00584       usecnt++;
00585       ast_mutex_unlock(&usecnt_lock);
00586       ast_update_use_count();
00587       if (state != AST_STATE_DOWN) {
00588          if (ast_pbx_start(tmp)) {
00589             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00590             ast_hangup(tmp);
00591             tmp = NULL;
00592          }
00593       }
00594    } else
00595       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00596    return tmp;
00597 }

int ast_modem_read_response struct ast_modem_pvt p,
int  timeout
 

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 }

int ast_modem_send struct ast_modem_pvt p,
char *  cmd,
int  len
 

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 }

void ast_modem_trim char *  s  ) 
 

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 }

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  ) 
 

Register a driver

Definition at line 194 of file chan_modem.c.

Referenced by load_module().

00195 {
00196    mc->next = drivers;
00197    drivers = mc;
00198    return 0;
00199 }

int ast_unregister_modem_driver struct ast_modem_driver mc  ) 
 

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 }

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 1102 of file chan_modem.c.

References desc.

01103 {
01104    return (char *) desc;
01105 }

static void* do_monitor void *  data  )  [static]
 

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 }

static struct ast_modem_driver* find_capability char *  ident  )  [static]
 

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 }

static struct ast_modem_driver* find_driver char *  drv  )  [static]
 

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 }

static ast_group_t get_group char *  s  )  [static]
 

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 }

char* key void   ) 
 

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;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 1107 of file chan_modem.c.

References ASTERISK_GPL_KEY.

01108 {
01109    return ASTERISK_GPL_KEY;
01110 }

int load_module void   ) 
 

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.

Returns:
int Always 0.

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 }

static struct ast_modem_pvt* mkif char *  iface  )  [static]
 

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 }

static int modem_answer struct ast_channel ast  )  [static]
 

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 }

static int modem_call struct ast_channel ast,
char *  idest,
int  timeout
[static]
 

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 }

static int modem_digit struct ast_channel ast,
char  digit
[static]
 

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 }

static int modem_fixup struct ast_channel oldchan,
struct ast_channel newchan
[static]
 

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 }

static int modem_hangup struct ast_channel ast  )  [static]
 

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 }

static void modem_mini_packet struct ast_modem_pvt i  )  [static]
 

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 }

static struct ast_frame * modem_read struct ast_channel  )  [static]
 

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 }

static struct ast_channel * modem_request const char *  type,
int  format,
void *  data,
int *  cause
[static]
 

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 }

static int modem_setup struct ast_modem_pvt p,
int  baudrate
[static]
 

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 }

static int modem_write struct ast_channel ast,
struct ast_frame frame
[static]
 

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 }

static int restart_monitor void   )  [static]
 

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 }

static void stty struct ast_modem_pvt p  )  [static]
 

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 }

int unload_module void   ) 
 

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).

Returns:
Zero on success, or non-zero on error.

Definition at line 971 of file chan_modem.c.

References __unload_module().

00972 {
00973    return __unload_module();
00974 }

int usecount void   ) 
 

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.

Returns:
The module's usecount.

Definition at line 1097 of file chan_modem.c.

References usecnt.

01098 {
01099    return usecnt;
01100 }


Variable Documentation

int baudrate = 115200 [static]
 

Definition at line 96 of file chan_modem.c.

Referenced by mkif().

const char config[] = "modem.conf" [static]
 

Definition at line 60 of file chan_modem.c.

char context[AST_MAX_EXTENSION] = "default" [static]
 

Definition at line 67 of file chan_modem.c.

ast_group_t cur_group = 0 [static]
 

Definition at line 92 of file chan_modem.c.

Referenced by load_module(), mkif(), mkintf(), and setup_zap().

int dep_warning = 0
 

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().

const char desc[] = "Generic Voice Modem Driver" [static]
 

Definition at line 57 of file chan_modem.c.

char dialtype = 'T' [static]
 

Definition at line 61 of file chan_modem.c.

Referenced by load_module(), and mkif().

struct ast_modem_driver* drivers = NULL [static]
 

Definition at line 155 of file chan_modem.c.

struct ast_dsp* dsp = NULL
 

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().

int dtmfmode = MODEM_DTMF_AST [static]
 

Definition at line 82 of file chan_modem.c.

int dtmfmodegen = MODEM_DTMF_AST [static]
 

Definition at line 84 of file chan_modem.c.

Referenced by load_module(), and mkif().

int gmode = MODEM_MODE_IMMEDIATE [static]
 

Definition at line 62 of file chan_modem.c.

Referenced by load_module(), and mkif().

struct ast_modem_pvt* iflist = NULL [static]
 

Definition at line 143 of file chan_modem.c.

char incomingmsn[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 79 of file chan_modem.c.

Referenced by load_module(), and mkif().

char initstr[AST_MAX_INIT_STR] = "ATE0Q0" [static]
 

Definition at line 73 of file chan_modem.c.

Referenced by load_module(), and mkif().

char language[MAX_LANGUAGE] = "" [static]
 

Definition at line 70 of file chan_modem.c.

const struct ast_channel_tech modem_tech [static]
 

Definition at line 126 of file chan_modem.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]
 

Definition at line 111 of file chan_modem.c.

char msn[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 76 of file chan_modem.c.

Referenced by load_module(), and mkif().

char mtype[80] = "autodetect" [static]
 

Definition at line 65 of file chan_modem.c.

Referenced by load_module(), and modem_setup().

char outgoingmsn[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 89 of file chan_modem.c.

Referenced by load_module(), and mkif().

int stripmsd = 0 [static]
 

Definition at line 98 of file chan_modem.c.

Referenced by load_module(), mkif(), mkintf(), and setup_zap().

const char tdesc[] = "Generic Voice Modem Channel Driver" [static]
 

Definition at line 58 of file chan_modem.c.

const char type[] = "Modem" [static]
 

Definition at line 59 of file chan_modem.c.

int usecnt = 0 [static]
 

Definition at line 94 of file chan_modem.c.


Generated on Sun Aug 6 15:06:12 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2