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