X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=ss5.cpp;h=321f4f3cc0f30e8210d390b9bbbc51e37824ad01;hp=d038769469baca8d0b8d03499559cc7723b45901;hb=7f0d14c706328e1ff74fe8b8c16ae54407cc8055;hpb=323cbc387b1a068f8e2bcfd1034666406ba18c93 diff --git a/ss5.cpp b/ss5.cpp index d038769..321f4f3 100644 --- a/ss5.cpp +++ b/ss5.cpp @@ -35,6 +35,8 @@ #include "main.h" +//#define DEBUG_DETECT + /* ss5 signal states */ enum { SS5_STATE_IDLE, /* no signal */ @@ -225,13 +227,13 @@ static void ss5_trace_header(struct mISDNport *mISDNport, class PmISDN *port, un /* - * changes release tone int busy signal - * this makes the line more authentic + * changes release tone into silence + * this makes the line sound more authentic */ void Pss5::set_tone(const char *dir, const char *name) { if (name && !strcmp(name, "cause_10")) - name = "busy"; + name = NULL; PmISDN::set_tone(dir, name); } @@ -250,7 +252,7 @@ void ss5_create_channel(struct mISDNport *mISDNport, int i) memset(&port_settings, 0, sizeof(port_settings)); SCPY(port_settings.tones_dir, options.tones_dir); - ss5port = new Pss5(PORT_TYPE_SS5_IDLE, mISDNport, portname, &port_settings, i + (i>=15) + 1, 1, B_MODE_TRANSPARENT); + ss5port = new Pss5(PORT_TYPE_SS5_IDLE, mISDNport, portname, &port_settings, mISDNport->ifport->interface, i + (i>=15) + 1, 1, B_MODE_TRANSPARENT); if (!ss5port) FATAL("No memory for Pss5 class.\n"); if (!ss5port->p_m_b_channel) @@ -331,11 +333,12 @@ class Pss5 *ss5_hunt_line(struct mISDNport *mISDNport) return NULL; } +int queue_event(struct lcr_work *work, void *instance, int index); /* * constructor */ -Pss5::Pss5(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode) +Pss5::Pss5(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, struct interface *interface, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, interface, channel, exclusive, mode) { p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN; p_m_s_state = SS5_STATE_IDLE; @@ -344,13 +347,14 @@ Pss5::Pss5(int type, struct mISDNport *mISDNport, char *portname, struct port_se p_m_s_digit_i = 0; p_m_s_pulsecount = 0; p_m_s_last_digit = ' '; + p_m_s_last_digit_used = ' '; p_m_s_signal_loss = 0; p_m_s_decoder_count = 0; //p_m_s_decoder_buffer; p_m_s_sample_nr = 0; p_m_s_recog = 0; - p_m_s_timer = 0.0; - p_m_s_timer_fn = NULL; + memset(&p_m_s_queue, 0, sizeof(p_m_s_queue)); + add_work(&p_m_s_queue, queue_event, this, 0); p_m_s_answer = 0; p_m_s_busy_flash = 0; p_m_s_clear_back = 0; @@ -369,6 +373,7 @@ Pss5::Pss5(int type, struct mISDNport *mISDNport, char *portname, struct port_se */ Pss5::~Pss5() { + del_work(&p_m_s_queue); } @@ -380,7 +385,47 @@ void Pss5::_new_ss5_state(int state, const char *func, int line) PDEBUG(DEBUG_SS5, "%s(%s:%d): changing SS5 state from %s to %s\n", p_name, func, line, ss5_state_name[p_m_s_state], ss5_state_name[state]); p_m_s_state = state; p_m_s_signal = SS5_SIGNAL_NULL; + + if (p_m_s_state == SS5_STATE_IDLE && (p_m_s_answer || p_m_s_busy_flash || p_m_s_clear_back)) + trigger_work(&p_m_s_queue); +} + +int queue_event(struct lcr_work *work, void *instance, int index) +{ + class Pss5 *ss5port = (class Pss5 *)instance; + + if (ss5port->p_m_s_state == SS5_STATE_IDLE) { + /* if answer signal is queued */ + if (ss5port->p_m_s_answer) { + ss5port->p_m_s_answer = 0; + /* start answer */ + ss5_trace_header(ss5port->p_m_mISDNport, ss5port, SS5_ANSWER_REQ, ss5port->p_m_b_channel); + end_trace(); + ss5port->start_signal(SS5_STATE_ANSWER); + } + + /* if busy-flash signal is queued */ + if (ss5port->p_m_s_busy_flash) { + ss5port->p_m_s_busy_flash = 0; + /* start busy-flash */ + ss5_trace_header(ss5port->p_m_mISDNport, ss5port, SS5_BUSY_FLASH_REQ, ss5port->p_m_b_channel); + end_trace(); + ss5port->start_signal(SS5_STATE_BUSY_FLASH); + } + + /* if clear-back signal is queued */ + if (ss5port->p_m_s_clear_back) { + ss5port->p_m_s_clear_back = 0; + /* start clear-back */ + ss5_trace_header(ss5port->p_m_mISDNport, ss5port, SS5_CLEAR_BACK_REQ, ss5port->p_m_b_channel); + end_trace(); + ss5port->start_signal(SS5_STATE_CLEAR_BACK); + } + } + + return 0; } + void Pss5::_new_ss5_signal(int signal, const char *func, int line) { if (p_m_s_signal) @@ -426,7 +471,7 @@ void Pss5::inband_receive(unsigned char *buffer, int len) PDEBUG(DEBUG_SS5, "%s: detecting signal '%c' start (state=%s signal=%s)\n", p_name, digit, ss5_state_name[p_m_s_state], ss5_signal_name[p_m_s_signal]); #endif - /* ignore short loss of signal */ + /* ignore short loss of signal, or change within one decode window */ if (p_m_s_signal_loss) { if (digit == ' ') { /* still lost */ @@ -458,11 +503,19 @@ void Pss5::inband_receive(unsigned char *buffer, int len) p_m_s_last_digit = digit; /* starting to loose signal */ p_m_s_signal_loss = SS5_DECODER_NPOINTS; + } else if (digit != p_m_s_last_digit) { + /* digit changes, but we keep old digit until it is detected twice */ +#ifdef DEBUG_DETECT + PDEBUG(DEBUG_SS5, "%s: signal '%c' changes to '%c'\n", p_name, p_m_s_last_digit, digit); +#endif + p_m_s_last_digit = digit; + digit = p_m_s_last_digit_used; } else { /* storing last signal, in case it is lost */ p_m_s_last_digit = digit; } } + p_m_s_last_digit_used = digit; /* update mute */ if ((p_m_mISDNport->ss5 & SS5_FEATURE_SUPPRESS)) { @@ -504,7 +557,6 @@ void Pss5::inband_receive(unsigned char *buffer, int len) PDEBUG(DEBUG_SS5, "%s: received clear-forward in idle state, waiting for recognition\n", p_name); break; } - new_state(PORT_STATE_RELEASE); new_ss5_state(SS5_STATE_RELEASE_GUARD); new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG); p_m_s_recog = 0; @@ -795,6 +847,7 @@ void Pss5::inband_receive(unsigned char *buffer, int len) PDEBUG(DEBUG_SS5, "%s: incomming release-guard is recognized, responding...\n", p_name); else PDEBUG(DEBUG_SS5, "%s: incomming clear-forward is recognized, responding...\n", p_name); + new_state(PORT_STATE_RELEASE); new_ss5_signal(SS5_SIGNAL_RECEIVE); p_m_s_sample_nr = 0; inband_send_on(); @@ -948,7 +1001,7 @@ int Pss5::inband_send(unsigned char *buffer, int len) if (duration > 0 && p_m_s_sample_nr >= duration) { PDEBUG(DEBUG_SS5, "%s: sending tone '%c' complete, starting delay\n", p_name, digit); if (p_m_s_state == SS5_STATE_DOUBLE_SEIZE) { - do_release(CAUSE_NOCHANNEL, LOCATION_BEYOND); + do_release(CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL); break; } new_ss5_state(SS5_STATE_DELAY); @@ -1264,6 +1317,7 @@ void Pss5::seizing_ind(void) end_trace(); new_state(PORT_STATE_IN_SETUP); + set_tone("", "noise"); } void Pss5::digit_ind(char digit) @@ -1344,7 +1398,7 @@ void Pss5::digit_ind(char digit) end_trace(); new_ss5_state(SS5_STATE_IDLE); - do_setup(dial); + do_setup(dial, 1); new_state(PORT_STATE_IN_PROCEEDING); } @@ -1389,7 +1443,7 @@ void Pss5::pulse_ind(int on) } if (p_state == PORT_STATE_IN_SETUP) { /* sending digit as setup */ - do_setup(dial); /* include 'a' == KP1 */ + do_setup(dial, 0); /* include 'a' == KP1 */ new_state(PORT_STATE_IN_OVERLAP); } else { /* sending digit as information */ @@ -1615,13 +1669,13 @@ void Pss5::do_release(int cause, int location) /* * create endpoint and send setup */ -void Pss5::do_setup(char *dial) +void Pss5::do_setup(char *dial, int complete) { class Endpoint *epoint; struct lcr_msg *message; SCPY(p_dialinginfo.id, dial); - p_dialinginfo.sending_complete = 1; + p_dialinginfo.sending_complete = complete; p_callerinfo.present = INFO_PRESENT_NOTAVAIL; p_callerinfo.screen = INFO_SCREEN_NETWORK; p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT; @@ -1640,8 +1694,7 @@ void Pss5::do_setup(char *dial) FATAL("Incoming call but already got an endpoint.\n"); if (!(epoint = new Endpoint(p_serial, 0))) FATAL("No memory for Endpoint instance\n"); - if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming - FATAL("No memory for Endpoint Application instance\n"); + epoint->ep_app = new_endpointapp(epoint, 0, p_m_mISDNport->ifport->interface->app); //incoming epointlist_new(epoint->ep_serial); /* send setup message to endpoit */ @@ -1658,52 +1711,6 @@ void Pss5::do_setup(char *dial) } -/* - * handler - */ -int Pss5::handler(void) -{ - int ret; - - if ((ret = PmISDN::handler())) - return(ret); - - /* handle timer */ - if (p_m_s_timer && p_m_s_timer < now) { - p_m_s_timer = 0.0; - (this->*(p_m_s_timer_fn))(); - } - - /* if answer signal is queued */ - if (p_m_s_answer && p_m_s_state == SS5_STATE_IDLE) { - p_m_s_answer = 0; - /* start answer */ - ss5_trace_header(p_m_mISDNport, this, SS5_ANSWER_REQ, p_m_b_channel); - end_trace(); - start_signal(SS5_STATE_ANSWER); - } - - /* if busy-flash signal is queued */ - if (p_m_s_busy_flash && p_m_s_state == SS5_STATE_IDLE) { - p_m_s_busy_flash = 0; - /* start busy-flash */ - ss5_trace_header(p_m_mISDNport, this, SS5_BUSY_FLASH_REQ, p_m_b_channel); - end_trace(); - start_signal(SS5_STATE_BUSY_FLASH); - } - - /* if clear-back signal is queued */ - if (p_m_s_clear_back && p_m_s_state == SS5_STATE_IDLE) { - p_m_s_clear_back = 0; - /* start clear-back */ - ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_BACK_REQ, p_m_b_channel); - end_trace(); - start_signal(SS5_STATE_CLEAR_BACK); - } - - return(0); -} - /* * handles all messages from endpoint @@ -1732,8 +1739,8 @@ void Pss5::message_setup(unsigned int epoint_id, int message_id, union parameter memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo)); memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo)); /* screen outgoing caller id */ - do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface); - do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface); + do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface->name); + do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface->name); /* parse dial string */ dash = 0; /* dash must be used next time */ @@ -1903,6 +1910,7 @@ void Pss5::message_connect(unsigned int epoint_id, int message_id, union paramet if (p_state != PORT_STATE_CONNECT) { new_state(PORT_STATE_CONNECT); p_m_s_answer = 1; + trigger_work(&p_m_s_queue); } set_tone("", NULL); @@ -1931,6 +1939,10 @@ void Pss5::message_release(unsigned int epoint_id, int message_id, union paramet do_release(param->disconnectinfo.cause, param->disconnectinfo.location); } +void Pss5::register_timeout(void) +{ + do_release(CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL); +} /* * endpoint sends messages to the port