#include <murphy/common.h>
#include <murphy/core.h>
-#include "murphy/plugins/telephony/ofono.h"
-#include "murphy/plugins/telephony/telephony.h"
+#include "telephony/resctl.h"
+#include "telephony/ofono.h"
+#include "telephony/telephony.h"
+
+enum {
+ ARG_ZONE, /* resource set zone */
+ ARG_CLASS, /* application class */
+ ARG_PRIORITY, /* priority within class */
+ ARG_PLAYBACK, /* playback resource config */
+ ARG_RECORDING, /* recording resource config */
+ ARG_ROLE, /* (media) role attribute */
+};
mrp_plugin_t *telephony_plugin;
+
static int telephony_init(mrp_plugin_t *plugin)
{
- mrp_context_t *ctx = plugin->ctx;
-
- mrp_log_info("%s() called...", __FUNCTION__);
+ mrp_context_t *ctx = plugin->ctx;
+ mrp_plugin_arg_t *args = plugin->args;
+ const char *zone = args[ARG_ZONE].str;
+ const char *cls = args[ARG_CLASS].str;
+ uint32_t prio = args[ARG_PRIORITY].u32;
+ const char *play = args[ARG_PLAYBACK].str;
+ const char *rec = args[ARG_RECORDING].str;
+ const char *role = args[ARG_ROLE].str;
+
+ if (!resctl_config(zone, cls, prio, play, rec, role)) {
+ mrp_log_error("Failed to configure telephony resource-set.");
+
+ return FALSE;
+ }
if (ctx != NULL) {
/* use the mainloop from the plugin context */
{
MRP_UNUSED(plugin);
- mrp_log_info("%s() called...", __FUNCTION__);
-
tel_exit_listeners();
}
"The telephony plugin follows ofono DBUS activity" \
"and updates Murphy database with telephony calls information"
-MRP_REGISTER_CORE_PLUGIN("telephony", \
- TELEPHONY_VERSION, TELEPHONY_DESCRIPTION, \
- TELEPHONY_AUTHORS, TELEPHONY_HELP, MRP_SINGLETON, \
- telephony_init, telephony_exit,
- NULL, 0, /* args */
- NULL, 0, /* exports */
- NULL, 0, /* imports */
- NULL /* commands */ );
+#define DEFAULT_ZONE "driver"
+#define DEFAULT_CLASS "phone"
+#define DEFAULT_PRIORITY 1
+#define DEFAULT_PLAYBACK "audio_playback,mandatory,shared"
+#define DEFAULT_RECORDING "audio_recording,mandatory,exclusive"
+#define DEFAULT_ROLE "phone"
+
+static mrp_plugin_arg_t telephony_args[] = {
+ MRP_PLUGIN_ARGIDX(ARG_ZONE , STRING, "zone" , DEFAULT_ZONE),
+ MRP_PLUGIN_ARGIDX(ARG_CLASS , STRING, "class" , DEFAULT_CLASS),
+ MRP_PLUGIN_ARGIDX(ARG_PRIORITY , UINT32, "priority" , DEFAULT_PRIORITY),
+ MRP_PLUGIN_ARGIDX(ARG_PLAYBACK , STRING, "playback" , DEFAULT_PLAYBACK),
+ MRP_PLUGIN_ARGIDX(ARG_RECORDING, STRING, "recording", DEFAULT_RECORDING),
+ MRP_PLUGIN_ARGIDX(ARG_ROLE , STRING, "role" , DEFAULT_ROLE),
+};
+
+MRP_REGISTER_CORE_PLUGIN("telephony",
+ TELEPHONY_VERSION, TELEPHONY_DESCRIPTION,
+ TELEPHONY_AUTHORS, TELEPHONY_HELP, MRP_SINGLETON,
+ telephony_init, telephony_exit,
+ telephony_args, MRP_ARRAY_SIZE(telephony_args),
+ NULL, 0, /* exports */
+ NULL, 0, /* imports */
+ NULL /* commands */ );
static void event_cb(uint32_t reqid, mrp_resource_set_t *rset, void *user_data);
+
+typedef struct {
+ char *zone;
+ char *cls;
+ uint32_t prio;
+ char *play;
+ int pmnd;
+ int pshr;
+ char *rec;
+ int rmnd;
+ int rshr;
+ char *role;
+} config_t;
+
+
+static config_t cfg;
+
+#define EXCLUSIVE "exclusive"
+#define SHARED "shared"
+#define MANDATORY "mandatory"
+#define OPTIONAL "optional"
+#define EXCLEN (sizeof(EXCLUSIVE) - 1)
+#define SHRLEN (sizeof(SHARED) - 1)
+#define MNDLEN (sizeof(MANDATORY) - 1)
+#define OPTLEN (sizeof(OPTIONAL) - 1)
+
+#define PLAYBACK "playback"
+#define RECORDING "recording"
+
+static int parse_resource(const char *key, const char *value)
+{
+ const char *p, *e;
+ char **resp;
+ int *mndp, *shrp, l;
+
+ if (!strcmp(key, PLAYBACK)) {
+ resp = &cfg.play;
+ mndp = &cfg.pmnd;
+ shrp = &cfg.pshr;
+ }
+ else if (!strcmp(key, RECORDING)) {
+ resp = &cfg.rec;
+ mndp = &cfg.rmnd;
+ shrp = &cfg.rshr;
+ }
+ else
+ return FALSE;
+
+ mrp_free(*resp);
+ *resp = NULL;
+ *mndp = 1;
+ *shrp = 0;
+
+ p = value;
+ while (p) {
+ while (*p && (*p == ' ' || *p == '\t' || *p == ','))
+ p++;
+
+ e = strchr(p, ',');
+
+ if (e != NULL)
+ l = e - p;
+ else
+ l = strlen(p);
+
+ if (l == SHRLEN && !strncmp(p, SHARED , l)) *shrp = 1;
+ else if (l == EXCLEN && !strncmp(p, EXCLUSIVE, l)) *shrp = 0;
+ else if (l == OPTLEN && !strncmp(p, OPTIONAL , l)) *mndp = 0;
+ else if (l == MNDLEN && !strncmp(p, MANDATORY, l)) *mndp = 1;
+ else {
+ if (*resp != NULL || (*resp = mrp_datadup((void *)p, l+1)) == NULL)
+ return FALSE;
+
+ (*resp)[l] = '\0';
+ }
+
+ p = e && *e ? e + 1 : NULL;
+ }
+
+ if (*resp != NULL)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+int resctl_config(const char *zone, const char *cls, uint32_t priority,
+ const char *playback, const char *recording, const char *role)
+{
+ mrp_free(cfg.zone);
+ mrp_free(cfg.cls);
+ mrp_free(cfg.play);
+ mrp_free(cfg.rec);
+ mrp_free(cfg.role);
+ mrp_clear(&cfg);
+
+ if (!(cfg.zone = mrp_strdup(zone)) ||
+ !(cfg.cls = mrp_strdup(cls)) ||
+ !(cfg.role = mrp_strdup(role)))
+ goto fail;
+
+ if (!parse_resource(PLAYBACK , playback) ||
+ !parse_resource(RECORDING, recording))
+ goto fail;
+
+ cfg.prio = priority;
+
+ mrp_log_info("Telephony resource-set configuration:");
+ mrp_log_info(" zone: %s, class: %s, priority: %u", cfg.zone, cfg.cls,
+ cfg.prio);
+ mrp_log_info(" playback: %s %s %s%s%s",
+ cfg.pmnd ? "mandatory" : "optional",
+ cfg.pshr ? "shared" : "exclusive",
+ cfg.play,
+ cfg.role && *cfg.role ? " role:s:" : "",
+ cfg.role && *cfg.role ? cfg.role : "");
+ mrp_log_info(" recording: %s %s %s%s%s",
+ cfg.rmnd ? "mandatory" : "optional",
+ cfg.rshr ? "shared" : "exclusive",
+ cfg.rec,
+ cfg.role && *cfg.role ? " role:s:" : "",
+ cfg.role && *cfg.role ? cfg.role : "");
+
+ return TRUE;
+
+ fail:
+ mrp_free(cfg.zone);
+ mrp_free(cfg.cls);
+ mrp_free(cfg.play);
+ mrp_free(cfg.rec);
+ mrp_free(cfg.role);
+ mrp_clear(&cfg);
+
+ return FALSE;
+}
+
+
resctl_t *resctl_init(void)
{
+ const char *zone = cfg.zone;
+ const char *cls = cfg.cls;
+ uint32_t prio = cfg.prio;
+ const char *play = cfg.play;
+ bool pshr = !!cfg.pshr;
+ bool pmnd = !!cfg.pmnd;
+ const char *rec = cfg.rec;
+ bool rshr = !!cfg.rshr;
+ bool rmnd = !!cfg.rmnd;
+ const char *role = cfg.role && *cfg.role ? cfg.role : NULL;
+ bool ar = false;
+ bool nowait = false;
resctl_t *ctl;
mrp_resource_client_t *client;
mrp_resource_set_t *set;
- const char *zone = "driver";
- const char *play = "audio_playback";
- const char *rec = "audio_recording";
- const char *cls = "phone";
- bool ar = false;
- bool nowait = false;
- uint32_t prio = 1; /* what is this ? */
+ mrp_attr_t attrs[3], *attrp;
ctl = NULL;
client = NULL;
goto fail;
}
- if (mrp_resource_set_add_resource(set, play, false, NULL, true) < 0 ||
- mrp_resource_set_add_resource(set, rec , false, NULL, true) < 0) {
+ attrs[0].name = "policy";
+ attrs[0].type = mqi_string;
+ attrs[0].value.string = "relaxed";
+
+ if (role != NULL) {
+ attrs[1].type = mqi_string;
+ attrs[1].name = "role";
+ attrs[1].value.string = role;
+ attrs[2].name = NULL;
+ }
+ else
+ attrs[1].name = NULL;
+
+ attrp = &attrs[0];
+
+ if (mrp_resource_set_add_resource(set, play, pshr, attrp, pmnd) < 0 ||
+ mrp_resource_set_add_resource(set, rec , rshr, attrp, rmnd) < 0) {
mrp_log_error("Failed to initialize telephony resource set.");
goto fail;
}
mrp_free(ctl);
}
+
+ mrp_free(cfg.zone);
+ mrp_free(cfg.cls);
+ mrp_free(cfg.play);
+ mrp_free(cfg.rec);
+ mrp_free(cfg.role);
+ mrp_clear(&cfg);
}