fixed audio preload of tones. this reduces the propability of audio gaps resulting...
[lcr.git] / mISDN.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN port abstraction for dss1                                           **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13 #include "myisdn.h"
14
15 extern "C" {
16 }
17 #include <q931.h>
18
19 #undef offsetof
20 #ifdef __compiler_offsetof
21 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
22 #else
23 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
24 #endif
25
26 #define container_of(ptr, type, member) ({                      \
27         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
28         (type *)( (char *)__mptr - offsetof(type,member) );})
29
30 // timeouts if activating/deactivating response from mISDN got lost
31 #define B_TIMER_ACTIVATING 1 // seconds
32 #define B_TIMER_DEACTIVATING 1 // seconds
33
34 /* list of mISDN ports */
35 struct mISDNport *mISDNport_first;
36
37 /* noise randomizer */
38 unsigned char mISDN_rand[256];
39 int mISDN_rand_count = 0;
40
41 unsigned int mt_assign_pid = ~0;
42
43 int mISDNsocket = -1;
44
45 int mISDN_initialize(void)
46 {
47         char filename[256];
48
49         /* try to open raw socket to check kernel */
50         mISDNsocket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
51         if (mISDNsocket < 0)
52         {
53                 fprintf(stderr, "Cannot open mISDN due to '%s'. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
54                 return(-1);
55         }
56
57         /* init mlayer3 */
58         init_layer3(4); // buffer of 4
59
60         /* open debug, if enabled and not only stack debugging */
61         if (options.deb)
62         {
63                 SPRINT(filename, "%s/debug.log", INSTALL_DATA);
64                 debug_fp = fopen(filename, "a");
65         }
66
67         if (options.deb & DEBUG_STACK)
68         {
69                 SPRINT(filename, "%s/debug_mISDN.log", INSTALL_DATA);
70                 mISDN_debug_init(0xffffffff, filename, filename, filename);
71         } else
72                 mISDN_debug_init(0, NULL, NULL, NULL);
73
74         return(0);
75 }
76
77 void mISDN_deinitialize(void)
78 {
79         cleanup_layer3();
80
81         mISDN_debug_close();
82
83         if (debug_fp)
84                 fclose(debug_fp);
85         debug_fp = NULL;
86
87         if (mISDNsocket > -1)
88                 close(mISDNsocket);
89 }
90
91 /*
92  * constructor
93  */
94 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Port(type, portname, settings)
95 {
96         p_m_mISDNport = mISDNport;
97         p_m_portnum = mISDNport->portnum;
98         p_m_b_index = -1;
99         p_m_b_channel = 0;
100         p_m_b_exclusive = 0;
101         p_m_b_reserve = 0;
102         p_m_b_mode = mode;
103         p_m_delete = 0;
104         p_m_hold = 0;
105         p_m_tx_gain = mISDNport->ifport->interface->tx_gain;
106         p_m_rx_gain = mISDNport->ifport->interface->rx_gain;
107         p_m_conf = 0;
108         p_m_txdata = 0;
109         p_m_delay = 0;
110         p_m_echo = 0;
111         p_m_tone = 0;
112         p_m_rxoff = 0;
113         p_m_joindata = 0;
114         p_m_dtmf = !mISDNport->ifport->nodtmf;
115         p_m_timeout = 0;
116         p_m_timer = 0;
117         p_m_remote_ref = 0; /* channel shall be exported to given remote */
118         p_m_remote_id = 0; /* remote admin socket */
119         SCPY(p_m_pipeline, mISDNport->ifport->interface->pipeline);
120         
121         /* audio */
122         p_m_load = 0;
123         p_m_last_tv_sec = 0;
124
125         /* crypt */
126         p_m_crypt = 0;
127         p_m_crypt_listen = 0;
128         p_m_crypt_msg_loops = 0;
129         p_m_crypt_msg_loops = 0;
130         p_m_crypt_msg_len = 0;
131         p_m_crypt_msg[0] = '\0';
132         p_m_crypt_msg_current = 0;
133         p_m_crypt_key_len = 0;
134         p_m_crypt_listen = 0;
135         p_m_crypt_listen_state = 0;
136         p_m_crypt_listen_len = 0;
137         p_m_crypt_listen_msg[0] = '\0';
138         p_m_crypt_listen_crc = 0;
139         if (mISDNport->ifport->interface->bf_len >= 4 && mISDNport->ifport->interface->bf_len <= 56)
140         {
141                 memcpy(p_m_crypt_key, mISDNport->ifport->interface->bf_key, p_m_crypt_key_len);
142                 p_m_crypt_key_len = mISDNport->ifport->interface->bf_len;
143                 p_m_crypt = 1;
144         }
145
146         /* if any channel requested by constructor */
147         if (channel == CHANNEL_ANY)
148         {
149                 /* reserve channel */
150                 p_m_b_reserve = 1;
151                 mISDNport->b_reserved++;
152         }
153
154         /* reserve channel */
155         if (channel > 0) // only if constructor was called with a channel resevation
156                 seize_bchannel(channel, exclusive);
157
158         /* we increase the number of objects: */
159         mISDNport->use++;
160         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
161 }
162
163
164 /*
165  * destructor
166  */
167 PmISDN::~PmISDN()
168 {
169         struct lcr_msg *message;
170
171         /* remove bchannel relation */
172         drop_bchannel();
173
174         /* release epoint */
175         while (p_epointlist)
176         {
177                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
178                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
179                 message->param.disconnectinfo.cause = 16;
180                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
181                 message_put(message);
182                 /* remove from list */
183                 free_epointlist(p_epointlist);
184         }
185
186         /* we decrease the number of objects: */
187         p_m_mISDNport->use--;
188         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
189 }
190
191
192 /*
193  * trace
194  */
195 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
196 {
197         /* init trace with given values */
198         start_trace(mISDNport?mISDNport->portnum:0,
199                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
200                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
201                     port?port->p_dialinginfo.id:NULL,
202                     direction,
203                     CATEGORY_CH,
204                     port?port->p_serial:0,
205                     msgtext);
206 }
207
208
209 /*
210  * layer trace header
211  */
212 static struct isdn_message {
213         char *name;
214         unsigned int value;
215 } isdn_message[] = {
216         {"PH_ACTIVATE", L1_ACTIVATE_REQ},
217         {"PH_DEACTIVATE", L1_DEACTIVATE_REQ},
218         {"DL_ESTABLISH", L2_ESTABLISH_REQ},
219         {"DL_RELEASE", L2_RELEASE_REQ},
220         {"UNKNOWN", L3_UNKNOWN},
221         {"MT_TIMEOUT", L3_TIMEOUT_REQ},
222         {"MT_SETUP", L3_SETUP_REQ},
223         {"MT_SETUP_ACK", L3_SETUP_ACKNOWLEDGE_REQ},
224         {"MT_PROCEEDING", L3_PROCEEDING_REQ},
225         {"MT_ALERTING", L3_ALERTING_REQ},
226         {"MT_CONNECT", L3_CONNECT_REQ},
227         {"MT_CONNECT_ACK", L3_CONNECT_ACKNOWLEDGE_REQ},
228         {"MT_DISCONNECT", L3_DISCONNECT_REQ},
229         {"MT_RELEASE", L3_RELEASE_REQ},
230         {"MT_RELEASE_COMP", L3_RELEASE_COMPLETE_REQ},
231         {"MT_INFORMATION", L3_INFORMATION_REQ},
232         {"MT_PROGRESS", L3_PROGRESS_REQ},
233         {"MT_NOTIFY", L3_NOTIFY_REQ},
234         {"MT_SUSPEND", L3_SUSPEND_REQ},
235         {"MT_SUSPEND_ACK", L3_SUSPEND_ACKNOWLEDGE_REQ},
236         {"MT_SUSPEND_REJ", L3_SUSPEND_REJECT_REQ},
237         {"MT_RESUME", L3_RESUME_REQ},
238         {"MT_RESUME_ACK", L3_RESUME_ACKNOWLEDGE_REQ},
239         {"MT_RESUME_REJ", L3_RESUME_REJECT_REQ},
240         {"MT_HOLD", L3_HOLD_REQ},
241         {"MT_HOLD_ACK", L3_HOLD_ACKNOWLEDGE_REQ},
242         {"MT_HOLD_REJ", L3_HOLD_REJECT_REQ},
243         {"MT_RETRIEVE", L3_RETRIEVE_REQ},
244         {"MT_RETRIEVE_ACK", L3_RETRIEVE_ACKNOWLEDGE_REQ},
245         {"MT_RETRIEVE_REJ", L3_RETRIEVE_REJECT_REQ},
246         {"MT_FACILITY", L3_FACILITY_REQ},
247         {"MT_STATUS", L3_STATUS_REQ},
248         {"MT_RESTART", L3_RESTART_REQ},
249         {"MT_NEW_L3ID", L3_NEW_L3ID_REQ},
250         {"MT_RELEASE_L3ID", L3_RELEASE_L3ID_REQ},
251         {NULL, 0},
252 };
253 static char *isdn_prim[4] = {
254         " REQUEST",
255         " CONFIRM",
256         " INDICATION",
257         " RESPONSE",
258 };
259 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg, int direction)
260 {
261         int i;
262         char msgtext[64] = "<<UNKNOWN MESSAGE>>";
263
264         /* select message and primitive text */
265         i = 0;
266         while(isdn_message[i].name)
267         {
268                 if (isdn_message[i].value == (msg&0xffffff00))
269                 {
270                         SCPY(msgtext, isdn_message[i].name);
271                         break;
272                 }
273                 i++;
274         }
275         SCAT(msgtext, isdn_prim[msg&0x00000003]);
276
277         /* add direction */
278         if (direction && (msg&0xffffff00)!=L3_NEW_L3ID_REQ && (msg&0xffffff00)!=L3_RELEASE_L3ID_REQ)
279         {
280                 if (mISDNport)
281                 {
282                         if (mISDNport->ntmode)
283                         {
284                                 if (direction == DIRECTION_OUT)
285                                         SCAT(msgtext, " N->U");
286                                 else
287                                         SCAT(msgtext, " N<-U");
288                         } else
289                         {
290                                 if (direction == DIRECTION_OUT)
291                                         SCAT(msgtext, " U->N");
292                                 else
293                                         SCAT(msgtext, " U<-N");
294                         }
295                 }
296         }
297
298         /* init trace with given values */
299         start_trace(mISDNport?mISDNport->portnum:0,
300                     mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
301                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
302                     port?port->p_dialinginfo.id:NULL,
303                     direction,
304                     CATEGORY_CH,
305                     port?port->p_serial:0,
306                     msgtext);
307 }
308
309
310 /*
311  * send control information to the channel (dsp-module)
312  */
313 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, unsigned int c1, unsigned int c2, char *trace_name, int trace_value)
314 {
315         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
316         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
317         unsigned int *d = (unsigned int *)(buffer+MISDN_HEADER_LEN);
318         int ret;
319
320         if (sock < 0)
321                 return;
322
323         ctrl->prim = PH_CONTROL_REQ;
324         ctrl->id = 0;
325         *d++ = c1;
326         *d++ = c2;
327         ret = sendto(sock, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
328         if (ret <= 0)
329                 PERROR("Failed to send to socket %d\n", sock);
330         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
331         if (c1 == DSP_CONF_JOIN)
332                 add_trace(trace_name, NULL, "0x%08x", trace_value);
333         else
334                 add_trace(trace_name, NULL, "%d", trace_value);
335         end_trace();
336 }
337
338 void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, unsigned int c1, void *c2, int c2_len, char *trace_name, int trace_value)
339 {
340         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
341         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
342         unsigned int *d = (unsigned int *)(buffer+MISDN_HEADER_LEN);
343         int ret;
344
345         if (sock < 0)
346                 return;
347
348         ctrl->prim = PH_CONTROL_REQ;
349         ctrl->id = 0;
350         *d++ = c1;
351         memcpy(d, c2, c2_len);
352         ret = sendto(sock, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
353         if (ret <= 0)
354                 PERROR("Failed to send to socket %d\n", sock);
355         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
356         add_trace(trace_name, NULL, "%d", trace_value);
357         end_trace();
358 }
359
360
361 /*
362  * subfunction for bchannel_event
363  * create stack
364  */
365 static int _bchannel_create(struct mISDNport *mISDNport, int i)
366 {
367         int ret;
368         unsigned int on = 1;
369         struct sockaddr_mISDN addr;
370
371         if (mISDNport->b_socket[i] > -1)
372         {
373                 PERROR("Error: Socket already created for index %d\n", i);
374                 return(0);
375         }
376
377         /* open socket */
378 //#warning testing without DSP
379 //      mISDNport->b_socket[i] = socket(PF_ISDN, SOCK_DGRAM, (mISDNport->b_mode[i]==B_MODE_HDLC)?ISDN_P_B_HDLC:ISDN_P_B_RAW);
380         mISDNport->b_socket[i] = socket(PF_ISDN, SOCK_DGRAM, (mISDNport->b_mode[i]==B_MODE_HDLC)?ISDN_P_B_L2DSPHDLC:ISDN_P_B_L2DSP);
381         if (mISDNport->b_socket[i] < 0)
382         {
383                 PERROR("Error: Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
384                 return(0);
385         }
386         
387         /* set nonblocking io */
388         ret = ioctl(mISDNport->b_socket[i], FIONBIO, &on);
389         if (ret < 0)
390         {
391                 PERROR("Error: Failed to set bchannel-socket index %d into nonblocking IO\n", i);
392                 close(mISDNport->b_socket[i]);
393                 mISDNport->b_socket[i] = -1;
394                 return(0);
395         }
396
397         /* bind socket to bchannel */
398         addr.family = AF_ISDN;
399         addr.dev = mISDNport->portnum-1;
400         addr.channel = i+1+(i>=15);
401         ret = bind(mISDNport->b_socket[i], (struct sockaddr *)&addr, sizeof(addr));
402         if (ret < 0)
403         {
404                 PERROR("Error: Failed to bind bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
405                 close(mISDNport->b_socket[i]);
406                 mISDNport->b_socket[i] = -1;
407                 return(0);
408         }
409
410         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create socket", DIRECTION_OUT);
411         add_trace("channel", NULL, "%d", i+1+(i>=15));
412         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
413         end_trace();
414
415         return(1);
416 }
417
418
419 /*
420  * subfunction for bchannel_event
421  * activate / deactivate request
422  */
423 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
424 {
425         struct mISDNhead act;
426         int ret;
427
428         if (mISDNport->b_socket[i] < 0)
429                 return;
430         act.prim = (activate)?PH_ACTIVATE_REQ:PH_DEACTIVATE_REQ; 
431         act.id = 0;
432         ret = sendto(mISDNport->b_socket[i], &act, MISDN_HEADER_LEN, 0, NULL, 0);
433         if (ret <= 0)
434                 PERROR("Failed to send to socket %d\n", mISDNport->b_socket[i]);
435
436         /* trace */
437         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
438         add_trace("channel", NULL, "%d", i+1+(i>=15));
439         if (mISDNport->b_timer[i])
440                 add_trace("event", NULL, "timeout recovery");
441         end_trace();
442 }
443
444
445 /*
446  * subfunction for bchannel_event
447  * set features
448  */
449 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
450 {
451         struct PmISDN *port;
452         int handle, mode;
453
454         if (mISDNport->b_socket[i] < 0)
455                 return;
456         handle = mISDNport->b_socket[i];
457         port = mISDNport->b_port[i];
458         mode = mISDNport->b_mode[i];
459         if (!port)
460         {
461                 PERROR("bchannel index i=%d not associated with a port object\n", i);
462                 return;
463         }
464
465         /* set dsp features */
466         if (port->p_m_txdata)
467                 ph_control(mISDNport, port, handle, (port->p_m_txdata)?DSP_TXDATA_ON:DSP_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
468         if (port->p_m_delay && mode == B_MODE_TRANSPARENT)
469                 ph_control(mISDNport, port, handle, DSP_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
470         if (port->p_m_tx_gain && mode == B_MODE_TRANSPARENT)
471                 ph_control(mISDNport, port, handle, DSP_VOL_CHANGE_TX, port->p_m_tx_gain, "DSP-TX_GAIN", port->p_m_tx_gain);
472         if (port->p_m_rx_gain && mode == B_MODE_TRANSPARENT)
473                 ph_control(mISDNport, port, handle, DSP_VOL_CHANGE_RX, port->p_m_rx_gain, "DSP-RX_GAIN", port->p_m_rx_gain);
474         if (port->p_m_pipeline[0] && mode == B_MODE_TRANSPARENT)
475                 ph_control_block(mISDNport, port, handle, DSP_PIPELINE_CFG, port->p_m_pipeline, strlen(port->p_m_pipeline)+1, "DSP-PIPELINE", 0);
476         if (port->p_m_conf)
477                 ph_control(mISDNport, port, handle, DSP_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
478         if (port->p_m_echo)
479                 ph_control(mISDNport, port, handle, DSP_ECHO_ON, 0, "DSP-ECHO", 1);
480         if (port->p_m_tone && mode == B_MODE_TRANSPARENT)
481                 ph_control(mISDNport, port, handle, DSP_TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
482         if (port->p_m_rxoff)
483                 ph_control(mISDNport, port, handle, DSP_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
484 //      if (port->p_m_txmix && mode == B_MODE_TRANSPARENT)
485 //              ph_control(mISDNport, port, handle, DSP_MIX_ON, 0, "DSP-MIX", 1);
486         if (port->p_m_dtmf && mode == B_MODE_TRANSPARENT)
487                 ph_control(mISDNport, port, handle, DTMF_TONE_START, 0, "DSP-DTMF", 1);
488         if (port->p_m_crypt && mode == B_MODE_TRANSPARENT)
489                 ph_control_block(mISDNport, port, handle, DSP_BF_ENABLE_KEY, port->p_m_crypt_key, port->p_m_crypt_key_len, "DSP-CRYPT", port->p_m_crypt_key_len);
490 }
491
492 /*
493  * subfunction for bchannel_event
494  * destroy stack
495  */
496 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
497 {
498         if (mISDNport->b_socket[i] < 0)
499                 return;
500         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove socket", DIRECTION_OUT);
501         add_trace("channel", NULL, "%d", i+1+(i>=15));
502         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
503         end_trace();
504         close(mISDNport->b_socket[i]);
505         mISDNport->b_socket[i] = -1;
506 }
507
508
509 /*
510 bchannel procedure
511 ------------------
512
513 A bchannel goes through the following states in this order:
514
515 - B_STATE_IDLE
516 No one is using the bchannel.
517 It is available and not linked to Port class, nor reserved.
518
519 - B_STATE_ACTIVATING
520 The bchannel stack is created and an activation request is sent.
521 It MAY be linked to Port class, but already unlinked due to Port class removal.
522
523 - B_STATE_ACTIVE
524 The bchannel is active and cofigured to the Port class needs.
525 Also it is linked to a Port class, otherwhise it would be deactivated.
526
527 - B_STATE_DEACTIVATING
528 The bchannel is in deactivating state, due to deactivation request.
529 It may be linked to a Port class, that likes to reactivate it.
530
531 - B_STATE_IDLE
532 See above.
533 After deactivating bchannel, and if not used, the bchannel becomes idle again.
534
535 Also the bchannel may be exported, but only if the state is or becomes idle:
536
537 - B_STATE_EXPORTING
538 The bchannel assignment has been sent to the remove application.
539
540 - B_STATE_REMOTE
541 The bchannel assignment is acknowledged by the remote application.
542
543 - B_STATE_IMPORTING
544 The bchannel is re-imported by mISDN port object.
545
546 - B_STATE_IDLE
547 See above.
548 After re-importing bchannel, and if not used, the bchannel becomes idle again.
549
550
551 A bchannel can have the following events:
552
553 - B_EVENT_USE
554 A bchannel is required by a Port class.
555
556 - B_EVENT_ACTIVATED
557 The bchannel beomes active.
558
559 - B_EVENT_DROP
560 The bchannel is not required by Port class anymore
561
562 - B_EVENT_DEACTIVATED
563 The bchannel becomes inactive.
564
565 - B_EVENT_EXPORTED
566 The bchannel is now used by remote application.
567
568 - B_EVENT_IMPORTED
569 The bchannel is not used by remote application.
570
571 - B_EVENT_EXPORTREQUEST
572 The bchannel shall be exported to the remote application.
573
574 - B_EVENT_IMPORTREQUEST
575 The bchannel is released from the remote application.
576
577 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
578
579 if an export request is receive by remote application, p_m_remote_* is set.
580 the b_remote_*[index] indicates if and where the channel is exported to. (set from the point on, where export is initiated, until imported is acknowledged.)
581 - set on export request from remote application (if port is assigned)
582 - set on channel use, if requested by remote application (p_m_remote_*)
583 - cleared on drop request
584
585 the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
586 the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
587 the bchannel import/export is acknowledged with stack given.
588
589 if exporting, b_remote_*[index] is set to the remote socket id.
590 if importing has been acknowledged. b_remote_*[index] is cleared.
591
592 */
593
594 /*
595  * process bchannel events
596  * - mISDNport is a pointer to the port's structure
597  * - i is the index of the bchannel
598  * - event is the B_EVENT_* value
599  * - port is the PmISDN class pointer
600  */
601 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
602 {
603         class PmISDN *b_port = mISDNport->b_port[i];
604         int state = mISDNport->b_state[i];
605         double timer = mISDNport->b_timer[i];
606         unsigned int p_m_remote_ref = 0;
607         unsigned int p_m_remote_id = 0;
608         int p_m_tx_gain = 0;
609         int p_m_rx_gain = 0;
610         char *p_m_pipeline = NULL;
611         unsigned char *p_m_crypt_key = NULL;
612         int p_m_crypt_key_len = 0;
613         int p_m_crypt_key_type = 0;
614         unsigned int portid = (mISDNport->portnum<<8) + i+1+(i>=15);
615
616         if (b_port)
617         {
618                 p_m_remote_id = b_port->p_m_remote_id;
619                 p_m_remote_ref = b_port->p_m_remote_ref;
620                 p_m_tx_gain = b_port->p_m_tx_gain;
621                 p_m_rx_gain = b_port->p_m_rx_gain;
622                 p_m_pipeline = b_port->p_m_pipeline;
623                 p_m_crypt_key = b_port->p_m_crypt_key;
624                 p_m_crypt_key_len = b_port->p_m_crypt_key_len;
625                 p_m_crypt_key_type = /*b_port->p_m_crypt_key_type*/1;
626         }
627
628         switch(event)
629         {
630                 case B_EVENT_USE:
631                 /* port must be linked in order to allow activation */
632                 if (!b_port)
633                         FATAL("bchannel must be linked to a Port class\n");
634                 switch(state)
635                 {
636                         case B_STATE_IDLE:
637                         if (p_m_remote_ref)
638                         {
639                                 /* export bchannel */
640                                 message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
641                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
642                                 add_trace("type", NULL, "assign");
643                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
644                                 end_trace();
645                                 state = B_STATE_EXPORTING;
646                                 mISDNport->b_remote_id[i] = p_m_remote_id;
647                                 mISDNport->b_remote_ref[i] = p_m_remote_ref;
648                         } else
649                         {
650                                 /* create stack and send activation request */
651                                 if (_bchannel_create(mISDNport, i))
652                                 {
653                                         _bchannel_activate(mISDNport, i, 1);
654                                         state = B_STATE_ACTIVATING;
655                                         timer = now_d + B_TIMER_ACTIVATING;
656                                 }
657                         }
658                         break;
659
660                         case B_STATE_ACTIVATING:
661                         case B_STATE_EXPORTING:
662                         /* do nothing, because it is already activating */
663                         break;
664
665                         case B_STATE_DEACTIVATING:
666                         case B_STATE_IMPORTING:
667                         /* do nothing, because we must wait until we can reactivate */
668                         break;
669
670                         default:
671                         /* problems that might ocurr:
672                          * B_EVENT_USE is received when channel already in use.
673                          * bchannel exported, but not freed by other port
674                          */
675                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
676                 }
677                 break;
678
679                 case B_EVENT_EXPORTREQUEST:
680                 /* special case where the bchannel is requested by remote */
681                 if (!p_m_remote_ref)
682                 {
683                         PERROR("export request without remote channel set, please correct.\n");
684                         break;
685                 }
686                 switch(state)
687                 {
688                         case B_STATE_IDLE:
689                         /* in case, the bchannel is exported right after seize_bchannel */
690                         /* export bchannel */
691                         /* p_m_remote_id is set, when this event happens. */
692                         message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
693                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
694                         add_trace("type", NULL, "assign");
695                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
696                         end_trace();
697                         state = B_STATE_EXPORTING;
698                         mISDNport->b_remote_id[i] = p_m_remote_id;
699                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
700                         break;
701
702                         case B_STATE_ACTIVATING:
703                         case B_STATE_EXPORTING:
704                         /* do nothing, because it is already activating */
705                         break;
706
707                         case B_STATE_DEACTIVATING:
708                         case B_STATE_IMPORTING:
709                         /* do nothing, because we must wait until we can reactivate */
710                         break;
711
712                         case B_STATE_ACTIVE:
713                         /* bchannel is active, so we deactivate */
714                         _bchannel_activate(mISDNport, i, 0);
715                         state = B_STATE_DEACTIVATING;
716                         timer = now_d + B_TIMER_DEACTIVATING;
717                         break;
718
719                         default:
720                         /* problems that might ocurr:
721                          * ... when channel already in use.
722                          * bchannel exported, but not freed by other port
723                          */
724                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
725                 }
726                 break;
727
728                 case B_EVENT_IMPORTREQUEST:
729                 /* special case where the bchannel is released by remote */
730                 if (p_m_remote_ref)
731                 {
732                         PERROR("import request with remote channel set, please correct.\n");
733                         break;
734                 }
735                 switch(state)
736                 {
737                         case B_STATE_IDLE:
738                         case B_STATE_ACTIVE:
739                         /* bchannel is not exported */
740                         break;
741
742                         case B_STATE_ACTIVATING:
743                         case B_STATE_EXPORTING:
744                         /* do nothing because we must wait until bchanenl is active before deactivating */
745                         break;
746
747                         case B_STATE_REMOTE:
748                         /* bchannel is exported, so we re-import */
749                         message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
750                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
751                         add_trace("type", NULL, "remove");
752                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
753                         end_trace();
754                         state = B_STATE_IMPORTING;
755                         break;
756
757                         case B_STATE_DEACTIVATING:
758                         case B_STATE_IMPORTING:
759                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
760                         break;
761
762                         default:
763                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
764                 }
765                 break;
766
767                 case B_EVENT_ACTIVATED:
768                 timer = 0;
769                 switch(state)
770                 {
771                         case B_STATE_ACTIVATING:
772                         if (b_port && !p_m_remote_id)
773                         {
774                                 /* bchannel is active and used by Port class, so we configure bchannel */
775                                 _bchannel_configure(mISDNport, i);
776                                 state = B_STATE_ACTIVE;
777                                 b_port->p_m_load = 0;
778                         } else
779                         {
780                                 /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
781                                 _bchannel_activate(mISDNport, i, 0);
782                                 state = B_STATE_DEACTIVATING;
783                                 timer = now_d + B_TIMER_DEACTIVATING;
784                         }
785                         break;
786
787                         default:
788                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
789                 }
790                 break;
791
792                 case B_EVENT_EXPORTED:
793                 switch(state)
794                 {
795                         case B_STATE_EXPORTING:
796                         if (b_port && p_m_remote_ref && p_m_remote_ref==mISDNport->b_remote_ref[i])
797                         {
798                                 /* remote export done */
799                                 state = B_STATE_REMOTE;
800                         } else
801                         {
802                                 /* bchannel is now exported, but we need bchannel back
803                                  * OR bchannel is not used anymore
804                                  * OR bchannel has been exported to an obsolete ref,
805                                  * so reimport, to later export to new remote */
806                                 message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
807                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
808                                 add_trace("type", NULL, "remove");
809                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
810                                 end_trace();
811                                 state = B_STATE_IMPORTING;
812                         }
813                         break;
814
815                         default:
816                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
817                 }
818                 break;
819
820                 case B_EVENT_DROP:
821                 if (!b_port)
822                         FATAL("bchannel must be linked to a Port class\n");
823                 switch(state)
824                 {
825                         case B_STATE_IDLE:
826                         /* bchannel is idle due to an error, so we do nothing */
827                         break;
828
829                         case B_STATE_ACTIVATING:
830                         case B_STATE_EXPORTING:
831                         /* do nothing because we must wait until bchanenl is active before deactivating */
832                         break;
833
834                         case B_STATE_ACTIVE:
835                         /* bchannel is active, so we deactivate */
836                         _bchannel_activate(mISDNport, i, 0);
837                         state = B_STATE_DEACTIVATING;
838                         timer = now_d + B_TIMER_DEACTIVATING;
839                         break;
840
841                         case B_STATE_REMOTE:
842                         /* bchannel is exported, so we re-import */
843                         message_bchannel_to_remote(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
844                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
845                         add_trace("type", NULL, "remove");
846                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
847                         end_trace();
848                         state = B_STATE_IMPORTING;
849                         break;
850
851                         case B_STATE_DEACTIVATING:
852                         case B_STATE_IMPORTING:
853                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
854                         break;
855
856                         default:
857                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
858                 }
859                 break;
860
861                 case B_EVENT_DEACTIVATED:
862                 timer = 0;
863                 switch(state)
864                 {
865                         case B_STATE_IDLE:
866                         /* ignore due to deactivation confirm after unloading */
867                         break;
868
869                         case B_STATE_DEACTIVATING:
870                         _bchannel_destroy(mISDNport, i);
871                         state = B_STATE_IDLE;
872                         if (b_port)
873                         {
874                                 /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
875                                 if (p_m_remote_ref)
876                                 {
877                                         message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
878                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
879                                         add_trace("type", NULL, "assign");
880                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
881                                         end_trace();
882                                         state = B_STATE_EXPORTING;
883                                         mISDNport->b_remote_id[i] = p_m_remote_id;
884                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
885                                 } else
886                                 {
887                                         if (_bchannel_create(mISDNport, i))
888                                         {
889                                                 _bchannel_activate(mISDNport, i, 1);
890                                                 state = B_STATE_ACTIVATING;
891                                                 timer = now_d + B_TIMER_ACTIVATING;
892                                         }
893                                 }
894                         }
895                         break;
896
897                         default:
898                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
899                 }
900                 break;
901
902                 case B_EVENT_IMPORTED:
903                 switch(state)
904                 {
905                         case B_STATE_IMPORTING:
906                         state = B_STATE_IDLE;
907                         mISDNport->b_remote_id[i] = 0;
908                         mISDNport->b_remote_ref[i] = 0;
909                         if (b_port)
910                         {
911                                 /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
912                                 if (p_m_remote_ref)
913                                 {
914                                         message_bchannel_to_remote(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
915                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
916                                         add_trace("type", NULL, "assign");
917                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
918                                         end_trace();
919                                         state = B_STATE_EXPORTING;
920                                         mISDNport->b_remote_id[i] = p_m_remote_id;
921                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
922                                 } else
923                                 {
924                                         if (_bchannel_create(mISDNport, i))
925                                         {
926                                                 _bchannel_activate(mISDNport, i, 1);
927                                                 state = B_STATE_ACTIVATING;
928                                                 timer = now_d + B_TIMER_ACTIVATING;
929                                         }
930                                 }
931                         }
932                         break;
933
934                         default:
935                         /* ignore, because not assigned */
936                         ;
937                 }
938                 break;
939
940                 case B_EVENT_TIMEOUT:
941                 timer = 0;
942                 switch(state)
943                 {
944                         case B_STATE_IDLE:
945                         /* ignore due to deactivation confirm after unloading */
946                         break;
947
948                         case B_STATE_ACTIVATING:
949                         _bchannel_activate(mISDNport, i, 1);
950                         timer = now_d + B_TIMER_ACTIVATING;
951                         break;
952
953                         case B_STATE_DEACTIVATING:
954                         _bchannel_activate(mISDNport, i, 0);
955                         timer = now_d + B_TIMER_DEACTIVATING;
956                         break;
957
958                         default:
959                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
960                 }
961                 break;
962
963                 default:
964                 PERROR("Illegal event %d, please correct.\n", event);
965         }
966
967         mISDNport->b_state[i] = state;
968         mISDNport->b_timer[i] = timer;
969 }
970
971
972
973
974 /*
975  * check for available channel and reserve+set it.
976  * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
977  * give exclusiv flag
978  * returns -(cause value) or x = channel x or 0 = no channel
979  * NOTE: no activation is done here
980  */
981 int PmISDN::seize_bchannel(int channel, int exclusive)
982 {
983         int i;
984
985         /* the channel is what we have */
986         if (p_m_b_channel == channel)
987                 return(channel);
988
989         /* if channel already in use, release it */
990         if (p_m_b_channel)
991                 drop_bchannel();
992
993         /* if CHANNEL_NO */
994         if (channel==CHANNEL_NO || channel==0)
995                 return(0);
996         
997         /* is channel in range ? */
998         if (channel==16
999          || (channel>p_m_mISDNport->b_num && channel<16)
1000          || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
1001                 return(-6); /* channel unacceptable */
1002
1003         /* request exclusive channel */
1004         if (exclusive && channel>0)
1005         {
1006                 i = channel-1-(channel>16);
1007                 if (p_m_mISDNport->b_port[i])
1008                         return(-44); /* requested channel not available */
1009                 goto seize;
1010         }
1011
1012         /* ask for channel */
1013         if (channel>0)
1014         {
1015                 i = channel-1-(channel>16);
1016                 if (p_m_mISDNport->b_port[i] == NULL)
1017                         goto seize;
1018         }
1019
1020         /* search for channel */
1021         i = 0;
1022         while(i < p_m_mISDNport->b_num)
1023         {
1024                 if (!p_m_mISDNport->b_port[i])
1025                 {
1026                         channel = i+1+(i>=15);
1027                         goto seize;
1028                 }
1029                 i++;
1030         }
1031         return(-34); /* no free channel */
1032
1033 seize:
1034         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
1035
1036         /* link Port, set parameters */
1037         p_m_mISDNport->b_port[i] = this;
1038         p_m_b_index = i;
1039         p_m_b_channel = channel;
1040         p_m_b_exclusive = exclusive;
1041         p_m_mISDNport->b_mode[i] = p_m_b_mode;
1042
1043         /* reserve channel */
1044         if (!p_m_b_reserve)
1045         {
1046                 p_m_b_reserve = 1;
1047                 p_m_mISDNport->b_reserved++;
1048         }
1049
1050         return(channel);
1051 }
1052
1053 /*
1054  * drop reserved channel and unset it.
1055  * deactivation is also done
1056  */
1057 void PmISDN::drop_bchannel(void)
1058 {
1059         /* unreserve channel */
1060         if (p_m_b_reserve)
1061                 p_m_mISDNport->b_reserved--;
1062         p_m_b_reserve = 0;
1063
1064         /* if not in use */
1065         if (p_m_b_index < 0)
1066                 return;
1067         if (!p_m_b_channel)
1068                 return;
1069
1070         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1071
1072         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1073                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
1074         p_m_mISDNport->b_port[p_m_b_index] = NULL;
1075         p_m_mISDNport->b_mode[p_m_b_index] = 0;
1076         p_m_b_index = -1;
1077         p_m_b_channel = 0;
1078         p_m_b_exclusive = 0;
1079 }
1080
1081 /* process bchannel export/import message from join */
1082 void message_bchannel_from_remote(class JoinRemote *joinremote, int type, unsigned int handle)
1083 {
1084         class Endpoint *epoint;
1085         class Port *port;
1086         class PmISDN *isdnport;
1087         struct mISDNport *mISDNport;
1088         int i, ii;
1089
1090         switch(type)
1091         {
1092                 case BCHANNEL_REQUEST:
1093                 /* find the port object for the join object ref */
1094                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1095                 {
1096                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1097                         return;
1098                 }
1099                 if (!epoint->ep_portlist)
1100                 {
1101                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1102                         return;
1103                 }
1104                 if (epoint->ep_portlist->next)
1105                 {
1106                         PERROR("join %d has enpoint %d with more than one port. this shall not happen to remote joins.\n", joinremote->j_serial, epoint->ep_serial);
1107                 }
1108                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1109                 {
1110                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1111                         return;
1112                 }
1113                 if ((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN)
1114                 {
1115                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1116                 }
1117                 isdnport = (class PmISDN *)port;
1118
1119                 /* assign */
1120                 if (isdnport->p_m_remote_id)
1121                 {
1122                         PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1123                         break;
1124                 }
1125                 mISDNport = isdnport->p_m_mISDNport;
1126                 i = isdnport->p_m_b_index;
1127                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1128                 add_trace("type", NULL, "export request");
1129                 end_trace();
1130                 isdnport->p_m_remote_ref = joinremote->j_serial;
1131                 isdnport->p_m_remote_id = joinremote->j_remote_id;
1132                 if (mISDNport && i>=0)
1133                 {
1134                         bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
1135                 }
1136                 break;
1137
1138                 case BCHANNEL_RELEASE:
1139                 case BCHANNEL_ASSIGN_ACK:
1140                 case BCHANNEL_REMOVE_ACK:
1141                 /* find mISDNport for stack ID */
1142                 mISDNport = mISDNport_first;
1143                 while(mISDNport)
1144                 {
1145                         i = 0;
1146                         ii = mISDNport->b_num;
1147                         while(i < ii)
1148                         {
1149                                 if ((unsigned int)(mISDNport->portnum<<8)+i+1+(i>=15) == handle)
1150                                         break;
1151                                 i++;
1152                         }
1153                         if (i != ii)
1154                                 break;
1155                         mISDNport = mISDNport->next;
1156                 }
1157                 if (!mISDNport)
1158                 {
1159                         PERROR("received assign/remove ack for bchannel's handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
1160                         break;
1161                 }
1162                 
1163                 if (type!=BCHANNEL_RELEASE)
1164                 {
1165                         /* ack */
1166                         chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1167                         add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1168                         end_trace();
1169                         bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
1170                 } else
1171                 {
1172                         /* release */
1173                         isdnport = mISDNport->b_port[i];
1174                         chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1175                         add_trace("type", NULL, "import request");
1176                         end_trace();
1177                         if (isdnport)
1178                         {
1179                                 isdnport->p_m_remote_ref = 0;
1180                                 isdnport->p_m_remote_id = 0;
1181                         }
1182                         bchannel_event(mISDNport, i, B_EVENT_IMPORTREQUEST);
1183                 }
1184                 break;
1185                 default:
1186                 PERROR("received wrong bchannel message type %d from remote\n", type);
1187         }
1188 }
1189
1190
1191 /*
1192  * handler
1193
1194 audio transmission procedure:
1195 -----------------------------
1196
1197 * priority
1198 three sources of audio transmission:
1199 - crypto-data high priority
1200 - tones high priority (also high)
1201 - remote-data low priority
1202
1203 * elapsed
1204 a variable that temporarily shows the number of samples elapsed since last transmission process.
1205 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1206
1207 * load
1208 a variable that is increased whenever data is transmitted.
1209 it is decreased while time elapses. it stores the number of samples that
1210 are currently loaded to dsp module.
1211 since clock in dsp module is the same clock for user space process, these 
1212 times have no skew.
1213
1214 * levels
1215 there are two levels:
1216 ISDN_LOAD will give the load that have to be kept in dsp.
1217 ISDN_MAXLOAD will give the maximum load before dropping.
1218
1219 * procedure for low priority data
1220 see txfromup() for procedure
1221 in short: remote data is ignored during high priority tones
1222
1223 * procedure for high priority data
1224 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1225 if no more data is available, load becomes empty again.
1226
1227 'load' variable:
1228 0                    ISDN_LOAD           ISDN_MAXLOAD
1229 +--------------------+----------------------+
1230 |                    |                      |
1231 +--------------------+----------------------+
1232
1233 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1234 0                    ISDN_LOAD           ISDN_MAXLOAD
1235 +--------------------+----------------------+
1236 |TTTTTTTTTTTTTTTTTTTT|                      |
1237 +--------------------+----------------------+
1238
1239 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1240 0                    ISDN_LOAD           ISDN_MAXLOAD
1241 +--------------------+----------------------+
1242 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
1243 +--------------------+----------------------+
1244
1245  */
1246 int PmISDN::handler(void)
1247 {
1248         struct lcr_msg *message;
1249         int elapsed = 0;
1250         int ret;
1251
1252         if ((ret = Port::handler()))
1253                 return(ret);
1254
1255         /* get elapsed */
1256         if (p_m_last_tv_sec)
1257         {
1258                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1259                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1260         } else
1261         {
1262                 /* set clock of first process ever in this instance */
1263                 p_m_last_tv_sec = now_tv.tv_sec;
1264                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1265         }
1266         /* process only if we have a minimum of samples, to make packets not too small */
1267         if (elapsed >= ISDN_TRANSMIT
1268          && p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1269         {
1270                 /* set clock of last process! */
1271                 p_m_last_tv_sec = now_tv.tv_sec;
1272                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1273
1274                 /* update load */
1275                 if (elapsed < p_m_load)
1276                         p_m_load -= elapsed;
1277                 else
1278                         p_m_load = 0;
1279
1280                 /* to send data, tone must be active OR crypt messages must be on */
1281                 if ((p_tone_name[0] || p_m_crypt_msg_loops)
1282                  && (p_m_load < ISDN_LOAD)
1283                  && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones))
1284                 {
1285                         int tosend = ISDN_LOAD - p_m_load, length; 
1286                         unsigned char buf[MISDN_HEADER_LEN+tosend];
1287                         struct mISDNhead *frm = (struct mISDNhead *)buf;
1288                         unsigned char *p = buf+MISDN_HEADER_LEN;
1289
1290                         /* copy crypto loops */
1291                         while (p_m_crypt_msg_loops && tosend)
1292                         {
1293                                 /* how much do we have to send */
1294                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1295
1296                                 /* clip tosend */
1297                                 if (length > tosend)
1298                                         length = tosend;
1299
1300                                 /* copy message (part) to buffer */
1301                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1302
1303                                 /* new position */
1304                                 p_m_crypt_msg_current += length;
1305                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1306                                 {
1307                                         /* next loop */
1308                                         p_m_crypt_msg_current = 0;
1309                                         p_m_crypt_msg_loops--;
1310 //                                      puts("eine loop weniger");
1311                                 }
1312
1313                                 /* new length */
1314                                 tosend -= length;
1315                         }
1316
1317                         /* copy tones */
1318                         if (p_tone_name[0] && tosend)
1319                         {
1320                                 tosend -= read_audio(p, tosend);
1321                         }
1322
1323                         /* send data */
1324                         if (ISDN_LOAD - p_m_load - tosend > 0)
1325                         {
1326                                 frm->prim = PH_DATA_REQ;
1327                                 frm->id = 0;
1328                                 ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
1329                                 if (ret <= 0)
1330                                         PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_socket[p_m_b_index], ISDN_LOAD-p_m_load-tosend);
1331                                 p_m_load += ISDN_LOAD - p_m_load - tosend;
1332                         }
1333                 }
1334         }
1335
1336         // NOTE: deletion is done by the child class
1337
1338         /* handle timeouts */
1339         if (p_m_timeout)
1340         {
1341                 if (p_m_timer+p_m_timeout < now_d)
1342                 {
1343                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1344                         p_m_timeout = 0;
1345                         /* send timeout to endpoint */
1346                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1347                         message->param.state = p_state;
1348                         message_put(message);
1349                         return(1);
1350                 }
1351         }
1352         
1353         return(0); /* nothing done */
1354 }
1355
1356
1357 /*
1358  * whenever we get audio data from bchannel, we process it here
1359  */
1360 void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
1361 {
1362         unsigned int cont = *((unsigned int *)data);
1363         unsigned char *data_temp;
1364         unsigned int length_temp;
1365         struct lcr_msg *message;
1366         unsigned char *p;
1367         int l;
1368
1369         if (hh->prim == PH_CONTROL_IND)
1370         {
1371                 if (len < 4)
1372                 {
1373                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1374                         return;
1375                 }
1376                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1377                 {
1378                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1379                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1380                         end_trace();
1381                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1382                         message->param.dtmf = cont & DTMF_TONE_MASK;
1383                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
1384                         message_put(message);
1385                         return;
1386                 }
1387                 switch(cont)
1388                 {
1389                         case DSP_BF_REJECT:
1390                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1391                         add_trace("DSP-CRYPT", NULL, "error");
1392                         end_trace();
1393                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1394                         message->param.crypt.type = CC_ERROR_IND;
1395                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
1396                         message_put(message);
1397                         break;
1398
1399                         case DSP_BF_ACCEPT:
1400                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1401                         add_trace("DSP-CRYPT", NULL, "ok");
1402                         end_trace();
1403                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1404                         message->param.crypt.type = CC_ACTBF_CONF;
1405                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
1406                         message_put(message);
1407                         break;
1408
1409                         default:
1410                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1411                         add_trace("unknown", NULL, "0x%x", cont);
1412                         end_trace();
1413                 }
1414                 return;
1415         }
1416         if (hh->prim == PH_CONTROL_IND)
1417         {
1418                 switch(hh->id)
1419                 {
1420                         default:
1421                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1422                         add_trace("unknown", NULL, "0x%x", hh->id);
1423                         end_trace();
1424                 }
1425                 return;
1426         }
1427         if (hh->prim == PH_DATA_REQ || hh->prim == DL_DATA_REQ)
1428         {
1429                 if (!p_m_txdata)
1430                 {
1431                         /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1432                         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1433                         return;
1434                 }
1435                 /* see below (same condition) */
1436                 if (p_state!=PORT_STATE_CONNECT
1437                          && !p_m_mISDNport->tones)
1438                         return;
1439 //              printf(".");fflush(stdout);return;
1440                 if (p_record)
1441                         record(data, len, 1); // from up
1442                 return;
1443         }
1444         if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND)
1445         {
1446                 PERROR("Bchannel received unknown primitve: 0x%x\n", hh->prim);
1447                 return;
1448         }
1449
1450         /* calls will not process any audio data unless
1451          * the call is connected OR tones feature is enabled.
1452          */
1453 #ifndef DEBUG_COREBRIDGE
1454         if (p_state!=PORT_STATE_CONNECT
1455          && !p_m_mISDNport->tones)
1456                 return;
1457 #endif
1458
1459 #if 0
1460         /* the bearer capability must be audio in order to send and receive
1461          * audio prior or after connect.
1462          */
1463         if (!(p_bearerinfo.capability&CLASS_CAPABILITY_AUDIO) && p_state!=PORT_STATE_CONNECT)
1464                 return;
1465 #endif
1466
1467         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1468         if (p_m_rxoff)
1469         {
1470                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1471                 return;
1472         }
1473
1474         /* record data */
1475         if (p_record)
1476                 record(data, len, 0); // from down
1477
1478         /* randomize and listen to crypt message if enabled */
1479         if (p_m_crypt_listen)
1480         {
1481                 /* the noisy randomizer */
1482                 p = data;
1483                 l = len;
1484                 while(l--)
1485                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1486
1487                 cryptman_listen_bch(data, len);
1488         }
1489
1490         p = data;
1491
1492         /* send data to epoint */
1493         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1494         {
1495                 length_temp = len;
1496                 data_temp = p;
1497                 while(length_temp)
1498                 {
1499                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1500                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1501                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1502                         message_put(message);
1503                         if (length_temp <= sizeof(message->param.data.data))
1504                                 break;
1505                         data_temp += sizeof(message->param.data.data);
1506                         length_temp -= sizeof(message->param.data.data);
1507                 }
1508         }
1509 }
1510
1511
1512 /*
1513  * set echotest
1514  */
1515 void PmISDN::set_echotest(int echo)
1516 {
1517         if (p_m_echo != echo)
1518         {
1519                 p_m_echo = echo;
1520                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1521                 if (p_m_b_channel)
1522                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1523                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_echo?DSP_ECHO_ON:DSP_ECHO_OFF, 0, "DSP-ECHO", p_m_echo);
1524         }
1525 }
1526
1527 /*
1528  * set tone
1529  */
1530 void PmISDN::set_tone(char *dir, char *tone)
1531 {
1532         int id;
1533
1534         if (!tone)
1535                 tone = "";
1536         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1537         if (!tone[0])
1538         {
1539                 id = TONE_OFF;
1540                 goto setdsp;
1541         }
1542
1543         /* check if we NOT really have to use a dsp-tone */
1544         if (!options.dsptones)
1545         {
1546                 nodsp:
1547                 if (p_m_tone)
1548                 if (p_m_b_index > -1)
1549                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
1550                 {
1551                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1552                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], DSP_TONE_PATT_OFF, 0, "DSP-TONE", 0);
1553                 }
1554                 p_m_tone = 0;
1555                 Port::set_tone(dir, tone);
1556                 return;
1557         }
1558         if (p_tone_dir[0])
1559                 goto nodsp;
1560
1561         /* now we USE dsp-tone, convert name */
1562         else if (!strcmp(tone, "dialtone"))
1563         {
1564                 switch(options.dsptones) {
1565                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1566                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1567                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1568                 }
1569         } else if (!strcmp(tone, "dialpbx"))
1570         {
1571                 switch(options.dsptones) {
1572                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1573                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1574                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1575                 }
1576         } else if (!strcmp(tone, "ringing"))
1577         {
1578                 switch(options.dsptones) {
1579                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1580                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1581                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1582                 }
1583         } else if (!strcmp(tone, "ringpbx"))
1584         {
1585                 switch(options.dsptones) {
1586                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1587                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1588                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1589                 }
1590         } else if (!strcmp(tone, "busy"))
1591         {
1592                 busy:
1593                 switch(options.dsptones) {
1594                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1595                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1596                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1597                 }
1598         } else if (!strcmp(tone, "release"))
1599         {
1600                 hangup:
1601                 switch(options.dsptones) {
1602                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1603                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1604                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1605                 }
1606         } else if (!strcmp(tone, "cause_10"))
1607                 goto hangup;
1608         else if (!strcmp(tone, "cause_11"))
1609                 goto busy;
1610         else if (!strcmp(tone, "cause_22"))
1611         {
1612                 switch(options.dsptones) {
1613                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1614                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1615                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1616                 }
1617         } else if (!strncmp(tone, "cause_", 6))
1618                 id = TONE_SPECIAL_INFO;
1619         else
1620                 id = TONE_OFF;
1621
1622         /* if we have a tone that is not supported by dsp */
1623         if (id==TONE_OFF && tone[0])
1624                 goto nodsp;
1625
1626         setdsp:
1627         if (p_m_tone != id)
1628         {
1629                 /* set new tone */
1630                 p_m_tone = id;
1631                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1632                 if (p_m_b_index > -1)
1633                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
1634                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_tone?DSP_TONE_PATT_ON:DSP_TONE_PATT_OFF, p_m_tone, "DSP-TONE", p_m_tone);
1635         }
1636         /* turn user-space tones off in cases of no tone OR dsp tone */
1637         Port::set_tone("",NULL);
1638 }
1639
1640
1641 /* MESSAGE_mISDNSIGNAL */
1642 //extern struct lcr_msg *dddebug;
1643 void PmISDN::message_mISDNsignal(unsigned int epoint_id, int message_id, union parameter *param)
1644 {
1645         switch(param->mISDNsignal.message)
1646         {
1647                 case mISDNSIGNAL_VOLUME:
1648                 if (p_m_tx_gain != param->mISDNsignal.tx_gain)
1649                 {
1650                         p_m_tx_gain = param->mISDNsignal.tx_gain;
1651                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_tx_gain);
1652                         if (p_m_b_index > -1)
1653                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
1654                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], DSP_VOL_CHANGE_TX, p_m_tx_gain, "DSP-TX_GAIN", p_m_tx_gain);
1655                 } else
1656                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rx_gain);
1657                 if (p_m_rx_gain != param->mISDNsignal.rx_gain)
1658                 {
1659                         p_m_rx_gain = param->mISDNsignal.rx_gain;
1660                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rx_gain);
1661                         if (p_m_b_index > -1)
1662                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
1663                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], DSP_VOL_CHANGE_RX, p_m_rx_gain, "DSP-RX_GAIN", p_m_rx_gain);
1664                 } else
1665                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rx_gain);
1666                 break;
1667
1668                 case mISDNSIGNAL_CONF:
1669 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1670 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1671                 if (p_m_conf != param->mISDNsignal.conf)
1672                 {
1673                         p_m_conf = param->mISDNsignal.conf;
1674                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1675                         if (p_m_b_index > -1)
1676                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1677                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], (p_m_conf)?DSP_CONF_JOIN:DSP_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1678                 } else
1679                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1680                 /* we must set, even if currently tone forbids conf */
1681                 p_m_conf = param->mISDNsignal.conf;
1682 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1683                 break;
1684
1685                 case mISDNSIGNAL_JOINDATA:
1686                 if (p_m_joindata != param->mISDNsignal.joindata)
1687                 {
1688                         p_m_joindata = param->mISDNsignal.joindata;
1689                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1690                 } else
1691                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1692                 break;
1693                 
1694                 case mISDNSIGNAL_DELAY:
1695                 if (p_m_delay != param->mISDNsignal.delay)
1696                 {
1697                         p_m_delay = param->mISDNsignal.delay;
1698                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1699                         if (p_m_b_index > -1)
1700                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
1701                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_delay?DSP_DELAY:DSP_JITTER, p_m_delay, "DSP-DELAY", p_m_delay);
1702                 } else
1703                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1704                 break;
1705
1706                 default:
1707                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1708         }
1709 }
1710
1711 /* MESSAGE_CRYPT */
1712 void PmISDN::message_crypt(unsigned int epoint_id, int message_id, union parameter *param)
1713 {
1714         struct lcr_msg *message;
1715
1716         switch(param->crypt.type)
1717         {
1718                 case CC_ACTBF_REQ:           /* activate blowfish */
1719                 p_m_crypt = 1;
1720                 p_m_crypt_key_len = param->crypt.len;
1721                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1722                 {
1723                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1724                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1725                         message->param.crypt.type = CC_ERROR_IND;
1726                         message_put(message);
1727                         break;
1728                 }
1729                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1730                 crypt_off:
1731                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1732                 if (p_m_b_index > -1)
1733                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
1734                         ph_control_block(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_crypt?DSP_BF_ENABLE_KEY:DSP_BF_DISABLE, p_m_crypt_key, p_m_crypt_key_len, "DSP-CRYPT", p_m_crypt_key_len);
1735                 break;
1736
1737                 case CC_DACT_REQ:            /* deactivate session encryption */
1738                 p_m_crypt = 0;
1739                 goto crypt_off;
1740                 break;
1741
1742                 case CR_LISTEN_REQ:          /* start listening to messages */
1743                 p_m_crypt_listen = 1;
1744                 p_m_crypt_listen_state = 0;
1745                 break;
1746
1747                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
1748                 p_m_crypt_listen = 0;
1749                 break;
1750
1751                 case CR_MESSAGE_REQ:         /* send message */
1752                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1753                 if (!p_m_crypt_msg_len)
1754                 {
1755                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1756                         break;
1757                 }
1758                 p_m_crypt_msg_current = 0; /* reset */
1759                 p_m_crypt_msg_loops = 6; /* enable */
1760 #if 0
1761                 /* disable txmix, or we get corrupt data due to audio process */
1762                 if (p_m_txmix && p_m_b_index>=0 && p_m_mISDNport->b_mode[p_m_b_index] == B_MODE_TRANSPARENT)
1763                 {
1764                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1765                         ph_control(p_m_mISDNport, this, p_mISDNport->b_socket[p_m_b_index], DSP_MIX_OFF, 0, "DSP-TXMIX", 0);
1766                 }
1767 #endif
1768                 break;
1769
1770                 default:
1771                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1772         }
1773
1774 }
1775
1776 /*
1777  * endpoint sends messages to the port
1778  */
1779 int PmISDN::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1780 {
1781         if (Port::message_epoint(epoint_id, message_id, param))
1782                 return(1);
1783
1784         switch(message_id)
1785         {
1786                 case MESSAGE_DATA: /* tx-data from upper layer */
1787                 txfromup(param->data.data, param->data.len);
1788                 return(1);
1789
1790                 case MESSAGE_mISDNSIGNAL: /* user command */
1791                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1792                 message_mISDNsignal(epoint_id, message_id, param);
1793                 return(1);
1794
1795                 case MESSAGE_CRYPT: /* crypt control command */
1796                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1797                 message_crypt(epoint_id, message_id, param);
1798                 return(1);
1799         }
1800
1801         return(0);
1802 }
1803
1804
1805 /*
1806  * main loop for processing messages from mISDN
1807  */
1808 int mISDN_handler(void)
1809 {
1810         int ret, work = 0;
1811         struct mISDNport *mISDNport;
1812         class PmISDN *isdnport;
1813         int i;
1814         unsigned char buffer[2048+MISDN_HEADER_LEN];
1815         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1816         struct mbuffer *mb;
1817         struct l3_msg *l3m;
1818
1819         /* process all ports */
1820         mISDNport = mISDNport_first;
1821         while(mISDNport)
1822         {
1823                 /* process all bchannels */
1824                 i = 0;
1825                 while(i < mISDNport->b_num)
1826                 {
1827                         /* process timer events for bchannel handling */
1828                         if (mISDNport->b_timer[i])
1829                         {
1830                                 if (mISDNport->b_timer[i] <= now_d)
1831                                         bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
1832                         }
1833                         /* handle port of bchannel */
1834                         isdnport=mISDNport->b_port[i];
1835                         if (isdnport)
1836                         {
1837                                 /* call bridges in user space OR crypto OR recording */
1838                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1839                                 {
1840                                         /* rx IS required */
1841                                         if (isdnport->p_m_rxoff)
1842                                         {
1843                                                 /* turn on RX */
1844                                                 isdnport->p_m_rxoff = 0;
1845                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n", __FUNCTION__);
1846                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1847                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[i], DSP_RECEIVE_ON, 0, "DSP-RXOFF", 0);
1848                                                 return(1);
1849                                         }
1850                                 } else
1851                                 {
1852                                         /* rx NOT required */
1853                                         if (!isdnport->p_m_rxoff)
1854                                         {
1855                                                 /* turn off RX */
1856                                                 isdnport->p_m_rxoff = 1;
1857                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n", __FUNCTION__);
1858                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1859                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[i], DSP_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
1860                                                 return(1);
1861                                         }
1862                                 }
1863                                 /* recording */
1864                                 if (isdnport->p_record)
1865                                 {
1866                                         /* txdata IS required */
1867                                         if (!isdnport->p_m_txdata)
1868                                         {
1869                                                 /* turn on RX */
1870                                                 isdnport->p_m_txdata = 1;
1871                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n", __FUNCTION__);
1872                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1873                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[i], DSP_TXDATA_ON, 0, "DSP-TXDATA", 1);
1874                                                 return(1);
1875                                         }
1876                                 } else
1877                                 {
1878                                         /* txdata NOT required */
1879                                         if (isdnport->p_m_txdata)
1880                                         {
1881                                                 /* turn off RX */
1882                                                 isdnport->p_m_txdata = 0;
1883                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n", __FUNCTION__);
1884                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1885                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[i], DSP_TXDATA_OFF, 0, "DSP-TXDATA", 0);
1886                                                 return(1);
1887                                         }
1888                                 }
1889                         }
1890
1891                         /* handle message from bchannel */
1892                         if (mISDNport->b_socket[i] > -1)
1893                         {
1894                                 ret = recv(mISDNport->b_socket[i], buffer, sizeof(buffer), 0);
1895                                 if (ret >= (int)MISDN_HEADER_LEN)
1896                                 {
1897                                         work = 1;
1898                                         switch(hh->prim)
1899                                         {
1900                                                 /* we don't care about confirms, we use rx data to sync tx */
1901                                                 case PH_DATA_CNF:
1902                                                 break;
1903
1904                                                 /* we receive audio data, we respond to it AND we send tones */
1905                                                 case PH_DATA_IND:
1906                                                 case DL_DATA_IND:
1907                                                 case PH_DATA_REQ:
1908                                                 case DL_DATA_REQ:
1909                                                 case PH_CONTROL_IND:
1910                                                 if (mISDNport->b_port[i])
1911                                                         mISDNport->b_port[i]->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
1912                                                 else
1913                                                         PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (socket %d), ignoring.\n", mISDNport->b_socket[i]);
1914                                                 break;
1915
1916                                                 case PH_ACTIVATE_IND:
1917                                                 case DL_ESTABLISH_IND:
1918                                                 case PH_ACTIVATE_CNF:
1919                                                 case DL_ESTABLISH_CNF:
1920                                                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", mISDNport->b_socket[i]);
1921                                                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
1922                                                 break;
1923
1924                                                 case PH_DEACTIVATE_IND:
1925                                                 case DL_RELEASE_IND:
1926                                                 case PH_DEACTIVATE_CNF:
1927                                                 case DL_RELEASE_CNF:
1928                                                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", mISDNport->b_socket[i]);
1929                                                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
1930                                                 break;
1931
1932                                                 default:
1933                                                 PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, mISDNport->b_socket[i], ret-MISDN_HEADER_LEN);
1934                                         }
1935                                 } else
1936                                 {
1937                                         if (ret < 0 && errno != EWOULDBLOCK)
1938                                                 PERROR("Read from port %d, index %d failed with return code %d\n", mISDNport->portnum, i, ret);
1939                                 }
1940                         }
1941                         
1942                         i++;
1943                 }
1944
1945                 /* handle queued up-messages (d-channel) */
1946                 while ((mb = mdequeue(&mISDNport->upqueue)))
1947                 {
1948                         l3m = &mb->l3;
1949                         switch(l3m->type)
1950                         {
1951                                 case MPH_ACTIVATE_IND:
1952                                 l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
1953                                 end_trace();
1954                                 mISDNport->l1link = 1;
1955                                 break;
1956         
1957                                 case MPH_DEACTIVATE_IND:
1958                                 l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
1959                                 end_trace();
1960                                 mISDNport->l1link = 0;
1961                                 break;
1962
1963                                 case MPH_INFORMATION_IND:
1964                                 PDEBUG(DEBUG_ISDN, "Received MPH_INFORMATION_IND for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
1965                                 switch (l3m->pid)
1966                                 {
1967                                         case L1_SIGNAL_LOS_ON:
1968                                         mISDNport->los = 1;
1969                                         break;
1970                                         case L1_SIGNAL_LOS_OFF:
1971                                         mISDNport->los = 0;
1972                                         break;
1973                                         case L1_SIGNAL_AIS_ON:
1974                                         mISDNport->ais = 1;
1975                                         break;
1976                                         case L1_SIGNAL_AIS_OFF:
1977                                         mISDNport->ais = 0;
1978                                         break;
1979                                         case L1_SIGNAL_RDI_ON:
1980                                         mISDNport->rdi = 1;
1981                                         break;
1982                                         case L1_SIGNAL_RDI_OFF:
1983                                         mISDNport->rdi = 0;
1984                                         break;
1985                                         case L1_SIGNAL_SLIP_TX:
1986                                         mISDNport->slip_tx++;
1987                                         break;
1988                                         case L1_SIGNAL_SLIP_RX:
1989                                         mISDNport->slip_rx++;
1990                                         break;
1991                                 }
1992                                 break;
1993
1994                                 case MT_L2ESTABLISH:
1995                                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
1996                                 add_trace("tei", NULL, "%d", l3m->pid);
1997                                 end_trace();
1998                                 if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
1999                                 {
2000                                         if (mISDNport->l2establish)
2001                                         {
2002                                                 mISDNport->l2establish = 0;
2003                                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2004                                         }
2005                                         mISDNport->l2link = 1;
2006                                 }
2007                                 break;
2008
2009                                 case MT_L2RELEASE:
2010                                 if (!mISDNport->l2establish)
2011                                 {
2012                                         l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
2013                                         add_trace("tei", NULL, "%d", l3m->pid);
2014                                         end_trace();
2015                                 }
2016                                 if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
2017                                 {
2018                                         mISDNport->l2link = 0;
2019                                         if (!mISDNport->l2establish && mISDNport->l2hold)
2020                                         {
2021                                                 PDEBUG(DEBUG_ISDN, "set timer and establish.\n");
2022                                                 time(&mISDNport->l2establish);
2023                                                 mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2024                                         }
2025                                 }
2026                                 break;
2027
2028                                 default:
2029                                 /* l3-data is sent to LCR */
2030                                 stack2manager(mISDNport, l3m->type, l3m->pid, l3m);
2031                         }
2032                         /* free message */
2033                         free_l3_msg(l3m);
2034                 }
2035
2036 #if 0
2037                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2038                 { ---}
2039                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2040                         mISDNport->l1timeout = 0;
2041 #endif
2042
2043                 /* layer 2 establish timer */
2044                 if (mISDNport->l2establish)
2045                 {
2046                         if (now-mISDNport->l2establish > 5)
2047                         {
2048                                 mISDNport->l2establish = 0;
2049                                 if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
2050                                 {
2051
2052                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
2053                                         mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2054                                         time(&mISDNport->l2establish);
2055                                         return(1);
2056                                 }
2057                         }
2058                 }
2059
2060
2061                 mISDNport = mISDNport->next;
2062         }
2063
2064         /* if we received at least one b-frame, we will return 1 */
2065         return(work);
2066 }
2067
2068 int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
2069 {
2070         /* IMPORTAINT:
2071          *
2072          * l3m must be queued, except for MT_ASSIGN
2073          *
2074          */
2075         struct mISDNport *mISDNport = (struct mISDNport *)ml3->priv;
2076         struct mbuffer *mb;
2077
2078         /* special MT_ASSIGN handling:
2079          *
2080          * if we request a PID from mlayer, we always do it while lcr is locked.
2081          * therefore we must check the MT_ASSIGN reply first before we lock.
2082          * this is because the MT_ASSIGN reply is received with the requesting
2083          * process, not by the mlayer thread!
2084          * this means, that the reply is sent during call of the request.
2085          * we must check if we get a reply and we know that we lcr is currently
2086          * locked.
2087          */
2088         if (cmd==MT_ASSIGN && (pid&MISDN_PID_CR_FLAG) && (pid>>16)==MISDN_CES_MASTER)
2089         {
2090                 /* let's do some checking if someone changes stack behaviour */
2091                 if (mt_assign_pid != 0)
2092                         FATAL("someone played with the mISDNuser stack. MT_ASSIGN not currently expected.\n");
2093                 mt_assign_pid = pid;
2094                 return(0);
2095         }
2096         
2097         /* queue message, create, if required */
2098         if (!l3m)
2099         {
2100                 l3m = alloc_l3_msg();
2101                 if (!l3m)
2102                         FATAL("No memory for layer 3 message\n");
2103         }
2104         mb = container_of(l3m, struct mbuffer, l3);
2105         l3m->type = cmd;
2106         l3m->pid = pid;
2107         mqueue_tail(&mISDNport->upqueue, mb);
2108         return 0;
2109 }
2110
2111
2112 /*
2113  * global function to add a new card (port)
2114  */
2115 struct mISDNport *mISDNport_open(int port, int ptp, int force_nt, int l2hold, struct interface *interface)
2116 {
2117         int ret;
2118         struct mISDNport *mISDNport, **mISDNportp;
2119         int i, cnt;
2120         int pri, bri, pots;
2121         int nt, te;
2122 //      struct mlayer3 *ml3;
2123         struct mISDN_devinfo devinfo;
2124         unsigned int protocol, prop;
2125
2126         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
2127         if (ret < 0)
2128         {
2129                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2130                 return(NULL);
2131         }
2132
2133         if (cnt <= 0)
2134         {
2135                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2136                 return(NULL);
2137         }
2138         if (port>cnt || port<1)
2139         {
2140                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2141                 return(NULL);
2142         }
2143
2144         pri = bri = pots = nt = te = 0;
2145         devinfo.id = port - 1;
2146         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
2147         if (ret < 0)
2148         {
2149                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
2150                 return(NULL);
2151         }
2152         /* output the port info */
2153         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2154         {
2155                 bri = 1;
2156                 te = 1;
2157         }
2158         if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2159         {
2160                 bri = 1;
2161                 nt = 1;
2162         }
2163         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2164         {
2165                 pri = 1;
2166                 te = 1;
2167         }
2168         if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2169         {
2170                 pri = 1;
2171                 nt = 1;
2172         }
2173 #ifdef ISDN_P_FXS
2174         if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2175         {
2176                 pots = 1;
2177                 te = 1;
2178         }
2179 #endif
2180 #ifdef ISDN_P_FXO
2181         if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2182         {
2183                 pots = 1;
2184                 nt = 1;
2185         }
2186 #endif
2187         if (force_nt && !nt)
2188         {
2189                 PERROR_RUNTIME("Port %d does not support NT-mode\n", port);
2190                 return(NULL);
2191         }
2192         if (bri && pri)
2193         {
2194                 PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
2195                 return(NULL);
2196         }
2197         if (pots && !bri && !pri)
2198         {
2199                 PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
2200                 return(NULL);
2201         }
2202         if (!bri && !pri)
2203         {
2204                 PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
2205                 return(NULL);
2206         }
2207         if (!nt && !te)
2208         {
2209                 PERROR_RUNTIME("Port %d does not support NT-mode nor TE-mode!\n", port);
2210                 return(NULL);
2211         }
2212         /* set NT by turning off TE */
2213         if (force_nt && nt)
2214                 te = 0;
2215         /* if TE an NT is supported (and not forced to NT), turn off NT */
2216         if (te && nt)
2217                 nt = 0;
2218
2219         /* add mISDNport structure */
2220         mISDNportp = &mISDNport_first;
2221         while(*mISDNportp)
2222                 mISDNportp = &((*mISDNportp)->next);
2223         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2224         mISDNport->l1link = -1;
2225         pmemuse++;
2226         *mISDNportp = mISDNport;
2227
2228         /* if pri, must set PTP */
2229         if (pri)
2230                 ptp = 1;
2231         
2232         /* set l2hold */
2233         switch (l2hold)
2234         {
2235                 case -1: // off
2236                 l2hold = 0;
2237                 break;
2238                 case 1: // on
2239                 l2hold = 1;
2240                 break;
2241                 default:
2242                 if (ptp)
2243                         l2hold = 1;
2244                 else
2245                         l2hold = 0;
2246                 break;
2247         }
2248                 
2249         /* allocate ressources of port */
2250         /* open layer 3 and init upqueue */
2251         protocol = (nt)?L3_PROTOCOL_DSS1_NET:L3_PROTOCOL_DSS1_USER;
2252         prop = (1 << MISDN_FLG_L2_CLEAN);
2253         if (ptp) // ptp forced
2254                prop |= (1 << MISDN_FLG_PTP);
2255         if (nt) // supports hold/retrieve on nt-mode
2256                prop |= (1 << MISDN_FLG_NET_HOLD);
2257         if (l2hold) // supports layer 2 hold
2258                prop |= (1 << MISDN_FLG_L2_HOLD);
2259         /* queue must be initializes, because l3-thread may send messages during open_layer3() */
2260         mqueue_init(&mISDNport->upqueue);
2261         mISDNport->ml3 = open_layer3(port-1, protocol, prop , do_layer3, mISDNport);
2262         if (!mISDNport->ml3)
2263         {
2264                 mqueue_purge(&mISDNport->upqueue);
2265                 PERROR_RUNTIME("open_layer3() failed for port %d\n", port);
2266                 start_trace(port,
2267                         interface,
2268                         NULL,
2269                         NULL,
2270                         DIRECTION_NONE,
2271                         CATEGORY_CH,
2272                         0,
2273                         "PORT (open failed)");
2274                 end_trace();
2275                 mISDNport_close(mISDNport);
2276                 return(NULL);
2277         }
2278
2279 #if 0
2280         /* if ntmode, establish L1 to send the tei removal during start */
2281         if (mISDNport->ntmode)
2282         {
2283                 iframe_t act;
2284                 /* L1 */
2285                 act.prim = PH_ACTIVATE | REQUEST; 
2286                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2287                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2288                 act.dinfo = 0;
2289                 act.len = 0;
2290                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2291                 usleep(10000); /* to be sure, that l1 is up */
2292         }
2293 #endif
2294
2295         SCPY(mISDNport->name, devinfo.name);
2296         mISDNport->b_num = devinfo.nrbchan;
2297         mISDNport->portnum = port;
2298         mISDNport->ntmode = nt;
2299         mISDNport->pri = pri;
2300         mISDNport->ptp = ptp;
2301         mISDNport->l2hold = l2hold;
2302         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
2303         i = 0;
2304         while(i < mISDNport->b_num)
2305         {
2306                 mISDNport->b_state[i] = B_STATE_IDLE;
2307                 mISDNport->b_socket[i] = -1;
2308                 i++;
2309         }
2310
2311         /* if ptp, pull up the link */
2312         if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
2313         {
2314                 mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2315                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
2316                 add_trace("tei", NULL, "%d", 0);
2317                 end_trace();
2318                 time(&mISDNport->l2establish);
2319         }
2320
2321         /* initially, we assume that the link is down, exept for nt-ptmp */
2322         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
2323
2324         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
2325
2326         start_trace(mISDNport->portnum,
2327                     interface,
2328                     NULL,
2329                     NULL,
2330                     DIRECTION_NONE,
2331                     CATEGORY_CH,
2332                     0,
2333                     "PORT (open)");
2334         add_trace("mode", NULL, (mISDNport->ntmode)?"network":"terminal");
2335         add_trace("channels", NULL, "%d", mISDNport->b_num);
2336         end_trace();
2337         return(mISDNport);
2338 }
2339
2340
2341 /*
2342  * function to free ALL cards (ports)
2343  */
2344 void mISDNport_close_all(void)
2345 {
2346         /* free all ports */
2347         while(mISDNport_first)
2348                 mISDNport_close(mISDNport_first);
2349 }
2350
2351 /*
2352  * free only one port
2353  */
2354 void mISDNport_close(struct mISDNport *mISDNport)
2355 {
2356         struct mISDNport **mISDNportp;
2357         class Port *port;
2358         class PmISDN *isdnport;
2359         int i;
2360
2361         /* remove all port instance that are linked to this mISDNport */
2362         port = port_first;
2363         while(port)
2364         {
2365                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
2366                 {
2367                         isdnport = (class PmISDN *)port;
2368                         if (isdnport->p_m_mISDNport)
2369                         {
2370                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
2371                                 delete isdnport;
2372                         }
2373                 }
2374                 port = port->next;
2375         }
2376
2377         /* only if we are already part of interface */
2378         if (mISDNport->ifport)
2379         {
2380                 start_trace(mISDNport->portnum,
2381                             mISDNport->ifport->interface,
2382                             NULL,
2383                             NULL,
2384                             DIRECTION_NONE,
2385                             CATEGORY_CH,
2386                             0,
2387                             "PORT (close)");
2388                 end_trace();
2389         }
2390
2391         /* free bchannels */
2392         i = 0;
2393         while(i < mISDNport->b_num)
2394         {
2395                 if (mISDNport->b_socket[i] > -1)
2396                 {
2397                         _bchannel_destroy(mISDNport, i);
2398                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
2399                 }
2400                 i++;
2401         }
2402
2403         /* close layer 3, if open and purge upqueue */
2404         if (mISDNport->ml3)
2405         {
2406                 close_layer3(mISDNport->ml3);
2407                 mqueue_purge(&mISDNport->upqueue);
2408         }
2409
2410         /* remove from list */
2411         mISDNportp = &mISDNport_first;
2412         while(*mISDNportp)
2413         {
2414                 if (*mISDNportp == mISDNport)
2415                 {
2416                         *mISDNportp = (*mISDNportp)->next;
2417                         mISDNportp = NULL;
2418                         break;
2419                 }
2420                 mISDNportp = &((*mISDNportp)->next);
2421         }
2422
2423         if (mISDNportp)
2424                 FATAL("mISDNport not in list\n");
2425         
2426         FREE(mISDNport, sizeof(struct mISDNport));
2427         pmemuse--;
2428
2429 }
2430
2431
2432 /*
2433  * enque data from upper buffer
2434  */
2435 void PmISDN::txfromup(unsigned char *data, int length)
2436 {
2437         unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
2438         struct mISDNhead *hh = (struct mISDNhead *)buf;
2439         int ret;
2440
2441         if (p_m_b_index < 0)
2442                 return;
2443         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE)
2444                 return;
2445
2446         /* check if high priority tones exist
2447          * ignore data in this case
2448          */
2449         if (p_tone_name[0] || p_m_crypt_msg_loops)
2450                 return;
2451
2452         /* preload procedure
2453          * if transmit buffer in DSP module is empty,
2454          * preload it to DSP_LOAD to prevent jitter gaps.
2455          */
2456         if (p_m_load==0 && ISDN_LOAD>0)
2457         {
2458                 hh->prim = PH_DATA_REQ; 
2459                 hh->id = 0;
2460                 memset(buf+MISDN_HEADER_LEN, (options.law=='a')?0x2a:0xff, ISDN_LOAD);
2461                 ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+ISDN_LOAD, 0, NULL, 0);
2462                 if (ret <= 0)
2463                         PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_socket[p_m_b_index]);
2464                 p_m_load += ISDN_LOAD;
2465         }
2466
2467         /* drop if load would exceed ISDN_MAXLOAD
2468          * this keeps the delay not too high
2469          */
2470         if (p_m_load+length > ISDN_MAXLOAD)
2471                 return;
2472
2473         /* make and send frame */
2474         hh->prim = PH_DATA_REQ;
2475         hh->id = 0;
2476         memcpy(buf+MISDN_HEADER_LEN, data, length);
2477         ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+length, 0, NULL, 0);
2478         if (ret <= 0)
2479                 PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_socket[p_m_b_index]);
2480         p_m_load += length;
2481 }
2482