2f8dd5f7c3b7a87612dddf9a884e9ec182a228de
[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(0xffffffff, filename, filename, filename);
75         } else
76                 mISDN_debug_init(0, NULL, NULL, NULL);
77
78         return(0);
79 }
80
81 void mISDN_deinitialize(void)
82 {
83         cleanup_layer3();
84
85         mISDN_debug_close();
86
87         if (debug_fp)
88                 fclose(debug_fp);
89         debug_fp = NULL;
90
91         if (mISDNsocket > -1)
92                 close(mISDNsocket);
93 }
94
95 /*
96  * constructor
97  */
98 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Port(type, portname, settings)
99 {
100         p_m_mISDNport = mISDNport;
101         p_m_portnum = mISDNport->portnum;
102         p_m_b_index = -1;
103         p_m_b_channel = 0;
104         p_m_b_exclusive = 0;
105         p_m_b_reserve = 0;
106         p_m_b_mode = mode;
107         p_m_delete = 0;
108         p_m_hold = 0;
109         p_m_tx_gain = mISDNport->ifport->interface->tx_gain;
110         p_m_rx_gain = mISDNport->ifport->interface->rx_gain;
111         p_m_conf = 0;
112         p_m_txdata = 0;
113         p_m_delay = 0;
114         p_m_echo = 0;
115         p_m_tone = 0;
116         p_m_rxoff = 0;
117         p_m_joindata = 0;
118         p_m_dtmf = !mISDNport->ifport->nodtmf;
119         p_m_timeout = 0;
120         p_m_timer = 0;
121         p_m_remote_ref = 0; /* channel shall be exported to given remote */
122         p_m_remote_id = 0; /* remote admin socket */
123         SCPY(p_m_pipeline, mISDNport->ifport->interface->pipeline);
124         
125         /* audio */
126         p_m_load = 0;
127         p_m_last_tv_sec = 0;
128
129         /* crypt */
130         p_m_crypt = 0;
131         p_m_crypt_listen = 0;
132         p_m_crypt_msg_loops = 0;
133         p_m_crypt_msg_loops = 0;
134         p_m_crypt_msg_len = 0;
135         p_m_crypt_msg[0] = '\0';
136         p_m_crypt_msg_current = 0;
137         p_m_crypt_key_len = 0;
138         p_m_crypt_listen = 0;
139         p_m_crypt_listen_state = 0;
140         p_m_crypt_listen_len = 0;
141         p_m_crypt_listen_msg[0] = '\0';
142         p_m_crypt_listen_crc = 0;
143         if (mISDNport->ifport->interface->bf_len >= 4 && mISDNport->ifport->interface->bf_len <= 56)
144         {
145                 memcpy(p_m_crypt_key, mISDNport->ifport->interface->bf_key, p_m_crypt_key_len);
146                 p_m_crypt_key_len = mISDNport->ifport->interface->bf_len;
147                 p_m_crypt = 1;
148         }
149
150         /* if any channel requested by constructor */
151         if (channel == CHANNEL_ANY)
152         {
153                 /* reserve channel */
154                 p_m_b_reserve = 1;
155                 mISDNport->b_reserved++;
156         }
157
158         /* reserve channel */
159         if (channel > 0) // only if constructor was called with a channel resevation
160                 seize_bchannel(channel, exclusive);
161
162         /* we increase the number of objects: */
163         mISDNport->use++;
164         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
165 }
166
167
168 /*
169  * destructor
170  */
171 PmISDN::~PmISDN()
172 {
173         struct lcr_msg *message;
174
175         /* remove bchannel relation */
176         drop_bchannel();
177
178         /* release epoint */
179         while (p_epointlist)
180         {
181                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
182                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
183                 message->param.disconnectinfo.cause = 16;
184                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
185                 message_put(message);
186                 /* remove from list */
187                 free_epointlist(p_epointlist);
188         }
189
190         /* we decrease the number of objects: */
191         p_m_mISDNport->use--;
192         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
193 }
194
195
196 /*
197  * trace
198  */
199 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, const char *msgtext, int direction)
200 {
201         /* init trace with given values */
202         start_trace(mISDNport?mISDNport->portnum:-1,
203                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
204                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
205                     port?port->p_dialinginfo.id:NULL,
206                     direction,
207                     CATEGORY_CH,
208                     port?port->p_serial:0,
209                     msgtext);
210 }
211
212
213 /*
214  * layer trace header
215  */
216 static struct isdn_message {
217         const char *name;
218         unsigned int value;
219 } isdn_message[] = {
220         {"PH_ACTIVATE", L1_ACTIVATE_REQ},
221         {"PH_DEACTIVATE", L1_DEACTIVATE_REQ},
222         {"DL_ESTABLISH", L2_ESTABLISH_REQ},
223         {"DL_RELEASE", L2_RELEASE_REQ},
224         {"UNKNOWN", L3_UNKNOWN_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 ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
2010                                 {
2011                                         if (mISDNport->l2establish)
2012                                         {
2013                                                 mISDNport->l2establish = 0;
2014                                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2015                                         }
2016                                 }
2017                                 break;
2018
2019                                 case MT_L2RELEASE:
2020                                 if (!mISDNport->l2establish)
2021                                 {
2022                                         l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
2023                                         add_trace("tei", NULL, "%d", l3m->pid);
2024                                         end_trace();
2025                                         /* down if not nt-ptmp */ 
2026                                         if (!mISDNport->ntmode || mISDNport->ptp)
2027                                                 mISDNport->l2link = 0;
2028                                 }
2029                                 if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
2030                                 {
2031                                         if (!mISDNport->l2establish && mISDNport->l2hold)
2032                                         {
2033                                                 PDEBUG(DEBUG_ISDN, "set timer and establish.\n");
2034                                                 time(&mISDNport->l2establish);
2035                                                 mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2036                                         }
2037                                 }
2038                                 break;
2039
2040                                 default:
2041                                 /* l3-data is sent to LCR */
2042                                 stack2manager(mISDNport, l3m->type, l3m->pid, l3m);
2043                         }
2044                         /* free message */
2045                         free_l3_msg(l3m);
2046                 }
2047
2048 #if 0
2049                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2050                 { ---}
2051                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2052                         mISDNport->l1timeout = 0;
2053 #endif
2054
2055                 /* layer 2 establish timer */
2056                 if (mISDNport->l2establish)
2057                 {
2058                         if (now-mISDNport->l2establish > 5)
2059                         {
2060                                 mISDNport->l2establish = 0;
2061                                 if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
2062                                 {
2063
2064                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
2065                                         mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2066                                         time(&mISDNport->l2establish);
2067                                         return(1);
2068                                 }
2069                         }
2070                 }
2071
2072
2073                 mISDNport = mISDNport->next;
2074         }
2075
2076         /* if we received at least one b-frame, we will return 1 */
2077         return(work);
2078 }
2079
2080 int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
2081 {
2082         /* IMPORTAINT:
2083          *
2084          * l3m must be queued, except for MT_ASSIGN
2085          *
2086          */
2087         struct mISDNport *mISDNport = (struct mISDNport *)ml3->priv;
2088         struct mbuffer *mb;
2089
2090         /* special MT_ASSIGN handling:
2091          *
2092          * if we request a PID from mlayer, we always do it while lcr is locked.
2093          * therefore we must check the MT_ASSIGN reply first before we lock.
2094          * this is because the MT_ASSIGN reply is received with the requesting
2095          * process, not by the mlayer thread!
2096          * this means, that the reply is sent during call of the request.
2097          * we must check if we get a reply and we know that we lcr is currently
2098          * locked.
2099          */
2100         if (cmd==MT_ASSIGN && (pid&MISDN_PID_CR_FLAG) && (pid>>16)==MISDN_CES_MASTER)
2101         {
2102                 /* let's do some checking if someone changes stack behaviour */
2103                 if (mt_assign_pid != 0)
2104                         FATAL("someone played with the mISDNuser stack. MT_ASSIGN not currently expected.\n");
2105                 mt_assign_pid = pid;
2106                 return(0);
2107         }
2108         
2109         /* queue message, create, if required */
2110         if (!l3m)
2111         {
2112                 l3m = alloc_l3_msg();
2113                 if (!l3m)
2114                         FATAL("No memory for layer 3 message\n");
2115         }
2116         mb = container_of(l3m, struct mbuffer, l3);
2117         l3m->type = cmd;
2118         l3m->pid = pid;
2119         mqueue_tail(&mISDNport->upqueue, mb);
2120         return 0;
2121 }
2122
2123
2124 /*
2125  * global function to add a new card (port)
2126  */
2127 struct mISDNport *mISDNport_open(int port, char *portname, int ptp, int force_nt, int te_special, int l2hold, struct interface *interface)
2128 {
2129         int ret;
2130         struct mISDNport *mISDNport, **mISDNportp;
2131         int i, cnt;
2132         int pri, bri, pots;
2133         int nt, te;
2134 //      struct mlayer3 *ml3;
2135         struct mISDN_devinfo devinfo;
2136         unsigned int protocol, prop;
2137
2138         /* check port counts */
2139         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
2140         if (ret < 0)
2141         {
2142                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2143                 return(NULL);
2144         }
2145
2146         if (cnt <= 0)
2147         {
2148                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2149                 return(NULL);
2150         }
2151         if (port < 0)
2152         {
2153                 /* resolve name */
2154                 port = 0;
2155                 while (port < cnt)
2156                 {
2157                         devinfo.id = port;
2158                         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
2159                         if (ret < 0)
2160                         {
2161                                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", port, ret);
2162                                 return(NULL);
2163                         }
2164                         if (!strcasecmp(devinfo.name, portname))
2165                                 break;
2166                         port++;
2167                 }
2168                 if (port == cnt)
2169                 {
2170                         PERROR_RUNTIME("Port name '%s' not found, use 'misdn_info' tool to list all existing ports.\n", portname);
2171                         return(NULL);
2172                 }
2173                 // note: 'port' has still the port number
2174         }
2175         if (port>cnt || port<0)
2176         {
2177                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 0, cnt);
2178                 return(NULL);
2179         }
2180
2181         /* get port attributes */
2182         pri = bri = pots = nt = te = 0;
2183         devinfo.id = port;
2184         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
2185         if (ret < 0)
2186         {
2187                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", port, ret);
2188                 return(NULL);
2189         }
2190         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2191         {
2192                 bri = 1;
2193                 te = 1;
2194         }
2195         if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2196         {
2197                 bri = 1;
2198                 nt = 1;
2199         }
2200         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2201         {
2202                 pri = 1;
2203                 te = 1;
2204         }
2205         if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2206         {
2207                 pri = 1;
2208                 nt = 1;
2209         }
2210 #ifdef ISDN_P_FXS
2211         if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2212         {
2213                 pots = 1;
2214                 te = 1;
2215         }
2216 #endif
2217 #ifdef ISDN_P_FXO
2218         if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2219         {
2220                 pots = 1;
2221                 nt = 1;
2222         }
2223 #endif
2224         if (force_nt && !nt)
2225         {
2226                 PERROR_RUNTIME("Port %d does not support NT-mode\n", port);
2227                 return(NULL);
2228         }
2229         if (bri && pri)
2230         {
2231                 PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
2232                 return(NULL);
2233         }
2234         if (pots && !bri && !pri)
2235         {
2236                 PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
2237                 return(NULL);
2238         }
2239         if (!bri && !pri)
2240         {
2241                 PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
2242                 return(NULL);
2243         }
2244         if (!nt && !te)
2245         {
2246                 PERROR_RUNTIME("Port %d does not support NT-mode nor TE-mode!\n", port);
2247                 return(NULL);
2248         }
2249         /* set NT by turning off TE */
2250         if (force_nt && nt)
2251                 te = 0;
2252         /* if TE an NT is supported (and not forced to NT), turn off NT */
2253         if (te && nt)
2254                 nt = 0;
2255
2256         /* check for double use of port */
2257         if (nt)
2258         {
2259                 mISDNport = mISDNport_first;
2260                 while(mISDNport)
2261                 {
2262                         if (mISDNport->portnum == port)
2263                                 break;
2264                         mISDNport = mISDNport->next;
2265                 }
2266                 if (mISDNport)
2267                 {
2268                         PERROR_RUNTIME("Port %d already in use by LCR. You can't use a NT port multiple times.\n", port);
2269                         return(NULL);
2270                 }
2271         }
2272
2273
2274         /* add mISDNport structure */
2275         mISDNportp = &mISDNport_first;
2276         while(*mISDNportp)
2277                 mISDNportp = &((*mISDNportp)->next);
2278         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2279         mISDNport->l1link = -1;
2280         mISDNport->l2link = -1;
2281         pmemuse++;
2282         *mISDNportp = mISDNport;
2283
2284         /* if pri, must set PTP */
2285         if (pri)
2286                 ptp = 1;
2287         
2288         /* set l2hold */
2289         switch (l2hold)
2290         {
2291                 case -1: // off
2292                 l2hold = 0;
2293                 break;
2294                 case 1: // on
2295                 l2hold = 1;
2296                 break;
2297                 default:
2298                 if (ptp)
2299                         l2hold = 1;
2300                 else
2301                         l2hold = 0;
2302                 break;
2303         }
2304                 
2305         /* allocate ressources of port */
2306         /* open layer 3 and init upqueue */
2307         protocol = (nt)?L3_PROTOCOL_DSS1_NET:L3_PROTOCOL_DSS1_USER;
2308         prop = (1 << MISDN_FLG_L2_CLEAN);
2309         if (ptp) // ptp forced
2310                prop |= (1 << MISDN_FLG_PTP);
2311         if (nt) // supports hold/retrieve on nt-mode
2312                prop |= (1 << MISDN_FLG_NET_HOLD);
2313         if (l2hold) // supports layer 2 hold
2314                prop |= (1 << MISDN_FLG_L2_HOLD);
2315         /* queue must be initializes, because l3-thread may send messages during open_layer3() */
2316         mqueue_init(&mISDNport->upqueue);
2317         mISDNport->ml3 = open_layer3(port, protocol, prop , do_layer3, mISDNport);
2318         if (!mISDNport->ml3)
2319         {
2320                 mqueue_purge(&mISDNport->upqueue);
2321                 PERROR_RUNTIME("open_layer3() failed for port %d\n", port);
2322                 start_trace(port,
2323                         interface,
2324                         NULL,
2325                         NULL,
2326                         DIRECTION_NONE,
2327                         CATEGORY_CH,
2328                         0,
2329                         "PORT (open failed)");
2330                 end_trace();
2331                 mISDNport_close(mISDNport);
2332                 return(NULL);
2333         }
2334
2335 #if 0
2336         /* if ntmode, establish L1 to send the tei removal during start */
2337         if (mISDNport->ntmode)
2338         {
2339                 iframe_t act;
2340                 /* L1 */
2341                 act.prim = PH_ACTIVATE | REQUEST; 
2342                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2343                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2344                 act.dinfo = 0;
2345                 act.len = 0;
2346                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2347                 usleep(10000); /* to be sure, that l1 is up */
2348         }
2349 #endif
2350
2351         SCPY(mISDNport->name, devinfo.name);
2352         mISDNport->b_num = devinfo.nrbchan;
2353         mISDNport->portnum = port;
2354         mISDNport->ntmode = nt;
2355         mISDNport->tespecial = te_special;
2356         mISDNport->pri = pri;
2357         mISDNport->ptp = ptp;
2358         mISDNport->l2hold = l2hold;
2359         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
2360         i = 0;
2361         while(i < mISDNport->b_num)
2362         {
2363                 mISDNport->b_state[i] = B_STATE_IDLE;
2364                 mISDNport->b_socket[i] = -1;
2365                 i++;
2366         }
2367
2368         /* if ptp, pull up the link */
2369         if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
2370         {
2371                 mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2372                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
2373                 add_trace("tei", NULL, "%d", 0);
2374                 end_trace();
2375                 time(&mISDNport->l2establish);
2376         }
2377
2378         /* for nt-mode ptmp the link is always up */
2379         if (mISDNport->ntmode && !mISDNport->ptp)
2380                 mISDNport->l2link = 1;
2381
2382         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
2383
2384         start_trace(mISDNport->portnum,
2385                     interface,
2386                     NULL,
2387                     NULL,
2388                     DIRECTION_NONE,
2389                     CATEGORY_CH,
2390                     0,
2391                     "PORT (open)");
2392         add_trace("mode", NULL, (mISDNport->ntmode)?"network":"terminal");
2393         add_trace("channels", NULL, "%d", mISDNport->b_num);
2394         end_trace();
2395         return(mISDNport);
2396 }
2397
2398
2399 /*
2400  * function to free ALL cards (ports)
2401  */
2402 void mISDNport_close_all(void)
2403 {
2404         /* free all ports */
2405         while(mISDNport_first)
2406                 mISDNport_close(mISDNport_first);
2407 }
2408
2409 /*
2410  * free only one port
2411  */
2412 void mISDNport_close(struct mISDNport *mISDNport)
2413 {
2414         struct mISDNport **mISDNportp;
2415         class Port *port;
2416         class PmISDN *isdnport;
2417         int i;
2418
2419         /* remove all port instance that are linked to this mISDNport */
2420         port = port_first;
2421         while(port)
2422         {
2423                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
2424                 {
2425                         isdnport = (class PmISDN *)port;
2426                         if (isdnport->p_m_mISDNport)
2427                         {
2428                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
2429                                 delete isdnport;
2430                         }
2431                 }
2432                 port = port->next;
2433         }
2434
2435         /* only if we are already part of interface */
2436         if (mISDNport->ifport)
2437         {
2438                 start_trace(mISDNport->portnum,
2439                             mISDNport->ifport->interface,
2440                             NULL,
2441                             NULL,
2442                             DIRECTION_NONE,
2443                             CATEGORY_CH,
2444                             0,
2445                             "PORT (close)");
2446                 end_trace();
2447         }
2448
2449         /* free bchannels */
2450         i = 0;
2451         while(i < mISDNport->b_num)
2452         {
2453                 if (mISDNport->b_socket[i] > -1)
2454                 {
2455                         _bchannel_destroy(mISDNport, i);
2456                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
2457                 }
2458                 i++;
2459         }
2460
2461         /* close layer 3, if open and purge upqueue */
2462         if (mISDNport->ml3)
2463         {
2464                 close_layer3(mISDNport->ml3);
2465                 mqueue_purge(&mISDNport->upqueue);
2466         }
2467
2468         /* remove from list */
2469         mISDNportp = &mISDNport_first;
2470         while(*mISDNportp)
2471         {
2472                 if (*mISDNportp == mISDNport)
2473                 {
2474                         *mISDNportp = (*mISDNportp)->next;
2475                         mISDNportp = NULL;
2476                         break;
2477                 }
2478                 mISDNportp = &((*mISDNportp)->next);
2479         }
2480
2481         if (mISDNportp)
2482                 FATAL("mISDNport not in list\n");
2483         
2484         FREE(mISDNport, sizeof(struct mISDNport));
2485         pmemuse--;
2486
2487 }
2488
2489
2490 /*
2491  * enque data from upper buffer
2492  */
2493 void PmISDN::txfromup(unsigned char *data, int length)
2494 {
2495         unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
2496         struct mISDNhead *hh = (struct mISDNhead *)buf;
2497         int ret;
2498
2499         if (p_m_b_index < 0)
2500                 return;
2501         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE)
2502                 return;
2503
2504         /* check if high priority tones exist
2505          * ignore data in this case
2506          */
2507         if (p_tone_name[0] || p_m_crypt_msg_loops)
2508                 return;
2509
2510         /* preload procedure
2511          * if transmit buffer in DSP module is empty,
2512          * preload it to DSP_LOAD to prevent jitter gaps.
2513          */
2514         if (p_m_load==0 && ISDN_LOAD>0)
2515         {
2516                 hh->prim = PH_DATA_REQ; 
2517                 hh->id = 0;
2518                 memset(buf+MISDN_HEADER_LEN, (options.law=='a')?0x2a:0xff, ISDN_LOAD);
2519                 ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+ISDN_LOAD, 0, NULL, 0);
2520                 if (ret <= 0)
2521                         PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_socket[p_m_b_index]);
2522                 p_m_load += ISDN_LOAD;
2523         }
2524
2525         /* drop if load would exceed ISDN_MAXLOAD
2526          * this keeps the delay not too high
2527          */
2528         if (p_m_load+length > ISDN_MAXLOAD)
2529                 return;
2530
2531         /* make and send frame */
2532         hh->prim = PH_DATA_REQ;
2533         hh->id = 0;
2534         memcpy(buf+MISDN_HEADER_LEN, data, length);
2535         ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+length, 0, NULL, 0);
2536         if (ret <= 0)
2537                 PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_socket[p_m_b_index]);
2538         p_m_load += length;
2539 }
2540