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