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