Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:32 2009

## Asterisk developer's documentation

# 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)
struct 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
struct 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 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 923 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, ast_modem_pvt::next, and ast_modem_pvt::owner.

    00924 {
    00925    struct ast_modem_pvt *p, *pl;
    00926    /* First, take us out of the channel loop */
    00927    ast_channel_unregister(&modem_tech);
    00928    if (!ast_mutex_lock(&iflock)) {
    00929       /* Hangup all interfaces if they have an owner */
    00930       p = iflist;
    00931       while(p) {
    00932          if (p->owner)
    00933             ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
    00934          p = p->next;
    00935       }
    00936       iflist = NULL;
    00937       ast_mutex_unlock(&iflock);
    00938    } else {
    00939       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    00940       return -1;
    00941    }
    00942    if (!ast_mutex_lock(&monlock)) {
    00943       if (monitor_thread != AST_PTHREADT_NULL && monitor_thread != AST_PTHREADT_STOP) {
    00944          pthread_cancel(monitor_thread);
    00945          pthread_join(monitor_thread, NULL);
    00946       }
    00947       monitor_thread = AST_PTHREADT_STOP;
    00948       ast_mutex_unlock(&monlock);
    00949    } else {
    00950       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    00951       return -1;
    00952    }
    00953
    00954    if (!ast_mutex_lock(&iflock)) {
    00955       /* Destroy all the interfaces and free their memory */
    00956       p = iflist;
    00957       while(p) {
    00958          /* Close the socket, assuming it's real */
    00959          if (p->fd > -1)
    00960             close(p->fd);
    00961          pl = p;
    00962          p = p->next;
    00963          /* Free associated memory */
    00964          free(pl);
    00965       }
    00966       iflist = NULL;
    00967       ast_mutex_unlock(&iflock);
    00968    } else {
    00969       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    00970       return -1;
    00971    }
    00972
    00973    return 0;
    00974 }

int ast_modem_expect | ( | struct ast_modem_pvt * | p,
|  | char * | result,
|  | int | timeout |
| ) |  |  |

Waits for result

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 |
| ) |  |  | `[read]`

Used to start up the PBX on a RING

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_setstate(), AST_STATE_DOWN, AST_STATE_RING, ast_strlen_zero(), ast_update_use_count(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_name, ast_modem_pvt::cid_name, ast_callerid::cid_num, 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, strdup, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, 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       if (!ast_strlen_zero(i->cid_num)) {
    00577          tmp->cid.cid_num = strdup(i->cid_num);
    00578          tmp->cid.cid_ani = strdup(i->cid_num);
    00579       }
    00580       if (!ast_strlen_zero(i->cid_name))
    00581          tmp->cid.cid_name = strdup(i->cid_name);
    00582
    00583       if (!ast_strlen_zero(i->language))
    00584          strncpy(tmp->language,i->language, sizeof(tmp->language)-1);
    00585       if (!ast_strlen_zero(i->dnid))
    00586          strncpy(tmp->exten, i->dnid, sizeof(tmp->exten) - 1);
    00587       i->owner = tmp;
    00588       ast_mutex_lock(&usecnt_lock);
    00589       usecnt++;
    00590       ast_mutex_unlock(&usecnt_lock);
    00591       ast_update_use_count();
    00592       if (state != AST_STATE_DOWN) {
    00593          if (ast_pbx_start(tmp)) {
    00594             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
    00595             ast_hangup(tmp);
    00596             tmp = NULL;
    00597          }
    00598       }
    00599    } else
    00600       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
    00601    return tmp;
    00602 }

int ast_modem_read_response | ( | struct ast_modem_pvt * | p,
|  | int | timeout |
| ) |  |  |

Waits for result

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 }

int ast_modem_send | ( | struct ast_modem_pvt * | p,
|  | char * | cmd,
|  | int | len |
| ) |  |  |

Sends command

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 string of trailing stuff

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 modem driver

Register a driver

Definition at line 194 of file chan_modem.c.

References ast_modem_driver::next.

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

Unregisters a modem driver

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 1107 of file chan_modem.c.

    01108 {
    01109    return (char *) desc;
    01110 }

static void* do_monitor | ( | void * | data | ) | `[static]`

Definition at line 616 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.

    00617 {
    00618    fd_set rfds, efds;
    00619    int n, res;
    00620    struct ast_modem_pvt *i;
    00621    /* This thread monitors all the frame relay interfaces which are not yet in use
    00622       (and thus do not have a separate thread) indefinitely */
    00623    /* From here on out, we die whenever asked */
    00624 #if 0
    00625    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
    00626       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
    00627       return NULL;
    00628    }
    00629 #endif
    00630    for(;;) {
    00631       /* Don't let anybody kill us right away.  Nobody should lock the interface list
    00632          and wait for the monitor list, but the other way around is okay. */
    00633       if (ast_mutex_lock(&monlock)) {
    00634          ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
    00635          return NULL;
    00636       }
    00637       /* Lock the interface list */
    00638       if (ast_mutex_lock(&iflock)) {
    00639          ast_log(LOG_ERROR, "Unable to grab interface lock\n");
    00640          ast_mutex_unlock(&monlock);
    00641          return NULL;
    00642       }
    00643       /* Build the stuff we're going to select on, that is the socket of every
    00644          ast_modem_pvt that does not have an associated owner channel */
    00645       n = -1;
    00646       FD_ZERO(&rfds);
    00647       FD_ZERO(&efds);
    00648       i = iflist;
    00649       while(i) {
    00650          if (FD_ISSET(i->fd, &rfds))
    00651             ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
    00652          if (!i->owner) {
    00653             /* This needs to be watched, as it lacks an owner */
    00654             FD_SET(i->fd, &rfds);
    00655             FD_SET(i->fd, &efds);
    00656             if (i->fd > n)
    00657                n = i->fd;
    00658          }
    00659
    00660          i = i->next;
    00661       }
    00662       /* Okay, now that we know what to do, release the interface lock */
    00663       ast_mutex_unlock(&iflock);
    00664
    00665       /* And from now on, we're okay to be killed, so release the monitor lock as well */
    00666       ast_mutex_unlock(&monlock);
    00667 #if 0
    00668       ast_log(LOG_DEBUG, "In monitor, n=%d, pid=%d\n", n, getpid());
    00669 #endif
    00670       /* Wait indefinitely for something to happen */
    00671       pthread_testcancel();
    00672       res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
    00673       pthread_testcancel();
    00674       /* Okay, select has finished.  Let's see what happened.  */
    00675       if (res < 1) {
    00676          if ((errno != EINTR) && (errno != EAGAIN))
    00677             ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
    00678          continue;
    00679       }
    00680       /* Alright, lock the interface list again, and let's look and see what has
    00681          happened */
    00682       if (ast_mutex_lock(&iflock)) {
    00683          ast_log(LOG_WARNING, "Unable to lock the interface list\n");
    00684          continue;
    00685       }
    00686       i = iflist;
    00687       while(i) {
    00688          if (FD_ISSET(i->fd, &rfds) || FD_ISSET(i->fd, &efds)) {
    00689             if (i->owner) {
    00690                ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d, %s)...\n", i->fd, i->dev);
    00691                i = i->next;
    00692                continue;
    00693             }
    00694             modem_mini_packet(i);
    00695          }
    00696          i=i->next;
    00697       }
    00698       ast_mutex_unlock(&iflock);
    00699    }
    00700    /* Never reached */
    00701    return NULL;
    00702
    00703 }

static struct ast_modem_driver* find_capability | ( | char * | ident | ) | `[static, read]`

Definition at line 157 of file chan_modem.c.

References ast_modem_driver::idents, ast_modem_driver::incusecnt, 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, read]`

Definition at line 178 of file chan_modem.c.

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

static ast_group_t get_group | ( | char * | s | ) | `[static]`

Definition at line 887 of file chan_modem.c.

References ast_log(), ast_strdupa, copy(), group, LOG_ERROR, LOG_WARNING, and strsep().

Referenced by load_module().

    00888 {
    00889    char *piece;
    00890    int start, finish,x;
    00891    ast_group_t group = 0;
    00892    char *copy = ast_strdupa(s);
    00893    char *stringp=NULL;
    00894    if (!copy) {
    00895       ast_log(LOG_ERROR, "Out of memory\n");
    00896       return 0;
    00897    }
    00898    stringp=copy;
    00899    piece = strsep(&stringp, ",");
    00900    while(piece) {
    00901       if (sscanf(piece, "%30d-%30d", &start, &finish) == 2) {
    00902          /* Range */
    00903       } else if (sscanf(piece, "%30d", &start)) {
    00904          /* Just one */
    00905          finish = start;
    00906       } else {
    00907          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'.  Using '0'\n", s,piece);
    00908          return 0;
    00909       }
    00910       piece = strsep(&stringp, ",");
    00911
    00912       for (x=start;x<=finish;x++) {
    00913          if ((x > 63) || (x < 0)) {
    00914             ast_log(LOG_WARNING, "Ignoring invalid group %d\n", x);
    00915             break;
    00916          }
    00917          group |= (1 << x);
    00918       }
    00919    }
    00920    return group;
    00921 }

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 1112 of file chan_modem.c.

References ASTERISK_GPL_KEY.

    01113 {
    01114    return ASTERISK_GPL_KEY;
    01115 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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.

TE STUFF END

Definition at line 981 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(), 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, ast_variable::name, ast_variable::next, ast_modem_pvt::next, option_verbose, restart_monitor(), ast_variable::value, and VERBOSE_PREFIX_2.

    00982 {
    00983    struct ast_config *cfg;
    00984    struct ast_variable *v;
    00985    struct ast_modem_pvt *tmp;
    00986    char driver[80];
    00987    cfg = ast_config_load(config);
    00988
    00989    /* We *must* have a config file otherwise stop immediately */
    00990    if (!cfg) {
    00991       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
    00992       return -1;
    00993    }
    00994    if (ast_mutex_lock(&iflock)) {
    00995       /* It's a little silly to lock it, but we mind as well just to be sure */
    00996       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
    00997       return -1;
    00998    }
    00999    v = ast_variable_browse(cfg, "interfaces");
    01000    while(v) {
    01001       /* Create the interface list */
    01002       if (!strcasecmp(v->name, "device")) {
    01003             tmp = mkif(v->value);
    01004             if (tmp) {
    01005                tmp->next = iflist;
    01006                iflist = tmp;
    01007
    01008             } else {
    01009                ast_log(LOG_ERROR, "Unable to register channel '%s'\n", v->value);
    01010                ast_config_destroy(cfg);
    01011                ast_mutex_unlock(&iflock);
    01012                __unload_module();
    01013                return -1;
    01014             }
    01015       } else if (!strcasecmp(v->name, "driver")) {
    01016          snprintf(driver, sizeof(driver), "chan_modem_%s.so", v->value);
    01017          if (option_verbose > 1)
    01018             ast_verbose(VERBOSE_PREFIX_2 "Loading modem driver %s", driver);
    01019
    01020          if (ast_load_resource(driver)) {
    01021             ast_log(LOG_ERROR, "Failed to load driver %s\n", driver);
    01022             ast_config_destroy(cfg);
    01023             ast_mutex_unlock(&iflock);
    01024             __unload_module();
    01025             return -1;
    01026          }
    01027       } else if (!strcasecmp(v->name, "mode")) {
    01028          if (!strncasecmp(v->value, "ri", 2))
    01029             gmode = MODEM_MODE_WAIT_RING;
    01030          else if (!strncasecmp(v->value, "im", 2))
    01031             gmode = MODEM_MODE_IMMEDIATE;
    01032          else if (!strncasecmp(v->value, "an", 2))
    01033             gmode = MODEM_MODE_WAIT_ANSWER;
    01034          else
    01035             ast_log(LOG_WARNING, "Unknown mode: %s\n", v->value);
    01036       } else if (!strcasecmp(v->name, "stripmsd")) {
    01037          stripmsd = atoi(v->value);
    01038       } else if (!strcasecmp(v->name, "type")) {
    01039          strncpy(mtype, v->value, sizeof(mtype)-1);
    01040       } else if (!strcasecmp(v->name, "initstr")) {
    01041          strncpy(initstr, v->value, sizeof(initstr)-1);
    01042       } else if (!strcasecmp(v->name, "dialtype")) {
    01043          dialtype = toupper(v->value[0]);
    01044       } else if (!strcasecmp(v->name, "context")) {
    01045          strncpy(context, v->value, sizeof(context)-1);
    01046       } else if (!strcasecmp(v->name, "msn")) {
    01047          strncpy(msn, v->value, sizeof(msn)-1);
    01048       } else if (!strcasecmp(v->name, "incomingmsn")) {
    01049          strncpy(incomingmsn, v->value, sizeof(incomingmsn)-1);
    01050       } else if (!strcasecmp(v->name, "dtmfmode")) {
    01051          char tmp[80];
    01052          char *alt;
    01053          strncpy(tmp, v->value, sizeof(tmp) - 1);
    01054          alt = strchr(tmp, '/');
    01055          if (!strcasecmp(tmp, "none"))
    01056             dtmfmode=MODEM_DTMF_NONE;
    01057          else if (!strcasecmp(tmp, "asterisk"))
    01058             dtmfmode = MODEM_DTMF_AST;
    01059          else if (!strcasecmp(tmp, "i4l"))
    01060             dtmfmode = MODEM_DTMF_I4L;
    01061          else {
    01062             ast_log(LOG_WARNING, "Unknown dtmf detection mode '%s', using 'asterisk'\n", v->value);
    01063             dtmfmode = MODEM_DTMF_AST;
    01064          }
    01065          if (alt) {
    01066             if (!strcasecmp(alt, "none"))
    01067                dtmfmodegen=MODEM_DTMF_NONE;
    01068             else if (!strcasecmp(alt, "asterisk"))
    01069                dtmfmodegen = MODEM_DTMF_AST;
    01070             else if (!strcasecmp(alt, "i4l"))
    01071                dtmfmodegen = MODEM_DTMF_I4L;
    01072             else if (!strcasecmp(alt, "both"))
    01073                dtmfmodegen = MODEM_DTMF_I4L | MODEM_DTMF_AST;
    01074             else {
    01075                ast_log(LOG_WARNING, "Unknown dtmf generation mode '%s', using 'asterisk'\n", v->value);
    01076                dtmfmodegen = MODEM_DTMF_AST;
    01077             }
    01078          } else
    01079             dtmfmodegen = dtmfmode;
    01080       } else if (!strcasecmp(v->name, "outgoingmsn")) {
    01081          strncpy(outgoingmsn, v->value, sizeof(outgoingmsn)-1);
    01082       } else if (!strcasecmp(v->name, "language")) {
    01083          strncpy(language, v->value, sizeof(language)-1);
    01084       } else if (!strcasecmp(v->name, "group")) {
    01085          cur_group = get_group(v->value);
    01086       }
    01087       v = v->next;
    01088    }
    01089    ast_mutex_unlock(&iflock);
    01090    if (ast_channel_register(&modem_tech)) {
    01091       ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
    01092       ast_config_destroy(cfg);
    01093       __unload_module();
    01094       return -1;
    01095    }
    01096    ast_config_destroy(cfg);
    01097    /* And start the monitor for the first time */
    01098    restart_monitor();
    01099    return 0;
    01100 }

static struct ast_modem_pvt* mkif | ( | char * | iface | ) | `[static, read]`

Definition at line 760 of file chan_modem.c.

References ast_log(), ast_modem_pvt::cid_name, ast_modem_pvt::cid_num, ast_modem_pvt::context, ast_modem_pvt::dev, ast_modem_pvt::dialtype, ast_modem_pvt::dtmfmode, ast_modem_pvt::dtmfmodegen, ast_modem_pvt::f, ast_modem_pvt::fd, free, ast_modem_pvt::group, ast_modem_pvt::incomingmsn, ast_modem_pvt::initstr, ast_modem_pvt::language, LOG_WARNING, malloc, ast_modem_pvt::ministate, ast_modem_pvt::mode, modem_setup(), ast_modem_pvt::msn, ast_modem_pvt::next, ast_modem_pvt::obuflen, ast_modem_pvt::outgoingmsn, ast_modem_pvt::owner, ast_modem_pvt::stripmsd, and stty().

Referenced by load_module().

    00761 {
    00762    /* Make a ast_modem_pvt structure for this interface */
    00763    struct ast_modem_pvt *tmp;
    00764 #if 0
    00765    int flags;
    00766 #endif
    00767
    00768    tmp = malloc(sizeof(struct ast_modem_pvt));
    00769    if (tmp) {
    00770       memset(tmp, 0, sizeof(struct ast_modem_pvt));
    00771       tmp->fd = open(iface, O_RDWR | O_NONBLOCK);
    00772       if (tmp->fd < 0) {
    00773          ast_log(LOG_WARNING, "Unable to open '%s'\n", iface);
    00774          free(tmp);
    00775          return NULL;
    00776       }
    00777       strncpy(tmp->language, language, sizeof(tmp->language)-1);
    00778       strncpy(tmp->msn, msn, sizeof(tmp->msn)-1);
    00779       strncpy(tmp->incomingmsn, incomingmsn, sizeof(tmp->incomingmsn)-1);
    00780       tmp->dtmfmode = dtmfmode;
    00781       tmp->dtmfmodegen = dtmfmodegen;
    00782       snprintf(tmp->outgoingmsn, sizeof(tmp->outgoingmsn), ",%s,", outgoingmsn);
    00783       strncpy(tmp->dev, iface, sizeof(tmp->dev)-1);
    00784       /* Maybe in the future we want to allow variable
    00785          serial settings */
    00786       stty(tmp);
    00787       tmp->f = fdopen(tmp->fd, "w+");
    00788       /* Disable buffering */
    00789       setvbuf(tmp->f, NULL, _IONBF,0);
    00790       if (tmp->f < 0) {
    00791          ast_log(LOG_WARNING, "Unable to fdopen '%s'\n", iface);
    00792          free(tmp);
    00793          return NULL;
    00794       }
    00795       tmp->owner = NULL;
    00796       tmp->ministate = 0;
    00797       tmp->stripmsd = stripmsd;
    00798       tmp->dialtype = dialtype;
    00799       tmp->mode = gmode;
    00800       tmp->group = cur_group;
    00801       memset(tmp->cid_num, 0, sizeof(tmp->cid_num));
    00802       memset(tmp->cid_name, 0, sizeof(tmp->cid_name));
    00803       strncpy(tmp->context, context, sizeof(tmp->context)-1);
    00804       strncpy(tmp->initstr, initstr, sizeof(tmp->initstr)-1);
    00805       tmp->next = NULL;
    00806       tmp->obuflen = 0;
    00807
    00808       if (modem_setup(tmp, baudrate) < 0) {
    00809          ast_log(LOG_WARNING, "Unable to configure modem '%s'\n", iface);
    00810          free(tmp);
    00811          return NULL;
    00812       }
    00813    }
    00814    return tmp;
    00815 }

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

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_pvt::cid_name, ast_modem_pvt::cid_num, ast_modem_pvt::dnid, ast_modem_driver::hangup, ast_modem_driver::init, LOG_DEBUG, LOG_WARNING, ast_modem_pvt::mc, ast_channel::name, option_debug, option_verbose, ast_modem_pvt::owner, restart_monitor(), ast_channel::tech_pvt, 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 604 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().

    00605 {
    00606    struct ast_frame *fr;
    00607    fr = i->mc->read(i);
    00608    if (!fr) return;
    00609    if (fr->frametype == AST_FRAME_CONTROL) {
    00610       if (fr->subclass == AST_CONTROL_RING) {
    00611          ast_modem_new(i, AST_STATE_RING);
    00612       }
    00613    }
    00614 }

static struct ast_frame * modem_read | ( | struct ast_channel * | ast | ) | `[static, read]`

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, read]`

Definition at line 817 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, LOG_ERROR, LOG_WARNING, ast_modem_pvt::mc, ast_modem_pvt::next, ast_modem_pvt::owner, restart_monitor(), and strsep().

    00818 {
    00819    int oldformat;
    00820    struct ast_modem_pvt *p;
    00821    struct ast_channel *tmp = NULL;
    00822    char dev[80];
    00823    ast_group_t group = 0;
    00824    int groupint;
    00825    char *stringp=NULL;
    00826    strncpy(dev, (char *)data, sizeof(dev)-1);
    00827    stringp=dev;
    00828    strsep(&stringp, ":");
    00829    oldformat = format;
    00830
    00831    if (!dep_warning) {
    00832       ast_log(LOG_WARNING, "This channel driver is deprecated.  Please see the UPGRADE.txt file.\n");
    00833       dep_warning = 1;
    00834    }
    00835
    00836    if (dev[0]=='g' && isdigit(dev[1])) {
    00837       /* Retrieve the group number */
    00838       if (sscanf(dev+1, "%30u", &groupint) < 1) {
    00839          ast_log(LOG_WARNING, "Unable to determine group from [%s]\n", (char *)data);
    00840          return NULL;
    00841       }
    00842       group = 1 << groupint;
    00843    }
    00844
    00845    /* Search for an unowned channel */
    00846    if (ast_mutex_lock(&iflock)) {
    00847       ast_log(LOG_ERROR, "Unable to lock interface list???\n");
    00848       return NULL;
    00849    }
    00850    p = iflist;
    00851    while(p) {
    00852       if (group) {
    00853          /* if it belongs to the proper group, and the format matches
    00854           * and it is not in use, we found a candidate! */
    00855          if (p->group & group &&
    00856              p->mc->formats & format &&
    00857              !p->owner) {
    00858             /* XXX Not quite sure that not having an owner is
    00859              * sufficient evidence of beeing a free device XXX */
    00860             tmp = ast_modem_new(p, AST_STATE_DOWN);
    00861             restart_monitor();
    00862             break;
    00863          }
    00864       } else {
    00865          if (!strcmp(dev, p->dev + 5)) {
    00866             if (p->mc->formats & format) {
    00867                if (!p->owner) {
    00868                   tmp = ast_modem_new(p, AST_STATE_DOWN);
    00869                   restart_monitor();
    00870                   break;
    00871                } else
    00872                   ast_log(LOG_WARNING, "Device '%s' is busy\n", p->dev);
    00873             } else
    00874                ast_log(LOG_WARNING, "Asked for a format %s line on %s\n", ast_getformatname(format), p->dev);
    00875             break;
    00876          }
    00877       }
    00878       p = p->next;
    00879    }
    00880    if (!p)
    00881       ast_log(LOG_WARNING, "Requested device '%s' does not exist\n", dev);
    00882
    00883    ast_mutex_unlock(&iflock);
    00884    return tmp;
    00885 }

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, 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_channel::_state, AST_STATE_UP, ast_channel::fds, ast_modem_pvt::mc, ast_channel::tech_pvt, 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 705 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.

    00706 {
    00707    /* If we're supposed to be stopped -- stay stopped */
    00708    if (monitor_thread == AST_PTHREADT_STOP)
    00709       return 0;
    00710    if (ast_mutex_lock(&monlock)) {
    00711       ast_log(LOG_WARNING, "Unable to lock monitor\n");
    00712       return -1;
    00713    }
    00714    if (monitor_thread == pthread_self()) {
    00715       ast_mutex_unlock(&monlock);
    00716       ast_log(LOG_WARNING, "Cannot kill myself\n");
    00717       return -1;
    00718    }
    00719    if (monitor_thread != AST_PTHREADT_NULL) {
    00720       /* Wake up the thread */
    00721       pthread_kill(monitor_thread, SIGURG);
    00722    } else {
    00723       /* Start a new monitor */
    00724       if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
    00725          ast_mutex_unlock(&monlock);
    00726          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
    00727          return -1;
    00728       }
    00729    }
    00730    ast_mutex_unlock(&monlock);
    00731    return 0;
    00732 }

static void stty | ( | struct ast_modem_pvt * | p | ) | `[static]`

Definition at line 734 of file chan_modem.c.

References ast_log(), ast_modem_pvt::dev, ECHO, ast_modem_pvt::fd, and LOG_WARNING.

Referenced by mkif().

    00735 {
    00736    struct termios mode;
    00737    memset(&mode, 0, sizeof(mode));
    00738    if (tcgetattr(p->fd, &mode)) {
    00739       ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", p->dev, strerror(errno));
    00740       return;
    00741    }
    00742 #ifndef SOLARIS
    00743    cfmakeraw(&mode);
    00744 #else
    00745         mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
    00746                         |INLCR|IGNCR|ICRNL|IXON);
    00747         mode.c_oflag &= ~OPOST;
    00748         mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
    00749         mode.c_cflag &= ~(CSIZE|PARENB);
    00750         mode.c_cflag |= CS8;
    00751 #endif
    00752
    00753    cfsetispeed(&mode, B115200);
    00754    cfsetospeed(&mode, B115200);
    00755    if (tcsetattr(p->fd, TCSANOW, &mode))
    00756       ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", p->dev, strerror(errno));
    00757
    00758 }

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 976 of file chan_modem.c.

References __unload_module().

    00977 {
    00978    return __unload_module();
    00979 }

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 1102 of file chan_modem.c.

    01103 {
    01104    return usecnt;
    01105 }

## Variable Documentation

int baudrate = 115200`[static]`

Definition at line 96 of file chan_modem.c.

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.

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

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(), and conf_run().

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.

int gmode = MODEM_MODE_IMMEDIATE`[static]`

Definition at line 62 of file chan_modem.c.

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.

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

Definition at line 73 of file chan_modem.c.

char language[MAX_LANGUAGE] = ""`[static]`

Definition at line 70 of file chan_modem.c.

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.

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

Definition at line 65 of file chan_modem.c.

char outgoingmsn[AST_MAX_EXTENSION] = ""`[static]`

Definition at line 89 of file chan_modem.c.

int stripmsd = 0`[static]`

Definition at line 98 of file chan_modem.c.

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.