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