#include #include "../libtimer/timer.h" #include "../libosmocc/endpoint.h" #include "../libosmocc/helper.h" #include "../libsample/sample.h" #include "../libjitter/jitter.h" #include "ph_socket.h" #define B_MODE_TRANSPARENT 0 #define B_MODE_HDLC 1 #define B_STATE_IDLE 0 /* not open */ #define B_STATE_ACTIVATING 1 /* DL_ESTABLISH sent */ #define B_STATE_ACTIVE 2 /* channel active */ #define B_STATE_DEACTIVATING 3 /* DL_RELEASE sent */ #define B_EVENT_USE 0 /* activate bchannel */ #define B_EVENT_ACTIVATED 1 /* DL_ESTABLISH received */ #define B_EVENT_DROP 2 /* deactivate bchannel */ #define B_EVENT_DEACTIVATED 3 /* DL_RELEASE received */ #define B_EVENT_TIMEOUT 4 /* timeout happed during (de)activation */ #define TONES_TYPE_AMERICAN 1 #define TONES_TYPE_GERMAN 2 #define TONES_TYPE_OLDGERMAN 3 enum isdn_state { ISDN_STATE_IDLE = 0, /* no call */ ISDN_STATE_IN_SETUP, /* incoming connection */ ISDN_STATE_OUT_SETUP, /* outgoing connection */ ISDN_STATE_IN_OVERLAP, /* more informatiopn needed */ ISDN_STATE_OUT_OVERLAP, /* more informatiopn needed */ ISDN_STATE_IN_PROCEEDING,/* call is proceeding */ ISDN_STATE_OUT_PROCEEDING,/* call is proceeding */ ISDN_STATE_IN_ALERTING, /* call is ringing */ ISDN_STATE_OUT_ALERTING,/* call is ringing */ ISDN_STATE_IN_CONNECTING,/* wait for ack after answer */ ISDN_STATE_OUT_CONNECTING,/* wait for ack after answer */ ISDN_STATE_CONNECT, /* call is connected and transmission is enabled */ ISDN_STATE_IN_DISCONNECT,/* incoming disconnected */ ISDN_STATE_OUT_DISCONNECT,/* outgoing disconnected */ ISDN_STATE_OUT_RELEASE, /* call released */ ISDN_STATE_SUSPENDED, /* call suspended */ }; struct isdn; struct b_timer_inst { struct isdn *isdn_ep; int index; }; struct msn_list { struct msn_list *next; char msn[0]; }; struct select_channel { struct select_channel *next; int channel; }; struct call_list; typedef struct isdn { struct call_list *call_list; struct msn_list *msn_list; /* settings */ char law; struct select_channel *out_channel; /* list of outgoing channels to select */ struct select_channel *in_channel; /* the same for incoming channels */ int out_channel_exclusive; /* force channel */ int serving_location; /* who we serve when sending causes towards interface */ const char *timeouts; int tx_delay; int tx_gain; int rx_gain; const char *pipeline; int dtmf; int local_tones; /* osmo-cc */ struct osmo_cc_endpoint cc_ep; /* mISDN */ char *portname; int portnum; int ntmode; int ptp; int pri; int l1hold; int l2hold; int l2sock; void *l2inst; ph_socket_t *ph_socket; pthread_mutex_t upqueue_lock; struct mqueue upqueue; int upqueue_initialized; struct mlayer3 *ml3; int los, ais, rdi, slip_rx, slip_tx; int l1link; /* current state */ int l2link; /* current state */ struct timer l2establish_timer; int b_num; int b_reserved; int b_mode[128]; int b_state[128]; int b_sock[128]; struct call_list *b_call[128]; struct timer b_timer[128]; struct b_timer_inst b_timer_inst[128]; uint8_t b_buffer[128][160]; int b_buffer_pos[128]; unsigned char l2mask[16]; /* 128 bits for each tei */ } isdn_t; typedef struct call_list { struct call_list *next; isdn_t *isdn_ep; /* mISDN states */ uint32_t l3_pid; uint16_t l3_ces; int tx_gain; int rx_gain; int mute; int txdata; int tx_delay; int echo; int conf; int tone; int rxoff; int dtmf; int dtmf_threshold; const char *pipeline; /* osmo-cc states */ uint32_t cc_callref; osmo_cc_session_t *cc_session; osmo_cc_session_codec_t *codec; const char *sdp; char codec_law; int codec_negotiated; int audio_path; /* bchannel states */ int b_index; int b_channel; int b_exclusive; int b_reserve; int b_mode; /* call states */ enum isdn_state state; int any_dialing; /* if any digit was dialed, we track this for dial tone */ int channel_negotiated; int send_local_tones; /* using locally generated tones, because upper layer does not provide them */ int send_remote_tones; /* using remote tones, as we received a progress indicator 1 or 8 from upper layer */ int proceeding_sent; int sending_complete; /* send proceeding when osmo-cc requests overlap */ int setup_comp_req_channel_assignment; /* must assign channel on setup comp req */ uint8_t collect_cause, collect_location; int hold; /* if call is on hold */ int conference_3pty; /* if call is the active call in a 3pty conference */ int park_len; uint8_t park_callid[8]; /* jitter buffer for 3pty call */ jitter_t dejitter; } call_t; int check_mISDN_dsp(void); /* channel selection */ int hunt_bchannel_in(isdn_t *isdn_ep, int channel, int exclusive); int hunt_bchannel_out(isdn_t *isdn_ep, int *channel, int *exclusive); int open_bchannel_in(call_t *call, int channel, int exclusive); int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive); /* isdn instance */ isdn_t *isdn_create(void); void isdn_destroy(isdn_t *isdn_ep); int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int tx_gain, int rx_gain, const char *pipeline, int dtmf, int local_tones, int serving_location); int isdn_open(isdn_t *isdn_ep); void isdn_close(isdn_t *isdn_ep); void isdn_add_msn(isdn_t *isdn_ep, const char *msn); int isdn_dchannel_work(isdn_t *isdn_ep); void isdn_bchannel_work(isdn_t *isdn_ep); void isdn_rtp_work(isdn_t *isdn_ep); /* call instance */ call_t *call_create(isdn_t *isdn_ep, int channel, int exclusive, int mode); void call_destroy(call_t *call); /* channel allocation and handling */ void bchannel_tone(call_t *call, int tone); void bchannel_event(isdn_t *isdn_ep, int index, int event); int seize_bchannel(call_t *call, int channel, int exclusive); void drop_bchannel(call_t *call); void bchannel_send(struct osmo_cc_session_codec *codec, uint16_t sequence_number, uint32_t timestamp, uint8_t *data, int len);