diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index c02c37ca85..56d66b3115 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -109,6 +109,19 @@ static skinny_profile_t *skinny_find_profile(const char *profile_name) return (skinny_profile_t *) switch_core_hash_find(globals.profile_hash, profile_name); } +static switch_status_t skinny_profile_find_listener_by_device_name(skinny_profile_t *profile, const char *device_name, listener_t **listener) +{ + switch_mutex_lock(profile->listener_mutex); + for (listener_t *l = profile->listeners; l; l = l->next) { + if (!strcmp(l->device_name, device_name)) { + *listener = l; + } + } + switch_mutex_unlock(profile->listener_mutex); + + return SWITCH_STATUS_SUCCESS; +} + struct skinny_profile_find_listener_helper { skinny_profile_t *profile; listener_t *listener; @@ -123,20 +136,15 @@ static int skinny_profile_find_listener_callback(void *pArg, int argc, char **ar /* uint32_t position = atoi(argv[1]); */ uint32_t relative_position = atoi(argv[2]); - switch_mutex_lock(profile->listener_mutex); - for (listener_t *l = profile->listeners; l; l = l->next) { - if (!strcmp(l->device_name, device_name)) { - helper->listener = l; - } - } - switch_mutex_unlock(profile->listener_mutex); + skinny_profile_find_listener_by_device_name(profile, device_name, &helper->listener); + if(helper->listener) { helper->line = relative_position; } return 0; } -static switch_status_t skinny_profile_find_listener(skinny_profile_t *profile, const char *dest, listener_t **l, uint32_t *line) +static switch_status_t skinny_profile_find_listener_by_dest(skinny_profile_t *profile, const char *dest, listener_t **l, uint32_t *line) { char *sql; struct skinny_profile_find_listener_helper helper = {0}; @@ -810,7 +818,7 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi switch_channel_set_name(channel, name); - if ((skinny_profile_find_listener(profile, dest, &listener, &line) != SWITCH_STATUS_SUCCESS)) { + if ((skinny_profile_find_listener_by_dest(profile, dest, &listener, &line) != SWITCH_STATUS_SUCCESS)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Problem while retrieving listener and line for destination %s in profile %s\n", dest, profile_name); cause = SWITCH_CAUSE_UNALLOCATED_NUMBER; goto error; @@ -1479,6 +1487,82 @@ static switch_status_t cmd_status_profile_device(const char *profile_name, const return SWITCH_STATUS_SUCCESS; } +static switch_status_t cmd_profile_device_send_ringer_message(const char *profile_name, const char *device_name, const char *ring_type, const char *ring_mode, switch_stream_handle_t *stream) +{ + skinny_profile_t *profile; + + if ((profile = skinny_find_profile(profile_name))) { + listener_t *listener = NULL; + skinny_profile_find_listener_by_device_name(profile, device_name, &listener); + if(listener) { + set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0); + } else { + stream->write_function(stream, "Listener not found!\n"); + } + } else { + stream->write_function(stream, "Profile not found!\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t cmd_profile_device_send_lamp_message(const char *profile_name, const char *device_name, const char *stimulus, const char *instance, const char *lamp_mode, switch_stream_handle_t *stream) +{ + skinny_profile_t *profile; + + if ((profile = skinny_find_profile(profile_name))) { + listener_t *listener = NULL; + skinny_profile_find_listener_by_device_name(profile, device_name, &listener); + if(listener) { + set_lamp(listener, skinny_str2stimulus(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode)); + } else { + stream->write_function(stream, "Listener not found!\n"); + } + } else { + stream->write_function(stream, "Profile not found!\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t cmd_profile_device_send_speaker_mode_message(const char *profile_name, const char *device_name, const char *speaker_mode, switch_stream_handle_t *stream) +{ + skinny_profile_t *profile; + + if ((profile = skinny_find_profile(profile_name))) { + listener_t *listener = NULL; + skinny_profile_find_listener_by_device_name(profile, device_name, &listener); + if(listener) { + set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode)); + } else { + stream->write_function(stream, "Listener not found!\n"); + } + } else { + stream->write_function(stream, "Profile not found!\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t cmd_profile_device_send_call_state_message(const char *profile_name, const char *device_name, const char *call_state, const char *line_instance, const char *call_id, switch_stream_handle_t *stream) +{ + skinny_profile_t *profile; + + if ((profile = skinny_find_profile(profile_name))) { + listener_t *listener = NULL; + skinny_profile_find_listener_by_device_name(profile, device_name, &listener); + if(listener) { + send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id)); + } else { + stream->write_function(stream, "Listener not found!\n"); + } + } else { + stream->write_function(stream, "Profile not found!\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + SWITCH_STANDARD_API(skinny_function) { char *argv[1024] = { 0 }; @@ -1490,6 +1574,10 @@ SWITCH_STANDARD_API(skinny_function) "skinny help\n" "skinny status profile \n" "skinny status profile device \n" + "skinny profile device send SetRingerMessage \n" + "skinny profile device send SetLampMessage \n" + "skinny profile device send SetSpeakerModeMessage \n" + "skinny profile device send CallState \n" "--------------------------------------------------------------------------------\n"; if (session) { return SWITCH_STATUS_FALSE; @@ -1510,13 +1598,27 @@ SWITCH_STANDARD_API(skinny_function) goto done; } - if (argc == 3 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile")) { - status = cmd_status_profile(argv[2], stream); - } else if (argc == 5 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile") && !strcasecmp(argv[3], "device")) { - status = cmd_status_profile_device(argv[2], argv[4], stream); - } else if (!strcasecmp(argv[0], "help")) { + if (!strcasecmp(argv[0], "help")) {/* skinny help */ stream->write_function(stream, "%s", usage_string); goto done; + } else if (argc == 3 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile")) { + /* skinny status profile */ + status = cmd_status_profile(argv[2], stream); + } else if (argc == 5 && !strcasecmp(argv[0], "status") && !strcasecmp(argv[1], "profile") && !strcasecmp(argv[3], "device")) { + /* skinny status profile device */ + status = cmd_status_profile_device(argv[2], argv[4], stream); + } else if (argc == 8 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "device") && !strcasecmp(argv[4], "send") && !strcasecmp(argv[5], "SetRingerMessage")) { + /* skinny profile device send SetRingerMessage */ + status = cmd_profile_device_send_ringer_message(argv[1], argv[3], argv[6], argv[7], stream); + } else if (argc == 9 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "device") && !strcasecmp(argv[4], "send") && !strcasecmp(argv[5], "SetLampMessage")) { + /* skinny profile device send SetLampMessage */ + status = cmd_profile_device_send_lamp_message(argv[1], argv[3], argv[6], argv[7], argv[8], stream); + } else if (argc == 7 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "device") && !strcasecmp(argv[4], "send") && !strcasecmp(argv[5], "SetSpeakerModeMessage")) { + /* skinny profile device send SetSpeakerModeMessage */ + status = cmd_profile_device_send_speaker_mode_message(argv[1], argv[3], argv[6], stream); + } else if (argc == 9 && !strcasecmp(argv[0], "profile") && !strcasecmp(argv[2], "device") && !strcasecmp(argv[4], "send") && !strcasecmp(argv[5], "CallState")) { + /* skinny profile device send CallState */ + status = cmd_profile_device_send_call_state_message(argv[1], argv[3], argv[6], argv[7], argv[8], stream); } else { stream->write_function(stream, "Unknown Command [%s]\n", argv[0]); } @@ -1574,7 +1676,7 @@ static switch_status_t skinny_list_devices(const char *line, const char *cursor, { struct match_helper h = { 0 }; switch_status_t status = SWITCH_STATUS_FALSE; - skinny_profile_t *profile; + skinny_profile_t *profile = NULL; char *sql; char *myline; @@ -1589,7 +1691,13 @@ static switch_status_t skinny_list_devices(const char *line, const char *cursor, return status; } - if((profile = skinny_find_profile(argv[3]))) { + if(!strcasecmp(argv[1], "profile")) {/* skinny profile ... */ + profile = skinny_find_profile(argv[2]); + } else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile ... */ + profile = skinny_find_profile(argv[3]); + } + + if(profile) { if ((sql = switch_mprintf("SELECT name FROM skinny_devices"))) { skinny_execute_sql_callback(profile, profile->listener_mutex, sql, skinny_list_devices_callback, &h); switch_safe_free(sql); @@ -1604,6 +1712,96 @@ static switch_status_t skinny_list_devices(const char *line, const char *cursor, return status; } +static switch_status_t skinny_list_stimuli(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + SKINNY_PUSH_STIMULI + return status; +} + +static switch_status_t skinny_list_ring_type(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + SKINNY_PUSH_RING_TYPES + return status; +} + +static switch_status_t skinny_list_ring_mode(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + SKINNY_PUSH_RING_MODES + return status; +} + +static switch_status_t skinny_list_stimulus_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + switch_console_callback_match_t *my_matches = NULL; + + switch_console_push_match(&my_matches, ""); + switch_console_push_match(&my_matches, "0"); + + if (my_matches) { + *matches = my_matches; + status = SWITCH_STATUS_SUCCESS; + } + return status; +} + +static switch_status_t skinny_list_stimulus_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + SKINNY_PUSH_LAMP_MODES + return status; +} + +static switch_status_t skinny_list_speaker_mode(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + SKINNY_PUSH_SPEAKER_MODES + return status; +} + +static switch_status_t skinny_list_call_states(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + SKINNY_PUSH_CALL_STATES + return status; +} + +static switch_status_t skinny_list_line_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + switch_console_callback_match_t *my_matches = NULL; + + /* TODO */ + switch_console_push_match(&my_matches, "1"); + switch_console_push_match(&my_matches, ""); + + if (my_matches) { + *matches = my_matches; + status = SWITCH_STATUS_SUCCESS; + } + return status; +} + +static switch_status_t skinny_list_call_ids(const char *line, const char *cursor, switch_console_callback_match_t **matches) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + switch_console_callback_match_t *my_matches = NULL; + + /* TODO */ + switch_console_push_match(&my_matches, "1345"); + switch_console_push_match(&my_matches, ""); + + if (my_matches) { + *matches = my_matches; + status = SWITCH_STATUS_SUCCESS; + } + return status; +} + +/*****************************************************************************/ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) { switch_hash_index_t *hi; @@ -1646,11 +1844,27 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) SWITCH_ADD_API(api_interface, "skinny", "Skinny Controls", skinny_function, " "); switch_console_set_complete("add skinny help"); + switch_console_set_complete("add skinny status profile ::skinny::list_profiles"); switch_console_set_complete("add skinny status profile ::skinny::list_profiles device ::skinny::list_devices"); + switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetRingerMessage ::skinny::list_ring_type ::skinny::list_ring_mode"); + switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetLampMessage ::skinny::list_stimuli ::skinny::list_stimulus_instances ::skinny::list_stimulus_modes"); + switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send SetSpeakerModeMessage ::skinny::list_speaker_mode"); + switch_console_set_complete("add skinny profile ::skinny::list_profiles device ::skinny::list_devices send CallState ::skinny::list_call_states ::skinny::list_line_instances ::skinny::list_call_ids"); + switch_console_add_complete_func("::skinny::list_profiles", skinny_list_profiles); switch_console_add_complete_func("::skinny::list_devices", skinny_list_devices); + switch_console_add_complete_func("::skinny::list_ring_type", skinny_list_ring_type); + switch_console_add_complete_func("::skinny::list_ring_mode", skinny_list_ring_mode); + switch_console_add_complete_func("::skinny::list_stimuli", skinny_list_stimuli); + switch_console_add_complete_func("::skinny::list_stimulus_instances", skinny_list_stimulus_instances); + switch_console_add_complete_func("::skinny::list_stimulus_modes", skinny_list_stimulus_modes); + switch_console_add_complete_func("::skinny::list_speaker_mode", skinny_list_speaker_mode); + switch_console_add_complete_func("::skinny::list_call_states", skinny_list_call_states); + switch_console_add_complete_func("::skinny::list_line_instances", skinny_list_line_instances); + switch_console_add_complete_func("::skinny::list_call_ids", skinny_list_call_ids); + /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index 09924d2be8..1318481103 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -35,12 +35,31 @@ skinny_globals_t globals; -struct skinny_message_type_table { - const char *name; - uint32_t type; +struct soft_key_template_definition soft_key_template_default[] = { + { "\200\001", SOFTKEY_REDIAL }, + { "\200\002", SOFTKEY_NEWCALL }, + { "\200\003", SOFTKEY_HOLD }, + { "\200\004", SOFTKEY_TRANSFER }, + { "\200\005", SOFTKEY_CFWDALL }, + { "\200\006", SOFTKEY_CFWDBUSY }, + { "\200\007", SOFTKEY_CFWDNOANSWER }, + { "\200\010", SOFTKEY_BACKSPACE }, + { "\200\011", SOFTKEY_ENDCALL }, + { "\200\012", SOFTKEY_RESUME }, + { "\200\013", SOFTKEY_ANSWER }, + { "\200\014", SOFTKEY_INFO }, + { "\200\015", SOFTKEY_CONFRM }, + { "\200\016", SOFTKEY_PARK }, + { "\200\017", SOFTKEY_JOIN }, + { "\200\020", SOFTKEY_MEETMECONFRM }, + { "\200\021", SOFTKEY_CALLPICKUP }, + { "\200\022", SOFTKEY_GRPCALLPICKUP }, + { "\200\077", SOFTKEY_DND }, + { "\200\120", SOFTKEY_IDIVERT }, }; -static struct skinny_message_type_table SKINNY_MESSAGE_TYPES[] = { +/* Translation tables */ +struct skinny_table SKINNY_MESSAGE_TYPES[] = { {"KEEP_ALIVE_MESSAGE", KEEP_ALIVE_MESSAGE}, {"REGISTER_MESSAGE", REGISTER_MESSAGE}, {"PORT_MESSAGE", PORT_MESSAGE}, @@ -94,119 +113,94 @@ static struct skinny_message_type_table SKINNY_MESSAGE_TYPES[] = { {"SKINNY_MESSAGE_MAXSIZE", SKINNY_MESSAGE_MAXSIZE}, {NULL, 0} }; +SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UNKNOWN_MESSAGE") +SKINNY_DECLARE_STR2ID(skinny_str2message_type, SKINNY_MESSAGE_TYPES, -1) -struct soft_key_template_definition soft_key_template_default[] = { - { "\200\001", SOFTKEY_REDIAL }, - { "\200\002", SOFTKEY_NEWCALL }, - { "\200\003", SOFTKEY_HOLD }, - { "\200\004", SOFTKEY_TRANSFER }, - { "\200\005", SOFTKEY_CFWDALL }, - { "\200\006", SOFTKEY_CFWDBUSY }, - { "\200\007", SOFTKEY_CFWDNOANSWER }, - { "\200\010", SOFTKEY_BACKSPACE }, - { "\200\011", SOFTKEY_ENDCALL }, - { "\200\012", SOFTKEY_RESUME }, - { "\200\013", SOFTKEY_ANSWER }, - { "\200\014", SOFTKEY_INFO }, - { "\200\015", SOFTKEY_CONFRM }, - { "\200\016", SOFTKEY_PARK }, - { "\200\017", SOFTKEY_JOIN }, - { "\200\020", SOFTKEY_MEETMECONFRM }, - { "\200\021", SOFTKEY_CALLPICKUP }, - { "\200\022", SOFTKEY_GRPCALLPICKUP }, - { "\200\077", SOFTKEY_DND }, - { "\200\120", SOFTKEY_IDIVERT }, -}; - -struct skinny_key_set_table { - const char *name; - uint32_t id; -}; - -static struct skinny_key_set_table SKINNY_KEY_SETS[] = { - {"SKINNY_KEY_SET_ON_HOOK", 0}, - {"SKINNY_KEY_SET_CONNECTED", 1}, - {"SKINNY_KEY_SET_ON_HOLD", 2}, - {"SKINNY_KEY_SET_RING_IN", 3}, - {"SKINNY_KEY_SET_OFF_HOOK", 4}, - {"SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER", 5}, - {"SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT", 6}, - {"SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE", 7}, - {"SKINNY_KEY_SET_RING_OUT", 8}, - {"SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES", 9}, +struct skinny_table SKINNY_RING_TYPES[] = { + {"RingOff", SKINNY_RING_OFF}, + {"RingInside", SKINNY_RING_INSIDE}, + {"RingOutside", SKINNY_RING_OUTSIDE}, + {"RingFeature", SKINNY_RING_FEATURE}, {NULL, 0} }; +SKINNY_DECLARE_ID2STR(skinny_ring_type2str, SKINNY_RING_TYPES, "RingTypeUnknown") +SKINNY_DECLARE_STR2ID(skinny_str2ring_type, SKINNY_RING_TYPES, -1) +struct skinny_table SKINNY_RING_MODES[] = { + {"RingForever", SKINNY_RING_FOREVER}, + {"RingOnce", SKINNY_RING_ONCE}, + {NULL, 0} +}; +SKINNY_DECLARE_ID2STR(skinny_ring_mode2str, SKINNY_RING_MODES, "RingModeUnknown") +SKINNY_DECLARE_STR2ID(skinny_str2ring_mode, SKINNY_RING_MODES, -1) + +struct skinny_table SKINNY_STIMULI[] = { + {"LastNumberRedial", SKINNY_BUTTON_LAST_NUMBER_REDIAL}, + {"SpeedDial", SKINNY_BUTTON_SPEED_DIAL}, + {"Line", SKINNY_BUTTON_LINE}, + {"Voicemail", SKINNY_BUTTON_VOICEMAIL}, + {"Undefined", SKINNY_BUTTON_UNDEFINED}, + {NULL, 0} +}; +SKINNY_DECLARE_ID2STR(skinny_stimulus2str, SKINNY_STIMULI, "Unknown") +SKINNY_DECLARE_STR2ID(skinny_str2stimulus, SKINNY_STIMULI, -1) + +struct skinny_table SKINNY_LAMP_MODES[] = { + {"Off", SKINNY_LAMP_OFF}, + {"On", SKINNY_LAMP_ON}, + {"Wink", SKINNY_LAMP_WINK}, + {"Flash", SKINNY_LAMP_FLASH}, + {"Blink", SKINNY_LAMP_BLINK}, + {NULL, 0} +}; +SKINNY_DECLARE_ID2STR(skinny_lamp_mode2str, SKINNY_LAMP_MODES, "Unknown") +SKINNY_DECLARE_STR2ID(skinny_str2lamp_mode, SKINNY_LAMP_MODES, -1) + +struct skinny_table SKINNY_SPEAKER_MODES[] = { + {"SpeakerOn", SKINNY_SPEAKER_ON}, + {"SpeakerOff", SKINNY_SPEAKER_OFF}, + {NULL, 0} +}; +SKINNY_DECLARE_ID2STR(skinny_speaker_mode2str, SKINNY_SPEAKER_MODES, "Unknown") +SKINNY_DECLARE_STR2ID(skinny_str2speaker_mode, SKINNY_SPEAKER_MODES, -1) + +struct skinny_table SKINNY_KEY_SETS[] = { + {"KeySetOnHook", SKINNY_KEY_SET_ON_HOOK}, + {"KeySetConnected", SKINNY_KEY_SET_CONNECTED}, + {"KeySetOnHold", SKINNY_KEY_SET_ON_HOLD}, + {"KeySetRingIn", SKINNY_KEY_SET_RING_IN}, + {"KeySetOffHook", SKINNY_KEY_SET_OFF_HOOK}, + {"KeySetConnectedWithTransfer", SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER}, + {"KeySetDigitsAfterDialingFirstDigit", SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT}, + {"KeySetConnectedWithConference", SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE}, + {"KeySetRingOut", SKINNY_KEY_SET_RING_OUT}, + {"KeySetOffHookWithFeatures", SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES}, + {NULL, 0} +}; +SKINNY_DECLARE_ID2STR(skinny_soft_key_set2str, SKINNY_KEY_SETS, "UNKNOWN_SOFT_KEY_SET") +SKINNY_DECLARE_STR2ID(skinny_str2soft_key_set, SKINNY_KEY_SETS, -1) + +struct skinny_table SKINNY_CALL_STATES[] = { + {"OffHook", SKINNY_OFF_HOOK}, + {"OnHook", SKINNY_ON_HOOK}, + {"RingOut", SKINNY_RING_OUT}, + {"RingIn", SKINNY_RING_IN}, + {"Connected", SKINNY_CONNECTED}, + {"Busy", SKINNY_BUSY}, + {"Congestion", SKINNY_CONGESTION}, + {"Hold", SKINNY_HOLD}, + {"CallWaiting", SKINNY_CALL_WAITING}, + {"CallTransfer", SKINNY_CALL_TRANSFER}, + {"CallPark", SKINNY_CALL_PARK}, + {"Proceed", SKINNY_PROCEED}, + {"CallRemoteMultiline", SKINNY_CALL_REMOTE_MULTILINE}, + {"InvalidNumber", SKINNY_INVALID_NUMBER}, + {NULL, 0} +}; +SKINNY_DECLARE_ID2STR(skinny_call_state2str, SKINNY_CALL_STATES, "CallStateUnknown") +SKINNY_DECLARE_STR2ID(skinny_str2call_state, SKINNY_CALL_STATES, -1) /*****************************************************************************/ /* SKINNY FUNCTIONS */ -/*****************************************************************************/ -const char *skinny_message_type2str(uint32_t type) -{ - uint8_t x; - const char *str = "UNKNOWN_MESSAGE"; - - for (x = 0; x < (sizeof(SKINNY_MESSAGE_TYPES) / sizeof(struct skinny_message_type_table)) - 1; x++) { - if (SKINNY_MESSAGE_TYPES[x].type == type) { - str = SKINNY_MESSAGE_TYPES[x].name; - break; - } - } - - return str; -} - -uint32_t skinny_str2message_type(const char *str) -{ - uint8_t x; - uint32_t type = -1; - - if (*str > 47 && *str < 58) { - type = atoi(str); - } else { - for (x = 0; x < (sizeof(SKINNY_MESSAGE_TYPES) / sizeof(struct skinny_message_type_table)) - 1 && SKINNY_MESSAGE_TYPES[x].name; x++) { - if (!strcasecmp(SKINNY_MESSAGE_TYPES[x].name, str)) { - type = SKINNY_MESSAGE_TYPES[x].type; - break; - } - } - } - return type; -} - -/*****************************************************************************/ -const char *skinny_soft_key_set2str(uint32_t id) -{ - uint8_t x; - const char *str = "UNKNOWN_SOFT_KEY_SET"; - - for (x = 0; x < (sizeof(SKINNY_KEY_SETS) / sizeof(struct skinny_key_set_table)) - 1; x++) { - if (SKINNY_KEY_SETS[x].id == id) { - str = SKINNY_KEY_SETS[x].name; - break; - } - } - - return str; -} - -uint32_t skinny_str2soft_key_set(const char *str) -{ - uint8_t x; - uint32_t id = -1; - - if (*str > 47 && *str < 58) { - id = atoi(str); - } else { - for (x = 0; x < (sizeof(SKINNY_KEY_SETS) / sizeof(struct skinny_key_set_table)) - 1 && SKINNY_KEY_SETS[x].name; x++) { - if (!strcasecmp(SKINNY_KEY_SETS[x].name, str)) { - id = SKINNY_KEY_SETS[x].id; - break; - } - } - } - return id; -} - /*****************************************************************************/ char* skinny_codec2string(enum skinny_codecs skinnycodec) { @@ -644,7 +638,7 @@ int skinny_line_get_callback(void *pArg, int argc, char **argv, char **columnNam helper->button->number = helper->pos; strncpy(helper->button->name, argv[2], 24); /* label */ strncpy(helper->button->shortname, argv[3], 40); /* value */ - strncpy(helper->button->displayname, argv[2], 44); /* settings */ + strncpy(helper->button->displayname, argv[4], 44); /* settings */ } return 0; } @@ -1567,6 +1561,9 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn } /* Close/Hold busy lines */ for(int i = 0 ; i < SKINNY_MAX_BUTTON_COUNT ; i++) { + if(i == line) { + continue; + } if(listener->session[i]) { channel = switch_core_session_get_channel(listener->session[i]); assert(channel != NULL); @@ -1610,6 +1607,9 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn skinny_unhold_line(listener, line); } switch(request->data.soft_key_event.event) { + case SOFTKEY_ANSWER: + skinny_answer(listener->session[line]); + break; case SOFTKEY_ENDCALL: channel = switch_core_session_get_channel(listener->session[line]); assert(channel != NULL); diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index 60f1b9d6a3..8668a1d626 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -190,16 +190,6 @@ struct start_tone_message { uint32_t call_id; }; -enum skinny_tone { - SKINNY_TONE_SILENCE = 0x00, - SKINNY_TONE_DIALTONE = 0x21, - SKINNY_TONE_BUSYTONE = 0x23, - SKINNY_TONE_ALERT = 0x24, - SKINNY_TONE_REORDER = 0x25, - SKINNY_TONE_CALLWAITTONE = 0x2D, - SKINNY_TONE_NOTONE = 0x7F, -}; - /* StopToneMessage */ #define STOP_TONE_MESSAGE 0x0083 struct stop_tone_message { @@ -215,18 +205,6 @@ struct set_ringer_message { uint32_t unknown; /* ?? */ }; -enum skinny_ring_type { - SKINNY_RING_OFF = 1, - SKINNY_RING_INSIDE = 2, - SKINNY_RING_OUTSIDE = 3, - SKINNY_RING_FEATURE = 4 -}; - -enum skinny_ring_mode { - SKINNY_RING_FOREVER = 1, - SKINNY_RING_ONCE = 2, -}; - /* SetLampMessage */ #define SET_LAMP_MESSAGE 0x0086 struct set_lamp_message { @@ -235,25 +213,12 @@ struct set_lamp_message { uint32_t mode; /* See enum skinny_lamp_mode */ }; -enum skinny_lamp_mode { - SKINNY_LAMP_OFF = 1, - SKINNY_LAMP_ON = 2, - SKINNY_LAMP_WINK = 3, - SKINNY_LAMP_FLASH = 4, - SKINNY_LAMP_BLINK = 5, -}; - /* SetSpeakerModeMessage */ #define SET_SPEAKER_MODE_MESSAGE 0x0088 struct set_speaker_mode_message { uint32_t mode; /* See enum skinny_speaker_mode */ }; -enum skinny_speaker_mode { - SKINNY_SPEAKER_ON = 1, - SKINNY_SPEAKER_OFF = 2, -}; - /* StartMediaTransmissionMessage */ #define START_MEDIA_TRANSMISSION_MESSAGE 0x008A struct start_media_transmission_message { @@ -304,12 +269,6 @@ struct call_info_message { uint32_t party_pi_restriction_bits; }; -enum skinny_call_type { - SKINNY_INBOUND_CALL = 1, - SKINNY_OUTBOUND_CALL = 2, - SKINNY_FORWARD_CALL = 3, -}; - /* SpeedDialStatMessage */ #define SPEED_DIAL_STAT_RES_MESSAGE 0x0091 struct speed_dial_stat_res_message { @@ -360,14 +319,6 @@ struct button_definition { uint8_t button_definition; /* See enum skinny_button_definition */ }; -enum skinny_button_definition { - SKINNY_BUTTON_LAST_NUMBER_REDIAL = 0x01, - SKINNY_BUTTON_SPEED_DIAL = 0x02, - SKINNY_BUTTON_LINE = 0x09, - SKINNY_BUTTON_VOICEMAIL = 0x0F, - SKINNY_BUTTON_UNDEFINED = 0xFF, -}; - #define SKINNY_MAX_BUTTON_COUNT 42 struct button_template_message { uint32_t button_offset; @@ -424,29 +375,6 @@ struct soft_key_template_res_message { struct soft_key_template_definition soft_key[32]; }; -enum skinny_soft_key_event { - SOFTKEY_REDIAL = 0x01, - SOFTKEY_NEWCALL = 0x02, - SOFTKEY_HOLD = 0x03, - SOFTKEY_TRANSFER = 0x04, - SOFTKEY_CFWDALL = 0x05, - SOFTKEY_CFWDBUSY = 0x06, - SOFTKEY_CFWDNOANSWER = 0x07, - SOFTKEY_BACKSPACE = 0x08, - SOFTKEY_ENDCALL = 0x09, - SOFTKEY_RESUME = 0x0A, - SOFTKEY_ANSWER = 0x0B, - SOFTKEY_INFO = 0x0C, - SOFTKEY_CONFRM = 0x0D, - SOFTKEY_PARK = 0x0E, - SOFTKEY_JOIN = 0x0F, - SOFTKEY_MEETMECONFRM = 0x10, - SOFTKEY_CALLPICKUP = 0x11, - SOFTKEY_GRPCALLPICKUP = 0x12, - SOFTKEY_DND = 0x13, - SOFTKEY_IDIVERT = 0x14, -}; - /* SoftKeySetResMessage */ #define SOFT_KEY_SET_RES_MESSAGE 0x0109 struct soft_key_set_definition { @@ -471,19 +399,6 @@ struct select_soft_keys_message { uint32_t valid_key_mask; }; -enum skinny_key_set { - SKINNY_KEY_SET_ON_HOOK = 0, - SKINNY_KEY_SET_CONNECTED = 1, - SKINNY_KEY_SET_ON_HOLD = 2, - SKINNY_KEY_SET_RING_IN = 3, - SKINNY_KEY_SET_OFF_HOOK = 4, - SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER = 5, - SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT = 6, - SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE = 7, - SKINNY_KEY_SET_RING_OUT = 8, - SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES = 9, -}; - /* CallStateMessage */ #define CALL_STATE_MESSAGE 0x0111 struct call_state_message { @@ -492,23 +407,6 @@ struct call_state_message { uint32_t call_id; }; -enum skinny_call_state { - SKINNY_OFF_HOOK = 1, - SKINNY_ON_HOOK = 2, - SKINNY_RING_OUT = 3, - SKINNY_RING_IN = 4, - SKINNY_CONNECTED = 5, - SKINNY_BUSY = 6, - SKINNY_CONGESTION = 7, - SKINNY_HOLD = 8, - SKINNY_CALL_WAITING = 9, - SKINNY_CALL_TRANSFER = 10, - SKINNY_CALL_PARK = 11, - SKINNY_PROCEED = 12, - SKINNY_CALL_REMOTE_MULTILINE = 13, - SKINNY_INVALID_NUMBER = 14 -}; - /* DisplayPromptStatusMessage */ #define DISPLAY_PROMPT_STATUS_MESSAGE 0x0112 struct display_prompt_status_message { @@ -645,6 +543,194 @@ enum skinny_codecs { typedef switch_status_t (*skinny_command_t) (char **argv, int argc, switch_stream_handle_t *stream); +/*****************************************************************************/ +/* SKINNY TABLES */ +/*****************************************************************************/ +struct skinny_table { + const char *name; + uint32_t id; +}; + +#define SKINNY_DECLARE_ID2STR(func, TABLE, DEFAULT_STR) \ +const char *func(uint32_t id) \ +{ \ + const char *str = DEFAULT_STR; \ + \ + for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1; x++) {\ + if (TABLE[x].id == id) {\ + str = TABLE[x].name;\ + break;\ + }\ + }\ + \ + return str;\ +} + +#define SKINNY_DECLARE_STR2ID(func, TABLE, DEFAULT_ID) \ +uint32_t func(const char *str)\ +{\ + uint32_t id = DEFAULT_ID;\ + \ + if (*str > 47 && *str < 58) {\ + id = atoi(str);\ + } else {\ + for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1 && TABLE[x].name; x++) {\ + if (!strcasecmp(TABLE[x].name, str)) {\ + id = TABLE[x].id;\ + break;\ + }\ + }\ + }\ + return id;\ +} + +#define SKINNY_DECLARE_PUSH_MATCH(TABLE) \ + switch_console_callback_match_t *my_matches = NULL;\ + for (uint8_t x = 0; x < (sizeof(TABLE) / sizeof(struct skinny_table)) - 1; x++) {\ + switch_console_push_match(&my_matches, TABLE[x].name);\ + }\ + if (my_matches) {\ + *matches = my_matches;\ + status = SWITCH_STATUS_SUCCESS;\ + } + +struct skinny_table SKINNY_MESSAGE_TYPES[52]; +const char *skinny_message_type2str(uint32_t id); +uint32_t skinny_str2message_type(const char *str); +#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES) + +enum skinny_tone { + SKINNY_TONE_SILENCE = 0x00, + SKINNY_TONE_DIALTONE = 0x21, + SKINNY_TONE_BUSYTONE = 0x23, + SKINNY_TONE_ALERT = 0x24, + SKINNY_TONE_REORDER = 0x25, + SKINNY_TONE_CALLWAITTONE = 0x2D, + SKINNY_TONE_NOTONE = 0x7F, +}; + +enum skinny_ring_type { + SKINNY_RING_OFF = 1, + SKINNY_RING_INSIDE = 2, + SKINNY_RING_OUTSIDE = 3, + SKINNY_RING_FEATURE = 4 +}; +struct skinny_table SKINNY_RING_TYPES[5]; +const char *skinny_ring_type2str(uint32_t id); +uint32_t skinny_str2ring_type(const char *str); +#define SKINNY_PUSH_RING_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_RING_TYPES) + +enum skinny_ring_mode { + SKINNY_RING_FOREVER = 1, + SKINNY_RING_ONCE = 2, +}; +struct skinny_table SKINNY_RING_MODES[3]; +const char *skinny_ring_mode2str(uint32_t id); +uint32_t skinny_str2ring_mode(const char *str); +#define SKINNY_PUSH_RING_MODES SKINNY_DECLARE_PUSH_MATCH(SKINNY_RING_MODES) + + +enum skinny_lamp_mode { + SKINNY_LAMP_OFF = 1, + SKINNY_LAMP_ON = 2, + SKINNY_LAMP_WINK = 3, + SKINNY_LAMP_FLASH = 4, + SKINNY_LAMP_BLINK = 5, +}; +struct skinny_table SKINNY_LAMP_MODES[6]; +const char *skinny_lamp_mode2str(uint32_t id); +uint32_t skinny_str2lamp_mode(const char *str); +#define SKINNY_PUSH_LAMP_MODES SKINNY_DECLARE_PUSH_MATCH(SKINNY_LAMP_MODES) + +enum skinny_speaker_mode { + SKINNY_SPEAKER_ON = 1, + SKINNY_SPEAKER_OFF = 2, +}; +struct skinny_table SKINNY_SPEAKER_MODES[3]; +const char *skinny_speaker_mode2str(uint32_t id); +uint32_t skinny_str2speaker_mode(const char *str); +#define SKINNY_PUSH_SPEAKER_MODES SKINNY_DECLARE_PUSH_MATCH(SKINNY_SPEAKER_MODES) + +enum skinny_call_type { + SKINNY_INBOUND_CALL = 1, + SKINNY_OUTBOUND_CALL = 2, + SKINNY_FORWARD_CALL = 3, +}; + +enum skinny_button_definition { + SKINNY_BUTTON_LAST_NUMBER_REDIAL = 0x01, + SKINNY_BUTTON_SPEED_DIAL = 0x02, + SKINNY_BUTTON_LINE = 0x09, + SKINNY_BUTTON_VOICEMAIL = 0x0F, + SKINNY_BUTTON_UNDEFINED = 0xFF, +}; +struct skinny_table SKINNY_STIMULI[6]; +const char *skinny_stimulus2str(uint32_t id); +uint32_t skinny_str2stimulus(const char *str); +#define SKINNY_PUSH_STIMULI SKINNY_DECLARE_PUSH_MATCH(SKINNY_STIMULI) + +enum skinny_soft_key_event { + SOFTKEY_REDIAL = 0x01, + SOFTKEY_NEWCALL = 0x02, + SOFTKEY_HOLD = 0x03, + SOFTKEY_TRANSFER = 0x04, + SOFTKEY_CFWDALL = 0x05, + SOFTKEY_CFWDBUSY = 0x06, + SOFTKEY_CFWDNOANSWER = 0x07, + SOFTKEY_BACKSPACE = 0x08, + SOFTKEY_ENDCALL = 0x09, + SOFTKEY_RESUME = 0x0A, + SOFTKEY_ANSWER = 0x0B, + SOFTKEY_INFO = 0x0C, + SOFTKEY_CONFRM = 0x0D, + SOFTKEY_PARK = 0x0E, + SOFTKEY_JOIN = 0x0F, + SOFTKEY_MEETMECONFRM = 0x10, + SOFTKEY_CALLPICKUP = 0x11, + SOFTKEY_GRPCALLPICKUP = 0x12, + SOFTKEY_DND = 0x13, + SOFTKEY_IDIVERT = 0x14, +}; + +enum skinny_key_set { + SKINNY_KEY_SET_ON_HOOK = 0, + SKINNY_KEY_SET_CONNECTED = 1, + SKINNY_KEY_SET_ON_HOLD = 2, + SKINNY_KEY_SET_RING_IN = 3, + SKINNY_KEY_SET_OFF_HOOK = 4, + SKINNY_KEY_SET_CONNECTED_WITH_TRANSFER = 5, + SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT = 6, + SKINNY_KEY_SET_CONNECTED_WITH_CONFERENCE = 7, + SKINNY_KEY_SET_RING_OUT = 8, + SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES = 9, +}; +struct skinny_table SKINNY_KEY_SETS[11]; +const char *skinny_soft_key_set2str(uint32_t id); +uint32_t skinny_str2soft_key_set(const char *str); +#define SKINNY_PUSH_SOFT_KEY_SETS SKINNY_DECLARE_PUSH_MATCH(SKINNY_KEY_SETS) + + +enum skinny_call_state { + SKINNY_OFF_HOOK = 1, + SKINNY_ON_HOOK = 2, + SKINNY_RING_OUT = 3, + SKINNY_RING_IN = 4, + SKINNY_CONNECTED = 5, + SKINNY_BUSY = 6, + SKINNY_CONGESTION = 7, + SKINNY_HOLD = 8, + SKINNY_CALL_WAITING = 9, + SKINNY_CALL_TRANSFER = 10, + SKINNY_CALL_PARK = 11, + SKINNY_PROCEED = 12, + SKINNY_CALL_REMOTE_MULTILINE = 13, + SKINNY_INVALID_NUMBER = 14 +}; +struct skinny_table SKINNY_CALL_STATES[15]; +const char *skinny_call_state2str(uint32_t id); +uint32_t skinny_str2call_state(const char *str); +#define SKINNY_PUSH_CALL_STATES SKINNY_DECLARE_PUSH_MATCH(SKINNY_CALL_STATES) + /*****************************************************************************/ /* SKINNY FUNCTIONS */ /*****************************************************************************/ @@ -654,13 +740,6 @@ typedef switch_status_t (*skinny_command_t) (char **argv, int argc, switch_strea return SWITCH_STATUS_FALSE;\ } - -const char *skinny_message_type2str(uint32_t type); -uint32_t skinny_str2message_type(const char *str); - -const char *skinny_soft_key_set2str(uint32_t id); -uint32_t skinny_str2soft_key_set(const char *str); - switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req); switch_status_t skinny_device_event(listener_t *listener, switch_event_t **ev, switch_event_types_t event_id, const char *subclass_name);