mirror of git://git.sysmocom.de/ofono
isimodem: implement SSN handling
This commit is contained in:
parent
0f147e1cd5
commit
912b128b97
|
@ -739,6 +739,362 @@ static void isi_call_terminated_ind_cb(const GIsiMessage *msg, void *data)
|
|||
isi_call_notify(ovc, call);
|
||||
}
|
||||
|
||||
static gboolean decode_notify(GIsiSubBlockIter *iter)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &byte, 2))
|
||||
return FALSE;
|
||||
|
||||
switch (byte) {
|
||||
case CALL_NOTIFY_USER_SUSPENDED:
|
||||
DBG("CALL_NOTIFY_USER_SUSPENDED");
|
||||
break;
|
||||
|
||||
case CALL_NOTIFY_USER_RESUMED:
|
||||
DBG("CALL_NOTIFY_USER_RESUMED");
|
||||
break;
|
||||
|
||||
case CALL_NOTIFY_BEARER_CHANGE:
|
||||
DBG("CALL_NOTIFY_BEARER_CHANGE");
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG("Unknown notification: 0x%02X", byte);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_ss_code(GIsiSubBlockIter *iter, int *cssi, int *cssu)
|
||||
{
|
||||
uint16_t word;
|
||||
|
||||
if (!g_isi_sb_iter_get_word(iter, &word, 2))
|
||||
return FALSE;
|
||||
|
||||
switch (word) {
|
||||
case CALL_SSC_ALL_FWDS:
|
||||
DBG("Call forwarding is active");
|
||||
break;
|
||||
|
||||
case CALL_SSC_ALL_COND_FWD:
|
||||
*cssi = SS_MO_CONDITIONAL_FORWARDING;
|
||||
DBG("Some of conditional call forwardings active");
|
||||
break;
|
||||
|
||||
case CALL_SSC_CFU:
|
||||
*cssi = SS_MO_UNCONDITIONAL_FORWARDING;
|
||||
DBG("Unconditional call forwarding is active");
|
||||
break;
|
||||
|
||||
case CALL_SSC_OUTGOING_BARR_SERV:
|
||||
*cssi = SS_MO_OUTGOING_BARRING;
|
||||
DBG("Outgoing calls are barred");
|
||||
break;
|
||||
|
||||
case CALL_SSC_INCOMING_BARR_SERV:
|
||||
*cssi = SS_MO_INCOMING_BARRING;
|
||||
DBG("Incoming calls are barred");
|
||||
break;
|
||||
|
||||
case CALL_SSC_CALL_WAITING:
|
||||
DBG("Incoming calls are barred");
|
||||
break;
|
||||
|
||||
case CALL_SSC_CLIR:
|
||||
DBG("CLIR connected unknown indication.");
|
||||
break;
|
||||
|
||||
case CALL_SSC_MPTY:
|
||||
*cssu = SS_MT_MULTIPARTY_VOICECALL;
|
||||
DBG("Multiparty call entered.");
|
||||
break;
|
||||
|
||||
case CALL_SSC_CALL_HOLD:
|
||||
*cssu = SS_MT_VOICECALL_HOLD_RELEASED;
|
||||
DBG("Call on hold has been released.");
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG("Unknown/unhandled notification: 0x%02X", word);
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_ss_status(GIsiSubBlockIter *iter)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &byte, 2))
|
||||
return FALSE;
|
||||
|
||||
if (byte & CALL_SS_STATUS_ACTIVE)
|
||||
DBG("CALL_SS_STATUS_ACTIVE");
|
||||
|
||||
if (byte & CALL_SS_STATUS_REGISTERED)
|
||||
DBG("CALL_SS_STATUS_REGISTERED");
|
||||
|
||||
if (byte & CALL_SS_STATUS_PROVISIONED)
|
||||
DBG("CALL_SS_STATUS_PROVISIONED");
|
||||
|
||||
if (byte & CALL_SS_STATUS_QUIESCENT)
|
||||
DBG("CALL_SS_STATUS_QUIESCENT");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_ss_notify(GIsiSubBlockIter *iter, int *cssi, int *cssu)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &byte, 2))
|
||||
return FALSE;
|
||||
|
||||
if (byte & CALL_SSN_INCOMING_IS_FWD) {
|
||||
*cssu = SS_MT_CALL_FORWARDED;
|
||||
DBG("This is a forwarded call #1.");
|
||||
}
|
||||
|
||||
if (byte & CALL_SSN_INCOMING_FWD)
|
||||
DBG("This is a forwarded call #2.");
|
||||
|
||||
if (byte & CALL_SSN_OUTGOING_FWD) {
|
||||
*cssi = SS_MO_CALL_FORWARDED;
|
||||
DBG("Call has been forwarded.");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_ss_notify_indicator(GIsiSubBlockIter *iter, int *cssi)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &byte, 2))
|
||||
return FALSE;
|
||||
|
||||
if (byte & CALL_SSI_CALL_IS_WAITING) {
|
||||
*cssi = SS_MO_CALL_WAITING;
|
||||
DBG("Call is waiting.");
|
||||
}
|
||||
|
||||
if (byte & CALL_SSI_MPTY)
|
||||
DBG("Multiparty call");
|
||||
|
||||
if (byte & CALL_SSI_CLIR_SUPPR_REJ) {
|
||||
*cssi = SS_MO_CLIR_SUPPRESSION_REJECTED;
|
||||
DBG("CLIR suppression rejected");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_ss_hold_indicator(GIsiSubBlockIter *iter, int *cssu)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &byte, 2))
|
||||
return FALSE;
|
||||
|
||||
if (byte == CALL_HOLD_IND_RETRIEVED) {
|
||||
*cssu = SS_MT_VOICECALL_RETRIEVED;
|
||||
DBG("Call has been retrieved");
|
||||
} else if (byte & CALL_HOLD_IND_ON_HOLD) {
|
||||
*cssu = SS_MT_VOICECALL_ON_HOLD;
|
||||
DBG("Call has been put on hold");
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_ss_ect_indicator(GIsiSubBlockIter *iter, int *cssu)
|
||||
{
|
||||
uint8_t byte;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &byte, 2))
|
||||
return FALSE;
|
||||
|
||||
if (byte & CALL_ECT_CALL_STATE_ALERT) {
|
||||
*cssu = SS_MT_VOICECALL_IN_TRANSFER;
|
||||
DBG("Call is being connected with the remote party in "
|
||||
"alerting state");
|
||||
}
|
||||
|
||||
if (byte & CALL_ECT_CALL_STATE_ACTIVE) {
|
||||
*cssu = SS_MT_VOICECALL_TRANSFERRED;
|
||||
DBG("Call has been connected with the other remote "
|
||||
"party in explicit call transfer operation.");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_remote_address(GIsiSubBlockIter *iter,
|
||||
struct ofono_phone_number *number,
|
||||
int *index)
|
||||
{
|
||||
uint8_t type, len;
|
||||
char *addr;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &type, 2))
|
||||
return FALSE;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &len, 5))
|
||||
return FALSE;
|
||||
|
||||
if (len > OFONO_MAX_PHONE_NUMBER_LENGTH)
|
||||
return FALSE;
|
||||
|
||||
if (!g_isi_sb_iter_get_alpha_tag(iter, &addr, 2 * len, 6))
|
||||
return FALSE;
|
||||
|
||||
strncpy(number->number, addr, len);
|
||||
number->number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
|
||||
number->type = type;
|
||||
|
||||
g_free(addr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean decode_cug_info(GIsiSubBlockIter *iter, int *index, int *cssu)
|
||||
{
|
||||
uint8_t pref;
|
||||
uint8_t access;
|
||||
uint16_t word;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &pref, 2))
|
||||
return FALSE;
|
||||
|
||||
if (!g_isi_sb_iter_get_byte(iter, &access, 3))
|
||||
return FALSE;
|
||||
|
||||
if (!g_isi_sb_iter_get_word(iter, &word, 4))
|
||||
return FALSE;
|
||||
|
||||
DBG("Preferential CUG: 0x%02X", pref);
|
||||
DBG("CUG output access: 0x%02X", access);
|
||||
|
||||
*index = word;
|
||||
*cssu = SS_MO_CUG_CALL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void notification_ind_cb(const GIsiMessage *msg, void *data)
|
||||
{
|
||||
struct ofono_voicecall *ovc = data;
|
||||
GIsiSubBlockIter iter;
|
||||
|
||||
struct ofono_phone_number number;
|
||||
int index = 0;
|
||||
int cssi = -1;
|
||||
int cssu = -1;
|
||||
uint8_t call_id;
|
||||
|
||||
if (ovc == NULL || g_isi_msg_id(msg) != CALL_GSM_NOTIFICATION_IND ||
|
||||
!g_isi_msg_data_get_byte(msg, 0, &call_id) ||
|
||||
(call_id & 7) == 0)
|
||||
return;
|
||||
|
||||
DBG("Received CallServer notification for call: 0x%02X", call_id);
|
||||
|
||||
for (g_isi_sb_iter_init(&iter, msg, 2);
|
||||
g_isi_sb_iter_is_valid(&iter);
|
||||
g_isi_sb_iter_next(&iter)) {
|
||||
|
||||
switch (g_isi_sb_iter_get_id(&iter)) {
|
||||
case CALL_GSM_NOTIFY:
|
||||
|
||||
if (!decode_notify(&iter))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_SS_CODE:
|
||||
|
||||
if (!decode_ss_code(&iter, &cssi, &cssu))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_SS_STATUS:
|
||||
|
||||
if (!decode_ss_status(&iter))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_SS_NOTIFY:
|
||||
|
||||
if (!decode_ss_notify(&iter, &cssi, &cssu))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_SS_NOTIFY_INDICATOR:
|
||||
|
||||
if (!decode_ss_notify_indicator(&iter, &cssi))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_SS_HOLD_INDICATOR:
|
||||
|
||||
|
||||
if (!decode_ss_hold_indicator(&iter, &cssu))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_SS_ECT_INDICATOR:
|
||||
|
||||
if (!decode_ss_ect_indicator(&iter, &cssu))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_REMOTE_ADDRESS:
|
||||
|
||||
if (!decode_remote_address(&iter, &number, &index))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_GSM_REMOTE_SUBADDRESS:
|
||||
break;
|
||||
|
||||
case CALL_GSM_CUG_INFO:
|
||||
|
||||
if (!decode_cug_info(&iter, &index, &cssu))
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case CALL_ORIGIN_INFO:
|
||||
break;
|
||||
|
||||
case CALL_GSM_ALERTING_PATTERN:
|
||||
break;
|
||||
|
||||
case CALL_ALERTING_INFO:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cssi != -1)
|
||||
ofono_voicecall_ssn_mo_notify(ovc, call_id & 7, cssi, index);
|
||||
|
||||
if (cssu != -1)
|
||||
ofono_voicecall_ssn_mt_notify(ovc, call_id & 7, cssu, index,
|
||||
&number);
|
||||
}
|
||||
|
||||
static void isi_call_answer_resp(const GIsiMessage *msg, void *data)
|
||||
{
|
||||
struct isi_call_req_ctx *irc = data;
|
||||
|
@ -1436,6 +1792,9 @@ static void call_verify_cb(const GIsiMessage *msg, void *data)
|
|||
DBG("Failed to request call status");
|
||||
|
||||
ofono_voicecall_register(ovc);
|
||||
|
||||
g_isi_client_ind_subscribe(ivc->client, CALL_GSM_NOTIFICATION_IND,
|
||||
notification_ind_cb, ovc);
|
||||
}
|
||||
|
||||
static int probe_by_resource(struct ofono_voicecall *ovc, uint8_t resource,
|
||||
|
|
Loading…
Reference in New Issue