Fixed detection of Code 11 (CCITT#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 //#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 int busy signal
231  * this makes the line more authentic
232  */
233 void Pss5::set_tone(const char *dir, const char *name)
234 {
235         if (name && !strcmp(name, "cause_10"))
236                 name = "busy";
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_state(PORT_STATE_RELEASE);
510                 new_ss5_state(SS5_STATE_RELEASE_GUARD);
511                 new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
512                 p_m_s_recog = 0;
513         } else
514         switch(p_m_s_state) {
515                 case SS5_STATE_IDLE:
516                 /* seizing only recognized in port idle state */
517                 if (p_state == PORT_STATE_IDLE) {
518                         if (digit != 'A')
519                                 break;
520                         seize:
521                         PDEBUG(DEBUG_SS5, "%s: received seize, waiting for recognition\n", p_name);
522                         p_type = PORT_TYPE_SS5_IN;
523                         new_ss5_state(SS5_STATE_PROCEED_TO_SEND);
524                         new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
525                         p_m_s_recog = 0;
526                         break;
527                 }
528                 /* other signals */
529                 if (digit == 'A') {
530                         if (p_type != PORT_TYPE_SS5_OUT)
531                                 break;
532                         PDEBUG(DEBUG_SS5, "%s: received answer, waiting for recognition\n", p_name);
533                         new_ss5_state(SS5_STATE_ACK_ANSWER);
534                         new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
535                         p_m_s_recog = 0;
536                         break;
537                 }
538                 if (digit == 'B') {
539                         if (p_type == PORT_TYPE_SS5_IN) {
540                                 if ((p_m_mISDNport->ss5 & SS5_FEATURE_BELL)) {
541                                         new_ss5_state(SS5_STATE_DIAL_IN_PULSE); /* go pulsing state */
542                                         new_ss5_signal(SS5_SIGNAL_PULSE_OFF); /* we are starting with pulse off */
543                                         p_m_s_pulsecount = 0; /* init pulse counter */
544                                         p_m_s_dial[0] = '\0'; /* init dial string */
545                                         pulse_ind(1); /* also inits recogition timer... */
546                                         break;
547                                 }
548                                 PDEBUG(DEBUG_SS5, "%s: received forward-transfer, waiting for recognition\n", p_name);
549                                 /* forward transfer on incomming lines */
550                                 new_ss5_state(SS5_STATE_FORWARD_TRANSFER);
551                                 new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
552                                 p_m_s_recog = 0;
553                                 break;
554                         }
555                         if (p_state == PORT_STATE_CONNECT) {
556                                 PDEBUG(DEBUG_SS5, "%s: received clear-back, waiting for recognition\n", p_name);
557                                 new_ss5_state(SS5_STATE_ACK_CLEAR_BACK);
558                         } else {
559                                 PDEBUG(DEBUG_SS5, "%s: received busy-flash, waiting for recognition\n", p_name);
560                                 new_ss5_state(SS5_STATE_ACK_BUSY_FLASH);
561                         }
562                         new_ss5_signal(SS5_SIGNAL_RECEIVE_RECOG);
563                         p_m_s_recog = 0;
564                         break;
565                 }
566                 /* dialing only allowed in incomming setup state */
567                 if (p_state == PORT_STATE_IN_SETUP) {
568                         if (!strchr("1234567890*#abc", digit))
569                                 break;
570                         PDEBUG(DEBUG_SS5, "%s: received dialing start with '%c'\n", p_name, digit);
571                         new_ss5_state(SS5_STATE_DIAL_IN);
572                         new_ss5_signal(SS5_SIGNAL_DIGIT_ON);
573                         p_m_s_dial[0] = '\0';
574                         digit_ind(digit);
575                         break;
576                 }
577                 break;
578                 /* sending seizing */
579                 case SS5_STATE_SEIZING:
580                 switch (p_m_s_signal) {
581                         case SS5_SIGNAL_SEND_ON:
582                         if (digit == 'A') { /* double seize */
583                                 PDEBUG(DEBUG_SS5, "%s: received double seizure\n", p_name, digit);
584                                 double_seizure_ind();
585                                 break;
586                         }
587                         if (digit == 'B') {
588                                 PDEBUG(DEBUG_SS5, "%s: received answer to outgoing seize, waiting for recognition\n", p_name);
589                                 /* set recognition timer */
590                                 new_ss5_signal(SS5_SIGNAL_SEND_ON_RECOG);
591                                 p_m_s_recog = 0;
592                         }
593                         break;
594                         case SS5_SIGNAL_SEND_ON_RECOG:
595                         if (digit != 'B') { /* seize */
596                                 PDEBUG(DEBUG_SS5, "%s: answer to outgoing seize is gone before recognition\n", p_name);
597                                 new_ss5_signal(SS5_SIGNAL_SEND_ON);
598 //                              p_m_s_sample_nr = 0;
599 //                              inband_send_on();
600                                 break;
601                         }
602                         p_m_s_recog += SS5_DECODER_NPOINTS;
603                         if (p_m_s_recog < SS5_TIMER_RECOG_SEIZE)
604                                 break;
605                         PDEBUG(DEBUG_SS5, "%s: answer to outgoing seize recognized, turning off, waiting for recognition\n", p_name);
606                         new_ss5_signal(SS5_SIGNAL_SEND_OFF);
607                         break;
608                         case SS5_SIGNAL_SEND_OFF:
609                         if (digit == 'B')
610                                 break;
611                         PDEBUG(DEBUG_SS5, "%s: outgoing seizure is complete, proceeding...\n", p_name);
612                         new_ss5_state(SS5_STATE_IDLE);
613                         proceed_to_send_ind();
614                         break;
615                 }
616                 break;
617                 /* answer to seize */
618                 case SS5_STATE_PROCEED_TO_SEND:
619                 if (p_m_s_signal == SS5_SIGNAL_RECEIVE_RECOG) {
620                         if (digit != 'A') {
621                                 PDEBUG(DEBUG_SS5, "%s: incomming seize is gone before recognition\n", p_name);
622                                 new_ss5_state(SS5_STATE_IDLE);
623                                 p_type = PORT_TYPE_SS5_IDLE;
624                                 break;
625                         }
626                         p_m_s_recog += SS5_DECODER_NPOINTS;
627                         if (p_m_s_recog < SS5_TIMER_RECOG_SEIZE)
628                                 break;
629                         PDEBUG(DEBUG_SS5, "%s: incomming seize is recognized, responding...\n", p_name);
630                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
631                         p_m_s_sample_nr = 0;
632                         inband_send_on();
633                         break;
634                 }
635                 if (digit != 'A') {
636                         PDEBUG(DEBUG_SS5, "%s: incomming seize is gone after responding\n", p_name);
637                         new_ss5_state(SS5_STATE_IDLE);
638                         seizing_ind();
639                 }
640                 break;
641                 /* sending busy flash / answer / clear-back */
642                 case SS5_STATE_BUSY_FLASH:
643                 case SS5_STATE_ANSWER:
644                 case SS5_STATE_CLEAR_BACK:
645                 switch (p_m_s_signal) {
646                         case SS5_SIGNAL_SEND_ON:
647                         if (digit == 'A') {
648                                 PDEBUG(DEBUG_SS5, "%s: received acknowledge, waiting for recognition\n", p_name);
649                                 /* set recognition timer */
650                                 new_ss5_signal(SS5_SIGNAL_SEND_ON_RECOG);
651                                 p_m_s_recog = 0;
652                         }
653                         break;
654                         case SS5_SIGNAL_SEND_ON_RECOG:
655                         if (digit != 'A') {
656                                 PDEBUG(DEBUG_SS5, "%s: acknowledge is gone before recognition\n", p_name);
657                                 new_ss5_signal(SS5_SIGNAL_SEND_ON);
658 //                              p_m_s_sample_nr = 0;
659 //                              inband_send_on();
660                                 break;
661                         }
662                         p_m_s_recog += SS5_DECODER_NPOINTS;
663                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
664                                 break;
665                         PDEBUG(DEBUG_SS5, "%s: acknowledge recognized, turning off, waiting for recognition\n", p_name);
666                         new_ss5_signal(SS5_SIGNAL_SEND_OFF);
667                         break;
668                         case SS5_SIGNAL_SEND_OFF:
669                         if (digit == 'A')
670                                 break;
671                         PDEBUG(DEBUG_SS5, "%s: outgoing signal is complete\n", p_name);
672                         new_ss5_state(SS5_STATE_IDLE);
673                         break;
674                 }
675                 break;
676                 /* answer to busy-flash / clear back */
677                 case SS5_STATE_ACK_BUSY_FLASH:
678                 case SS5_STATE_ACK_CLEAR_BACK:
679                 if (p_m_s_signal == SS5_SIGNAL_RECEIVE_RECOG) {
680                         if (digit != 'B') {
681                                 PDEBUG(DEBUG_SS5, "%s: incomming clear-back/busy-flash is gone before recognition\n", p_name);
682                                 new_ss5_state(SS5_STATE_IDLE);
683                                 break;
684                         }
685                         p_m_s_recog += SS5_DECODER_NPOINTS;
686                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
687                                 break;
688                         PDEBUG(DEBUG_SS5, "%s: incomming clear-back/busy-flash is recognized, responding...\n", p_name);
689                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
690                         p_m_s_sample_nr = 0;
691                         inband_send_on();
692                         break;
693                 }
694                 if (digit != 'B') {
695                         PDEBUG(DEBUG_SS5, "%s: incomming clear-back/busy-flash is gone after responding\n", p_name);
696                         new_ss5_state(SS5_STATE_IDLE);
697                         if (p_m_s_state == SS5_STATE_ACK_BUSY_FLASH)
698                                 busy_flash_ind();
699                         else
700                                 clear_back_ind();
701                 }
702                 break;
703                 /* answer to answer */
704                 case SS5_STATE_ACK_ANSWER:
705                 if (p_m_s_signal == SS5_SIGNAL_RECEIVE_RECOG) {
706                         if (digit != 'A') {
707                                 PDEBUG(DEBUG_SS5, "%s: incomming answer is gone before recognition\n", p_name);
708                                 new_ss5_state(SS5_STATE_IDLE);
709                                 break;
710                         }
711                         p_m_s_recog += SS5_DECODER_NPOINTS;
712                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
713                                 break;
714                         PDEBUG(DEBUG_SS5, "%s: incomming answer is recognized, responding...\n", p_name);
715                         new_ss5_signal(SS5_SIGNAL_RECEIVE);
716                         p_m_s_sample_nr = 0;
717                         inband_send_on();
718                         break;
719                 }
720                 if (digit != 'A') {
721                         PDEBUG(DEBUG_SS5, "%s: incomming answer is gone after responding\n", p_name);
722                         new_ss5_state(SS5_STATE_IDLE);
723                         answer_ind();
724                 }
725                 break;
726                 /* sending clear-forward */
727                 case SS5_STATE_CLEAR_FORWARD:
728                 switch (p_m_s_signal) {
729                         case SS5_SIGNAL_SEND_ON:
730                         if (digit == 'C') {
731                                 PDEBUG(DEBUG_SS5, "%s: received answer to clear-forward, waiting for recognition\n", p_name);
732                                 /* set recognition timer */
733                                 new_ss5_signal(SS5_SIGNAL_SEND_ON_RECOG);
734                                 p_m_s_recog = 0;
735                         }
736                         break;
737                         case SS5_SIGNAL_SEND_ON_RECOG:
738                         if (digit != 'C') {
739                                 PDEBUG(DEBUG_SS5, "%s: answer to clear-forward is gone before recognition\n", p_name);
740                                 new_ss5_signal(SS5_SIGNAL_SEND_ON);
741 //                              p_m_s_sample_nr = 0;
742 //                              inband_send_on();
743                                 break;
744                         }
745                         p_m_s_recog += SS5_DECODER_NPOINTS;
746                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
747                                 break;
748                         PDEBUG(DEBUG_SS5, "%s: answer to clear-forward recognized, turning off, waiting for recognition\n", p_name);
749                         new_ss5_signal(SS5_SIGNAL_SEND_OFF);
750                         break;
751                         case SS5_SIGNAL_SEND_OFF:
752                         if (digit == 'A') {
753                                 PDEBUG(DEBUG_SS5, "%s: received seize right after clear-forward answer, continue with seize\n", p_name);
754                                 new_state(PORT_STATE_IDLE);
755                                 goto seize;
756                         }
757                         if (digit == 'C')
758                                 break;
759                         PDEBUG(DEBUG_SS5, "%s: answer to clear-forward is complete\n", p_name);
760                         release_guard_ind();
761                         new_ss5_signal(SS5_SIGNAL_DELAY);
762                         p_m_s_recog = 0; /* use recog to delay */
763                         PDEBUG(DEBUG_SS5, "%s: answer to clear-forward on outgoing interface starting delay to prevent ping-pong\n", p_name);
764                         break;
765                         case SS5_SIGNAL_DELAY:
766                         if (digit == 'A') {
767                                 PDEBUG(DEBUG_SS5, "%s: received seize right after clear-forward answer, continue with seize\n", p_name);
768                                 new_state(PORT_STATE_IDLE);
769                                 goto seize;
770                         }
771                         p_m_s_recog += SS5_DECODER_NPOINTS;
772                         if (p_m_s_recog < SS5_TIMER_RELEASE_DELAY)
773                                 break;
774                         PDEBUG(DEBUG_SS5, "%s: delay time over, going idle\n", p_name);
775                         new_ss5_state(SS5_STATE_IDLE);
776                         new_state(PORT_STATE_IDLE);
777                         p_type = PORT_TYPE_SS5_IDLE;
778                         break;
779                 }
780                 break;
781                 /* answer to release-guard*/
782                 case SS5_STATE_RELEASE_GUARD:
783                 switch (p_m_s_signal) {
784                         case SS5_SIGNAL_RECEIVE_RECOG:
785                         if (digit != 'C') {
786                                 if (p_type == PORT_TYPE_SS5_OUT)
787                                         PDEBUG(DEBUG_SS5, "%s: incomming release-guard is gone before recognition\n", p_name);
788                                 else
789                                         PDEBUG(DEBUG_SS5, "%s: incomming clear forward is gone before recognition\n", p_name);
790                                 new_ss5_state(SS5_STATE_IDLE);
791                                 break;
792                         }
793                         p_m_s_recog += SS5_DECODER_NPOINTS;
794                         if (p_m_s_recog < SS5_TIMER_RECOG_OTHER)
795                                 break;
796                         if (p_type == PORT_TYPE_SS5_OUT)
797                                 PDEBUG(DEBUG_SS5, "%s: incomming release-guard is recognized, responding...\n", p_name);
798                         else
799                                 PDEBUG(DEBUG_SS5, "%s: incomming clear-forward is recognized, responding...\n", p_name);
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 }
1270
1271 void Pss5::digit_ind(char digit)
1272 {
1273         int i;
1274         char string[128] = "", dial[128] = "";
1275         int dash, first_digit, last_was_digit;
1276
1277         /* add digit */
1278         SCCAT(p_m_s_dial, digit);
1279
1280         if (p_state == PORT_STATE_IN_SETUP)
1281                 new_state(PORT_STATE_IN_OVERLAP);
1282
1283         /* not last digit ? */
1284         if (digit != 'c')
1285                 return;
1286
1287         /* parse string */
1288         dash = 0; /* dash must be used next time */
1289         first_digit = 1;
1290         last_was_digit = 0;
1291         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1292         for (i = 0; p_m_s_dial[i]; i++) {
1293                 if (dash || (last_was_digit && (p_m_s_dial[i]<'0' || p_m_s_dial[i]>'9')))
1294                         SCCAT(string, '-');
1295                 dash = 0;
1296                 last_was_digit = 0;
1297                 switch(p_m_s_dial[i]) {
1298                         case '1':
1299                         case '2':
1300                         case '3':
1301                         case '4':
1302                         case '5':
1303                         case '6':
1304                         case '7':
1305                         case '8':
1306                         case '9':
1307                         case '0':
1308                         if (first_digit)
1309                                 dash = 1;
1310                         first_digit = 0;
1311                         last_was_digit = 1;
1312                         SCCAT(string, p_m_s_dial[i]);
1313                         SCCAT(dial, p_m_s_dial[i]);
1314                         break;
1315                         case '*':
1316                         SCAT(string, "C11");
1317                         SCCAT(dial, p_m_s_dial[i]);
1318                         dash = 1;
1319                         break;
1320                         case '#':
1321                         SCAT(string, "C12");
1322                         SCCAT(dial, p_m_s_dial[i]);
1323                         dash = 1;
1324                         break;
1325                         case 'a':
1326                         SCAT(string, "KP1");
1327                         SCCAT(dial, p_m_s_dial[i]);
1328                         dash = 1;
1329                         break;
1330                         case 'b':
1331                         SCAT(string, "KP2");
1332                         SCCAT(dial, p_m_s_dial[i]);
1333                         dash = 1;
1334                         break;
1335                         case 'c':
1336                         SCAT(string, "ST");
1337                         dash = 1;
1338                         break;
1339                         default:
1340                         break;
1341                 }
1342         }
1343         ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1344         add_trace("string", NULL, "%s", string);
1345         add_trace("number", NULL, "%s", dial);
1346         end_trace();
1347         new_ss5_state(SS5_STATE_IDLE);
1348
1349         do_setup(dial);
1350         new_state(PORT_STATE_IN_PROCEEDING);
1351 }
1352
1353 void Pss5::pulse_ind(int on)
1354 {
1355         struct lcr_msg *message;
1356         char dial[3] = "a.";
1357
1358         if (p_m_s_signal == SS5_SIGNAL_PULSE_OFF) {
1359                 if (on) {
1360                         /* pulse turns on */
1361                         p_m_s_recog = 0;
1362                         new_ss5_signal(SS5_SIGNAL_PULSE_ON);
1363                         /* pulse turns of, count it */
1364                         p_m_s_pulsecount++;
1365                         PDEBUG(DEBUG_SS5, "%s: pulse turns on, counting\n", p_name);
1366                 } else {
1367                         /* pulse remains off */
1368                         p_m_s_recog += SS5_DECODER_NPOINTS;
1369                         /* not recognized end of digit, we wait... */
1370                         if (p_m_s_recog < BELL_TIMER_RECOG_END)
1371                                 return;
1372                         PDEBUG(DEBUG_SS5, "%s: pulse remains off, counted %d pulses\n", p_name, p_m_s_pulsecount);
1373                         if (p_m_s_pulsecount >= 12)
1374                                 dial[1] = '#';
1375                         else if (p_m_s_pulsecount == 11)
1376                                 dial[1] = '*';
1377                         else if (p_m_s_pulsecount == 10)
1378                                 dial[1] = '0';
1379                         else
1380                                 dial[1] = p_m_s_pulsecount + '0';
1381                         ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1382                         add_trace("digit", NULL, "%s", dial+1);
1383                         add_trace("pulses", NULL, "%d", p_m_s_pulsecount);
1384                         end_trace();
1385                         /* special star release feature */
1386                         if ((p_m_mISDNport->ss5 & SS5_FEATURE_STAR_RELEASE) && dial[1] == '*') {
1387                                 ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1388                                 add_trace("star", NULL, "releases call");
1389                                 end_trace();
1390                                 goto star_release;
1391                         }
1392                         if (p_state == PORT_STATE_IN_SETUP) {
1393                                 /* sending digit as setup */
1394                                 do_setup(dial); /* include 'a' == KP1 */
1395                                 new_state(PORT_STATE_IN_OVERLAP);
1396                         } else {
1397                                 /* sending digit as information */
1398                                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
1399                                 SCPY(message->param.information.id, dial+1);
1400                                 message_put(message);
1401                         }
1402                                 new_ss5_state(SS5_STATE_IDLE);
1403                         /* done rx pulses, return to idle */
1404                         new_ss5_state(SS5_STATE_IDLE);
1405                 }
1406         } else {
1407                 if (on) {
1408                         /* pulse remains on */
1409                         p_m_s_recog += SS5_DECODER_NPOINTS;
1410                 } else {
1411                         /* pulse turns off */
1412                         if (p_m_s_recog >= BELL_TIMER_RECOG_HANGUP) {
1413                                 PDEBUG(DEBUG_SS5, "%s: long pulse turns off, releasing\n", p_name);
1414                                 ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_IND, p_m_b_channel);
1415                                 add_trace("longtone", NULL, "releases call");
1416                                 end_trace();
1417                                 star_release:
1418                                 /* long pulse is gone, release current connection, if any */
1419                                 while(p_epointlist) {
1420                                         message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1421                                         message->param.disconnectinfo.location = LOCATION_BEYOND;
1422                                         message->param.disconnectinfo.cause = CAUSE_NORMAL;
1423                                         message_put(message);
1424                                         free_epointlist(p_epointlist);
1425                                 }
1426                                 set_tone("", NULL);
1427                                 /* return to setup state */
1428                                 new_state(PORT_STATE_IN_SETUP);
1429                                 new_ss5_state(SS5_STATE_IDLE);
1430                                 return;
1431                         }
1432                         PDEBUG(DEBUG_SS5, "%s: short pulse turns off, releasing\n", p_name);
1433                         p_m_s_recog = 0;
1434                         new_ss5_signal(SS5_SIGNAL_PULSE_OFF);
1435                 }
1436         }
1437 }
1438
1439 void Pss5::proceed_to_send_ind(void)
1440 {
1441         ss5_trace_header(p_m_mISDNport, this, SS5_PROCEED_TO_SEND_IND, p_m_b_channel);
1442         end_trace();
1443
1444         SCPY(p_m_s_dial, p_dialinginfo.id);
1445         start_signal(SS5_STATE_DIAL_OUT);
1446
1447         new_state(PORT_STATE_OUT_OVERLAP);
1448 }
1449
1450 void Pss5::busy_flash_ind(void)
1451 {
1452         struct lcr_msg *message;
1453
1454         ss5_trace_header(p_m_mISDNport, this, SS5_BUSY_FLASH_IND, p_m_b_channel);
1455         end_trace();
1456
1457         /* busy before dialing ? */
1458         if (!p_epointlist)
1459                 return;
1460
1461         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_NODISCONNECT)) {
1462                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
1463                 message->param.disconnectinfo.location = LOCATION_BEYOND;
1464                 message->param.disconnectinfo.cause = CAUSE_BUSY;
1465                 message_put(message);
1466         }
1467
1468         new_state(PORT_STATE_IN_DISCONNECT);
1469 }
1470
1471 void Pss5::answer_ind(void)
1472 {
1473         struct lcr_msg *message;
1474
1475         ss5_trace_header(p_m_mISDNport, this, SS5_ANSWER_IND, p_m_b_channel);
1476         end_trace();
1477
1478         /* answer before dialing ? */
1479         if (!p_epointlist)
1480                 return;
1481
1482         /* already connected */
1483         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_CONNECT)) {
1484                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
1485                 message_put(message);
1486         }
1487
1488         new_state(PORT_STATE_CONNECT);
1489 }
1490
1491 void Pss5::forward_transfer_ind(void)
1492 {
1493 //      struct lcr_msg *message;
1494
1495         ss5_trace_header(p_m_mISDNport, this, SS5_FORWARD_TRANSFER_IND, p_m_b_channel);
1496         end_trace();
1497
1498 #if 0
1499         /* if BELL flavor bluebox flag is set, use it to seize a new line */
1500         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_BELL))
1501                 return;
1502
1503         /* special BELL flavor hack to clear a line and seize a new one */
1504         while(p_epointlist) {
1505                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1506                 message->param.disconnectinfo.location = LOCATION_BEYOND;
1507                 message->param.disconnectinfo.cause = CAUSE_NORMAL;
1508                 message_put(message);
1509                 free_epointlist(p_epointlist);
1510         }
1511         set_tone("", NULL);
1512         new_state(PORT_STATE_IN_SETUP);
1513 #endif
1514 }
1515
1516 void Pss5::clear_back_ind(void)
1517 {
1518         struct lcr_msg *message;
1519
1520         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_BACK_IND, p_m_b_channel);
1521         end_trace();
1522
1523         /* nobody? */
1524         if (!p_epointlist)
1525                 return;
1526
1527         if (!(p_m_mISDNport->ss5 & SS5_FEATURE_NODISCONNECT)) {
1528                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DISCONNECT);
1529                 message->param.disconnectinfo.location = LOCATION_BEYOND;
1530                 message->param.disconnectinfo.cause = CAUSE_NORMAL;
1531                 message_put(message);
1532         }
1533
1534         new_state(PORT_STATE_IN_DISCONNECT);
1535 }
1536
1537 void Pss5::clear_forward_ind(void)
1538 {
1539         struct lcr_msg *message;
1540
1541         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_FORWARD_IND, p_m_b_channel);
1542         end_trace();
1543
1544         new_state(PORT_STATE_IDLE);
1545         set_tone("", NULL);
1546         p_type = PORT_TYPE_SS5_IDLE;
1547
1548         /* someone ? */
1549         if (!p_epointlist)
1550                 return;
1551
1552         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
1553         message->param.disconnectinfo.location = LOCATION_BEYOND;
1554         message->param.disconnectinfo.cause = CAUSE_NORMAL;
1555         message_put(message);
1556         free_epointlist(p_epointlist);
1557
1558 }
1559
1560 void Pss5::release_guard_ind(void)
1561 {
1562         struct lcr_msg *message;
1563
1564         ss5_trace_header(p_m_mISDNport, this, SS5_RELEASE_GUARD_IND, p_m_b_channel);
1565         end_trace();
1566
1567         set_tone("", NULL);
1568
1569         /* someone ? */
1570         if (!p_epointlist)
1571                 return;
1572
1573         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
1574         message->param.disconnectinfo.location = LOCATION_BEYOND;
1575         message->param.disconnectinfo.cause = CAUSE_NORMAL;
1576         message_put(message);
1577         free_epointlist(p_epointlist);
1578 }
1579
1580 void Pss5::double_seizure_ind(void)
1581 {
1582         ss5_trace_header(p_m_mISDNport, this, SS5_DOUBLE_SEIZURE_IND, p_m_b_channel);
1583         end_trace();
1584         ss5_trace_header(p_m_mISDNport, this, SS5_DOUBLE_SEIZURE_REQ, p_m_b_channel);
1585         end_trace();
1586
1587         /* start double seizure sequence, so remote exchange will recognize it */
1588         start_signal(SS5_STATE_DOUBLE_SEIZE);
1589 }
1590
1591
1592 /*
1593  * shuts down by sending a clear forward and releasing endpoint
1594  */
1595 void Pss5::do_release(int cause, int location)
1596 {
1597         struct lcr_msg *message;
1598
1599         /* sending release to endpoint */
1600         while(p_epointlist) {
1601                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1602                 message->param.disconnectinfo.location = location;
1603                 message->param.disconnectinfo.cause = cause;
1604                 message_put(message);
1605                 free_epointlist(p_epointlist);
1606         }
1607
1608         /* start clear-forward */
1609         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_FORWARD_REQ, p_m_b_channel);
1610         end_trace();
1611         start_signal(SS5_STATE_CLEAR_FORWARD);
1612
1613         new_state(PORT_STATE_RELEASE);
1614 }
1615
1616
1617 /*
1618  * create endpoint and send setup
1619  */
1620 void Pss5::do_setup(char *dial)
1621 {
1622         class Endpoint *epoint;
1623         struct lcr_msg *message;
1624
1625         SCPY(p_dialinginfo.id, dial);
1626         p_dialinginfo.sending_complete = 1;
1627         p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
1628         p_callerinfo.screen = INFO_SCREEN_NETWORK;
1629         p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1630         p_callerinfo.isdn_port = p_m_portnum;
1631         SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
1632
1633         p_capainfo.bearer_capa = INFO_BC_AUDIO;
1634         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
1635         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
1636         p_capainfo.hlc = INFO_HLC_NONE;
1637         p_capainfo.exthlc = INFO_HLC_NONE;
1638         p_capainfo.source_mode = B_MODE_TRANSPARENT;
1639
1640         /* create endpoint */
1641         if (p_epointlist)
1642                 FATAL("Incoming call but already got an endpoint.\n");
1643         if (!(epoint = new Endpoint(p_serial, 0)))
1644                 FATAL("No memory for Endpoint instance\n");
1645         if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
1646                 FATAL("No memory for Endpoint Application instance\n");
1647         epointlist_new(epoint->ep_serial);
1648
1649         /* send setup message to endpoit */
1650         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
1651         message->param.setup.isdn_port = p_m_portnum;
1652         message->param.setup.port_type = p_type;
1653 //      message->param.setup.dtmf = !p_m_mISDNport->ifport->nodtmf;
1654         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
1655         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
1656         memcpy(&message->param.setup.redirinfo, &p_redirinfo, sizeof(struct redir_info));
1657         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
1658         message_put(message);
1659
1660 }
1661
1662
1663 /*
1664  * handler
1665  */
1666 int Pss5::handler(void)
1667 {
1668         int ret;
1669
1670         if ((ret = PmISDN::handler()))
1671                 return(ret);
1672
1673         /* handle timer */
1674         if (p_m_s_timer && p_m_s_timer < now) {
1675                 p_m_s_timer = 0.0;
1676                 (this->*(p_m_s_timer_fn))();
1677         }
1678
1679         /* if answer signal is queued */
1680         if (p_m_s_answer && p_m_s_state == SS5_STATE_IDLE) {
1681                 p_m_s_answer = 0;
1682                 /* start answer */
1683                 ss5_trace_header(p_m_mISDNport, this, SS5_ANSWER_REQ, p_m_b_channel);
1684                 end_trace();
1685                 start_signal(SS5_STATE_ANSWER);
1686         }
1687
1688         /* if busy-flash signal is queued */
1689         if (p_m_s_busy_flash && p_m_s_state == SS5_STATE_IDLE) {
1690                 p_m_s_busy_flash = 0;
1691                 /* start busy-flash */
1692                 ss5_trace_header(p_m_mISDNport, this, SS5_BUSY_FLASH_REQ, p_m_b_channel);
1693                 end_trace();
1694                 start_signal(SS5_STATE_BUSY_FLASH);
1695         }
1696
1697         /* if clear-back signal is queued */
1698         if (p_m_s_clear_back && p_m_s_state == SS5_STATE_IDLE) {
1699                 p_m_s_clear_back = 0;
1700                 /* start clear-back */
1701                 ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_BACK_REQ, p_m_b_channel);
1702                 end_trace();
1703                 start_signal(SS5_STATE_CLEAR_BACK);
1704         }
1705
1706         return(0);
1707 }
1708
1709
1710 /*
1711  * handles all messages from endpoint
1712  */
1713
1714 /* MESSAGE_SETUP */
1715 void Pss5::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
1716 {
1717         struct lcr_msg *message;
1718         int i;
1719         char string[128] = "", dial[128] = "";
1720         int dash, first_digit, last_was_digit;
1721
1722         if (p_epointlist) {
1723                 PERROR("endpoint already exist.\n");
1724                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1725                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1726                 message->param.disconnectinfo.cause = CAUSE_UNSPECIFIED;
1727                 message_put(message);
1728                 return;
1729         }
1730
1731         /* copy setup infos to port */
1732         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
1733         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
1734         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
1735         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
1736         /* screen outgoing caller id */
1737         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
1738         do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
1739
1740         /* parse dial string  */
1741         dash = 0; /* dash must be used next time */
1742         first_digit = 1;
1743         last_was_digit = 0;
1744         for (i = 0; p_dialinginfo.id[i]; i++) {
1745                 if (dash || (last_was_digit && (p_dialinginfo.id[i]<'0' || p_dialinginfo.id[i]>'9')))
1746                         SCCAT(string, '-');
1747                 dash = 0;
1748                 last_was_digit = 0;
1749                 switch(p_dialinginfo.id[i]) {
1750                         case '1':
1751                         case '2':
1752                         case '3':
1753                         case '4':
1754                         case '5':
1755                         case '6':
1756                         case '7':
1757                         case '8':
1758                         case '9':
1759                         case '0':
1760                         if (i && first_digit)
1761                                 dash = 1;
1762                         first_digit = 0;
1763                         last_was_digit = 1;
1764                         SCCAT(string, p_dialinginfo.id[i]);
1765                         SCCAT(dial, p_dialinginfo.id[i]);
1766                         break;
1767                         case '*':
1768                         SCAT(string, "C11");
1769                         SCCAT(dial, '*');
1770                         dash = 1;
1771                         break;
1772                         case '#':
1773                         SCAT(string, "C12");
1774                         SCCAT(dial, '#');
1775                         dash = 1;
1776                         break;
1777                         case 'a':
1778                         SCAT(string, "KP1");
1779                         SCCAT(dial, 'a');
1780                         dash = 1;
1781                         break;
1782                         case 'b':
1783                         SCAT(string, "KP2");
1784                         SCCAT(dial, 'b');
1785                         dash = 1;
1786                         break;
1787                         case 'c':
1788                         SCAT(string, "ST");
1789                         SCCAT(dial, 'c');
1790                         dash = 1;
1791                         case 'K':
1792                         i++;
1793                         if (p_dialinginfo.id[i] != 'P')
1794                                 goto dial_error;
1795                         i++;
1796                         if (p_dialinginfo.id[i] == '1') {
1797                                 SCAT(string, "KP1");
1798                                 SCCAT(dial, 'a');
1799                                 dash = 1;
1800                                 break;
1801                         }
1802                         if (p_dialinginfo.id[i] == '2') {
1803                                 SCAT(string, "KP2");
1804                                 SCCAT(dial, 'b');
1805                                 dash = 1;
1806                                 break;
1807                         }
1808                         goto dial_error;
1809                         case 'C':
1810                         i++;
1811                         if (p_dialinginfo.id[i] != '1')
1812                                 goto dial_error;
1813                         i++;
1814                         if (p_dialinginfo.id[i] == '1') {
1815                                 SCAT(string, "C11");
1816                                 SCCAT(dial, 'a');
1817                                 dash = 1;
1818                                 break;
1819                         }
1820                         if (p_dialinginfo.id[i] == '2') {
1821                                 SCAT(string, "C12");
1822                                 SCCAT(dial, 'b');
1823                                 dash = 1;
1824                                 break;
1825                         }
1826                         goto dial_error;
1827                         case 'S':
1828                         i++;
1829                         if (p_dialinginfo.id[i] != 'T')
1830                                 goto dial_error;
1831                         SCAT(string, "ST");
1832                         SCCAT(dial, 'c');
1833                         dash = 1;
1834                         break;
1835                         default:
1836                         break;
1837                 }
1838                 /* stop, if ST */
1839                 if (dial[0] && dial[strlen(dial)-1] == 'c')
1840                         break;
1841         }
1842         /* terminate */
1843         if (dial[0] && dial[strlen(dial)-1]!='c') {
1844                 SCCAT(string, '-');
1845                 SCAT(string, "ST");
1846                 SCCAT(dial, 'c');
1847         }
1848
1849         /* error in dial string */
1850         if (!dial[0]) {
1851                 dial_error:
1852                 ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_REQ, p_m_b_channel);
1853                 add_trace("string", NULL, "%s", p_dialinginfo.id);
1854                 if (!dial[0])
1855                         add_trace("error", NULL, "no number", dial);
1856                 else if (dial[0]!='a' && dial[0]!='b')
1857                         add_trace("error", NULL, "number must start with KP1/KP2", dial);
1858                 else
1859                         add_trace("error", NULL, "illegal format", dial);
1860                 end_trace();
1861                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1862                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1863                 message->param.disconnectinfo.cause = CAUSE_INVALID;
1864                 message_put(message);
1865                 return;
1866         }
1867
1868         /* copy new dial string */
1869         SCPY(p_dialinginfo.id, dial);
1870
1871         /* attach only if not already */
1872         epointlist_new(epoint_id);
1873
1874         ss5_trace_header(p_m_mISDNport, this, SS5_DIALING_REQ, p_m_b_channel);
1875         add_trace("string", NULL, "%s", string);
1876         add_trace("type", NULL, "%s", (dial[0]=='b')?"international":"national");
1877         add_trace("number", NULL, "%s", dial);
1878         end_trace();
1879         /* connect auto path */
1880         if ((p_m_mISDNport->ss5 & SS5_FEATURE_CONNECT)) {
1881                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
1882                 message_put(message);
1883         } else {
1884                 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1885                 message_put(message);
1886         }
1887
1888         /* start seizing */
1889         ss5_trace_header(p_m_mISDNport, this, SS5_SEIZING_REQ, p_m_b_channel);
1890         end_trace();
1891         new_ss5_state(SS5_STATE_SEIZING);
1892         new_ss5_signal(SS5_SIGNAL_SEND_ON);
1893         p_m_s_sample_nr = 0;
1894         inband_send_on();
1895
1896         p_type = PORT_TYPE_SS5_OUT;
1897         new_state(PORT_STATE_OUT_SETUP);
1898 }
1899
1900 /* MESSAGE_CONNECT */
1901 void Pss5::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
1902 {
1903         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
1904
1905         if (p_state != PORT_STATE_CONNECT) {
1906                 new_state(PORT_STATE_CONNECT);
1907                 p_m_s_answer = 1;
1908         }
1909
1910         set_tone("", NULL);
1911 }
1912
1913 /* MESSAGE_DISCONNECT */
1914 void Pss5::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1915 {
1916         /* disconnect and clear forward (release guard) */
1917 //      if ((p_type==PORT_TYPE_SS5_IN && !p_m_mISDNport->tones) /* incomming exchange with no tones */
1918 if (0    || p_type==PORT_TYPE_SS5_OUT) { /* outgoing exchange */
1919                 do_release(param->disconnectinfo.cause, param->disconnectinfo.location);
1920                 return;
1921         }
1922
1923         ss5_trace_header(p_m_mISDNport, this, SS5_CLEAR_BACK_REQ, p_m_b_channel);
1924         end_trace();
1925         start_signal(SS5_STATE_CLEAR_BACK);
1926
1927         new_state(PORT_STATE_OUT_DISCONNECT);
1928 }
1929
1930 /* MESSAGE_RELEASE */
1931 void Pss5::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1932 {
1933         do_release(param->disconnectinfo.cause, param->disconnectinfo.location);
1934 }
1935
1936
1937 /*
1938  * endpoint sends messages to the port
1939  */
1940 int Pss5::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1941 {
1942         if (PmISDN::message_epoint(epoint_id, message_id, param))
1943                 return(1);
1944
1945         switch(message_id) {
1946                 case MESSAGE_SETUP: /* dial-out command received from epoint */
1947                 if (p_state!=PORT_STATE_IDLE) {
1948                         PERROR("Pss5(%s) ignoring setup because isdn port is not in idle state (or connected for sending display info).\n", p_name);
1949                         break;
1950                 }
1951                 if (p_epointlist && p_state==PORT_STATE_IDLE)
1952                         FATAL("Pss5(%s): epoint pointer is set in idle state, how bad!!\n", p_name);
1953                 message_setup(epoint_id, message_id, param);
1954                 break;
1955
1956                 case MESSAGE_CONNECT: /* call of endpoint is connected */
1957                 message_connect(epoint_id, message_id, param);
1958                 break;
1959
1960                 case MESSAGE_DISCONNECT: /* call has been disconnected */
1961                 message_disconnect(epoint_id, message_id, param);
1962                 break;
1963
1964                 case MESSAGE_RELEASE: /* release isdn port */
1965                 message_release(epoint_id, message_id, param);
1966                 break;
1967
1968                 default:
1969                 PDEBUG(DEBUG_SS5, "Pss5(%s) ss5 port with (caller id %s) received an unhandled message: %d\n", p_name, p_callerinfo.id, message_id);
1970         }
1971
1972         return(1);
1973 }
1974