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