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