/* * This file contains platform independent code only. */ #include <stdio.h> #include <syslog.h> #include <stdarg.h> #include <stdlib.h> #include "libvoice.h" #include "libvoice-priv.h" struct terminal_info_t terminal_info = { .num_voice_ports = 0, }; struct line_t *lines = NULL; // Array of phone lines including FXS and DECT struct connection_t *connections = NULL; int max_num_connections = 0; const struct voice_event_t event_map[] = { // List of events from the voice engine { .name = "DTMF0", .event = VOICE_EVT_DTMF0 }, { .name = "DTMF1", .event = VOICE_EVT_DTMF1 }, { .name = "DTMF2", .event = VOICE_EVT_DTMF2 }, { .name = "DTMF3", .event = VOICE_EVT_DTMF3 }, { .name = "DTMF4", .event = VOICE_EVT_DTMF4 }, { .name = "DTMF5", .event = VOICE_EVT_DTMF5 }, { .name = "DTMF6", .event = VOICE_EVT_DTMF6 }, { .name = "DTMF7", .event = VOICE_EVT_DTMF7 }, { .name = "DTMF8", .event = VOICE_EVT_DTMF8 }, { .name = "DTMF9", .event = VOICE_EVT_DTMF9 }, { .name = "DTMFS", .event = VOICE_EVT_DTMFS }, { .name = "DTMFH", .event = VOICE_EVT_DTMFH }, { .name = "DTMFA", .event = VOICE_EVT_DTMFA }, { .name = "DTMFB", .event = VOICE_EVT_DTMFB }, { .name = "DTMFC", .event = VOICE_EVT_DTMFC }, { .name = "DTMFD", .event = VOICE_EVT_DTMFD }, { .name = "OFFHOOK", .event = VOICE_EVT_OFFHOOK }, { .name = "ONHOOK", .event = VOICE_EVT_ONHOOK }, { .name = "FLASH", .event = VOICE_EVT_FLASH }, { .name = "", .event = VOICE_EVT_END } }; const struct dect_event_t dect_event_map[] = { // List of events from the dectmngr { .name = "SWITCH", .event = DECT_EVT_SWITCH }, { .name = "JOIN", .event = DECT_EVT_JOIN }, { .name = "RELEASE", .event = DECT_EVT_RELEASE }, { .name = "", .event = DECT_EVT_END } }; const struct voice_signal_t signal_map[] = { // List of signals requested by Asterisk { .name = "dial", .signal = VOICE_SIG_DIAL }, { .name = "ringback", .signal = VOICE_SIG_RINGBACK }, { .name = "stutter", .signal = VOICE_SIG_STUTTER }, { .name = "unobtainable", .signal = VOICE_SIG_UNOBTAINABLE }, { .name = "callwt", .signal = VOICE_SIG_CALL_WAITING }, { .name = "busy", .signal = VOICE_SIG_BUSY }, { .name = "ringing", .signal = VOICE_SIG_RINGING }, { .name = "callid_ringing", .signal = VOICE_SIG_CALLID_RINGING }, { .name = "callid", .signal = VOICE_SIG_CALLID }, { .name = "congestion", .signal = VOICE_SIG_NETBUSY }, { .name = "dtmf0", .signal = VOICE_SIG_DTMF0 }, { .name = "dtmf1", .signal = VOICE_SIG_DTMF1 }, { .name = "dtmf2", .signal = VOICE_SIG_DTMF2 }, { .name = "dtmf3", .signal = VOICE_SIG_DTMF3 }, { .name = "dtmf4", .signal = VOICE_SIG_DTMF4 }, { .name = "dtmf5", .signal = VOICE_SIG_DTMF5 }, { .name = "dtmf6", .signal = VOICE_SIG_DTMF6 }, { .name = "dtmf7", .signal = VOICE_SIG_DTMF7 }, { .name = "dtmf8", .signal = VOICE_SIG_DTMF8 }, { .name = "dtmf9", .signal = VOICE_SIG_DTMF9 }, { .name = "dtmf#", .signal = VOICE_SIG_DTMFH }, { .name = "dtmf*", .signal = VOICE_SIG_DTMFS }, { .name = "dtmfA", .signal = VOICE_SIG_DTMFA }, { .name = "dtmfB", .signal = VOICE_SIG_DTMFB }, { .name = "dtmfC", .signal = VOICE_SIG_DTMFC }, { .name = "dtmfD", .signal = VOICE_SIG_DTMFD }, { .name = "keypad", .signal = VOICE_SIG_INGRESS_DTMF }, { .name = "answer", .signal = VOICE_SIG_ANSWER }, { .name = "k-break", .signal = VOICE_SIG_K_BREAK }, { .name = "", .signal = VOICE_SIG_LAST }, }; // Callback function which is invoked when an event is detected from the voice engine void (*voice_cb_event_report)(int line, const char *event, int data) = NULL; // Callback function which is invoked when an encoded media packet is generated by the voice engine void (*voice_cb_egress_media)(const struct media_packet_t *packet, int size) = NULL; void voice_syslog(int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsyslog(level, fmt, ap); va_end(ap); } int voice_connection_find(int line, int connection) { int conIdx; for(conIdx = 0; conIdx < max_num_connections; conIdx++) { // If connection is -1, it means any connection on the line if(connections[conIdx].line == line && (connections[conIdx].connection_id == connection || connection == -1)) { return conIdx; } } return -1; } // Pre-initialization of data structures int voice_line_preinit(void) { int i; if(terminal_info.num_voice_ports <= 0) { ENDPT_DBG("terminal_info.num_voice_ports = %d\n", terminal_info.num_voice_ports); return -1; } // Initialize all contents as 0 by calloc lines = calloc(terminal_info.num_voice_ports, sizeof(struct line_t)); if(!lines) { ENDPT_ERR("%s: out out memory\n", __func__); return -1; } for(i = 0; i < terminal_info.num_voice_ports; i++) { lines[i].type = terminal_info.voice_ports[i]; ENDPT_DBG("lines[%d].type=%d\n", i, lines[i].type); lines[i].pcm_callid[PCM_0] = CALLID_INVALID; lines[i].pcm_callid[PCM_1] = CALLID_INVALID; } return 0; } // Shut down and free resources int voice_line_deinit(void) { char *digits; int i; // Free all line resources we have allocated for(i = 0; i < terminal_info.num_voice_ports; i++) { if(lines[i].pending_digits) { do { digits = pe_list_get(lines[i].pending_digits); free(digits); } while(digits); free(lines[i].pending_digits); lines[i].pending_digits = NULL; } voice_line_close(i); if(lines[i].line_conf.name) { free(lines[i].line_conf.name); lines[i].line_conf.name = NULL; } if(lines[i].priv) { free(lines[i].priv); lines[i].priv = NULL; } } free(lines); lines = NULL; return 0; } // Register the callback function for event report int voice_register_cb_event_report(void (*cb_event_report)(int line, const char *event, int data)) { voice_cb_event_report = cb_event_report; return 0; } // Register the callback function for handling an encoded media packet from the voice engine int voice_register_cb_egress_media(void (*cb_egress_media)(const struct media_packet_t *packet, int size)) { voice_cb_egress_media = cb_egress_media; return 0; } const char *voice_event2name(enum VOICE_EVENT evt) { const struct voice_event_t *item; for (item = event_map; item->event != evt && item->event != VOICE_EVT_END; item++) continue; return item->name; }