{
struct cb_data *cbd = user_data;
ofono_call_waiting_status_cb_t cb = cbd->cb;
+ int conditions = 0;
+ int status;
+ int cls;
struct ofono_error error;
GAtResultIter iter;
- int num = 0;
- struct ofono_cw_condition *list = NULL;
- int i;
dump_response("ccwa_query_cb", ok, result);
decode_at_error(&error, g_at_result_final_response(result));
g_at_result_iter_init(&iter, result);
- while (g_at_result_iter_next(&iter, "+CCWA:"))
- num += 1;
-
- /* Specification is really unclear about this
- * generate status=0 for all classes just in case
- */
- if (num == 0) {
- list = g_new(struct ofono_cw_condition, 1);
- num = 1;
-
- list->status = 0;
- list->cls = GPOINTER_TO_INT(cbd->user);
-
- goto out;
- }
-
- list = g_new(struct ofono_cw_condition, num);
-
- g_at_result_iter_init(&iter, result);
- num = 0;
-
while (g_at_result_iter_next(&iter, "+CCWA:")) {
- g_at_result_iter_next_number(&iter, &(list[num].status));
- g_at_result_iter_next_number(&iter, &(list[num].cls));
+ g_at_result_iter_next_number(&iter, &status);
+ g_at_result_iter_next_number(&iter, &cls);
- num += 1;
+ if (status == 1)
+ conditions |= cls;
}
- for (i = 0; i < num; i++)
- ofono_debug("ccwa_cb: %d, %d", list[i].status, list[i].cls);
+ ofono_debug("CW enabled for: %d", conditions);
out:
- cb(&error, num, list, cbd->data);
- g_free(list);
+ cb(&error, conditions, cbd->data);
}
static void at_ccwa_query(struct ofono_modem *modem, int cls,
{
DECLARE_FAILURE(error);
- cb(&error, 0, NULL, data);
+ cb(&error, 0, data);
}
}
struct ofono_call_waiting_ops *ops;
int flags;
DBusMessage *pending;
- GSList *cw_list;
+ int conditions;
int ss_req_type;
int ss_req_cls;
};
-static const char *enabled = "enabled";
-static const char *disabled = "disabled";
-
static void cw_register_ss_controls(struct ofono_modem *modem);
static void cw_unregister_ss_controls(struct ofono_modem *modem);
-static gint cw_condition_compare(gconstpointer a, gconstpointer b)
-{
- const struct ofono_cw_condition *ca = a;
- const struct ofono_cw_condition *cb = b;
-
- if (ca->cls < cb->cls)
- return -1;
-
- if (ca->cls > cb->cls)
- return 1;
-
- return 0;
-}
-
-static gint cw_condition_find_with_cls(gconstpointer a, gconstpointer b)
-{
- const struct ofono_cw_condition *c = a;
- int cls = GPOINTER_TO_INT(b);
-
- if (c->cls < cls)
- return -1;
-
- if (c->cls > cls)
- return 1;
-
- return 0;
-}
-
static struct call_waiting_data *call_waiting_create()
{
struct call_waiting_data *r;
- r = g_try_new0(struct call_waiting_data, 1);
-
- if (!r)
- return r;
+ r = g_new0(struct call_waiting_data, 1);
return r;
}
cw_unregister_ss_controls(modem);
- g_slist_foreach(cw->cw_list, (GFunc)g_free, NULL);
- g_slist_free(cw->cw_list);
-
g_free(cw);
}
-static void cw_cond_list_print(GSList *list)
-{
- GSList *l;
- struct ofono_cw_condition *cond;
-
- for (l = list; l; l = l->next) {
- cond = l->data;
-
- ofono_debug("CW condition status: %d, class: %d",
- cond->status, cond->cls);
- }
-}
-
-static GSList *cw_cond_list_create(int total,
- const struct ofono_cw_condition *list)
-{
- GSList *l = NULL;
- int i;
- int j;
- struct ofono_cw_condition *cond;
-
- /* Specification is not really clear on how the results are reported,
- * most modems report it as multiple list items, one for each class
- * however, specification does leave room for a single compound value
- * to be reported
- */
- for (i = 0; i < total; i++) {
- for (j = 1; j <= BEARER_CLASS_PAD; j = j << 1) {
- if (!(list[i].cls & j))
- continue;
-
- if (list[i].status == 0)
- continue;
-
- cond = g_new0(struct ofono_cw_condition, 1);
-
- memcpy(cond, &list[i], sizeof(struct ofono_cw_condition));
- cond->cls = j;
-
- l = g_slist_insert_sorted(l, cond,
- cw_condition_compare);
- }
- }
-
- return l;
-}
-
-static void set_new_cond_list(struct ofono_modem *modem, GSList *new_cw_list)
+static void update_conditions(struct ofono_modem *modem, int new_conditions,
+ int mask)
{
struct call_waiting_data *cw = modem->call_waiting;
DBusConnection *conn = dbus_gsm_connection();
- GSList *n;
- GSList *o;
- struct ofono_cw_condition *nc;
- struct ofono_cw_condition *oc;
char buf[64];
+ int j;
+ const char *value;
- for (n = new_cw_list; n; n = n->next) {
- nc = n->data;
-
- if (nc->cls > BEARER_CLASS_FAX)
+ for (j = 1; j <= BEARER_CLASS_PAD; j = j << 1) {
+ if ((j & mask) == 0)
continue;
- sprintf(buf, "%s", bearer_class_to_string(nc->cls));
-
- o = g_slist_find_custom(cw->cw_list, GINT_TO_POINTER(nc->cls),
- cw_condition_find_with_cls);
-
- if (o) {
- g_free(o->data);
- cw->cw_list = g_slist_remove(cw->cw_list, o->data);
- } else {
- dbus_gsm_signal_property_changed(conn, modem->path,
- CALL_WAITING_INTERFACE,
- buf, DBUS_TYPE_STRING,
- &enabled);
- }
- }
-
- for (o = cw->cw_list; o; o = o->next) {
- oc = o->data;
+ if ((cw->conditions & j) == (new_conditions & j))
+ continue;
- sprintf(buf, "%s", bearer_class_to_string(oc->cls));
+ if (new_conditions & j)
+ value = "enabled";
+ else
+ value = "disabled";
+ sprintf(buf, "%s", bearer_class_to_string(j));
dbus_gsm_signal_property_changed(conn, modem->path,
CALL_WAITING_INTERFACE,
buf, DBUS_TYPE_STRING,
- &disabled);
+ &value);
}
- g_slist_foreach(cw->cw_list, (GFunc)g_free, NULL);
- g_slist_free(cw->cw_list);
-
- cw->cw_list = new_cw_list;
+ cw->conditions = new_conditions;
}
static void property_append_cw_conditions(DBusMessageIter *dict,
- GSList *cw_list, int mask)
+ int conditions, int mask)
{
- GSList *l;
int i;
- struct ofono_cw_condition *cw;
const char *prop;
+ const char *value;
- for (i = 1, l = cw_list; i <= BEARER_CLASS_PAD; i = i << 1) {
+ for (i = 1; i <= BEARER_CLASS_PAD; i = i << 1) {
if (!(mask & i))
continue;
prop = bearer_class_to_string(i);
- while (l && (cw = l->data) && (cw->cls < i))
- l = l->next;
-
- if (!l || cw->cls != i) {
- dbus_gsm_dict_append(dict, prop, DBUS_TYPE_STRING,
- &disabled);
- continue;
- }
+ if (conditions & i)
+ value = "enabled";
+ else
+ value = "disabled";
- dbus_gsm_dict_append(dict, prop, DBUS_TYPE_STRING, &enabled);
+ dbus_gsm_dict_append(dict, prop, DBUS_TYPE_STRING, &value);
}
}
dbus_message_iter_open_container(&vstruct, DBUS_TYPE_ARRAY,
PROPERTIES_ARRAY_SIGNATURE, &dict);
- property_append_cw_conditions(&dict, cw->cw_list, cw->ss_req_cls);
+ property_append_cw_conditions(&dict, cw->conditions, cw->ss_req_cls);
dbus_message_iter_close_container(&vstruct, &dict);
dbus_gsm_pending_reply(&cw->pending, reply);
}
-static void cw_ss_query_callback(const struct ofono_error *error, int num,
- struct ofono_cw_condition *cond_list,
+static void cw_ss_query_callback(const struct ofono_error *error, int status,
void *data)
{
struct ofono_modem *modem = data;
struct call_waiting_data *cw = modem->call_waiting;
- GSList *l;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
ofono_debug("setting CW via SS failed");
return;
}
- l = cw_cond_list_create(num, cond_list);
-
- cw_cond_list_print(l);
-
- set_new_cond_list(modem, l);
+ update_conditions(modem, status, BEARER_CLASS_VOICE);
cw->flags |= CALL_WAITING_FLAG_CACHED;
generate_ss_query_reply(modem);
PROPERTIES_ARRAY_SIGNATURE,
&dict);
- property_append_cw_conditions(&dict, cw->cw_list, BEARER_CLASS_DEFAULT);
+ property_append_cw_conditions(&dict, cw->conditions,
+ BEARER_CLASS_VOICE);
dbus_message_iter_close_container(&iter, &dict);
return reply;
}
-static void cw_query_callback(const struct ofono_error *error, int num,
- struct ofono_cw_condition *cond_list, void *data)
+static void cw_query_callback(const struct ofono_error *error, int status,
+ void *data)
{
struct ofono_modem *modem = data;
struct call_waiting_data *cw = modem->call_waiting;
- GSList *l = NULL;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
ofono_debug("Error during cw query");
goto out;
}
- l = cw_cond_list_create(num, cond_list);
-
- cw_cond_list_print(l);
-
- set_new_cond_list(modem, l);
+ update_conditions(modem, status, BEARER_CLASS_VOICE);
cw->flags |= CALL_WAITING_FLAG_CACHED;
out:
return NULL;
}
-static void set_query_callback(const struct ofono_error *error, int num,
- struct ofono_cw_condition *cond_list, void *data)
+static void set_query_callback(const struct ofono_error *error, int status,
+ void *data)
{
struct ofono_modem *modem = data;
struct call_waiting_data *cw = modem->call_waiting;
- GSList *l = NULL;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
ofono_error("CW set succeeded, but query failed!");
dbus_gsm_pending_reply(&cw->pending,
dbus_message_new_method_return(cw->pending));
- l = cw_cond_list_create(num, cond_list);
-
- cw_cond_list_print(l);
-
- set_new_cond_list(modem, l);
+ update_conditions(modem, status, BEARER_CLASS_VOICE);
}
static void set_callback(const struct ofono_error *error, void *data)