diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 7e545d0980..c1e8628d50 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -63,6 +63,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include #include #include "sig_analog.h" +/* Analog signaling is currently still present in chan_dahdi for use with + * radio. Sig_analog does not currently handle any radio operations. If + * radio only uses analog signaling, then the radio handling logic could + * be placed in sig_analog and the duplicated code could be removed. + */ #ifdef HAVE_PRI #include "sig_pri.h" @@ -364,6 +369,37 @@ static const char config[] = "chan_dahdi.conf"; #define CALLPROGRESS_FAX_INCOMING 4 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING) +#define NUM_CADENCE_MAX 25 +static int num_cadence = 4; +static int user_has_defined_cadences = 0; + +static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = { + { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */ + { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */ + { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */ + { { 1000, 500, 2500, 5000 } }, /*!< Long ring */ +}; + +/*! \brief cidrings says in which pause to transmit the cid information, where the first pause + * is 1, the second pause is 2 and so on. + */ + +static int cidrings[NUM_CADENCE_MAX] = { + 2, /*!< Right after first long ring */ + 4, /*!< Right after long part */ + 3, /*!< After third chirp */ + 2, /*!< Second spell */ +}; + +/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */ +static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}; + +#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \ + (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI)) + +#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) +#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) + static char defaultcic[64] = ""; static char defaultozz[64] = ""; @@ -1153,19 +1189,12 @@ static struct dahdi_pvt { struct ast_event_sub *mwi_event_sub; /*! \brief Delayed dialing for E911. Overlap digits for ISDN. */ char dialdest[256]; - /*! \brief Time the interface went on-hook. */ - int onhooktime; - /*! \brief TRUE if the FXS port is off-hook */ - int fxsoffhookstate; - /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */ - int msgstate; #ifdef HAVE_DAHDI_LINEREVERSE_VMWI struct dahdi_vmwi_info mwisend_setting; /*!< Which VMWI methods to use */ unsigned int mwisend_fsk: 1; /*! Variable for enabling FSK MWI handling in chan_dahdi */ unsigned int mwisend_rpas:1; /*! Variable for enabling Ring Pulse Alert before MWI FSK Spill */ #endif int distinctivering; /*!< Which distinctivering to use */ - int cidrings; /*!< Which ring to deliver CID on */ int dtmfrelax; /*!< whether to run in relaxed DTMF mode */ /*! \brief Holding place for event injected from outside normal operation. */ int fake_event; @@ -1177,7 +1206,7 @@ static struct dahdi_pvt { /*! \brief Start delay time if polarityonanswerdelay is nonzero. */ struct timeval polaritydelaytv; /*! - * \brief Send caller ID after this many rings. + * \brief Send caller ID on FXS after this many rings. Set to 1 for US. * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf */ int sendcalleridafter; @@ -1557,6 +1586,7 @@ static int my_stop_cid_detect(void *pvt) static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_event *ev, size_t timeout) { struct dahdi_pvt *p = pvt; + struct analog_pvt *analog_p = p->sig_pvt; struct pollfd poller; char *name, *num; int index = SUB_REAL; @@ -1578,9 +1608,9 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e if (poller.revents & POLLIN) { /*** NOTES ***/ /* Change API: remove cid_signalling from get_callerid, add a new start_cid_detect and stop_cid_detect function - * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until - * either a timeout occurss or CID is detected (returns 0). returning 1 should be event received, and -1 should be fail - * and die */ + * to enable slin mode and allocate cid detector. get_callerid should be able to be called any number of times until + * either a timeout occurss or CID is detected (returns 0). returning 1 should be event received, and -1 should be + * a failure and die, and returning 2 means no event was received. */ res = read(p->subs[index].dfd, buf, sizeof(buf)); if (res < 0) { if (errno != ELAST) { @@ -1589,7 +1619,20 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e return -1; } } - res = callerid_feed(p->cs, buf, res, AST_LAW(p)); + + if (analog_p->ringt) { + analog_p->ringt--; + } + if (analog_p->ringt == 1) { + return -1; + } + + if (p->cid_signalling == CID_SIG_V23_JP) { + res = callerid_feed_jp(p->cs, buf, res, AST_LAW(p)); + } else { + res = callerid_feed(p->cs, buf, res, AST_LAW(p)); + } + if (res < 0) { ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); return -1; @@ -1608,7 +1651,128 @@ static int my_get_callerid(void *pvt, char *namebuf, char *numbuf, enum analog_e } *ev = ANALOG_EVENT_NONE; - return 1; + return 2; +} + +static const char *event2str(int event); +static int restore_gains(struct dahdi_pvt *p); + +static int my_distinctive_ring(struct ast_channel *chan, void *pvt, int idx, int *ringdata) +{ + unsigned char buf[256]; + int distMatches; + int curRingData[3]; + int receivedRingT; + int counter1; + int counter; + int i; + int res; + int checkaftercid = 0; + + struct dahdi_pvt *p = pvt; + struct analog_pvt *analog_p = p->sig_pvt; + + if (ringdata == NULL) { + ringdata = curRingData; + } else { + checkaftercid = 1; + } + + /* We must have a ring by now, so, if configured, lets try to listen for + * distinctive ringing */ + if ((checkaftercid && distinctiveringaftercid) || !checkaftercid) { + /* Clear the current ring data array so we dont have old data in it. */ + for (receivedRingT = 0; receivedRingT < ARRAY_LEN(ringdata); receivedRingT++) + ringdata[receivedRingT] = 0; + receivedRingT = 0; + if (checkaftercid && distinctiveringaftercid) + ast_verb(3, "Detecting post-CID distinctive ring\n"); + /* Check to see if context is what it should be, if not set to be. */ + else if (strcmp(p->context,p->defcontext) != 0) { + ast_copy_string(p->context, p->defcontext, sizeof(p->context)); + ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); + } + + for (;;) { + i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; + if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) { + ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); + ast_hangup(chan); + return 1; + } + if (i & DAHDI_IOMUX_SIGEVENT) { + res = dahdi_get_event(p->subs[idx].dfd); + ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); + res = 0; + /* Let us detect distinctive ring */ + + ringdata[receivedRingT] = analog_p->ringt; + + if (analog_p->ringt < analog_p->ringt_base/2) + break; + /* Increment the ringT counter so we can match it against + values in chan_dahdi.conf for distinctive ring */ + if (++receivedRingT == ARRAY_LEN(ringdata)) + break; + } else if (i & DAHDI_IOMUX_READ) { + res = read(p->subs[idx].dfd, buf, sizeof(buf)); + if (res < 0) { + if (errno != ELAST) { + ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); + ast_hangup(chan); + return 1; + } + break; + } + if (analog_p->ringt) + analog_p->ringt--; + if (analog_p->ringt == 1) { + res = -1; + break; + } + } + } + } + if ((checkaftercid && usedistinctiveringdetection) || !checkaftercid) { + /* this only shows up if you have n of the dring patterns filled in */ + ast_verb(3, "Detected ring pattern: %d,%d,%d\n",ringdata[0],ringdata[1],ringdata[2]); + for (counter = 0; counter < 3; counter++) { + /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this channel */ + distMatches = 0; + /* this only shows up if you have n of the dring patterns filled in */ + ast_verb(3, "Checking %d,%d,%d\n", + p->drings.ringnum[counter].ring[0], + p->drings.ringnum[counter].ring[1], + p->drings.ringnum[counter].ring[2]); + for (counter1 = 0; counter1 < 3; counter1++) { + ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range); + if (p->drings.ringnum[counter].ring[counter1] == -1) { + ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n", + ringdata[counter1]); + distMatches++; + } else if (ringdata[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) && + ringdata[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) { + ast_verb(3, "Ring pattern matched in range: %d to %d\n", + (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range), + (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range)); + distMatches++; + } + } + + if (distMatches == 3) { + /* The ring matches, set the context to whatever is for distinctive ring.. */ + ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context)); + ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context)); + ast_verb(3, "Distinctive Ring matched context %s\n",p->context); + break; + } + } + } + /* Restore linear mode (if appropriate) for Caller*ID processing */ + dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear); + restore_gains(p); + + return 0; } static int send_callerid(struct dahdi_pvt *p); @@ -1656,7 +1820,7 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_callerid *cid) { struct dahdi_pvt *p = pvt; - ast_log(LOG_ERROR, "Starting cid spill\n"); + ast_debug(2, "Starting cid spill\n"); if (p->cidspill) { ast_log(LOG_WARNING, "cidspill already exists??\n"); @@ -1809,17 +1973,66 @@ static void my_handle_dtmfup(void *pvt, struct ast_channel *ast, enum analog_sub static void my_lock_private(void *pvt) { struct dahdi_pvt *p = pvt; - ast_mutex_lock(&p->lock); } static void my_unlock_private(void *pvt) { struct dahdi_pvt *p = pvt; - ast_mutex_unlock(&p->lock); } +static int my_set_linear_mode(void *pvt, int idx, int linear_mode) +{ + struct dahdi_pvt *p = pvt; + if (!linear_mode) + linear_mode = p->subs[idx].linear; + return dahdi_setlinear(p->subs[idx].dfd, linear_mode); +} + +static int get_alarms(struct dahdi_pvt *p); +static void handle_alarms(struct dahdi_pvt *p, int alms); +static void my_get_and_handle_alarms(void *pvt) +{ + int res; + struct dahdi_pvt *p = pvt; + + res = get_alarms(p); + handle_alarms(p, res); +} + +static void *my_get_sigpvt_bridged_channel(struct ast_channel *chan) +{ + struct dahdi_pvt *p = ast_bridged_channel(chan)->tech_pvt; + if (p) + return p->sig_pvt; + else + return NULL; +} + +static int my_get_sub_fd(void *pvt, enum analog_sub sub) +{ + struct dahdi_pvt *p = pvt; + int dahdi_sub = analogsub_to_dahdisub(sub); + return p->subs[dahdi_sub].dfd; +} + +static void my_set_cadence(void *pvt, int *cidrings, struct ast_channel *ast) +{ + struct dahdi_pvt *p = pvt; + + /* Choose proper cadence */ + if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { + if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) + ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); + *cidrings = cidrings[p->distinctivering - 1]; + } else { + if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) + ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); + *cidrings = p->sendcalleridafter; + } +} + static void my_increase_ss_count(void) { ast_mutex_lock(&ss_thread_lock); @@ -2189,6 +2402,13 @@ static int my_ring(void *pvt) return dahdi_ring_phone(p); } +static int my_flash(void *pvt) +{ + struct dahdi_pvt *p = pvt; + int func = DAHDI_FLASH; + return ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &func); +} + static inline int dahdi_set_hook(int fd, int hs); static int my_off_hook(void *pvt) @@ -2263,9 +2483,7 @@ static int my_is_dialing(void *pvt, enum analog_sub sub) static int my_on_hook(void *pvt) { struct dahdi_pvt *p = pvt; - int x = DAHDI_ONHOOK; - - return ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_HOOK, &x); + return dahdi_set_hook(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_ONHOOK); } #ifdef HAVE_PRI @@ -2317,8 +2535,6 @@ static int sig_pri_tone_to_dahditone(enum analog_tone tone) } } -static const char *event2str(int event); - static void my_handle_dchan_exception(struct sig_pri_pri *pri, int index) { int x, res; @@ -2433,6 +2649,7 @@ static struct analog_callback dahdi_analog_callbacks = .is_off_hook = my_is_off_hook, .set_echocanceller = my_set_echocanceller, .ring = my_ring, + .flash = my_flash, .off_hook = my_off_hook, .dial_digits = my_dial_digits, .train_echocanceller = my_train_echocanceller, @@ -2464,6 +2681,12 @@ static struct analog_callback dahdi_analog_callbacks = .handle_notify_message = my_handle_notify_message, .increase_ss_count = my_increase_ss_count, .decrease_ss_count = my_decrease_ss_count, + .distinctive_ring = my_distinctive_ring, + .set_linear_mode = my_set_linear_mode, + .get_and_handle_alarms = my_get_and_handle_alarms, + .get_sigpvt_bridged_channel = my_get_sigpvt_bridged_channel, + .get_sub_fd = my_get_sub_fd, + .set_cadence = my_set_cadence, }; static struct dahdi_pvt *round_robin[32]; @@ -2492,36 +2715,6 @@ static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri) return 0; } #endif /* defined(HAVE_SS7) */ -#define NUM_CADENCE_MAX 25 -static int num_cadence = 4; -static int user_has_defined_cadences = 0; - -static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = { - { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */ - { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */ - { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */ - { { 1000, 500, 2500, 5000 } }, /*!< Long ring */ -}; - -/*! \brief cidrings says in which pause to transmit the cid information, where the first pause - * is 1, the second pause is 2 and so on. - */ - -static int cidrings[NUM_CADENCE_MAX] = { - 2, /*!< Right after first long ring */ - 4, /*!< Right after long part */ - 3, /*!< After third chirp */ - 2, /*!< Second spell */ -}; - -/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */ -static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}; - -#define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \ - (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI)) - -#define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) -#define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */) static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok) { @@ -2673,8 +2866,6 @@ static void dahdi_r2_on_call_init(openr2_chan_t *r2chan) ast_log(LOG_NOTICE, "New MFC/R2 call detected on chan %d.\n", openr2_chan_get_number(r2chan)); } -static int get_alarms(struct dahdi_pvt *p); -static void handle_alarms(struct dahdi_pvt *p, int alms); static void dahdi_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm) { int res; @@ -3051,8 +3242,6 @@ static openr2_transcoder_interface_t dahdi_r2_transcode_iface = { #endif /* HAVE_OPENR2 */ -static int restore_gains(struct dahdi_pvt *p); - static void swap_subs(struct dahdi_pvt *p, int a, int b) { int tchan; @@ -4111,29 +4300,6 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout) } #endif - /* Set the ring cadence */ - mysig = p->sig; - if (p->outsigmod > -1) - mysig = p->outsigmod; - switch (mysig) { - case SIG_FXOLS: - case SIG_FXOGS: - case SIG_FXOKS: - if (p->owner == ast) { - /* Choose proper cadence */ - if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { - if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) - ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); - p->cidrings = cidrings[p->distinctivering - 1]; - } else { - if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) - ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); - p->cidrings = p->sendcalleridafter; - } - } - break; - } - /* If this is analog signalling we can exit here */ if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { p->callwaitrings = 0; @@ -4142,6 +4308,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout) return res; } + mysig = p->outsigmod > -1 ? p->outsigmod : p->sig; switch (mysig) { case 0: /* Special pseudo -- automatically up*/ @@ -4877,12 +5044,10 @@ static int dahdi_hangup(struct ast_channel *ast) p->ringt = 0; p->distinctivering = 0; p->confirmanswer = 0; - p->cidrings = 1; p->outgoing = 0; p->digital = 0; p->faxhandled = 0; p->pulsedial = 0; - p->onhooktime = time(NULL); #if defined(HAVE_PRI) || defined(HAVE_SS7) p->proceeding = 0; p->dialing = 0; @@ -4970,6 +5135,7 @@ static int dahdi_hangup(struct ast_channel *ast) memset(&par, 0, sizeof(par)); res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par); if (!res) { + struct analog_pvt *analog_p = p->sig_pvt; #if 0 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); #endif @@ -4978,14 +5144,14 @@ static int dahdi_hangup(struct ast_channel *ast) tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION); else tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1); - p->fxsoffhookstate = par.rxisoffhook; + analog_p->fxsoffhookstate = par.rxisoffhook; } break; case SIG_FXSGS: case SIG_FXSLS: case SIG_FXSKS: /* Make sure we're not made available for at least two seconds assuming - we were actually used for an inbound or outbound call. */ + we were actually used for an inbound or outbound call. */ if (ast->_state != AST_STATE_RESERVED) { time(&p->guardtime); p->guardtime += 2; @@ -6371,9 +6537,6 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: - p->onhooktime = time(NULL); - p->fxsoffhookstate = 0; - p->msgstate = -1; /* Check for some special conditions regarding call waiting */ if (idx == SUB_REAL) { /* The normal line was hung up */ @@ -6524,7 +6687,6 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast) case SIG_FXOLS: case SIG_FXOGS: case SIG_FXOKS: - p->fxsoffhookstate = 1; switch (ast->_state) { case AST_STATE_RINGING: dahdi_enable_ec(p); @@ -7324,7 +7486,12 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) ast_mutex_unlock(&p->lock); return &p->subs[idx].f; } else if (errno == ELAST) { - f = __dahdi_exception(ast); + if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { + struct analog_pvt *analog_p = p->sig_pvt; + f = analog_exception(analog_p, ast); + } else { + f = __dahdi_exception(ast); + } } else ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno)); } @@ -7333,7 +7500,12 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast) } if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) { ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE); - f = __dahdi_exception(ast); + if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { + struct analog_pvt *analog_p = p->sig_pvt; + f = analog_exception(analog_p, ast); + } else { + f = __dahdi_exception(ast); + } ast_mutex_unlock(&p->lock); return f; } @@ -7555,8 +7727,10 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame) if (analog_lib_handles(p->sig, p->radio, p->oprmode)) { struct analog_pvt *ap = p->sig_pvt; - if (ap->dialing) + if (ap->dialing) { + ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); return 0; + } } if (p->dialing) { ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name); @@ -8934,8 +9108,9 @@ static void *analog_ss_thread(void *data) } break; } - if (p->ringt) + if (p->ringt) { p->ringt--; + } if (p->ringt == 1) { res = -1; break; @@ -9488,7 +9663,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event) case SIG_FXOGS: case SIG_FXOKS: res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK); - i->fxsoffhookstate = 1; if (res && (errno == EBUSY)) break; if (i->cidspill) { @@ -9636,9 +9810,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event) res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1); return -1; } - if (i->sig & __DAHDI_SIG_FXO) { - i->fxsoffhookstate = 0; - } break; case DAHDI_EVENT_POLARITY: switch (i->sig) { @@ -9801,12 +9972,13 @@ static void *do_monitor(void *data) if (!found && ((i == last) || ((i == iflist) && !last))) { last = i; if (last) { + struct analog_pvt *analog_p = last->sig_pvt; /* Only allow MWI to be initiated on a quiescent fxs port */ if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO && - !last->fxsoffhookstate && !last->owner && - !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) { + !analog_p->fxsoffhookstate && !last->owner && + !ast_strlen_zero(last->mailbox) && (thispass - analog_p->onhooktime > 3)) { res = has_voicemail(last); - if (last->msgstate != res) { + if (analog_p->msgstate != res) { /* Set driver resources for signalling VMWI */ res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res); if (res2) { @@ -9817,7 +9989,7 @@ static void *do_monitor(void *data) if (mwi_send_init(last)) { ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel); } - last->msgstate = res; + analog_p->msgstate = res; found ++; } } @@ -10746,23 +10918,12 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_END); } - tmp->msgstate = -1; #ifdef HAVE_DAHDI_LINEREVERSE_VMWI tmp->mwisend_setting = conf->chan.mwisend_setting; tmp->mwisend_fsk = conf->chan.mwisend_fsk; tmp->mwisend_rpas = conf->chan.mwisend_rpas; #endif - if (chan_sig & __DAHDI_SIG_FXO) { - memset(&p, 0, sizeof(p)); - res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); - if (!res) { - tmp->fxsoffhookstate = p.rxisoffhook; - } -#ifdef HAVE_DAHDI_LINEREVERSE_VMWI - res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); -#endif - } - tmp->onhooktime = time(NULL); + tmp->group = conf->chan.group; tmp->callgroup = conf->chan.callgroup; tmp->pickupgroup= conf->chan.pickupgroup; @@ -10841,7 +11002,6 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay; analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch; analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch; - analog_p->sendcalleridafter = conf->chan.sendcalleridafter; analog_p->permcallwaiting = 1; analog_p->callreturn = conf->chan.callreturn; analog_p->cancallforward = conf->chan.cancallforward; @@ -10860,7 +11020,23 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, analog_p->stripmsd = conf->chan.stripmsd; analog_p->cid_start = ANALOG_CID_START_RING; tmp->callwaitingcallerid = analog_p->callwaitingcallerid = 1; - + analog_p->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection; + analog_p->ringt = conf->chan.ringt; + analog_p->ringt_base = ringt_base; + analog_p->chan_tech = &dahdi_tech; + analog_p->onhooktime = time(NULL); + if (chan_sig & __DAHDI_SIG_FXO) { + memset(&p, 0, sizeof(p)); + res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p); + if (!res) { + analog_p->fxsoffhookstate = p.rxisoffhook; + } +#ifdef HAVE_DAHDI_LINEREVERSE_VMWI + res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting); +#endif + } + analog_p->msgstate = -1; + ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest)); ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num)); ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name)); diff --git a/channels/sig_analog.c b/channels/sig_analog.c index e397e5f4f9..e62eb0443f 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -38,6 +38,7 @@ #include "asterisk/astdb.h" #include "asterisk/features.h" #include "asterisk/cel.h" +#include "asterisk/causes.h" #include "sig_analog.h" @@ -89,6 +90,9 @@ static const struct { * way to do this in the dialplan now. */ }; +#define ISTRUNK(p) ((p->sig == ANALOG_SIG_FXSLS) || (p->sig == ANALOG_SIG_FXSKS) || \ + (p->sig == ANALOG_SIG_FXSGS)) + enum analog_sigtype analog_str_to_sigtype(const char *name) { int i; @@ -397,6 +401,14 @@ static int analog_ring(struct analog_pvt *p) return -1; } +static int analog_flash(struct analog_pvt *p) +{ + if (p->calls->flash) + return p->calls->flash(p->chan_pvt); + else + return -1; +} + static int analog_start(struct analog_pvt *p) { if (p->calls->start) @@ -676,6 +688,13 @@ static int analog_callwait(struct analog_pvt *p) return 0; } +static void analog_set_cadence(struct analog_pvt *p, struct ast_channel *chan) +{ + if (p->calls->set_cadence) { + return p->calls->set_cadence(p->chan_pvt, &p->cidrings, chan); + } +} + int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int timeout) { int res, index,mysig; @@ -712,20 +731,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int /* Don't send audio while on hook, until the call is answered */ p->dialing = 1; - /* XXX */ -#if 0 - /* Choose proper cadence */ - if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) { - if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1])) - ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno)); - p->cidrings = cidrings[p->distinctivering - 1]; - } else { - if (ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_SETCADENCE, NULL)) - ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno)); - p->cidrings = p->sendcalleridafter; - } -#endif - p->cidrings = p->sendcalleridafter; + analog_set_cadence(p, ast); /* and set p->cidrings */ /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */ c = strchr(dest, '/'); @@ -1042,13 +1048,10 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) { p->owner = NULL; -#if 0 p->ringt = 0; -#endif -#if 0 /* Since we set it in _call */ - p->cidrings = 1; -#endif p->outgoing = 0; + p->onhooktime = time(NULL); + p->cidrings = 1; /* Perform low level hangup if no owner left */ res = analog_on_hook(p); @@ -1115,9 +1118,7 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast) case ANALOG_SIG_FXSLS: case ANALOG_SIG_FXSGS: case ANALOG_SIG_FXSKS: -#if 0 p->ringt = 0; -#endif /* Fall through */ case ANALOG_SIG_EM: case ANALOG_SIG_EM_E1: @@ -1259,13 +1260,47 @@ static int analog_decrease_ss_count(struct analog_pvt *p) return -1; } +static int analog_distinctive_ring(struct ast_channel *chan, struct analog_pvt *p, int idx, int *ringdata) +{ + if (p->calls->distinctive_ring) { + return p->calls->distinctive_ring(chan, p->chan_pvt, idx, ringdata); + } else + return -1; + +} + +static int analog_set_linear_mode(struct analog_pvt *p, int index, int linear_mode) +{ + if (p->calls->set_linear_mode) { + return p->calls->set_linear_mode(p->chan_pvt, index, linear_mode); + } else + return -1; +} + +static void analog_get_and_handle_alarms(struct analog_pvt *p) +{ + if (p->calls->get_and_handle_alarms) + return p->calls->get_and_handle_alarms(p->chan_pvt); +} + +static void *analog_get_bridged_channel(struct analog_pvt *p, struct ast_channel *chan) +{ + if (p->calls->get_sigpvt_bridged_channel) + return p->calls->get_sigpvt_bridged_channel; + else + return NULL; +} + +static int analog_get_sub_fd(struct analog_pvt *p, enum analog_sub sub) +{ + if (p->calls->get_sub_fd) { + return p->calls->get_sub_fd(p->chan_pvt, sub); + } else + return -1; +} + #define ANALOG_NEED_MFDETECT(p) (((p)->sig == ANALOG_SIG_FEATDMF) || ((p)->sig == ANALOG_SIG_FEATDMF_TA) || ((p)->sig == ANALOG_SIG_E911) || ((p)->sig == ANALOG_SIG_FGC_CAMA) || ((p)->sig == ANALOG_SIG_FGC_CAMAMF) || ((p)->sig == ANALOG_SIG_FEATB)) -/* Note by jpeeler: This function has a rather large section of code ifdefed - * away. I'd like to leave the code there until more testing is done and I - * know for sure that nothing got left out. The plan is at the latest for this - * comment and code below to be removed shortly after the merging of sig_pri. - */ static void *__analog_ss_thread(void *data) { struct analog_pvt *p = data; @@ -1279,16 +1314,6 @@ static void *__analog_ss_thread(void *data) struct callerid_state *cs = NULL; char *name = NULL, *number = NULL; int flags; -#if 0 - unsigned char buf[256]; - int distMatches; - int curRingData[3]; - int receivedRingT; - int samples = 0; - int counter1; - int counter; - int i; -#endif int timeout; int getforward = 0; char *s1, *s2; @@ -1794,21 +1819,19 @@ static void *__analog_ss_thread(void *data) memset(exten, 0, sizeof(exten)); timeout = analog_firstdigittimeout; } else if (!strcmp(exten, "*0")) { -#ifdef XXX struct ast_channel *nbridge = p->subs[ANALOG_SUB_THREEWAY].owner; - struct dahdi_pvt *pbridge = NULL; + struct analog_pvt *pbridge = NULL; /* set up the private struct of the bridged one, if any */ if (nbridge && ast_bridged_channel(nbridge)) - pbridge = ast_bridged_channel(nbridge)->tech_pvt; + pbridge = analog_get_bridged_channel(p, nbridge); if (nbridge && pbridge && - (nbridge->tech == chan_tech) && - (ast_bridged_channel(nbridge)->tech == chan_tech) && + (nbridge->tech == p->chan_tech) && + (ast_bridged_channel(nbridge)->tech == p->chan_tech) && ISTRUNK(pbridge)) { - int func = DAHDI_FLASH; /* Clear out the dial buffer */ p->dop.dialstr[0] = '\0'; /* flash hookswitch */ - if ((ioctl(pbridge->subs[ANALOG_SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) { + if ((analog_flash(p) == -1) && (errno != EINPROGRESS)) { ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", nbridge->name, strerror(errno)); } @@ -1829,7 +1852,6 @@ static void *__analog_ss_thread(void *data) ast_hangup(chan); goto quit; } -#endif } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) && ((exten[0] != '*') || (strlen(exten) > 2))) { ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "", chan->context); @@ -1855,9 +1877,9 @@ static void *__analog_ss_thread(void *data) cs = NULL; ast_debug(1, "Receiving DTMF cid on " "channel %s\n", chan->name); -#if 0 - dahdi_setlinear(p->subs[index].dfd, 0); -#endif + + analog_set_linear_mode(p, index, 0); + res = 2000; for (;;) { struct ast_frame *f; @@ -1868,8 +1890,7 @@ static void *__analog_ss_thread(void *data) ast_hangup(chan); goto quit; } - f = ast_read(chan); - if (!f) + if (!(f = ast_read(chan))) break; if (f->frametype == AST_FRAME_DTMF) { dtmfbuf[i++] = f->subclass; @@ -1882,9 +1903,9 @@ static void *__analog_ss_thread(void *data) break; /* Got ring */ } dtmfbuf[i] = '\0'; -#if 0 - dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); -#endif + + analog_set_linear_mode(p, index, 1); + /* Got cid and ring. */ ast_debug(1, "CID got string '%s'\n", dtmfbuf); callerid_get_dtmf(dtmfbuf, dtmfcid, &flags); @@ -1895,82 +1916,51 @@ static void *__analog_ss_thread(void *data) number = dtmfcid; else number = NULL; -#if 0 + /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */ } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) { - cs = callerid_new(p->cid_signalling); - if (cs) { - samples = 0; -#if 1 - bump_gains(p); -#endif - /* Take out of linear mode for Caller*ID processing */ - dahdi_setlinear(p->subs[index].dfd, 0); - - /* First we wait and listen for the Caller*ID */ - for (;;) { - i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; - if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { - ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); - callerid_free(cs); - ast_hangup(chan); - goto quit; + int timeout = 10000; /* Ten seconds */ + struct timeval start = ast_tvnow(); + enum analog_event ev; + + namebuf[0] = 0; + numbuf[0] = 0; + + if (!analog_start_cid_detect(p, p->cid_signalling)) { + while (1) { + res = analog_get_callerid(p, namebuf, numbuf, &ev, timeout - ast_tvdiff_ms(ast_tvnow(), start)); + + if (res == 0) { + break; } - if (i & DAHDI_IOMUX_SIGEVENT) { - res = dahdi_get_event(p->subs[index].dfd); - ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); + if (res == 1) { if (p->cid_signalling == CID_SIG_V23_JP) { -#ifdef DAHDI_EVENT_RINGBEGIN - if (res == ANALOG_EVENT_RINGBEGIN) { - res = analog_off_hook(p); + if (ev == ANALOG_EVENT_RINGBEGIN) { + analog_off_hook(p); usleep(1); - } -#endif + } } else { - res = 0; + ev = ANALOG_EVENT_NONE; break; } - } else if (i & DAHDI_IOMUX_READ) { - res = read(p->subs[index].dfd, buf, sizeof(buf)); - if (res < 0) { - if (errno != ELAST) { - ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); - callerid_free(cs); - ast_hangup(chan); - goto quit; - } - break; - } - samples += res; - - if (p->cid_signalling == CID_SIG_V23_JP) { - res = callerid_feed_jp(cs, buf, res, AST_LAW(p)); - } else { - res = callerid_feed(cs, buf, res, AST_LAW(p)); - } - - if (res < 0) { - ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name); - break; - } else if (res) - break; - else if (samples > (8000 * 10)) - break; } + + if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) + break; + } - if (res == 1) { - callerid_get(cs, &name, &number, &flags); - ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); - } + name = namebuf; + number = numbuf; + + analog_stop_cid_detect(p); if (p->cid_signalling == CID_SIG_V23_JP) { res = analog_on_hook(p); usleep(1); res = 4000; } else { - - /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ + /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ res = 2000; } @@ -1982,7 +1972,7 @@ static void *__analog_ss_thread(void *data) "Exiting simple switch\n"); ast_hangup(chan); goto quit; - } + } if (!(f = ast_read(chan))) { ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n"); ast_hangup(chan); @@ -1990,18 +1980,19 @@ static void *__analog_ss_thread(void *data) } ast_frfree(f); if (chan->_state == AST_STATE_RING || - chan->_state == AST_STATE_RINGING) + chan->_state == AST_STATE_RINGING) break; /* Got ring */ } + + if (analog_distinctive_ring(chan, p, index, NULL)) + goto quit; - /* Restore linear mode (if appropriate) for Caller*ID processing */ - dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); -#if 1 - restore_gains(p); -#endif + if (res < 0) { + ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); + } } else - ast_log(LOG_WARNING, "Unable to get caller ID space\n"); -#endif + ast_log(LOG_WARNING, "Unable to get caller ID space\n"); + } else { ast_log(LOG_WARNING, "Channel %s in prering " "state, but I have nothing to do. " @@ -2015,6 +2006,8 @@ static void *__analog_ss_thread(void *data) int timeout = 10000; /* Ten seconds */ struct timeval start = ast_tvnow(); enum analog_event ev; + int curRingData[3] = { 0 }; + int receivedRingT = 0; namebuf[0] = 0; numbuf[0] = 0; @@ -2027,19 +2020,33 @@ static void *__analog_ss_thread(void *data) break; } - if (res == 1) { + if (res == 1 || res == 2) { if (ev == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); p->polarity = POLARITY_IDLE; ast_hangup(chan); goto quit; - } else if (ev != ANALOG_EVENT_NONE) { + } else if (ev != ANALOG_EVENT_NONE && ev != ANALOG_EVENT_RINGBEGIN && ev != ANALOG_EVENT_RINGOFFHOOK) { break; } + if (res != 2) { + /* Let us detect callerid when the telco uses distinctive ring */ + curRingData[receivedRingT] = p->ringt; + + if (p->ringt < p->ringt_base/2) { + break; + } + /* Increment the ringT counter so we can match it against + values in chan_dahdi.conf for distinctive ring */ + if (++receivedRingT == ARRAY_LEN(curRingData)) { + break; + } + } } - if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) + if (ast_tvdiff_ms(ast_tvnow(), start) > timeout) { break; + } } name = namebuf; @@ -2047,108 +2054,14 @@ static void *__analog_ss_thread(void *data) analog_stop_cid_detect(p); -#if 0 - /* XXX */ - if (strcmp(p->context,p->defcontext) != 0) { - ast_copy_string(p->context, p->defcontext, sizeof(p->context)); - ast_copy_string(chan->context,p->defcontext,sizeof(chan->context)); - } - - analog_get_callerid(p, name, number); - /* FSK Bell202 callerID */ - cs = callerid_new(p->cid_signalling); - if (cs) { -#if 1 - bump_gains(p); -#endif - samples = 0; - len = 0; - distMatches = 0; - /* Clear the current ring data array so we dont have old data in it. */ - for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++) - curRingData[receivedRingT] = 0; - receivedRingT = 0; - counter = 0; - counter1 = 0; - /* Check to see if context is what it should be, if not set to be. */ - - /* Take out of linear mode for Caller*ID processing */ - dahdi_setlinear(p->subs[index].dfd, 0); - for (;;) { - i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT; - if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) { - ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno)); - callerid_free(cs); - ast_hangup(chan); - goto quit; - } - if (i & DAHDI_IOMUX_SIGEVENT) { - res = dahdi_get_event(p->subs[index].dfd); - ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res)); - /* If we get a PR event, they hung up while processing calerid */ - if ( res == ANALOG_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) { - ast_debug(1, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel); - p->polarity = POLARITY_IDLE; - callerid_free(cs); - ast_hangup(chan); - goto quit; - } - res = 0; - /* Let us detect callerid when the telco uses distinctive ring */ - - curRingData[receivedRingT] = p->ringt; + if (analog_distinctive_ring(chan, p, index, curRingData)) + goto quit; - if (p->ringt < p->ringt_base/2) - break; - /* Increment the ringT counter so we can match it against - values in chan_dahdi.conf for distinctive ring */ - if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0]))) - break; - } else if (i & DAHDI_IOMUX_READ) { - res = read(p->subs[index].dfd, buf, sizeof(buf)); - if (res < 0) { - if (errno != ELAST) { - ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno)); - callerid_free(cs); - ast_hangup(chan); - goto quit; - } - break; - } - if (p->ringt) - p->ringt--; - if (p->ringt == 1) { - res = -1; - break; - } - samples += res; - res = callerid_feed(cs, buf, res, AST_LAW(p)); - if (res < 0) { - ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno)); - break; - } else if (res) - break; - else if (samples > (8000 * 10)) - break; - } - } - if (res == 1) { - callerid_get(cs, &name, &number, &flags); - ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags); - } - /* Restore linear mode (if appropriate) for Caller*ID processing */ - dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear); -#if 1 - restore_gains(p); -#endif if (res < 0) { ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name); } } else ast_log(LOG_WARNING, "Unable to get caller ID space\n"); -#endif - } else - ast_log(LOG_WARNING, "Unable to get caller ID space\n"); } else cs = NULL; @@ -2164,9 +2077,7 @@ static void *__analog_ss_thread(void *data) ast_setstate(chan, AST_STATE_RING); chan->rings = 1; -#if 0 p->ringt = p->ringt_base; -#endif res = ast_pbx_run(chan); if (res) { ast_hangup(chan); @@ -2287,15 +2198,16 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ break; case ANALOG_EVENT_ALARM: p->inalarm = 1; -#if 0 - res = get_alarms(p); - handle_alarms(p, res); -#endif + analog_get_and_handle_alarms(p); + case ANALOG_EVENT_ONHOOK: switch (p->sig) { case ANALOG_SIG_FXOLS: case ANALOG_SIG_FXOGS: case ANALOG_SIG_FXOKS: + p->fxsoffhookstate = 0; + p->onhooktime = time(NULL); + p->msgstate = -1; /* Check for some special conditions regarding call waiting */ if (index == ANALOG_SUB_REAL) { /* The normal line was hung up */ @@ -2337,7 +2249,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ /* It hasn't been long enough since the last flashook. This is probably a bounce on hanging up. Hangup both channels now */ if (p->subs[ANALOG_SUB_THREEWAY].owner) - ast_queue_hangup(p->subs[ANALOG_SUB_THREEWAY].owner); + ast_queue_hangup_with_cause(p->subs[ANALOG_SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER); ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV); ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel); ast_channel_unlock(p->subs[ANALOG_SUB_THREEWAY].owner); @@ -2427,6 +2339,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ case ANALOG_SIG_FXOLS: case ANALOG_SIG_FXOGS: case ANALOG_SIG_FXOKS: + p->fxsoffhookstate = 1; switch (ast->_state) { case AST_STATE_RINGING: analog_set_echocanceller(p, 1); @@ -2484,11 +2397,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ case ANALOG_SIG_FXSLS: case ANALOG_SIG_FXSGS: case ANALOG_SIG_FXSKS: -#if 0 if (ast->_state == AST_STATE_RING) { p->ringt = p->ringt_base; } -#endif /* Fall through */ case ANALOG_SIG_EM: @@ -2530,11 +2441,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ case ANALOG_SIG_FXSLS: case ANALOG_SIG_FXSGS: case ANALOG_SIG_FXSKS: -#if 0 if (ast->_state == AST_STATE_RING) { p->ringt = p->ringt_base; } -#endif break; } break; @@ -2572,10 +2481,9 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ case ANALOG_SIG_FXOLS: case ANALOG_SIG_FXOGS: case ANALOG_SIG_FXOKS: -#if 0 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n", - index, p->subs[ANALOG_SUB_REAL].dfd, p->subs[ANALOG_SUB_CALLWAIT].dfd, p->subs[ANALOG_SUB_THREEWAY].dfd); -#endif + index, analog_get_sub_fd(p, ANALOG_SUB_REAL), analog_get_sub_fd(p, ANALOG_SUB_CALLWAIT), analog_get_sub_fd(p, ANALOG_SUB_THREEWAY)); + p->callwaitcas = 0; if (index != ANALOG_SUB_REAL) { @@ -3045,6 +2953,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) case ANALOG_SIG_FXOGS: case ANALOG_SIG_FXOKS: res = analog_off_hook(i); + i->fxsoffhookstate = 1; if (res && (errno == EBUSY)) break; if (i->immediate) { @@ -3083,9 +2992,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) case ANALOG_SIG_FXSLS: case ANALOG_SIG_FXSGS: case ANALOG_SIG_FXSKS: -#if 0 i->ringt = i->ringt_base; -#endif /* Fall through */ case ANALOG_SIG_EMWINK: case ANALOG_SIG_FEATD: @@ -3139,16 +3046,15 @@ int analog_handle_init_event(struct analog_pvt *i, int event) break; case ANALOG_EVENT_ALARM: i->inalarm = 1; -#if 0 - res = get_alarms(i); - handle_alarms(i, res); -#endif + analog_get_and_handle_alarms(i); + /* fall thru intentionally */ case ANALOG_EVENT_ONHOOK: /* Back on hook. Hang up. */ switch (i->sig) { case ANALOG_SIG_FXOLS: case ANALOG_SIG_FXOGS: + i->fxsoffhookstate = 0; case ANALOG_SIG_FEATD: case ANALOG_SIG_FEATDMF: case ANALOG_SIG_FEATDMF_TA: @@ -3172,6 +3078,7 @@ int analog_handle_init_event(struct analog_pvt *i, int event) analog_on_hook(i); break; case ANALOG_SIG_FXOKS: + i->fxsoffhookstate = 0; analog_set_echocanceller(i, 0); /* Diddle the battery for the zhone */ #ifdef ZHONE_HACK @@ -3244,7 +3151,6 @@ struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog p->chan_pvt = private_data; /* Some defaults for values */ - p->sendcalleridafter = 1; p->cid_start = ANALOG_CID_START_RING; p->cid_signalling = CID_SIG_BELL; /* Sub real is assumed to always be alloc'd */ diff --git a/channels/sig_analog.h b/channels/sig_analog.h index 661179881f..89ac6b83d3 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -185,6 +185,13 @@ struct analog_callback { /* callbacks for increasing and decreasing ss_thread_count, will handle locking and condition signal */ void (* const increase_ss_count)(void); void (* const decrease_ss_count)(void); + + int (* const distinctive_ring)(struct ast_channel *chan, void *pvt, int idx, int *ringdata); + int (* const set_linear_mode)(void *pvt, int idx, int linear_mode); + void (* const get_and_handle_alarms)(void *pvt); + void * (* const get_sigpvt_bridged_channel)(struct ast_channel *chan); + int (* const get_sub_fd)(void *pvt, enum analog_sub sub); + void (* const set_cadence)(void *pvt, int *cidrings, struct ast_channel *chan); }; @@ -210,8 +217,12 @@ struct analog_pvt { /* All members after this are giong to be transient, and most will probably change */ struct ast_channel *owner; /*!< Our current active owner (if applicable) */ - struct analog_subchannel subs[3]; /*!< Sub-channels */ + struct analog_subchannel subs[3]; /*!< Sub-channels */ struct analog_dialoperation dop; + int onhooktime; /*< Time the interface went on-hook. */ + int fxsoffhookstate; /*< TRUE if the FXS port is off-hook */ + /*! \brief -1 = unknown, 0 = no messages, 1 = new messages available */ + int msgstate; /* XXX: Option Variables - Set by allocator of private structure */ unsigned int answeronpolarityswitch:1; @@ -228,17 +239,22 @@ struct analog_pvt { unsigned int transfer:1; unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */ unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */ + const struct ast_channel_tech *chan_tech; + /*! + * \brief TRUE if distinctive rings are to be detected. + * \note For FXO lines + * \note Set indirectly from the "usedistinctiveringdetection" value read in from chan_dahdi.conf + */ + unsigned int usedistinctiveringdetection:1; /* Not used for anything but log messages. Could be just the TCID */ - int channel; /*!< Channel Number or CRV */ + int channel; /*!< Channel Number */ enum analog_sigtype outsigmod; int echotraining; int cid_signalling; /*!< Asterisk callerid type we're using */ int polarityonanswerdelay; int stripmsd; enum analog_cid_start cid_start; - /* Number of rings to wait to send callerid on FXS. Set to 1 for US */ - int sendcalleridafter; int callwaitingcallerid; char mohsuggest[MAX_MUSICCLASS]; char cid_num[AST_MAX_EXTENSION]; @@ -282,10 +298,8 @@ struct analog_pvt { int callwaitcas; -#if 0 int ringt; int ringt_base; -#endif }; struct analog_pvt * analog_new(enum analog_sigtype signallingtype, struct analog_callback *c, void *private_data);