<commit_before>/**
 * @file callstate.c
 * Call state module -- this handles the call state for MCE
 * <p>
 * Copyright © 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
 * <p>
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>>
 *
 * mce is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * mce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with mce.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../mce.h"
#include "../mce-log.h"
#include "../mce-dbus.h"
#include "../mce-wltimer.h"

#include <stdlib.h>
#include <string.h>

#include <mce/dbus-names.h>

#include <gmodule.h>

#if 0 // DEBUG: make all logging from this module "critical"
# undef mce_log
# define mce_log(LEV, FMT, ARGS...) \
        mce_log_file(LL_CRIT, __FILE__, __FUNCTION__, FMT , ## ARGS)
#endif

/* ========================================================================= *
 * OFONO DBUS CONSTANTS
 * ========================================================================= */

#define OFONO_SERVICE                       "org.ofono"

#define OFONO_MANAGER_INTERFACE             "org.ofono.Manager"
#define OFONO_MANAGER_OBJECT                "/"
#define OFONO_MANAGER_REQ_GET_MODEMS        "GetModems"
#define OFONO_MANAGER_SIG_MODEM_ADDED       "ModemAdded"
#define OFONO_MANAGER_SIG_MODEM_REMOVED     "ModemRemoved"

#define OFONO_MODEM_INTERFACE               "org.ofono.Modem"
#define OFONO_MODEM_SIG_PROPERTY_CHANGED    "PropertyChanged"

#define OFONO_VCALLMANAGER_INTERFACE        "org.ofono.VoiceCallManager"
#define OFONO_VCALLMANAGER_REQ_GET_CALLS    "GetCalls"
#define OFONO_VCALLMANAGER_SIG_CALL_ADDED   "CallAdded"
#define OFONO_VCALLMANAGER_SIG_CALL_REMOVED "CallRemoved"

#define OFONO_VCALL_INTERFACE               "org.ofono.VoiceCall"
#define OFONO_VCALL_SIG_PROPERTY_CHANGED    "PropertyChanged"

/* ========================================================================= *
 * MODULE DETAILS
 * ========================================================================= */

/** Module name */
#define MODULE_NAME             "callstate"

/** Functionality provided by this module */
static const gchar *const provides[] = { MODULE_NAME, NULL };

/** Module information */
G_MODULE_EXPORT module_info_struct module_info = {
        /** Name of the module */
        .name = MODULE_NAME,
        /** Module provides */
        .provides = provides,
        /** Module priority */
        .priority = 250
};

/* ========================================================================= *
 * MODULE DATA
 * ========================================================================= */

/** Maximum number of concurrent call state requesters */
#define CLIENTS_MONITOR_COUNT 15

/** List of monitored call state requesters */
static GSList *clients_monitor_list = NULL;

/** Lookup table for state data / each call state requester */
static GHashTable *clients_state_lut = 0;

static void call_state_rethink_schedule(void);
static bool call_state_rethink_forced(void);

static void xofono_get_vcalls(const char *modem);

/* ========================================================================= *
 * OFONO CALL STATE HELPERS
 * ========================================================================= */

/** Enumeration of oFono voice call states */
typedef enum
{
    OFONO_CALL_STATE_UNKNOWN,
    OFONO_CALL_STATE_ACTIVE,
    OFONO_CALL_STATE_HELD,
    OFONO_CALL_STATE_DIALING,
    OFONO_CALL_STATE_ALERTING,
    OFONO_CALL_STATE_INCOMING,
    OFONO_CALL_STATE_WAITING,
    OFONO_CALL_STATE_DISCONNECTED,

    OFONO_CALL_STATE_COUNT
} ofono_callstate_t;

/** Lookup table for oFono voice call states */
static const char * const ofono_callstate_lut[OFONO_CALL_STATE_COUNT] =
{
    [OFONO_CALL_STATE_UNKNOWN]      = "unknown",
    [OFONO_CALL_STATE_ACTIVE]       = "active",
    [OFONO_CALL_STATE_HELD]         = "held",
    [OFONO_CALL_STATE_DIALING]      = "dialing",
    [OFONO_CALL_STATE_ALERTING]     = "alerting",
    [OFONO_CALL_STATE_INCOMING]     = "incoming",
    [OFONO_CALL_STATE_WAITING]      = "waiting",
    [OFONO_CALL_STATE_DISCONNECTED] = "disconnected",
};

/** oFono call state number to name
 */
#ifdef DEAD_CODE
static const char *
ofono_callstate_name(ofono_callstate_t callstate)
{
    if( callstate < OFONO_CALL_STATE_COUNT )
        return ofono_callstate_lut[callstate];
    return ofono_callstate_lut[OFONO_CALL_STATE_UNKNOWN];
}
#endif

/** oFono call state name to number
 */
static ofono_callstate_t
ofono_callstate_lookup(const char *name)
{
    ofono_callstate_t res = OFONO_CALL_STATE_UNKNOWN;

    for( int i = 0; i < OFONO_CALL_STATE_COUNT; ++i ) {
        if( !strcmp(ofono_callstate_lut[i], name) ) {
            res = i;
            break;
        }
    }

    return res;
}

/** oFono call state name to mce call state number
 */
static call_state_t
ofono_callstate_to_mce(const char *name)
{
    ofono_callstate_t ofono = ofono_callstate_lookup(name);
    call_state_t   mce = CALL_STATE_INVALID;

    switch( ofono ) {
    default:
    case OFONO_CALL_STATE_UNKNOWN:
    case OFONO_CALL_STATE_DISCONNECTED:
        mce = CALL_STATE_NONE;
        break;

    case OFONO_CALL_STATE_INCOMING:
        mce = CALL_STATE_RINGING;
        break;

    case OFONO_CALL_STATE_DIALING:
    case OFONO_CALL_STATE_ALERTING:
    case OFONO_CALL_STATE_ACTIVE:
    case OFONO_CALL_STATE_HELD:
    case OFONO_CALL_STATE_WAITING:
        mce = CALL_STATE_ACTIVE;
        break;
    }

    return mce;
}

/** oFono emergency flag to mce call type number
 */
static call_type_t ofono_calltype_to_mce(bool emergency)
{
    return emergency ? EMERGENCY_CALL : NORMAL_CALL;
}

/* ========================================================================= *
 * OFONO VOICECALL OBJECTS
 * ========================================================================= */

/** oFono voice call state data
 */
typedef struct
{
    char *name;
    bool probed;

    call_state_t state;
    call_type_t  type;
} ofono_vcall_t;

static void clients_merge_state_cb(gpointer key, gpointer val, gpointer aptr);<commit_msg>[callstate] Map ofono waiting state to mce ringing state. Fixes JB#31908<commit_after>/**
 * @file callstate.c
 * Call state module -- this handles the call state for MCE
 * <p>
 * Copyright © 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
 * <p>
 * @author <NAME> <<EMAIL>>
 * @author <NAME> <<EMAIL>.<EMAIL>>
 *
 * mce is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * mce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with mce.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "../mce.h"
#include "../mce-log.h"
#include "../mce-dbus.h"
#include "../mce-wltimer.h"

#include <stdlib.h>
#include <string.h>

#include <mce/dbus-names.h>

#include <gmodule.h>

#if 0 // DEBUG: make all logging from this module "critical"
# undef mce_log
# define mce_log(LEV, FMT, ARGS...) \
        mce_log_file(LL_CRIT, __FILE__, __FUNCTION__, FMT , ## ARGS)
#endif

/* ========================================================================= *
 * OFONO DBUS CONSTANTS
 * ========================================================================= */

#define OFONO_SERVICE                       "org.ofono"

#define OFONO_MANAGER_INTERFACE             "org.ofono.Manager"
#define OFONO_MANAGER_OBJECT                "/"
#define OFONO_MANAGER_REQ_GET_MODEMS        "GetModems"
#define OFONO_MANAGER_SIG_MODEM_ADDED       "ModemAdded"
#define OFONO_MANAGER_SIG_MODEM_REMOVED     "ModemRemoved"

#define OFONO_MODEM_INTERFACE               "org.ofono.Modem"
#define OFONO_MODEM_SIG_PROPERTY_CHANGED    "PropertyChanged"

#define OFONO_VCALLMANAGER_INTERFACE        "org.ofono.VoiceCallManager"
#define OFONO_VCALLMANAGER_REQ_GET_CALLS    "GetCalls"
#define OFONO_VCALLMANAGER_SIG_CALL_ADDED   "CallAdded"
#define OFONO_VCALLMANAGER_SIG_CALL_REMOVED "CallRemoved"

#define OFONO_VCALL_INTERFACE               "org.ofono.VoiceCall"
#define OFONO_VCALL_SIG_PROPERTY_CHANGED    "PropertyChanged"

/* ========================================================================= *
 * MODULE DETAILS
 * ========================================================================= */

/** Module name */
#define MODULE_NAME             "callstate"

/** Functionality provided by this module */
static const gchar *const provides[] = { MODULE_NAME, NULL };

/** Module information */
G_MODULE_EXPORT module_info_struct module_info = {
        /** Name of the module */
        .name = MODULE_NAME,
        /** Module provides */
        .provides = provides,
        /** Module priority */
        .priority = 250
};

/* ========================================================================= *
 * MODULE DATA
 * ========================================================================= */

/** Maximum number of concurrent call state requesters */
#define CLIENTS_MONITOR_COUNT 15

/** List of monitored call state requesters */
static GSList *clients_monitor_list = NULL;

/** Lookup table for state data / each call state requester */
static GHashTable *clients_state_lut = 0;

static void call_state_rethink_schedule(void);
static bool call_state_rethink_forced(void);

static void xofono_get_vcalls(const char *modem);

/* ========================================================================= *
 * OFONO CALL STATE HELPERS
 * ========================================================================= */

/** Enumeration of oFono voice call states */
typedef enum
{
    OFONO_CALL_STATE_UNKNOWN,
    OFONO_CALL_STATE_ACTIVE,
    OFONO_CALL_STATE_HELD,
    OFONO_CALL_STATE_DIALING,
    OFONO_CALL_STATE_ALERTING,
    OFONO_CALL_STATE_INCOMING,
    OFONO_CALL_STATE_WAITING,
    OFONO_CALL_STATE_DISCONNECTED,

    OFONO_CALL_STATE_COUNT
} ofono_callstate_t;

/** Lookup table for oFono voice call states */
static const char * const ofono_callstate_lut[OFONO_CALL_STATE_COUNT] =
{
    [OFONO_CALL_STATE_UNKNOWN]      = "unknown",
    [OFONO_CALL_STATE_ACTIVE]       = "active",
    [OFONO_CALL_STATE_HELD]         = "held",
    [OFONO_CALL_STATE_DIALING]      = "dialing",
    [OFONO_CALL_STATE_ALERTING]     = "alerting",
    [OFONO_CALL_STATE_INCOMING]     = "incoming",
    [OFONO_CALL_STATE_WAITING]      = "waiting",
    [OFONO_CALL_STATE_DISCONNECTED] = "disconnected",
};

/** oFono call state number to name
 */
#ifdef DEAD_CODE
static const char *
ofono_callstate_name(ofono_callstate_t callstate)
{
    if( callstate < OFONO_CALL_STATE_COUNT )
        return ofono_callstate_lut[callstate];
    return ofono_callstate_lut[OFONO_CALL_STATE_UNKNOWN];
}
#endif

/** oFono call state name to number
 */
static ofono_callstate_t
ofono_callstate_lookup(const char *name)
{
    ofono_callstate_t res = OFONO_CALL_STATE_UNKNOWN;

    for( int i = 0; i < OFONO_CALL_STATE_COUNT; ++i ) {
        if( !strcmp(ofono_callstate_lut[i], name) ) {
            res = i;
            break;
        }
    }

    return res;
}

/** oFono call state name to mce call state number
 */
static call_state_t
ofono_callstate_to_mce(const char *name)
{
    ofono_callstate_t ofono = ofono_callstate_lookup(name);
    call_state_t   mce = CALL_STATE_INVALID;

    switch( ofono ) {
    default:
    case OFONO_CALL_STATE_UNKNOWN:
    case OFONO_CALL_STATE_DISCONNECTED:
        mce = CALL_STATE_NONE;
        break;

    case OFONO_CALL_STATE_INCOMING:
    case OFONO_CALL_STATE_WAITING:
        mce = CALL_STATE_RINGING;
        break;

    case OFONO_CALL_STATE_DIALING:
    case OFONO_CALL_STATE_ALERTING:
    case OFONO_CALL_STATE_ACTIVE:
    case OFONO_CALL_STATE_HELD:
        mce = CALL_STATE_ACTIVE;
        break;
    }

    return mce;
}

/** oFono emergency flag to mce call type number
 */
static call_type_t ofono_calltype_to_mce(bool emergency)
{
    return emergency ? EMERGENCY_CALL : NORMAL_CALL;
}

/* ========================================================================= *
 * OFONO VOICECALL OBJECTS
 * ========================================================================= */

/** oFono voice call state data
 */
typedef struct
{
    char *name;
    bool probed;

    call_state_t state;
    call_type_t  type;
} ofono_vcall_t;

static void clients_merge_state_cb(gpointer key, gpointer val, gpointer aptr);
{'fraction_non_alphanumeric': 0.1937495188976984, 'fraction_numerical': 0.003156031098452775, 'mean_word_length': 3.979685703334611, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4076983', 'n_tokens_mistral': 4280, 'n_tokens_neox': 4108, 'n_words': 961}