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