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