add fsk callerid stuff to analog fxo
git-svn-id: http://svn.openzap.org/svn/openzap/trunk@220 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
parent
690b929ea6
commit
fa760fe233
|
@ -699,7 +699,7 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t
|
|||
private_t *tech_pvt = NULL;
|
||||
switch_channel_t *channel = NULL;
|
||||
char name[128];
|
||||
|
||||
|
||||
*sp = NULL;
|
||||
|
||||
if (!(session = switch_core_session_request(&channel_endpoint_interface, NULL))) {
|
||||
|
@ -716,16 +716,29 @@ zap_status_t zap_channel_from_event(zap_sigmsg_t *sigmsg, switch_core_session_t
|
|||
switch_core_session_destroy(&session);
|
||||
return ZAP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (switch_strlen_zero(sigmsg->channel->caller_data.cid_name)) {
|
||||
switch_set_string(sigmsg->channel->caller_data.cid_name, sigmsg->channel->chan_name);
|
||||
}
|
||||
|
||||
if (switch_strlen_zero(sigmsg->channel->caller_data.cid_num)) {
|
||||
if (!switch_strlen_zero(sigmsg->channel->caller_data.ani)) {
|
||||
switch_set_string(sigmsg->channel->caller_data.cid_num, sigmsg->channel->caller_data.ani);
|
||||
} else {
|
||||
switch_set_string(sigmsg->channel->caller_data.cid_num, sigmsg->channel->chan_number);
|
||||
}
|
||||
}
|
||||
|
||||
tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
|
||||
"OpenZAP",
|
||||
SPAN_CONFIG[sigmsg->channel->span_id].dialplan,
|
||||
sigmsg->channel->chan_name,
|
||||
sigmsg->channel->chan_number,
|
||||
NULL,
|
||||
sigmsg->channel->chan_number,
|
||||
NULL,
|
||||
sigmsg->channel->caller_data.cid_name,
|
||||
sigmsg->channel->caller_data.cid_num,
|
||||
NULL,
|
||||
sigmsg->channel->caller_data.ani,
|
||||
sigmsg->channel->caller_data.aniII,
|
||||
sigmsg->channel->caller_data.rdnis,
|
||||
(char *) modname,
|
||||
SPAN_CONFIG[sigmsg->channel->span_id].context,
|
||||
sigmsg->channel->caller_data.dnis);
|
||||
|
|
|
@ -223,13 +223,28 @@ struct zap_event {
|
|||
#define ZAP_TOKEN_STRLEN 128
|
||||
#define ZAP_MAX_TOKENS 10
|
||||
|
||||
static __inline__ char *zap_clean_string(char *s)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = s; p && *p; p++) {
|
||||
uint8_t x = (uint8_t) *p;
|
||||
if (x < 32 || x > 127) {
|
||||
*p = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
struct zap_caller_data {
|
||||
char cid_name[80];
|
||||
char cid_num[80];
|
||||
char cid_date[8];
|
||||
char ani[25];
|
||||
char aniII[25];
|
||||
char dnis[25];
|
||||
char rdnis[25];
|
||||
};
|
||||
|
||||
struct zap_channel {
|
||||
|
@ -271,6 +286,8 @@ struct zap_channel {
|
|||
char chan_name[128];
|
||||
char chan_number[32];
|
||||
zap_filehandle_t fds[2];
|
||||
zap_fsk_data_state_t fsk;
|
||||
uint8_t fsk_buf[80];
|
||||
struct zap_caller_data caller_data;
|
||||
struct zap_span *span;
|
||||
struct zap_io_interface *zio;
|
||||
|
@ -343,7 +360,7 @@ struct zap_io_interface {
|
|||
zio_span_next_event_t next_event;
|
||||
};
|
||||
|
||||
zap_status_t zap_fsk_data_parse(zap_fsk_data_state_t *state, zap_size_t *type, zap_size_t *len, char *data, size_t datalen);
|
||||
zap_status_t zap_fsk_data_parse(zap_fsk_data_state_t *state, zap_size_t *type, char **data, zap_size_t *len);
|
||||
zap_status_t zap_fsk_demod_feed(zap_fsk_data_state_t *state, int16_t *data, size_t samples);
|
||||
zap_status_t zap_fsk_demod_destroy(zap_fsk_data_state_t *state);
|
||||
int zap_fsk_demod_init(zap_fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize);
|
||||
|
|
|
@ -63,14 +63,22 @@ struct zap_io_interface;
|
|||
|
||||
typedef uint64_t zap_time_t;
|
||||
|
||||
typedef enum {
|
||||
ZAP_CID_TYPE_SDMF = 0x04,
|
||||
ZAP_CID_TYPE_MDMF = 0x80
|
||||
} zap_cid_type_t;
|
||||
|
||||
typedef enum {
|
||||
MDMF_DATETIME = 1,
|
||||
MDMF_PHONE_NUM = 2,
|
||||
MDMF_DDN = 3,
|
||||
MDMF_NO_NUM = 4,
|
||||
MDMF_NAME = 7,
|
||||
MDMF_NO_NAME = 8
|
||||
MDMF_PHONE_NAME = 7,
|
||||
MDMF_NO_NAME = 8,
|
||||
MDMF_INVALID = 9
|
||||
} zap_mdmf_type_t;
|
||||
|
||||
#define MDMF_STRINGS "X", "DATETIME", "PHONE_NUM", "DDN", "NO_NUM", "X", "X", "PHONE_NAME", "NO_NAME", "INVALID"
|
||||
ZAP_STR2ENUM_P(zap_str2zap_mdmf_type, zap_mdmf_type2str, zap_mdmf_type_t)
|
||||
|
||||
struct zap_fsk_data_state {
|
||||
dsp_fsk_handle_t *fsk1200_handle;
|
||||
|
@ -216,6 +224,8 @@ typedef enum {
|
|||
ZAP_COMMAND_DISABLE_PROGRESS_DETECT,
|
||||
ZAP_COMMAND_TRACE_INPUT,
|
||||
ZAP_COMMAND_TRACE_OUTPUT,
|
||||
ZAP_COMMAND_ENABLE_CALLERID_DETECT,
|
||||
ZAP_COMMAND_DISABLE_CALLERID_DETECT,
|
||||
ZAP_COMMAND_COUNT
|
||||
} zap_command_t;
|
||||
|
||||
|
@ -236,7 +246,8 @@ typedef enum {
|
|||
typedef enum {
|
||||
ZAP_CHANNEL_FEATURE_DTMF = (1 << 0),
|
||||
ZAP_CHANNEL_FEATURE_CODECS = (1 << 1),
|
||||
ZAP_CHANNEL_FEATURE_INTERVAL = (1 << 2)
|
||||
ZAP_CHANNEL_FEATURE_INTERVAL = (1 << 2),
|
||||
ZAP_CHANNEL_FEATURE_CALLERID = (1 << 3)
|
||||
} zap_channel_feature_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -252,9 +263,11 @@ typedef enum {
|
|||
ZAP_CHANNEL_STATE_IDLE,
|
||||
ZAP_CHANNEL_STATE_GENRING,
|
||||
ZAP_CHANNEL_STATE_DIALING,
|
||||
ZAP_CHANNEL_STATE_GET_CALLERID,
|
||||
ZAP_CHANNEL_STATE_INVALID
|
||||
} zap_channel_state_t;
|
||||
#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", "RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "INVALID"
|
||||
#define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", \
|
||||
"RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "INVALID"
|
||||
ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t)
|
||||
|
||||
typedef enum {
|
||||
|
@ -274,7 +287,8 @@ typedef enum {
|
|||
ZAP_CHANNEL_INUSE = (1 << 13),
|
||||
ZAP_CHANNEL_OFFHOOK = (1 << 14),
|
||||
ZAP_CHANNEL_RINGING = (1 << 15),
|
||||
ZAP_CHANNEL_PROGRESS_DETECT = (1 << 16)
|
||||
ZAP_CHANNEL_PROGRESS_DETECT = (1 << 16),
|
||||
ZAP_CHANNEL_CALLERID_DETECT = (1 << 17)
|
||||
} zap_channel_flag_t;
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ int main(int argc, char *argv[])
|
|||
int16_t buf[160] = {0};
|
||||
ssize_t len = 0;
|
||||
int type, mlen;
|
||||
char str[128];
|
||||
char *sp;
|
||||
char str[128] = "";
|
||||
char fbuf[256];
|
||||
|
||||
if (argc < 2 || zap_fsk_demod_init(&state, 8000, fbuf, sizeof(fbuf))) {
|
||||
|
@ -26,10 +27,14 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
while(zap_fsk_data_parse(&state, &type, &mlen, str, sizeof(str)) == ZAP_SUCCESS) {
|
||||
printf("TYPE %d LEN %d VAL [%s]\n", type, mlen, str);
|
||||
while(zap_fsk_data_parse(&state, &type, &sp, &mlen) == ZAP_SUCCESS) {
|
||||
zap_copy_string(str, sp, mlen+1);
|
||||
*(str+mlen) = '\0';
|
||||
zap_clean_string(str);
|
||||
printf("TYPE %d (%s) LEN %d VAL [%s]\n", type, zap_mdmf_type2str(type), mlen, str);
|
||||
}
|
||||
|
||||
zap_fsk_demod_destroy(&state);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
|
|
@ -164,6 +164,13 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
|
||||
if (!zap_test_flag(chan, ZAP_CHANNEL_STATE_CHANGE)) {
|
||||
switch(chan->state) {
|
||||
case ZAP_CHANNEL_STATE_GET_CALLERID:
|
||||
{
|
||||
if (state_counter > 5000 || !zap_test_flag(chan, ZAP_CHANNEL_CALLERID_DETECT)) {
|
||||
zap_set_state_locked(chan, ZAP_CHANNEL_STATE_IDLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZAP_CHANNEL_STATE_DIALING:
|
||||
{
|
||||
if (state_counter > dial_timeout) {
|
||||
|
@ -199,14 +206,17 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case ZAP_CHANNEL_STATE_ATTN:
|
||||
{
|
||||
if (state_counter > 20000) {
|
||||
zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DOWN);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZAP_CHANNEL_STATE_HANGUP:
|
||||
{
|
||||
if (state_counter > 2000) {
|
||||
if (chan->type == ZAP_CHAN_TYPE_FXO) {
|
||||
zap_set_state_locked(chan, ZAP_CHANNEL_STATE_DOWN);
|
||||
} else {
|
||||
zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY);
|
||||
}
|
||||
if (state_counter > 1000) {
|
||||
zap_set_state_locked(chan, ZAP_CHANNEL_STATE_BUSY);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -230,6 +240,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE);
|
||||
indicate = 0;
|
||||
state_counter = 0;
|
||||
zap_log(ZAP_LOG_DEBUG, "Executing state handler for %s\n", zap_channel_state2str(chan->state));
|
||||
switch(chan->state) {
|
||||
case ZAP_CHANNEL_STATE_UP:
|
||||
{
|
||||
|
@ -264,7 +275,13 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
{
|
||||
zap_channel_use(chan);
|
||||
sig.event_id = ZAP_SIGEVENT_START;
|
||||
zap_copy_string(chan->caller_data.dnis, dtmf, sizeof(chan->caller_data.dnis));
|
||||
|
||||
if (chan->type == ZAP_CHAN_TYPE_FXO) {
|
||||
zap_set_string(chan->caller_data.dnis, chan->chan_number);
|
||||
} else {
|
||||
zap_set_string(chan->caller_data.dnis, dtmf);
|
||||
}
|
||||
|
||||
data->sig_cb(&sig);
|
||||
continue;
|
||||
}
|
||||
|
@ -292,12 +309,18 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
zap_channel_command(chan, ZAP_COMMAND_GENERATE_RING_ON, NULL);
|
||||
}
|
||||
break;
|
||||
case ZAP_CHANNEL_STATE_RING:
|
||||
case ZAP_CHANNEL_STATE_GET_CALLERID:
|
||||
{
|
||||
zap_channel_done(chan);
|
||||
zap_channel_command(chan, ZAP_COMMAND_ENABLE_CALLERID_DETECT, NULL);
|
||||
}
|
||||
break;
|
||||
case ZAP_CHANNEL_STATE_RING:
|
||||
{
|
||||
zap_buffer_zero(dt_buffer);
|
||||
teletone_run(&ts, chan->span->tone_map[ZAP_TONEMAP_RING]);
|
||||
indicate = 1;
|
||||
|
||||
}
|
||||
break;
|
||||
case ZAP_CHANNEL_STATE_BUSY:
|
||||
|
@ -317,7 +340,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
zap_channel_done(chan);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -393,8 +415,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
zap_channel_write(chan, frame, sizeof(frame), &rlen);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!indicate) {
|
||||
continue;
|
||||
}
|
||||
|
@ -408,7 +429,6 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
}
|
||||
|
||||
rlen = zap_buffer_read_loop(dt_buffer, frame, len);
|
||||
|
||||
|
||||
if (chan->effective_codec != ZAP_CODEC_SLIN) {
|
||||
zio_codec_t codec_func = NULL;
|
||||
|
@ -431,7 +451,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj)
|
|||
}
|
||||
|
||||
done:
|
||||
|
||||
zap_channel_done(chan);
|
||||
if (chan->type == ZAP_CHAN_TYPE_FXO && zap_test_flag(chan, ZAP_CHANNEL_OFFHOOK)) {
|
||||
zap_channel_command(chan, ZAP_COMMAND_ONHOOK, NULL);
|
||||
}
|
||||
|
@ -484,11 +504,7 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event)
|
|||
|
||||
if (event->channel->state == ZAP_CHANNEL_STATE_DOWN && !zap_test_flag(event->channel, ZAP_CHANNEL_INTHREAD)) {
|
||||
/*zap_channel_command(event->channel, ZAP_COMMAND_TRACE_INPUT, "/tmp/inbound.ul");*/
|
||||
sig.event_id = ZAP_SIGEVENT_START;
|
||||
zap_set_string(event->channel->caller_data.dnis, event->channel->chan_number);
|
||||
data->sig_cb(&sig);
|
||||
zap_channel_command(event->channel, ZAP_COMMAND_OFFHOOK, NULL);
|
||||
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_RING);
|
||||
zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_GET_CALLERID);
|
||||
zap_thread_create_detached(zap_analog_channel_run, event->channel);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,9 @@ ZAP_STR2ENUM(zap_str2zap_signal_event, zap_signal_event2str, zap_signal_event_t,
|
|||
ZAP_ENUM_NAMES(CHANNEL_STATE_NAMES, CHANNEL_STATE_STRINGS)
|
||||
ZAP_STR2ENUM(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t, CHANNEL_STATE_NAMES, ZAP_CHANNEL_STATE_INVALID)
|
||||
|
||||
ZAP_ENUM_NAMES(MDMF_TYPE_NAMES, MDMF_STRINGS)
|
||||
ZAP_STR2ENUM(zap_str2zap_mdmf_type, zap_mdmf_type2str, zap_mdmf_type_t, MDMF_TYPE_NAMES, MDMF_INVALID)
|
||||
|
||||
static char *cut_path(char *in)
|
||||
{
|
||||
char *p, *ret = in;
|
||||
|
@ -795,6 +798,26 @@ zap_status_t zap_channel_command(zap_channel_t *zchan, zap_command_t command, vo
|
|||
zap_mutex_lock(zchan->mutex);
|
||||
|
||||
switch(command) {
|
||||
|
||||
case ZAP_COMMAND_ENABLE_CALLERID_DETECT:
|
||||
{
|
||||
if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CALLERID)) {
|
||||
if (zap_fsk_demod_init(&zchan->fsk, zchan->rate, zchan->fsk_buf, sizeof(zchan->fsk_buf)) != ZAP_SUCCESS) {
|
||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
|
||||
GOTO_STATUS(done, ZAP_FAIL);
|
||||
}
|
||||
zap_set_flag_locked(zchan, ZAP_CHANNEL_CALLERID_DETECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_DISABLE_CALLERID_DETECT:
|
||||
{
|
||||
if (!zap_channel_test_feature(zchan, ZAP_CHANNEL_FEATURE_CALLERID)) {
|
||||
zap_fsk_demod_destroy(&zchan->fsk);
|
||||
zap_clear_flag_locked(zchan, ZAP_CHANNEL_CALLERID_DETECT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZAP_COMMAND_TRACE_INPUT:
|
||||
{
|
||||
char *path = (char *) obj;
|
||||
|
@ -1285,7 +1308,8 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data
|
|||
}
|
||||
}
|
||||
|
||||
if (zap_test_flag(zchan, ZAP_CHANNEL_DTMF_DETECT) || zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT)) {
|
||||
if (zap_test_flag(zchan, ZAP_CHANNEL_DTMF_DETECT) || zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT) ||
|
||||
zap_test_flag(zchan, ZAP_CHANNEL_CALLERID_DETECT)) {
|
||||
uint8_t sln_buf[1024] = {0};
|
||||
int16_t *sln;
|
||||
zap_size_t slen = 0;
|
||||
|
@ -1319,6 +1343,61 @@ zap_status_t zap_channel_read(zap_channel_t *zchan, void *data, zap_size_t *data
|
|||
slen = len;
|
||||
}
|
||||
|
||||
if (zap_test_flag(zchan, ZAP_CHANNEL_CALLERID_DETECT)) {
|
||||
if (zap_fsk_demod_feed(&zchan->fsk, sln, slen) != ZAP_SUCCESS) {
|
||||
uint32_t type, mlen;
|
||||
char str[128], *sp;
|
||||
|
||||
|
||||
while(zap_fsk_data_parse(&zchan->fsk, &type, &sp, &mlen) == ZAP_SUCCESS) {
|
||||
*(str+mlen) = '\0';
|
||||
zap_copy_string(str, sp, ++mlen);
|
||||
zap_clean_string(str);
|
||||
zap_log(ZAP_LOG_DEBUG, "FSK: TYPE %s LEN %d VAL [%s]\n", zap_mdmf_type2str(type), mlen-1, str);
|
||||
|
||||
switch(type) {
|
||||
case MDMF_DDN:
|
||||
case MDMF_PHONE_NUM:
|
||||
{
|
||||
if (mlen > sizeof(zchan->caller_data.ani)) {
|
||||
mlen = sizeof(zchan->caller_data.ani);
|
||||
}
|
||||
zap_set_string(zchan->caller_data.ani, str);
|
||||
zap_set_string(zchan->caller_data.cid_num, zchan->caller_data.ani);
|
||||
}
|
||||
break;
|
||||
case MDMF_NO_NUM:
|
||||
{
|
||||
zap_set_string(zchan->caller_data.ani, *str == 'P' ? "private" : "unknown");
|
||||
zap_set_string(zchan->caller_data.cid_name, zchan->caller_data.ani);
|
||||
}
|
||||
break;
|
||||
case MDMF_PHONE_NAME:
|
||||
{
|
||||
if (mlen > sizeof(zchan->caller_data.cid_name)) {
|
||||
mlen = sizeof(zchan->caller_data.cid_name);
|
||||
}
|
||||
zap_set_string(zchan->caller_data.cid_name, str);
|
||||
}
|
||||
break;
|
||||
case MDMF_NO_NAME:
|
||||
{
|
||||
zap_set_string(zchan->caller_data.cid_name, *str == 'P' ? "private" : "unknown");
|
||||
}
|
||||
case MDMF_DATETIME:
|
||||
{
|
||||
if (mlen > sizeof(zchan->caller_data.cid_date)) {
|
||||
mlen = sizeof(zchan->caller_data.cid_date);
|
||||
}
|
||||
zap_set_string(zchan->caller_data.cid_date, str);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
zap_channel_command(zchan, ZAP_COMMAND_DISABLE_CALLERID_DETECT, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (zap_test_flag(zchan, ZAP_CHANNEL_PROGRESS_DETECT)) {
|
||||
uint32_t i;
|
||||
|
||||
|
|
|
@ -358,12 +358,13 @@ static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start,
|
|||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RXHOOK;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
|
||||
#if 0
|
||||
if (type == ZAP_CHAN_TYPE_FXS) {
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type = WP_TDMAPI_EVENT_RING;
|
||||
tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_mode = WP_TDMAPI_EVENT_ENABLE;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
}
|
||||
#endif
|
||||
|
||||
tdm_api.wp_tdm_cmd.cmd = SIOC_WP_TDM_GET_HW_CODING;
|
||||
wp_tdm_cmd_exec(chan, &tdm_api);
|
||||
|
|
Loading…
Reference in New Issue