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