Added support for signalling system no. 5.
[lcr.git] / ss5.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN ss5                                                                 **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 /*
13  * STATES:
14  *
15  * there are three types of states
16  *
17  * - the port state (p_state): used for current call state
18  * - the ss5 state (p_m_s_state): used for current tone
19  * - the ss5 signal state (p_m_s_signal): used for current signal state of current tone
20  *
21  * the port state differs from isdn state:
22  * 
23  * - PORT_STATE_IDLE: used until number is complete. outgoing overlap dialing is received in this state.
24  * - PORT_STATE_OUT_SETUP: the seizing procedure is started.
25  * - PORT_STATE_OUT_OVERLAP: the transmitter is sending the digits.
26  * - PORT_STATE_OUT_PROCEEDING: the digits are sent, we wait until someone answers.
27  * - PORT_STATE_CONNECT: a call is answered on either side.
28  * - PORT_STATE_IN_SETUP: the seizing is received, we wait for the first digit.
29  * - PORT_STATE_IN_OVERLAP: the digits are received.
30  * - PORT_STATE_IN_PROCEEDING: the number is complete, a SETUP is indicated.
31  * - PORT_STATE_IN_DISCONNECT: a clear-back was received, an DISCONNECT is indicated.
32  * - PORT_STATE_RELEASE: the clear forward procedure is started.
33  *
34  */
35
36 #include "main.h"
37
38 /* ss5 signal states */
39 enum {
40         SS5_STATE_IDLE,                 /* no signal */
41         SS5_STATE_SEIZING,              /* seizing */
42         SS5_STATE_PROCEED_TO_SEND,      /* proceed-to-send */
43         SS5_STATE_BUSY_FLASH,           /* busy-flash / clear back */
44         SS5_STATE_ACK_BUSY_FLASH,       /* acknowledge of busy/answer/clear-back */
45         SS5_STATE_ANSWER,               /* answer */
46         SS5_STATE_ACK_ANSWER,           /* acknowledge of busy/answer/clear-back */
47         SS5_STATE_FORWARD_TRANSFER,     /* forward transfer */
48         SS5_STATE_CLEAR_BACK,           /* clear-back */
49         SS5_STATE_ACK_CLEAR_BACK,       /* acknowledge of busy/answer/clear-back */
50         SS5_STATE_CLEAR_FORWARD,        /* clear-forward */
51         SS5_STATE_RELEASE_GUARD,        /* release-guard */
52         SS5_STATE_DIAL_OUT,             /* dialing state (transmitter) */
53         SS5_STATE_DIAL_IN,              /* dialing state (receiver) */
54         SS5_STATE_DIAL_IN_PULSE,        /* dialing state (receiver with pulses) */
55         SS5_STATE_DELAY,                /* after signal wait until next signal can be sent */
56         SS5_STATE_DOUBLE_SEIZE,         /* in case of a double seize, we make the remote size recognize it */
57 };
58 const char *ss5_state_name[] = {
59         "STATE_IDLE",
60         "STATE_SEIZING",
61         "STATE_PROCEED_TO_SEND",
62         "STATE_BUSY_FLASH",
63         "STATE_ACK_BUSY_FLASH",
64         "STATE_ANSWER",
65         "STATE_ACK_ANSWER",
66         "STATE_FORWARD_TRANSFER",
67         "STATE_CLEAR_BACK",
68         "STATE_ACK_CLEAR_BACK",
69         "STATE_CLEAR_FORWARD",
70         "STATE_RELEASE_GUARD",
71         "STATE_DIAL_OUT",
72         "STATE_DIAL_IN",
73         "STATE_DIAL_IN_PULSE",
74         "STATE_DELAY",
75         "STATE_DOUBLE_SEIZE",
76 };
77
78 enum {
79         SS5_SIGNAL_NULL,
80         /* sending signal states */
81         SS5_SIGNAL_SEND_ON,             /* sending signal, waiting for acknowledge */
82         SS5_SIGNAL_SEND_ON_RECOG,       /* sending signal, receiving ack, waiting for recogition timer */
83         SS5_SIGNAL_SEND_OFF,            /* silence, receiving ack, waiting for stop */
84         /* receiving signal states */
85         SS5_SIGNAL_RECEIVE_RECOG,       /* receiving signal, waiting for recognition timer */
86         SS5_SIGNAL_RECEIVE,             /* receiving signal / send ack, waiting for stop */
87         SS5_SIGNAL_DELAY,               /* delay after release guard to prevent ping-pong */
88         /* sending / receiving digit states */
89         SS5_SIGNAL_DIGIT_PAUSE,         /* pausing before sending (next) digit */
90         SS5_SIGNAL_DIGIT_ON,            /* sending digit */
91         SS5_SIGNAL_PULSE_OFF,           /* make */
92         SS5_SIGNAL_PULSE_ON,            /* break */
93 };
94 const char *ss5_signal_name[] = {
95         "NULL",
96         "SIGNAL_SEND_ON",
97         "SIGNAL_SEND_ON_RECOG",
98         "SIGNAL_SEND_OFF",
99         "SIGNAL_RECEIVE_RECOG",
100         "SIGNAL_RECEIVE",
101         "SIGNAL_DELAY",
102         "SIGNAL_DIGIT_PAUSE",
103         "SIGNAL_DIGIT_ON",
104         "SIGNAL_PULSE_OFF",
105         "SIGNAL_PULSE_ON",
106 };
107
108 /* ss5 signal timers (in samples) */
109 #define SS5_TIMER_AFTER_SIGNAL  (100*8) /* wait after signal is terminated */
110 #define SS5_TIMER_KP            (100*8) /* duration of KP1 or KP2 digit */
111 #define SS5_TIMER_DIGIT         (55*8)  /* duration of all other digits */
112 #define SS5_TIMER_PAUSE         (55*8)  /* pause between digits */
113 #define SS5_TIMER_FORWARD       (850*8) /* forward transfer length */
114 #define SS5_TIMER_RECOG_SEIZE   (40*8)  /* recognition time of seizing / proceed-to-send signal */
115 #define SS5_TIMER_RECOG_OTHER   (125*8) /* recognition time of all other f1/f2 signals */
116 #define SS5_TIMER_SIGNAL_LOSS   (15*8)  /* minimum time of signal loss for a continous signal */
117 #define SS5_TIMER_DOUBLE_SEIZE  (850*8) /* double seize length */
118 #define SS5_TIMER_RELEASE_GUARD (850*8) /* be sure to release after clear-forward */
119 #define SS5_TIMER_RELEASE_MAX   (2000*8)/* maximum time for release guard to prevent 'double-releasing' */
120 #define SS5_TIMER_RELEASE_DELAY (4000*8)/* wait after release guard to prevent ping-pong */
121 #define BELL_TIMER_BREAK        (50*8)  /* loop open, tone */
122 #define BELL_TIMER_MAKE         (50*8)  /* loop closed, no tone */
123 #define BELL_TIMER_PAUSE        (800*8) /* interdigit delay */
124 #define BELL_TIMER_RECOG_HANGUP (200*8) /* time to recognize hangup */
125 #define BELL_TIMER_RECOG_END    (300*8) /* recognize end of digit */
126
127 /* ss5 timers */
128 #define SS5_TIMER_OVERLAP       5.0     /* timeout for overlap digits received on outgoing exchange */
129
130
131 /*
132  * ss5 trace header
133  */
134 enum { /* even values are indications, odd values are requests */
135         SS5_SEIZING_IND,
136         SS5_SEIZING_REQ,
137         SS5_PROCEED_TO_SEND_IND,
138         SS5_PROCEED_TO_SEND_REQ,
139         SS5_BUSY_FLASH_IND,
140         SS5_BUSY_FLASH_REQ,
141         SS5_ANSWER_IND,
142         SS5_ANSWER_REQ,
143         SS5_CLEAR_BACK_IND,
144         SS5_CLEAR_BACK_REQ,
145         SS5_CLEAR_FORWARD_IND,
146         SS5_CLEAR_FORWARD_REQ,
147         SS5_RELEASE_GUARD_IND,
148         SS5_RELEASE_GUARD_REQ,
149         SS5_ACKNOWLEDGE_IND,
150         SS5_ACKNOWLEDGE_REQ,
151         SS5_DOUBLE_SEIZURE_IND,
152         SS5_DOUBLE_SEIZURE_REQ,
153         SS5_DIALING_IND,
154         SS5_DIALING_REQ,
155         SS5_FORWARD_TRANSFER_IND,
156         SS5_FORWARD_TRANSFER_REQ,
157 };
158 static struct isdn_message {
159         const char *name;
160         unsigned int value;
161 } ss5_message[] = {
162         {"SEIZING RECEIVED", SS5_SEIZING_IND},
163         {"SEIZING SENDING", SS5_SEIZING_REQ},
164         {"PROCEED-TO-SEND RECEIVED", SS5_PROCEED_TO_SEND_IND},
165         {"PROCEED-TO-SEND SENDING", SS5_PROCEED_TO_SEND_REQ},
166         {"BUSY-FLASH RECEIVED", SS5_BUSY_FLASH_IND},
167         {"BUSY-FLASH SENDING", SS5_BUSY_FLASH_REQ},
168         {"ANSWER RECEIVED", SS5_ANSWER_IND},
169         {"ANSWER SENDING", SS5_ANSWER_REQ},
170         {"CLEAR-BACK RECEIVED", SS5_CLEAR_BACK_IND},
171         {"CLEAR-BACK SENDING", SS5_CLEAR_BACK_REQ},
172         {"CLEAR-FORWARD RECEIVED", SS5_CLEAR_FORWARD_IND},
173         {"CLEAR-FORWARD SENDING", SS5_CLEAR_FORWARD_REQ},
174         {"RELEASE-GUARD RECEIVED", SS5_RELEASE_GUARD_IND},
175         {"RELEASE-GUARD SENDING", SS5_RELEASE_GUARD_REQ},
176         {"ACKNOWLEDGE RECEIVED", SS5_ACKNOWLEDGE_IND},
177         {"ACKNOWLEDGE SENDING", SS5_ACKNOWLEDGE_REQ},
178         {"DOUBLE-SEIZURE RECEIVED", SS5_DOUBLE_SEIZURE_IND},
179         {"DOUBLE-SEIZURE SENDING", SS5_DOUBLE_SEIZURE_REQ},
180         {"DIALING RECEIVED", SS5_DIALING_IND},
181         {"DIALING SENDING", SS5_DIALING_REQ},
182         {"FORWARD-TRANSFER RECEIVED", SS5_FORWARD_TRANSFER_IND},
183         {"FORWARD-TRANSFER SENDING", SS5_FORWARD_TRANSFER_REQ},
184         {NULL, 0},
185 };
186 static void ss5_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg, int channel)
187 {
188         int i;
189         char msgtext[64];
190
191         SCPY(msgtext, "<<UNKNOWN MESSAGE>>");
192         /* select message and primitive text */
193         i = 0;
194         while(ss5_message[i].name) {
195 //              if (msg == L3_NOTIFY_REQ) printf("val = %x %s\n", isdn_message[i].value, isdn_message[i].name);
196                 if (ss5_message[i].value == msg) {
197                         SCPY(msgtext, ss5_message[i].name);
198                         break;
199                 }
200                 i++;
201         }
202
203         /* init trace with given values */
204         start_trace(mISDNport?mISDNport->portnum:-1,
205                     mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
206                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
207                     port?port->p_dialinginfo.id:NULL,
208                     (msg&1)?DIRECTION_OUT:DIRECTION_IN,
209                     CATEGORY_CH,
210                     port?port->p_serial:0,
211                     msgtext);
212         add_trace("channel", NULL, "%d", channel);
213         switch (port->p_type) {
214                 case PORT_TYPE_SS5_OUT:
215                 add_trace("state", NULL, "outgoing");
216                 break;
217                 case PORT_TYPE_SS5_IN:
218                 add_trace("state", NULL, "incomming");
219                 break;
220                 default:
221                 add_trace("state", NULL, "idle");
222                 break;
223         }
224 }
225
226
227 /*
228  * changes release tone int busy signal
229  * this makes the line more authentic
230  */
231 void Pss5::set_tone(const char *dir, const char *name)
232 {
233         if (name && !strcmp(name, "cause_10"))
234                 name = "busy";
235
236         PmISDN::set_tone(dir, name);
237 }
238
239 /*
240  * creation of static channels
241  */
242 void ss5_create_channel(struct mISDNport *mISDNport, int i)
243 {
244         class Pss5              *ss5port;
245         char                    portname[32];
246         struct port_settings    port_settings;
247
248         SPRINT(portname, "%s-%d", mISDNport->name, i+1);
249
250         memset(&port_settings, 0, sizeof(port_settings));
251         SCPY(port_settings.tones_dir, options.tones_dir);
252
253         ss5port = new Pss5(PORT_TYPE_SS5_IDLE, mISDNport, portname, &port_settings, i + (i>=15) + 1, 1, B_MODE_TRANSPARENT);
254         if (!ss5port)
255                 FATAL("No memory for Pss5 class.\n");
256         if (!ss5port->p_m_b_channel)
257                 FATAL("No bchannel on given index.\n");
258
259         /* connect channel */
260         bchannel_event(mISDNport, ss5port->p_m_b_index, B_EVENT_USE);
261
262 }
263
264
265 /*
266  * hunt for a free line
267  * this function returns a port object in idle state.
268  */
269 class Pss5 *ss5_hunt_line(struct mISDNport *mISDNport)
270 {
271         int i;
272         class Port      *port;
273         class Pss5      *ss5port = NULL;
274         struct select_channel *selchannel; 
275
276         PDEBUG(DEBUG_SS5, "Entered name=%s\n", mISDNport->name);
277         selchannel = mISDNport->ifport->out_channel;
278         while(selchannel) {
279                 switch(selchannel->channel) {
280                         case CHANNEL_FREE: /* free channel */
281                         case CHANNEL_ANY: /* any channel */
282                         for (i = 0; i < mISDNport->b_num; i++) {
283                                 port = mISDNport->b_port[i];
284                                 PDEBUG(DEBUG_SS5, "Checking port %p on index\n", port, i);
285                                 if (!port)
286                                         continue;
287                                 if (port->p_type == PORT_TYPE_SS5_IN || port->p_type == PORT_TYPE_SS5_OUT)
288                                         PDEBUG(DEBUG_SS5, "Checking port %s: channel %d not available, because port not idle type.\n",
289                                                 mISDNport->name, i);
290                                 if (port->p_type != PORT_TYPE_SS5_IDLE)
291                                         continue;
292                                 ss5port = (class Pss5 *)port;
293                                 /* is really idle ? */
294                                 if (ss5port->p_state == PORT_STATE_IDLE
295                                  && ss5port->p_m_s_state == SS5_STATE_IDLE)
296                                         return ss5port;
297                                 PDEBUG(DEBUG_SS5, "Checking port %s: channel %d not available, because p_state=%d, ss5_state=%d.\n",
298                                         mISDNport->name, i, ss5port->p_state,ss5port->p_m_s_state);
299                         }
300                         PDEBUG(DEBUG_SS5, "no free interface\n");
301                         return NULL;
302
303                         case CHANNEL_NO:
304                         break;
305
306                         default:
307                         if (selchannel->channel<1 || selchannel->channel==16)
308                                 break;
309                         i = selchannel->channel-1-(selchannel->channel>=17);
310                         if (i >= mISDNport->b_num)
311                                 break;
312                         port = mISDNport->b_port[i];
313                         if (!port)
314                                 break;
315                         if (port->p_type == PORT_TYPE_SS5_IN || port->p_type == PORT_TYPE_SS5_OUT)
316                                 PDEBUG(DEBUG_SS5, "Checking port %s: channel %d not available, because port not idle type.\n",
317                                         mISDNport->name, i);
318                         if (port->p_type != PORT_TYPE_SS5_IDLE)
319                                 break;
320                         ss5port = (class Pss5 *)port;
321                         /* is really idle ? */
322                         if (ss5port->p_state == PORT_STATE_IDLE
323                          && ss5port->p_m_s_state == SS5_STATE_IDLE)
324                                 return ss5port;
325                         PDEBUG(DEBUG_SS5, "Checking port %s: channel %d not available, because p_state=%d, ss5_state=%d.\n",
326                                 mISDNport->name, i, ss5port->p_state,ss5port->p_m_s_state);
327                 }
328                 selchannel = selchannel->next;
329         }
330         PDEBUG(DEBUG_SS5, "no free interface in channel list\n");
331         return NULL;
332 }
333
334
335 /*
336  * constructor
337  */
338 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)
339 {
340         p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
341         p_m_s_state = SS5_STATE_IDLE;
342         p_m_s_signal = SS5_SIGNAL_NULL;
343         p_m_s_dial[0] = '\0';
344         p_m_s_digit_i = 0;
345         p_m_s_pulsecount = 0;
346         p_m_s_last_digit = ' ';
347         p_m_s_signal_loss = 0;
348         p_m_s_decoder_count = 0;
349         //p_m_s_decoder_buffer;
350         p_m_s_sample_nr = 0;
351         p_m_s_recog = 0;
352         p_m_s_timer = 0.0;
353         p_m_s_timer_fn = NULL;
354         p_m_s_answer = 0;
355         p_m_s_busy_flash = 0;
356         p_m_s_clear_back = 0;
357         memset(p_m_s_delay_digits, ' ', sizeof(p_m_s_delay_digits));
358         memset(p_m_s_delay_mute, ' ', sizeof(p_m_s_delay_mute));
359
360         /* turn on signalling receiver */
361         inband_receive_on();
362
363         PDEBUG(DEBUG_SS5, "Created new mISDNPort(%s). Currently %d objects use.\n", portname, mISDNport->use);
364 }
365
366
367 /*
368  * destructor
369  */
370 Pss5::~Pss5()
371 {
372 }
373
374
375 /*
376  * change ss5 states
377  */
378 void Pss5::_new_ss5_state(int state, const char *func, int line)
379 {
380         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]);
381         p_m_s_state = state;
382         p_m_s_signal = SS5_SIGNAL_NULL;
383 }
384 void Pss5::_new_ss5_signal(int signal, const char *func, int line)
385 {
386         if (p_m_s_signal)
387                 PDEBUG(DEBUG_SS5, "%s(%s:%d): changing SS5 signal state from %s to %s\n", p_name, func, line, ss5_signal_name[p_m_s_signal], ss5_signal_name[signal]);
388         else
389                 PDEBUG(DEBUG_SS5, "%s(%s:%d): changing SS5 signal state to %s\n", p_name, func, line, ss5_signal_name[signal]);
390         p_m_s_signal = signal;
391 }
392
393
394 /*
395  * signalling receiver
396  *
397  * this function will be called for every audio received.
398  */
399 void Pss5::inband_receive(unsigned char *buffer, int len)
400 {
401         int count = 0, tocopy, space;
402         char digit;
403
404         again:
405         /* how much to copy ? */
406         tocopy = len - count;
407         space = SS5_DECODER_NPOINTS - p_m_s_decoder_count;
408         if (space < 0)
409                 FATAL("p_m_s_decoder_count overflows\n");
410         if (space < tocopy)
411                 tocopy = space;
412         /* copy an count */
413         memcpy(p_m_s_decoder_buffer+p_m_s_decoder_count, buffer+count, tocopy);
414         p_m_s_decoder_count += tocopy;
415         count += tocopy;
416         /* decoder buffer not completely filled ? */
417         if (tocopy < space)
418                 return;
419
420         /* decode one frame */
421         digit = ss5_decode(p_m_s_decoder_buffer, SS5_DECODER_NPOINTS);
422         p_m_s_decoder_count = 0;
423
424 #ifdef DEBUG_DETECT
425         if (p_m_s_last_digit != digit && digit != ' ')
426                 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]);
427 #endif
428
429         /* ignore short loss of signal */
430         if (p_m_s_signal_loss) {
431                 if (digit == ' ') {
432                         /* still lost */
433                         if (p_m_s_signal_loss >= SS5_TIMER_SIGNAL_LOSS) {
434 #ifdef DEBUG_DETECT
435                                 PDEBUG(DEBUG_SS5, "%s: signal '%c' lost too long\n", p_name, p_m_s_last_digit);
436 #endif
437                                 /* long enough, we stop loss-timer */
438                                 p_m_s_signal_loss = 0;
439                         } else {
440                                 /* not long enough, so we use last signal */
441                                 p_m_s_signal_loss += SS5_DECODER_NPOINTS;
442                                 digit = p_m_s_last_digit;
443                         }
444                 } else {
445                         /* signal is back, we stop timer and store */
446 #ifdef DEBUG_DETECT
447                         PDEBUG(DEBUG_SS5, "%s: signal '%c' lost, but continues with '%c'\n", p_name, p_m_s_last_digit, digit);
448 #endif
449                         p_m_s_signal_loss = 0;
450                         p_m_s_last_digit = digit;
451                 }
452         } else {
453                 if (p_m_s_last_digit != ' ' && digit == ' ') {
454 #ifdef DEBUG_DETECT
455                         PDEBUG(DEBUG_SS5, "%s: signal '%c' lost\n", p_name, p_m_s_last_digit);
456 #endif
457                         /* restore last digit until signal is really lost */
458                         p_m_s_last_digit = digit;
459                         /* starting to loose signal */
460                         p_m_s_signal_loss = SS5_DECODER_NPOINTS;
461                 } else {
462                         /* storing last signal, in case it is lost */
463                         p_m_s_last_digit = digit;
464                 }
465         }
466
467         /* update mute */
468         if ((p_m_mISDNport->ss5 & SS5_FEATURE_SUPPRESS)) {
469                 int mdigit;
470                 memcpy(p_m_s_delay_mute, p_m_s_delay_mute+1, sizeof(p_m_s_delay_mute)-1);
471                 p_m_s_delay_mute[sizeof(p_m_s_delay_mute)-1] = digit;
472                 mdigit = p_m_s_delay_mute[0];
473                 if (p_m_mute) {
474                         /* mute is on */
475                         if (mdigit != 'A' && mdigit != 'B' && mdigit != 'C')
476                                 mute_off();
477                 } else {
478                         /* mute is off */
479                         if (mdigit == 'A' || mdigit == 'B' || mdigit == 'C')
480                                 mute_on();
481                 }
482         }
483
484         /* delay decoded tones */
485         if ((p_m_mISDNport->ss5 & SS5_FEATURE_DELAY)) {
486                 /* shift buffer */
487                 memcpy(p_m_s_delay_digits, p_m_s_delay_digits+1, sizeof(p_m_s_delay_digits)-1);
488                 /* first in */
489                 p_m_s_delay_digits[sizeof(p_m_s_delay_digits)-1] = digit;
490                 /* first out */
491                 digit = p_m_s_delay_digits[0];
492         }
493
494         /* clear forward is always recognized */
495         if (digit == 'C' && p_m_s_state != SS5_STATE_CLEAR_FORWARD && p_m_s_state != SS5_STATE_RELEASE_GUARD) {
496                 switch (p_type) {
497                         case PORT_TYPE_SS5_OUT:
498                         PDEBUG(DEBUG_SS5, "%s: received release-guard, waiting for recognition\n", p_name);
499                         break;
500                         case PORT_TYPE_SS5_IN:
501                         PDEBUG(DEBUG_SS5, "%s: received clear-forward, waiting for recognition\n", p_name);
502                         break;
503                         default:
504                         PDEBUG(DEBUG_SS5, "%s: received clear-forward in idle state, waiting for recognition\n", p_name);
505                         break;
506                 }
507                 new_state(PORT_STATE_RELEASE);
508                 new_ss5_state(SS5_STATE_RELEASE_GUARD);
509                 new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
510                 p_m_s_recog = 0;
511         } else
512         switch(p_m_s_state) {
513                 case SS5_STATE_IDLE:
514                 /* seizing only recognized in port idle state */
515                 if (p_state == PORT_STATE_IDLE) {
516                         if (digit != 'A')
517                                 break;
518                         seize:
519                         PDEBUG(DEBUG_SS5, "%s: received seize, waiting for recognition\n", p_name);
520                         p_type = PORT_TYPE_SS5_IN;
521                         new_ss5_state(SS5_STATE_PROCEED_TO_SEND);
522                         new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
523                         p_m_s_recog = 0;
524                         break;
525                 }
526                 /* other signals */
527                 if (digit == 'A') {
528                         if (p_type != PORT_TYPE_SS5_OUT)
529                                 break;
530                         PDEBUG(DEBUG_SS5, "%s: received answer, waiting for recognition\n", p_name);
531                         new_ss5_state(SS5_STATE_ACK_ANSWER);
532                         new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
533                         p_m_s_recog = 0;
534                         break;
535                 }
536                 if (digit == 'B') {
537                         if (p_type == PORT_TYPE_SS5_IN) {
538                                 if ((p_m_mISDNport->ss5 & SS5_FEATURE_BELL)) {
539                                         new_ss5_state(SS5_STATE_DIAL_IN_PULSE); /* go pulsing state */
540                                         new_ss5_signal(SS5_SIGNAL_PULSE_OFF); /* we are starting with pulse off */
541                                         p_m_s_pulsecount = 0; /* init pulse counter */
542                                         p_m_s_dial[0] = '\0'; /* init dial string */
543                                         pulse_ind(1); /* also inits recogition timer... */
544                                         break;
545                                 }
546                                 PDEBUG(DEBUG_SS5, "%s: received forward-transfer, waiting for recognition\n", p_name);
547                                 /* forward transfer on incomming lines */
548                                 new_ss5_state(SS5_STATE_FORWARD_TRANSFER);
549                                 new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
550                                 p_m_s_recog = 0;
551                                 break;
552                         }
553                         if (p_state == PORT_STATE_CONNECT) {
554                                 PDEBUG(DEBUG_SS5, "%s: received clear-back, waiting for recognition\n", p_name);
555                                 new_ss5_state(SS5_STATE_ACK_CLEAR_BACK);
556                         } else {
557                                 PDEBUG(DEBUG_SS5, "%s: received busy-flash, waiting for recognition\n", p_name);
558                                 new_ss5_state(SS5_STATE_ACK_BUSY_FLASH);
559                         }
560                         new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
561                         p_m_s_recog = 0;
562                         break;
563                 }
564                 /* dialing only allowed in incomming setup state */
565                 if (p_state == PORT_STATE_IN_SETUP) {
566                         if (!strchr("1234567890*#abc", digit))
567                                 break;
568                         PDEBUG(DEBUG_SS5, "%s: received dialing start with '%c'\n", p_name, digit);
569                         new_ss5_state(SS5_STATE_DIAL_IN);
570                         new_ss5_signal(SS5_SIGNAL_DIGIT_ON);
571                         p_m_s_dial[0] = '\0';
572                         digit_ind(digit);
573                         break;
574                 }
575                 break;
576                 /* sending seizing */
577                 case SS5_STATE_SEIZING:
578                 switch (p_m_s_signal) {
579                         case SS5_SIGNAL_SEND_ON:
580                         if (digit == 'A') { /* double seize */
581                                 PDEBUG(DEBUG_SS5, "%s: received double seizure\n", p_name, digit);
582                                 double_seizure_ind();
583                                 break;
584                         }
585                         if (digit == 'B') {
586                                 PDEBUG(DEBUG_SS5, "%s: received answer to outgoing seize, waiting for recognition\n", p_name);
587                                 /* set recognition timer */
588                                 new_ss5_signal(SS5_SIGNAL_SEND_ON_RECOG);
589                                 p_m_s_recog = 0;
590                         }
591                         break;
592                         case SS5_SIGNAL_SEND_ON_RECOG:
593                         if (digit != 'B') { /* seize */
594                                 PDEBUG(DEBUG_SS5, "%s: answer to outgoing seize is gone before recognition\n", p_name);
595                                 new_ss5_signal(SS5_SIGNAL_SEND_ON);
596 //                              p_m_s_sample_nr = 0;
597 //                              inband_send_on();
598                                 break;
599                         }
600                         p_m_s_recog += SS5_DECODER_NPOINTS;
601                         if (p_m_s_recog < SS5_TIMER_RECOG_SEIZE)
602                                 break;
603                         PDEBUG(DEBUG_SS5, "%s: answer to outgoing seize recognized, turning off, waiting for recognition\n", p_name);
604                         new_ss5_signal(SS5_SIGNAL_SEND_OFF);
605                         break;
606                         case SS5_SIGNAL_SEND_OFF:
607                         if (digit == 'B')
608                                 break;
609                         PDEBUG(DEBUG_SS5, "%s: outgoing seizure is complete, proceeding...\n", p_name);
610                         new_ss5_state(SS5_STATE_IDLE);
611                         proceed_to_send_ind();
612                         break;
613                 }
614                 break;
615                 /* answer to seize */
616                 case SS5_STATE_PROCEED_TO_SEND:
617                 if (p_m_s_signal == SS5_SIGNAL_RECEIVE_RECOG) {
618                         if (digit != 'A') {
619                                 PDEBUG(DEBUG_SS5, "%s: incomming seize is gone before recognition\n", p_name);
620                                 new_ss5_state(SS5_STATE_IDLE);
621                                 p_type = PORT_TYPE_SS5_IDLE;
622                                 break;
623                         }
624                         p_m_s_recog += SS5_DECODER_NPOINTS;
625                         if (p_m_s_recog < SS5_TIMER_RECOG_SEIZE)
626                                 break;
627                         PDEBUG(DEBUG_SS5, "%s: incomming seize is recognized, responding...\n", p_name);
628                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
629                         p_m_s_sample_nr = 0;
630                         inband_send_on();
631                         break;
632                 }
633                 if (digit != 'A') {
634                         PDEBUG(DEBUG_SS5, "%s: incomming seize is gone after responding\n", p_name);
635                         new_ss5_state(SS5_STATE_IDLE);
636                         seizing_ind();
637                 }
638                 break;
639                 /* sending busy flash / answer / clear-back */
640                 case SS5_STATE_BUSY_FLASH:
641                 case SS5_STATE_ANSWER:
642                 case SS5_STATE_CLEAR_BACK:
643                 switch (p_m_s_signal) {
644                         case SS5_SIGNAL_SEND_ON:
645                         if (digit == 'A') {
646                                 PDEBUG(DEBUG_SS5, "%s: received acknowledge, waiting for recognition\n", p_name);
647                                 /* set recognition timer */
648                                 new_ss5_signal(SS5_SIGNAL_SEND_ON_RECOG);
649                                 p_m_s_recog = 0;
650                         }
651                         break;
652                         case SS5_SIGNAL_SEND_ON_RECOG:
653                         if (digit != 'A') {
654                                 PDEBUG(DEBUG_SS5, "%s: acknowledge is gone before recognition\n", p_name);
655                                 new_ss5_signal(SS5_SIGNAL_SEND_ON);
656 //                              p_m_s_sample_nr = 0;
657 //                              inband_send_on();
658                                 break;
659                         }
660                         p_m_s_recog += SS5_DECODER_NPOINTS;
661                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
662                                 break;
663                         PDEBUG(DEBUG_SS5, "%s: acknowledge recognized, turning off, waiting for recognition\n", p_name);
664                         new_ss5_signal(SS5_SIGNAL_SEND_OFF);
665                         break;
666                         case SS5_SIGNAL_SEND_OFF:
667                         if (digit == 'A')
668                                 break;
669                         PDEBUG(DEBUG_SS5, "%s: outgoing signal is complete\n", p_name);
670                         new_ss5_state(SS5_STATE_IDLE);
671                         break;
672                 }
673                 break;
674                 /* answer to busy-flash / clear back */
675                 case SS5_STATE_ACK_BUSY_FLASH:
676                 case SS5_STATE_ACK_CLEAR_BACK:
677                 if (p_m_s_signal == SS5_SIGNAL_RECEIVE_RECOG) {
678                         if (digit != 'B') {
679                                 PDEBUG(DEBUG_SS5, "%s: incomming clear-back/busy-flash is gone before recognition\n", p_name);
680                                 new_ss5_state(SS5_STATE_IDLE);
681                                 break;
682                         }
683                         p_m_s_recog += SS5_DECODER_NPOINTS;
684                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
685                                 break;
686                         PDEBUG(DEBUG_SS5, "%s: incomming clear-back/busy-flash is recognized, responding...\n", p_name);
687                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
688                         p_m_s_sample_nr = 0;
689                         inband_send_on();
690                         break;
691                 }
692                 if (digit != 'B') {
693                         PDEBUG(DEBUG_SS5, "%s: incomming clear-back/busy-flash is gone after responding\n", p_name);
694                         new_ss5_state(SS5_STATE_IDLE);
695                         if (p_m_s_state == SS5_STATE_ACK_BUSY_FLASH)
696                                 busy_flash_ind();
697                         else
698                                 clear_back_ind();
699                 }
700                 break;
701                 /* answer to answer */
702                 case SS5_STATE_ACK_ANSWER:
703                 if (p_m_s_signal == SS5_SIGNAL_RECEIVE_RECOG) {
704                         if (digit != 'A') {
705                                 PDEBUG(DEBUG_SS5, "%s: incomming answer is gone before recognition\n", p_name);
706                                 new_ss5_state(SS5_STATE_IDLE);
707                                 break;
708                         }
709                         p_m_s_recog += SS5_DECODER_NPOINTS;
710                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
711                                 break;
712                         PDEBUG(DEBUG_SS5, "%s: incomming answer is recognized, responding...\n", p_name);
713                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
714                         p_m_s_sample_nr = 0;
715                         inband_send_on();
716                         break;
717                 }
718                 if (digit != 'A') {
719                         PDEBUG(DEBUG_SS5, "%s: incomming answer is gone after responding\n", p_name);
720                         new_ss5_state(SS5_STATE_IDLE);
721                         answer_ind();
722                 }
723                 break;
724                 /* sending clear-forward */
725                 case SS5_STATE_CLEAR_FORWARD:
726                 switch (p_m_s_signal) {
727                         case SS5_SIGNAL_SEND_ON:
728                         if (digit == 'C') {
729                                 PDEBUG(DEBUG_SS5, "%s: received answer to clear-forward, waiting for recognition\n", p_name);
730                                 /* set recognition timer */
731                                 new_ss5_signal(SS5_SIGNAL_SEND_ON_RECOG);
732                                 p_m_s_recog = 0;
733                         }
734                         break;
735                         case SS5_SIGNAL_SEND_ON_RECOG:
736                         if (digit != 'C') {
737                                 PDEBUG(DEBUG_SS5, "%s: answer to clear-forward is gone before recognition\n", p_name);
738                                 new_ss5_signal(SS5_SIGNAL_SEND_ON);
739 //                              p_m_s_sample_nr = 0;
740 //                              inband_send_on();
741                                 break;
742                         }
743                         p_m_s_recog += SS5_DECODER_NPOINTS;
744                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
745                                 break;
746                         PDEBUG(DEBUG_SS5, "%s: answer to clear-forward recognized, turning off, waiting for recognition\n", p_name);
747                         new_ss5_signal(SS5_SIGNAL_SEND_OFF);
748                         break;
749                         case SS5_SIGNAL_SEND_OFF:
750                         if (digit == 'A') {
751                                 PDEBUG(DEBUG_SS5, "%s: received seize right after clear-forward answer, continue with seize\n", p_name);
752                                 new_state(PORT_STATE_IDLE);
753                                 goto seize;
754                         }
755                         if (digit == 'C')
756                                 break;
757                         PDEBUG(DEBUG_SS5, "%s: answer to clear-forward is complete\n", p_name);
758                         release_guard_ind();
759                         new_ss5_signal(SS5_SIGNAL_DELAY);
760                         p_m_s_recog = 0; /* use recog to delay */
761                         PDEBUG(DEBUG_SS5, "%s: answer to clear-forward on outgoing interface starting delay to prevent ping-pong\n", p_name);
762                         break;
763                         case SS5_SIGNAL_DELAY:
764                         if (digit == 'A') {
765                                 PDEBUG(DEBUG_SS5, "%s: received seize right after clear-forward answer, continue with seize\n", p_name);
766                                 new_state(PORT_STATE_IDLE);
767                                 goto seize;
768                         }
769                         p_m_s_recog += SS5_DECODER_NPOINTS;
770                         if (p_m_s_recog < SS5_TIMER_RELEASE_DELAY)
771                                 break;
772                         PDEBUG(DEBUG_SS5, "%s: delay time over, going idle\n", p_name);
773                         new_ss5_state(SS5_STATE_IDLE);
774                         new_state(PORT_STATE_IDLE);
775                         p_type = PORT_TYPE_SS5_IDLE;
776                         break;
777                 }
778                 break;
779                 /* answer to release-guard*/
780                 case SS5_STATE_RELEASE_GUARD:
781                 switch (p_m_s_signal) {
782                         case SS5_SIGNAL_RECEIVE_RECOG:
783                         if (digit != 'C') {
784                                 if (p_type == PORT_TYPE_SS5_OUT)
785                                         PDEBUG(DEBUG_SS5, "%s: incomming release-guard is gone before recognition\n", p_name);
786                                 else
787                                         PDEBUG(DEBUG_SS5, "%s: incomming clear forward is gone before recognition\n", p_name);
788                                 new_ss5_state(SS5_STATE_IDLE);
789                                 break;
790                         }
791                         p_m_s_recog += SS5_DECODER_NPOINTS;
792                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
793                                 break;
794                         if (p_type == PORT_TYPE_SS5_OUT)
795                                 PDEBUG(DEBUG_SS5, "%s: incomming release-guard is recognized, responding...\n", p_name);
796                         else
797                                 PDEBUG(DEBUG_SS5, "%s: incomming clear-forward is recognized, responding...\n", p_name);
798                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
799                         p_m_s_sample_nr = 0;
800                         inband_send_on();
801                         break;
802                         case SS5_SIGNAL_RECEIVE:
803                         if (digit == 'C'
804                          || p_m_s_sample_nr < 256) /* small hack to keep answer for at least some time */
805                          break;
806 #if 0
807                         if (digit == 'A') {
808                                 PDEBUG(DEBUG_SS5, "%s: received seize right after clear-forward is received\n", p_name);
809                                 new_state(PORT_STATE_IDLE);
810                                 goto seize;
811                         }
812 #endif
813                         /* if clear forward stops right after recognition on the incomming side,
814                          * the release guard signal stops and may be too short to be recognized at the outgoing side.
815                          * to prevent this, a timer can be started to force a release guard that is long
816                          * enough to be recognized on the outgoing side.
817                          * this will prevent braking via blueboxing (other tricks may still be possible).
818                          */
819                         if ((p_m_mISDNport->ss5 & SS5_FEATURE_RELEASEGUARDTIMER)
820                          && p_m_s_sample_nr < SS5_TIMER_RELEASE_GUARD)
821                                 break;
822                         if (p_type == PORT_TYPE_SS5_OUT)
823                                 PDEBUG(DEBUG_SS5, "%s: incomming release-guard is gone after responding\n", p_name);
824                         else
825                                 PDEBUG(DEBUG_SS5, "%s: incomming clear-forward is gone after responding\n", p_name);
826                         if (p_type == PORT_TYPE_SS5_OUT) {
827                                 release_guard_ind();
828                                 new_ss5_signal(SS5_SIGNAL_DELAY);
829                                 p_m_s_recog = 0; /* use recog to delay */
830                                 PDEBUG(DEBUG_SS5, "%s: incomming release-guard on outgoing interface starting delay to prevent ping-pong\n", p_name);
831                         } else {
832                                 clear_forward_ind();
833                                 new_ss5_state(SS5_STATE_IDLE);
834                         }
835                         break;
836                         case SS5_SIGNAL_DELAY:
837                         if (digit == 'A') {
838                                 PDEBUG(DEBUG_SS5, "%s: received seize right after release guard is gone, continue with seize\n", p_name);
839                                 new_state(PORT_STATE_IDLE);
840                                 goto seize;
841                         }
842                         p_m_s_recog += SS5_DECODER_NPOINTS;
843                         if (p_m_s_recog < SS5_TIMER_RELEASE_DELAY)
844                                 break;
845                         PDEBUG(DEBUG_SS5, "%s: delay time over, going idle\n", p_name);
846                         new_ss5_state(SS5_STATE_IDLE);
847                         new_state(PORT_STATE_IDLE);
848                         p_type = PORT_TYPE_SS5_IDLE;
849                         break;
850                 }
851                 break;
852                 /* wait time to recognize forward transfer */
853                 case SS5_STATE_FORWARD_TRANSFER:
854                 if (p_m_s_signal == SS5_SIGNAL_RECEIVE_RECOG) {
855                         if (digit != 'B') {
856                                 PDEBUG(DEBUG_SS5, "%s: incomming forward-transfer is gone before recognition\n", p_name);
857                                 new_ss5_state(SS5_STATE_IDLE);
858                                 break;
859                         }
860                         p_m_s_recog += SS5_DECODER_NPOINTS;
861                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
862                                 break;
863                         PDEBUG(DEBUG_SS5, "%s: incomming forward-transfer is recognized, responding, if BELL feature was selected...\n", p_name);
864                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
865 #if 0
866                         p_m_s_sample_nr = 0;
867                         inband_send_on();
868 #endif
869                         break;
870                 }
871                 if (digit != 'B') {
872                         PDEBUG(DEBUG_SS5, "%s: incomming forward-transfer is gone after recognition\n", p_name);
873                         new_ss5_state(SS5_STATE_IDLE);
874                         forward_transfer_ind();
875                         break;
876                 }
877                 break;
878                 /* dialing is received */
879                 case SS5_STATE_DIAL_IN:
880                 if (strchr("1234567890*#abc", digit)) {
881                         if (p_m_s_signal != SS5_SIGNAL_DIGIT_PAUSE)
882                                 break;
883                         PDEBUG(DEBUG_SS5, "%s: incomming digit '%c' is recognized\n", p_name, digit);
884                         new_ss5_signal(SS5_SIGNAL_DIGIT_ON);
885                         digit_ind(digit);
886                 } else {
887                         if (p_m_s_signal != SS5_SIGNAL_DIGIT_ON)
888                                 break;
889                         PDEBUG(DEBUG_SS5, "%s: incomming digit is gone after recognition\n", p_name);
890                         new_ss5_signal(SS5_SIGNAL_DIGIT_PAUSE);
891                 }
892                 break;
893                 case SS5_STATE_DIAL_IN_PULSE:
894                 if (digit == 'B')
895                         pulse_ind(1);
896                 else
897                         pulse_ind(0);
898                 break;
899         }
900
901         /* something more to decode ? */
902         if (count != len)
903                 goto again;
904 }
905
906
907 /*
908  * signalling sender
909  *
910  * this function generates tones and assembles dial string with digits and pause
911  * the result is sent to mISDN. it uses the ss5_encode() function.
912  * except for dialing and forward-transfer, tones are continuous and will not change state.
913  */
914 int Pss5::inband_send(unsigned char *buffer, int len)
915 {
916         int count = 0; /* sample counter */
917         int duration;
918         char digit;
919         int tocode, tosend;
920
921         switch(p_m_s_state) {
922                 /* turn off transmitter in idle state */
923                 case SS5_STATE_IDLE:
924                 inband_send_off();
925                 break;
926
927                 case SS5_STATE_SEIZING:
928                 if (p_m_s_signal != SS5_SIGNAL_SEND_ON
929                  && p_m_s_signal != SS5_SIGNAL_SEND_ON_RECOG)
930                         break;
931                 duration = -1; /* continuous */
932                 digit = 'A';
933                 send:
934                 /* how much samples do we have left */
935                 if (duration < 0)
936                         tocode = len;
937                 else
938                         tocode = duration - p_m_s_sample_nr;
939                 if (tocode > 0) {
940                         if (tocode > len)
941                                 tocode = len;
942                         ss5_encode(buffer, tocode, digit, p_m_s_sample_nr);
943                         /* increase counters */
944                         p_m_s_sample_nr += tocode;
945                         count += tocode;
946                 }
947                 /* more to come ? */
948                 if (duration > 0 && p_m_s_sample_nr >= duration) {
949                         PDEBUG(DEBUG_SS5, "%s: sending tone '%c' complete, starting delay\n", p_name, digit);
950                         if (p_m_s_state == SS5_STATE_DOUBLE_SEIZE) {
951                                 do_release(CAUSE_NOCHANNEL, LOCATION_BEYOND);
952                                 break;
953                         }
954                         new_ss5_state(SS5_STATE_DELAY);
955                         p_m_s_sample_nr = 0;
956                 }
957 #if 0
958                 /* stop sending if too long */
959                 if (duration < 0 && p_m_s_sample_nr >= SS5_TIMER_MAX_SIGNAL) {
960                         PDEBUG(DEBUG_SS5, "%s: sending tone '%c' too long, stopping\n", p_name, digit);
961                         inband_send_off();
962                         break;
963                 }
964 #endif
965                 break;
966                 /* incomming seizing */
967                 case SS5_STATE_PROCEED_TO_SEND:
968                 if (p_m_s_signal != SS5_SIGNAL_RECEIVE)
969                         break;
970                 duration = -1; /* continuous */
971                 digit = 'B';
972                 goto send;
973
974                 case SS5_STATE_BUSY_FLASH:
975                 case SS5_STATE_CLEAR_BACK:
976                 if (p_m_s_signal != SS5_SIGNAL_SEND_ON
977                  && p_m_s_signal != SS5_SIGNAL_SEND_ON_RECOG)
978                         break;
979                 duration = -1; /* continuous */
980                 digit = 'B';
981                 goto send;
982
983                 case SS5_STATE_ANSWER:
984                 if (p_m_s_signal != SS5_SIGNAL_SEND_ON
985                  && p_m_s_signal != SS5_SIGNAL_SEND_ON_RECOG)
986                         break;
987                 duration = -1; /* continuous */
988                 digit = 'A';
989                 goto send;
990
991                 case SS5_STATE_ACK_BUSY_FLASH:
992                 case SS5_STATE_ACK_ANSWER:
993                 case SS5_STATE_ACK_CLEAR_BACK:
994                 if (p_m_s_signal != SS5_SIGNAL_RECEIVE)
995                         break;
996                 duration = -1; /* continuous */
997                 digit = 'A';
998                 goto send;
999
1000 #if 0
1001                 case SS5_STATE_FORWARD_TRANSFER:
1002                 if (p_m_s_signal != SS5_SIGNAL_RECEIVE)
1003                         break;
1004                 /* only on bell systems continue and acknowledge tone */
1005                 if (!(p_m_mISDNport->ss5 & SS5_FEATURE_BELL))
1006                         break;
1007                 duration = SS5_TIMER_FORWARD;
1008                 digit = 'B';
1009                 goto send;
1010 #endif
1011
1012                 case SS5_STATE_CLEAR_FORWARD:
1013                 if (p_m_s_signal != SS5_SIGNAL_SEND_ON
1014                  && p_m_s_signal != SS5_SIGNAL_SEND_ON_RECOG)
1015                         break;
1016                 duration = -1; /* continuous */
1017                 digit = 'C';
1018                 goto send;
1019
1020                 case SS5_STATE_RELEASE_GUARD:
1021                 if (p_m_s_signal != SS5_SIGNAL_RECEIVE
1022                  && p_m_s_signal != SS5_SIGNAL_DELAY)
1023                         break;
1024                 /* prevent from sending release guard too long */
1025                 if (p_m_s_sample_nr >= SS5_TIMER_RELEASE_MAX)
1026                         break;
1027                 duration = -1; /* continuous */
1028                 digit = 'C';
1029                 goto send;
1030
1031                 case SS5_STATE_DIAL_OUT:
1032                 if ((p_m_mISDNport->ss5 & SS5_FEATURE_PULSEDIALING))
1033                         count = inband_dial_pulse(buffer, len, count);
1034                 else
1035                         count = inband_dial_mf(buffer, len, count);
1036                 break;
1037                 break;
1038
1039                 case SS5_STATE_DELAY:
1040                 tosend = len - count;
1041                 memset(buffer+count, audio_s16_to_law[0], tosend);
1042                 p_m_s_sample_nr += tosend;
1043                 count += tosend;
1044                 if (p_m_s_sample_nr >= SS5_TIMER_AFTER_SIGNAL) {
1045                         PDEBUG(DEBUG_SS5, "%s: delay done, ready for next signal\n", p_name);
1046                         new_ss5_state(SS5_STATE_IDLE);
1047                         inband_send_off();
1048                 }
1049                 break;
1050
1051                 case SS5_STATE_DOUBLE_SEIZE:
1052                 duration = SS5_TIMER_DOUBLE_SEIZE;
1053                 digit = 'A';
1054                 goto send;
1055
1056                 /* nothing to send */
1057                 default:
1058                 PERROR("inband signalling is turned on, but no signal is processed here.");
1059                 new_ss5_state(SS5_STATE_IDLE);
1060                 inband_send_off();
1061                 return 0;
1062         }
1063
1064         /* return (partly) filled buffer */
1065         return count;
1066 }
1067
1068
1069 int Pss5::inband_dial_mf(unsigned char *buffer, int len, int count)
1070 {
1071         int duration;
1072         int tocode, tosend;
1073         char digit;
1074
1075         /* dialing
1076          *
1077          * p_m_s_dial: digits to be dialed
1078          * p_m_s_digit_i: current digit counter
1079          * p_m_s_signal: current signal state
1080          * p_m_s_sample_nr: current sample number
1081          */
1082         again:
1083         /* get digit and duration */
1084         digit = p_m_s_dial[p_m_s_digit_i];
1085         if (!digit) { /* if end of string reached */
1086                 new_ss5_state(SS5_STATE_DELAY);
1087                 p_m_s_sample_nr = 0;
1088                 return count;
1089         }
1090         if (p_m_s_signal == SS5_SIGNAL_DIGIT_ON) {
1091                 if (!p_m_s_digit_i) // first digit
1092                         duration = SS5_TIMER_KP;
1093                 else
1094                         duration = SS5_TIMER_DIGIT;
1095         } else {
1096                 duration = SS5_TIMER_PAUSE;
1097         }
1098         /* end of digit/pause ? */
1099         if (p_m_s_sample_nr >= duration) {
1100                 p_m_s_sample_nr = 0;
1101                 if (p_m_s_signal == SS5_SIGNAL_DIGIT_PAUSE)
1102                         new_ss5_signal(SS5_SIGNAL_DIGIT_ON);
1103                 else {
1104                         new_ss5_signal(SS5_SIGNAL_DIGIT_PAUSE);
1105                         p_m_s_digit_i++;
1106                         goto again;
1107                 }
1108         }
1109         /* how much samples do we have left */
1110         tosend = len - count;
1111         tocode = duration - p_m_s_sample_nr;
1112         if (tocode < 0)
1113                 FATAL("sample_nr overrun duration");
1114         if (tosend < tocode)
1115                 tocode = tosend;
1116         /* digit or pause */
1117         if (p_m_s_signal == SS5_SIGNAL_DIGIT_PAUSE) {
1118                 memset(buffer+count, audio_s16_to_law[0], tocode);
1119 //              printf("coding pause %d bytes\n", tocode);
1120         } else {
1121                 ss5_encode(buffer+count, tocode, digit, p_m_s_sample_nr);
1122 //              printf("coding digit '%c' %d bytes\n", digit, tocode);
1123         }
1124         /* increase counters */
1125         p_m_s_sample_nr += tocode;
1126         count += tocode;
1127         /* can we take more ? */
1128         if (len != count)
1129                 goto again;
1130         return count;
1131 }
1132
1133
1134 int Pss5::inband_dial_pulse(unsigned char *buffer, int len, int count)
1135 {
1136         int tocode, tosend;
1137         int duration;
1138         char digit;
1139
1140         /* dialing
1141          *
1142          * p_m_s_dial: digits to be dialed
1143          * p_m_s_digit_i: current digit counter
1144          * p_m_s_signal: current signal state
1145          * p_m_s_sample_nr: current sample number
1146          */
1147         again:
1148         /* get digit */
1149         digit = p_m_s_dial[p_m_s_digit_i];
1150         if (!digit) { /* if end of string reached */
1151                 new_ss5_state(SS5_STATE_DELAY);
1152                 p_m_s_sample_nr = 0;
1153                 return count;
1154         }
1155         /* convert digit to pulse */
1156         switch (digit) {
1157                 case '1':
1158                 case '2':
1159                 case '3':
1160                 case '4':
1161                 case '5':
1162                 case '6':
1163                 case '7':
1164                 case '8':
1165                 case '9':
1166                 digit -= '0';
1167                 break;
1168                 case '0':
1169                 digit = 10;
1170                 break;
1171                 case '*':
1172                 digit = 11;
1173                 break;
1174                 case '#':
1175                 digit = 12;
1176                 break;
1177                 default:
1178                 p_m_s_digit_i++;
1179                 goto again;
1180         }
1181         /* get duration */
1182         if (p_m_s_signal == SS5_SIGNAL_DIGIT_ON) {
1183                 if (p_m_s_pulsecount & 1)
1184                         duration = BELL_TIMER_MAKE; /* loop closed */
1185                 else
1186                         duration = BELL_TIMER_BREAK; /* loop open, tone */
1187         } else {
1188                 duration = BELL_TIMER_PAUSE;
1189         }
1190         /* end of digit/pause ? */
1191         if (p_m_s_sample_nr >= duration) {
1192                 p_m_s_sample_nr = 0;
1193                 if (p_m_s_signal == SS5_SIGNAL_DIGIT_PAUSE) {
1194                         new_ss5_signal(SS5_SIGNAL_DIGIT_ON);
1195                         PDEBUG(DEBUG_SS5, "%s: starting pusling digit '%c'\n", p_name, digit);
1196                 } else {
1197                         p_m_s_pulsecount++; /* toggle pulse */
1198                         if (!(p_m_s_pulsecount & 1)) {
1199                                 /* pulse now on again, but if end is reached... */
1200                                 if (p_m_s_pulsecount == (digit<<1)) {
1201                                         new_ss5_signal(SS5_SIGNAL_DIGIT_PAUSE);
1202                                         p_m_s_pulsecount = 0;
1203                                         p_m_s_digit_i++;
1204                                         goto again;
1205                                 }
1206                         }
1207                 }
1208         }
1209         /* how much samples do we have left */
1210         tosend = len - count;
1211         tocode = duration - p_m_s_sample_nr;
1212         if (tocode < 0)
1213                 FATAL("sample_nr overrun duration");
1214         if (tosend < tocode)
1215                 tocode = tosend;
1216         /* digit or pause */
1217         if (p_m_s_signal == SS5_SIGNAL_DIGIT_PAUSE
1218          || (p_m_s_pulsecount&1)) /* ...or currently on and no pulse */
1219                 memset(buffer+count, audio_s16_to_law[0], tocode);
1220         else
1221                 ss5_encode(buffer+count, tocode, 'B', p_m_s_sample_nr);
1222         /* increase counters */
1223         p_m_s_sample_nr += tocode;
1224         count += tocode;
1225         /* can we take more ? */
1226         if (len != count)
1227                 goto again;
1228         return count;
1229 }
1230
1231
1232 /*
1233  * start signal
1234  */ 
1235 void Pss5::start_signal(int state)
1236 {
1237         PDEBUG(DEBUG_SS5, "%s: starting singal '%s'\n", p_name, ss5_state_name[state]);
1238         /* start signal */
1239         new_ss5_state(state);
1240         if (state == SS5_STATE_DIAL_OUT) {
1241                 p_m_s_digit_i = 0;
1242                 p_m_s_pulsecount = 0;
1243                 new_ss5_signal(SS5_SIGNAL_DIGIT_ON);
1244         } else
1245                 new_ss5_signal(SS5_SIGNAL_SEND_ON);
1246
1247         /* double seize must continue the current seize tone, so don't reset sample_nr */
1248         if (state != SS5_STATE_DOUBLE_SEIZE) {
1249                 /* (re)set sound phase to 0 */
1250                 p_m_s_sample_nr = 0;
1251         }
1252
1253         /* turn on inband transmitter */
1254         inband_send_on();
1255 }
1256
1257
1258 /*
1259  * handles all indications
1260  */
1261 void Pss5::seizing_ind(void)
1262 {
1263         ss5_trace_header(p_m_mISDNport, this, SS5_SEIZING_IND, p_m_b_channel);
1264         end_trace();
1265
1266         new_state(PORT_STATE_IN_SETUP);
1267 }
1268
1269 void Pss5::digit_ind(char digit)
1270 {
1271         int i;
1272         char string[128] = "", dial[128] = "";
1273         int dash, first_digit, last_was_digit;
1274
1275         /* add digit */
1276         SCCAT(p_m_s_dial, digit);
1277
1278         if (p_state == PORT_STATE_IN_SETUP)
1279                 new_state(PORT_STATE_IN_OVERLAP);
1280
1281         /* not last digit ? */
1282         if (digit != 'c')
1283                 return;
1284
1285         /* parse string */
1286         dash = 0; /* dash must be used next time */
1287         first_digit = 1;
1288         last_was_digit = 0;
1289         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1290         for (i = 0; p_m_s_dial[i]; i++) {
1291                 if (dash || (last_was_digit && (p_m_s_dial[i]<'0' || p_m_s_dial[i]>'9')))
1292                         SCCAT(string, '-');
1293                 dash = 0;
1294                 last_was_digit = 0;
1295                 switch(p_m_s_dial[i]) {
1296                         case '1':
1297                         case '2':
1298                         case '3':
1299                         case '4':
1300                         case '5':
1301                         case '6':
1302                         case '7':
1303                         case '8':
1304                         case '9':
1305                         case '0':
1306                         if (first_digit)
1307                                 dash = 1;
1308                         first_digit = 0;
1309                         last_was_digit = 1;
1310                         SCCAT(string, p_m_s_dial[i]);
1311                         SCCAT(dial, p_m_s_dial[i]);
1312                         break;
1313                         case '*':
1314                         SCAT(string, "C11");
1315                         SCCAT(dial, p_m_s_dial[i]);
1316                         dash = 1;
1317                         break;
1318                         case '#':
1319                         SCAT(string, "C12");
1320                         SCCAT(dial, p_m_s_dial[i]);
1321                         dash = 1;
1322                         break;
1323                         case 'a':
1324                         SCAT(string, "KP1");
1325                         SCCAT(dial, p_m_s_dial[i]);
1326                         dash = 1;
1327                         break;
1328                         case 'b':
1329                         SCAT(string, "KP2");
1330                         SCCAT(dial, p_m_s_dial[i]);
1331                         dash = 1;
1332                         break;
1333                         case 'c':
1334                         SCAT(string, "ST");
1335                         dash = 1;
1336                         break;
1337                         default:
1338                         break;
1339                 }
1340         }
1341         ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1342         add_trace("string", NULL, "%s", string);
1343         add_trace("number", NULL, "%s", dial);
1344         end_trace();
1345         new_ss5_state(SS5_STATE_IDLE);
1346
1347         do_setup(dial);
1348         new_state(PORT_STATE_IN_PROCEEDING);
1349 }
1350
1351 void Pss5::pulse_ind(int on)
1352 {
1353         struct lcr_msg *message;
1354         char dial[3] = "a.";
1355
1356         if (p_m_s_signal == SS5_SIGNAL_PULSE_OFF) {
1357                 if (on) {
1358                         /* pulse turns on */
1359                         p_m_s_recog = 0;
1360                         new_ss5_signal(SS5_SIGNAL_PULSE_ON);
1361                         /* pulse turns of, count it */
1362                         p_m_s_pulsecount++;
1363                         PDEBUG(DEBUG_SS5, "%s: pulse turns on, counting\n", p_name);
1364                 } else {
1365                         /* pulse remains off */
1366                         p_m_s_recog += SS5_DECODER_NPOINTS;
1367                         /* not recognized end of digit, we wait... */
1368                         if (p_m_s_recog < BELL_TIMER_RECOG_END)
1369                                 return;
1370                         PDEBUG(DEBUG_SS5, "%s: pulse remains off, counted %d pulses\n", p_name, p_m_s_pulsecount);
1371                         if (p_m_s_pulsecount >= 12)
1372                                 dial[1] = '#';
1373                         else if (p_m_s_pulsecount == 11)
1374                                 dial[1] = '*';
1375                         else if (p_m_s_pulsecount == 10)
1376                                 dial[1] = '0';
1377                         else
1378                                 dial[1] = p_m_s_pulsecount + '0';
1379                         ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1380                         add_trace("digit", NULL, "%s", dial+1);
1381                         add_trace("pulses", NULL, "%d", p_m_s_pulsecount);
1382                         end_trace();
1383                         /* special star release feature */
1384                         if ((p_m_mISDNport->ss5 & SS5_FEATURE_STAR_RELEASE) && dial[1] == '*') {
1385                                 ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1386                                 add_trace("star", NULL, "releases call");
1387                                 end_trace();
1388                                 goto star_release;
1389                         }
1390                         if (p_state == PORT_STATE_IN_SETUP) {
1391                                 /* sending digit as setup */
1392                                 do_setup(dial); /* include 'a' == KP1 */
1393                                 new_state(PORT_STATE_IN_OVERLAP);
1394                         } else {
1395                                 /* sending digit as information */
1396                                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
1397                                 SCPY(message->param.information.id, dial+1);
1398                                 message_put(message);
1399                         }
1400                                 new_ss5_state(SS5_STATE_IDLE);
1401                         /* done rx pulses, return to idle */
1402                         new_ss5_state(SS5_STATE_IDLE);
1403                 }
1404         } else {
1405                 if (on) {
1406                         /* pulse remains on */
1407                         p_m_s_recog += SS5_DECODER_NPOINTS;
1408                 } else {
1409                         /* pulse turns off */
1410                         if (p_m_s_recog >= BELL_TIMER_RECOG_HANGUP) {
1411                                 PDEBUG(DEBUG_SS5, "%s: long pulse turns off, releasing\n", p_name);
1412                                 ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1413                                 add_trace("longtone", NULL, "releases call");
1414                                 end_trace();
1415                                 star_release:
1416                                 /* long pulse is gone, release current connection, if any */
1417                                 while(p_epointlist) {
1418                                         message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1419                                         message->param.disconnectinfo.location = LOCATION_BEYOND;
1420                                         message->param.disconnectinfo.cause = CAUSE_NORMAL;
1421                                         message_put(message);
1422                                         free_epointlist(p_epointlist);
1423                                 }
1424                                 set_tone("", NULL);
1425                                 /* return to setup state */
1426                                 new_state(PORT_STATE_IN_SETUP);
1427                                 new_ss5_state(SS5_STATE_IDLE);
1428                                 return;
1429                         }
1430                         PDEBUG(DEBUG_SS5, "%s: short pulse turns off, releasing\n", p_name);
1431                         p_m_s_recog = 0;
1432                         new_ss5_signal(SS5_SIGNAL_PULSE_OFF);
1433                 }
1434         }
1435 }
1436
1437 void Pss5::proceed_to_send_ind(void)
1438 {
1439         ss5_trace_header(p_m_mISDNport, this, SS5_PROCEED_TO_SEND_IND, p_m_b_channel);
1440         end_trace();
1441
1442         SCPY(p_m_s_dial, p_dialinginfo.id);
1443         start_signal(SS5_STATE_DIAL_OUT);
1444
1445         new_state(PORT_STATE_OUT_OVERLAP);
1446 }
1447
1448 void Pss5::busy_flash_ind(void)
1449 {
1450         struct lcr_msg *message;
1451
1452         ss5_trace_header(p_m_mISDNport, this, SS5_BUSY_FLASH_IND, p_m_b_channel);
1453         end_trace();
1454
1455         /* busy before dialing ? */
1456         if (!p_epointlist)
1457                 return;
1458
1459         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_NODISCONNECT)) {
1460                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
1461                 message->param.disconnectinfo.location = LOCATION_BEYOND;
1462                 message->param.disconnectinfo.cause = CAUSE_BUSY;
1463                 message_put(message);
1464         }
1465
1466         new_state(PORT_STATE_IN_DISCONNECT);
1467 }
1468
1469 void Pss5::answer_ind(void)
1470 {
1471         struct lcr_msg *message;
1472
1473         ss5_trace_header(p_m_mISDNport, this, SS5_ANSWER_IND, p_m_b_channel);
1474         end_trace();
1475
1476         /* answer before dialing ? */
1477         if (!p_epointlist)
1478                 return;
1479
1480         /* already connected */
1481         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_CONNECT)) {
1482                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
1483                 message_put(message);
1484         }
1485
1486         new_state(PORT_STATE_CONNECT);
1487 }
1488
1489 void Pss5::forward_transfer_ind(void)
1490 {
1491 //      struct lcr_msg *message;
1492
1493         ss5_trace_header(p_m_mISDNport, this, SS5_FORWARD_TRANSFER_IND, p_m_b_channel);
1494         end_trace();
1495
1496 #if 0
1497         /* if BELL flavor bluebox flag is set, use it to seize a new line */
1498         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_BELL))
1499                 return;
1500
1501         /* special BELL flavor hack to clear a line and seize a new one */
1502         while(p_epointlist) {
1503                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1504                 message->param.disconnectinfo.location = LOCATION_BEYOND;
1505                 message->param.disconnectinfo.cause = CAUSE_NORMAL;
1506                 message_put(message);
1507                 free_epointlist(p_epointlist);
1508         }
1509         set_tone("", NULL);
1510         new_state(PORT_STATE_IN_SETUP);
1511 #endif
1512 }
1513
1514 void Pss5::clear_back_ind(void)
1515 {
1516         struct lcr_msg *message;
1517
1518         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_BACK_IND, p_m_b_channel);
1519         end_trace();
1520
1521         /* nobody? */
1522         if (!p_epointlist)
1523                 return;
1524
1525         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_NODISCONNECT)) {
1526                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
1527                 message->param.disconnectinfo.location = LOCATION_BEYOND;
1528                 message->param.disconnectinfo.cause = CAUSE_NORMAL;
1529                 message_put(message);
1530         }
1531
1532         new_state(PORT_STATE_IN_DISCONNECT);
1533 }
1534
1535 void Pss5::clear_forward_ind(void)
1536 {
1537         struct lcr_msg *message;
1538
1539         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_FORWARD_IND, p_m_b_channel);
1540         end_trace();
1541
1542         new_state(PORT_STATE_IDLE);
1543         set_tone("", NULL);
1544         p_type = PORT_TYPE_SS5_IDLE;
1545
1546         /* someone ? */
1547         if (!p_epointlist)
1548                 return;
1549
1550         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
1551         message->param.disconnectinfo.location = LOCATION_BEYOND;
1552         message->param.disconnectinfo.cause = CAUSE_NORMAL;
1553         message_put(message);
1554         free_epointlist(p_epointlist);
1555
1556 }
1557
1558 void Pss5::release_guard_ind(void)
1559 {
1560         struct lcr_msg *message;
1561
1562         ss5_trace_header(p_m_mISDNport, this, SS5_RELEASE_GUARD_IND, p_m_b_channel);
1563         end_trace();
1564
1565         set_tone("", NULL);
1566
1567         /* someone ? */
1568         if (!p_epointlist)
1569                 return;
1570
1571         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
1572         message->param.disconnectinfo.location = LOCATION_BEYOND;
1573         message->param.disconnectinfo.cause = CAUSE_NORMAL;
1574         message_put(message);
1575         free_epointlist(p_epointlist);
1576 }
1577
1578 void Pss5::double_seizure_ind(void)
1579 {
1580         ss5_trace_header(p_m_mISDNport, this, SS5_DOUBLE_SEIZURE_IND, p_m_b_channel);
1581         end_trace();
1582         ss5_trace_header(p_m_mISDNport, this, SS5_DOUBLE_SEIZURE_REQ, p_m_b_channel);
1583         end_trace();
1584
1585         /* start double seizure sequence, so remote exchange will recognize it */
1586         start_signal(SS5_STATE_DOUBLE_SEIZE);
1587 }
1588
1589
1590 /*
1591  * shuts down by sending a clear forward and releasing endpoint
1592  */
1593 void Pss5::do_release(int cause, int location)
1594 {
1595         struct lcr_msg *message;
1596
1597         /* sending release to endpoint */
1598         while(p_epointlist) {
1599                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1600                 message->param.disconnectinfo.location = location;
1601                 message->param.disconnectinfo.cause = cause;
1602                 message_put(message);
1603                 free_epointlist(p_epointlist);
1604         }
1605
1606         /* start clear-forward */
1607         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_FORWARD_REQ, p_m_b_channel);
1608         end_trace();
1609         start_signal(SS5_STATE_CLEAR_FORWARD);
1610
1611         new_state(PORT_STATE_RELEASE);
1612 }
1613
1614
1615 /*
1616  * create endpoint and send setup
1617  */
1618 void Pss5::do_setup(char *dial)
1619 {
1620         class Endpoint *epoint;
1621         struct lcr_msg *message;
1622
1623         SCPY(p_dialinginfo.id, dial);
1624         p_dialinginfo.sending_complete = 1;
1625         p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
1626         p_callerinfo.screen = INFO_SCREEN_NETWORK;
1627         p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1628         p_callerinfo.isdn_port = p_m_portnum;
1629         SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
1630
1631         p_capainfo.bearer_capa = INFO_BC_AUDIO;
1632         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
1633         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
1634         p_capainfo.hlc = INFO_HLC_NONE;
1635         p_capainfo.exthlc = INFO_HLC_NONE;
1636         p_capainfo.source_mode = B_MODE_TRANSPARENT;
1637
1638         /* create endpoint */
1639         if (p_epointlist)
1640                 FATAL("Incoming call but already got an endpoint.\n");
1641         if (!(epoint = new Endpoint(p_serial, 0)))
1642                 FATAL("No memory for Endpoint instance\n");
1643         if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
1644                 FATAL("No memory for Endpoint Application instance\n");
1645         epointlist_new(epoint->ep_serial);
1646
1647         /* send setup message to endpoit */
1648         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
1649         message->param.setup.isdn_port = p_m_portnum;
1650         message->param.setup.port_type = p_type;
1651 //      message->param.setup.dtmf = !p_m_mISDNport->ifport->nodtmf;
1652         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
1653         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
1654         memcpy(&message->param.setup.redirinfo, &p_redirinfo, sizeof(struct redir_info));
1655         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
1656         message_put(message);
1657
1658 }
1659
1660
1661 /*
1662  * handler
1663  */
1664 int Pss5::handler(void)
1665 {
1666         int ret;
1667
1668         if ((ret = PmISDN::handler()))
1669                 return(ret);
1670
1671         /* handle timer */
1672         if (p_m_s_timer && p_m_s_timer < now) {
1673                 p_m_s_timer = 0.0;
1674                 (this->*(p_m_s_timer_fn))();
1675         }
1676
1677         /* if answer signal is queued */
1678         if (p_m_s_answer && p_m_s_state == SS5_STATE_IDLE) {
1679                 p_m_s_answer = 0;
1680                 /* start answer */
1681                 ss5_trace_header(p_m_mISDNport, this, SS5_ANSWER_REQ, p_m_b_channel);
1682                 end_trace();
1683                 start_signal(SS5_STATE_ANSWER);
1684         }
1685
1686         /* if busy-flash signal is queued */
1687         if (p_m_s_busy_flash && p_m_s_state == SS5_STATE_IDLE) {
1688                 p_m_s_busy_flash = 0;
1689                 /* start busy-flash */
1690                 ss5_trace_header(p_m_mISDNport, this, SS5_BUSY_FLASH_REQ, p_m_b_channel);
1691                 end_trace();
1692                 start_signal(SS5_STATE_BUSY_FLASH);
1693         }
1694
1695         /* if clear-back signal is queued */
1696         if (p_m_s_clear_back && p_m_s_state == SS5_STATE_IDLE) {
1697                 p_m_s_clear_back = 0;
1698                 /* start clear-back */
1699                 ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_BACK_REQ, p_m_b_channel);
1700                 end_trace();
1701                 start_signal(SS5_STATE_CLEAR_BACK);
1702         }
1703
1704         return(0);
1705 }
1706
1707
1708 /*
1709  * handles all messages from endpoint
1710  */
1711
1712 /* MESSAGE_SETUP */
1713 void Pss5::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
1714 {
1715         struct lcr_msg *message;
1716         int i;
1717         char string[128] = "", dial[128] = "";
1718         int dash, first_digit, last_was_digit;
1719
1720         if (p_epointlist) {
1721                 PERROR("endpoint already exist.\n");
1722                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1723                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1724                 message->param.disconnectinfo.cause = CAUSE_UNSPECIFIED;
1725                 message_put(message);
1726                 return;
1727         }
1728
1729         /* copy setup infos to port */
1730         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
1731         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
1732         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
1733         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
1734         /* screen outgoing caller id */
1735         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
1736         do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
1737
1738         /* parse dial string  */
1739         dash = 0; /* dash must be used next time */
1740         first_digit = 1;
1741         last_was_digit = 0;
1742         for (i = 0; p_dialinginfo.id[i]; i++) {
1743                 if (dash || (last_was_digit && (p_dialinginfo.id[i]<'0' || p_dialinginfo.id[i]>'9')))
1744                         SCCAT(string, '-');
1745                 dash = 0;
1746                 last_was_digit = 0;
1747                 switch(p_dialinginfo.id[i]) {
1748                         case '1':
1749                         case '2':
1750                         case '3':
1751                         case '4':
1752                         case '5':
1753                         case '6':
1754                         case '7':
1755                         case '8':
1756                         case '9':
1757                         case '0':
1758                         if (i && first_digit)
1759                                 dash = 1;
1760                         first_digit = 0;
1761                         last_was_digit = 1;
1762                         SCCAT(string, p_dialinginfo.id[i]);
1763                         SCCAT(dial, p_dialinginfo.id[i]);
1764                         break;
1765                         case '*':
1766                         SCAT(string, "C11");
1767                         SCCAT(dial, '*');
1768                         dash = 1;
1769                         break;
1770                         case '#':
1771                         SCAT(string, "C12");
1772                         SCCAT(dial, '#');
1773                         dash = 1;
1774                         break;
1775                         case 'a':
1776                         SCAT(string, "KP1");
1777                         SCCAT(dial, 'a');
1778                         dash = 1;
1779                         break;
1780                         case 'b':
1781                         SCAT(string, "KP2");
1782                         SCCAT(dial, 'b');
1783                         dash = 1;
1784                         break;
1785                         case 'c':
1786                         SCAT(string, "ST");
1787                         SCCAT(dial, 'c');
1788                         dash = 1;
1789                         case 'K':
1790                         i++;
1791                         if (p_dialinginfo.id[i] != 'P')
1792                                 goto dial_error;
1793                         i++;
1794                         if (p_dialinginfo.id[i] == '1') {
1795                                 SCAT(string, "KP1");
1796                                 SCCAT(dial, 'a');
1797                                 dash = 1;
1798                                 break;
1799                         }
1800                         if (p_dialinginfo.id[i] == '2') {
1801                                 SCAT(string, "KP2");
1802                                 SCCAT(dial, 'b');
1803                                 dash = 1;
1804                                 break;
1805                         }
1806                         goto dial_error;
1807                         case 'C':
1808                         i++;
1809                         if (p_dialinginfo.id[i] != '1')
1810                                 goto dial_error;
1811                         i++;
1812                         if (p_dialinginfo.id[i] == '1') {
1813                                 SCAT(string, "C11");
1814                                 SCCAT(dial, 'a');
1815                                 dash = 1;
1816                                 break;
1817                         }
1818                         if (p_dialinginfo.id[i] == '2') {
1819                                 SCAT(string, "C12");
1820                                 SCCAT(dial, 'b');
1821                                 dash = 1;
1822                                 break;
1823                         }
1824                         goto dial_error;
1825                         case 'S':
1826                         i++;
1827                         if (p_dialinginfo.id[i] != 'T')
1828                                 goto dial_error;
1829                         SCAT(string, "ST");
1830                         SCCAT(dial, 'c');
1831                         dash = 1;
1832                         break;
1833                         default:
1834                         break;
1835                 }
1836                 /* stop, if ST */
1837                 if (dial[0] && dial[strlen(dial)-1] == 'c')
1838                         break;
1839         }
1840         /* terminate */
1841         if (dial[0] && dial[strlen(dial)-1]!='c') {
1842                 SCCAT(string, '-');
1843                 SCAT(string, "ST");
1844                 SCCAT(dial, 'c');
1845         }
1846
1847         /* error in dial string */
1848         if (!dial[0]) {
1849                 dial_error:
1850                 ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_REQ, p_m_b_channel);
1851                 add_trace("string", NULL, "%s", p_dialinginfo.id);
1852                 if (!dial[0])
1853                         add_trace("error", NULL, "no number", dial);
1854                 else if (dial[0]!='a' && dial[0]!='b')
1855                         add_trace("error", NULL, "number must start with KP1/KP2", dial);
1856                 else
1857                         add_trace("error", NULL, "illegal format", dial);
1858                 end_trace();
1859                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1860                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1861                 message->param.disconnectinfo.cause = CAUSE_INVALID;
1862                 message_put(message);
1863                 return;
1864         }
1865
1866         /* copy new dial string */
1867         SCPY(p_dialinginfo.id, dial);
1868
1869         /* attach only if not already */
1870         epointlist_new(epoint_id);
1871
1872         ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_REQ, p_m_b_channel);
1873         add_trace("string", NULL, "%s", string);
1874         add_trace("type", NULL, "%s", (dial[0]=='b')?"international":"national");
1875         add_trace("number", NULL, "%s", dial);
1876         end_trace();
1877         /* connect auto path */
1878         if ((p_m_mISDNport->ss5 & SS5_FEATURE_CONNECT)) {
1879                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
1880                 message_put(message);
1881         } else {
1882                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1883                 message_put(message);
1884         }
1885
1886         /* start seizing */
1887         ss5_trace_header(p_m_mISDNport, this, SS5_SEIZING_REQ, p_m_b_channel);
1888         end_trace();
1889         new_ss5_state(SS5_STATE_SEIZING);
1890         new_ss5_signal(SS5_SIGNAL_SEND_ON);
1891         p_m_s_sample_nr = 0;
1892         inband_send_on();
1893
1894         p_type = PORT_TYPE_SS5_OUT;
1895         new_state(PORT_STATE_OUT_SETUP);
1896 }
1897
1898 /* MESSAGE_CONNECT */
1899 void Pss5::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
1900 {
1901         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
1902
1903         if (p_state != PORT_STATE_CONNECT) {
1904                 new_state(PORT_STATE_CONNECT);
1905                 p_m_s_answer = 1;
1906         }
1907
1908         set_tone("", NULL);
1909 }
1910
1911 /* MESSAGE_DISCONNECT */
1912 void Pss5::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1913 {
1914         /* disconnect and clear forward (release guard) */
1915 //      if ((p_type==PORT_TYPE_SS5_IN && !p_m_mISDNport->tones) /* incomming exchange with no tones */
1916 if (0    || p_type==PORT_TYPE_SS5_OUT) { /* outgoing exchange */
1917                 do_release(param->disconnectinfo.cause, param->disconnectinfo.location);
1918                 return;
1919         }
1920
1921         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_BACK_REQ, p_m_b_channel);
1922         end_trace();
1923         start_signal(SS5_STATE_CLEAR_BACK);
1924
1925         new_state(PORT_STATE_OUT_DISCONNECT);
1926 }
1927
1928 /* MESSAGE_RELEASE */
1929 void Pss5::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1930 {
1931         do_release(param->disconnectinfo.cause, param->disconnectinfo.location);
1932 }
1933
1934
1935 /*
1936  * endpoint sends messages to the port
1937  */
1938 int Pss5::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1939 {
1940         if (PmISDN::message_epoint(epoint_id, message_id, param))
1941                 return(1);
1942
1943         switch(message_id) {
1944                 case MESSAGE_SETUP: /* dial-out command received from epoint */
1945                 if (p_state!=PORT_STATE_IDLE) {
1946                         PERROR("Pss5(%s) ignoring setup because isdn port is not in idle state (or connected for sending display info).\n", p_name);
1947                         break;
1948                 }
1949                 if (p_epointlist && p_state==PORT_STATE_IDLE)
1950                         FATAL("Pss5(%s): epoint pointer is set in idle state, how bad!!\n", p_name);
1951                 message_setup(epoint_id, message_id, param);
1952                 break;
1953
1954                 case MESSAGE_CONNECT: /* call of endpoint is connected */
1955                 message_connect(epoint_id, message_id, param);
1956                 break;
1957
1958                 case MESSAGE_DISCONNECT: /* call has been disconnected */
1959                 message_disconnect(epoint_id, message_id, param);
1960                 break;
1961
1962                 case MESSAGE_RELEASE: /* release isdn port */
1963                 message_release(epoint_id, message_id, param);
1964                 break;
1965
1966                 default:
1967                 PDEBUG(DEBUG_SS5, "Pss5(%s) ss5 port with (caller id %s) received an unhandled message: %d\n", p_name, p_callerinfo.id, message_id);
1968         }
1969
1970         return(1);
1971 }
1972