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