static void create_mdl_cb(struct mcap_mdl *mcap_mdl, uint8_t type, GError *gerr, gpointer data) { GError *err = NULL; printf("%s\n", __func__); if (gerr) { printf("MDL error: %s\n", gerr->message); if (!no_close) g_main_loop_quit(mloop); return; } if (mdl) mcap_mdl_unref(mdl); mdl = mcap_mdl_ref(mcap_mdl); if (!mcap_connect_mdl(mdl, L2CAP_MODE_ERTM, dcpsm, connect_mdl_cb, NULL, NULL, &err)) { printf("Error connecting to mdl: %s\n", err->message); g_error_free(err); if (no_close) return; g_main_loop_quit(mloop); } }
static void unref_mdl(struct health_channel *channel) { if (!channel || !channel->mdl) return; mcap_mdl_unref(channel->mdl); channel->mdl = NULL; channel->mdl_conn = false; }
static void free_mcap_mdl_op(struct mcap_mdl_op_cb *op) { if (op->destroy) op->destroy(op->user_data); if (op->mdl) mcap_mdl_unref(op->mdl); g_free(op); }
static void mcap_del_mdl(gpointer elem, gpointer user_data) { struct mcap_mdl *mdl = elem; gboolean notify = *(gboolean *) user_data; shutdown_mdl(mdl); if (notify) mdl->mcl->cb->mdl_deleted(mdl, mdl->mcl->cb->user_data); mcap_mdl_unref(mdl); }
gboolean mcap_create_mdl(struct mcap_mcl *mcl, uint8_t mdepid, uint8_t conf, mcap_mdl_operation_conf_cb connect_cb, gpointer user_data, GDestroyNotify destroy, GError **err) { struct mcap_mdl *mdl; struct mcap_mdl_op_cb *con; mcap_md_create_mdl_req *cmd; uint16_t id; id = generate_mdlid(mcl); if (!id) { g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, "Not more mdlids available"); return FALSE; } mdl = g_new0(struct mcap_mdl, 1); mdl->mcl = mcap_mcl_ref(mcl); mdl->mdlid = id; mdl->mdep_id = mdepid; mdl->state = MDL_WAITING; con = g_new0(struct mcap_mdl_op_cb, 1); con->mdl = mcap_mdl_ref(mdl); con->cb.op_conf = connect_cb; con->destroy = destroy; con->user_data = user_data; cmd = create_mdl_req(id, mdepid, conf); if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_create_mdl_req), err)) { mcap_mdl_unref(con->mdl); g_free(con); g_free(cmd); return FALSE; } mcl->state = MCL_ACTIVE; mcl->priv_data = con; mcl->mdls = g_slist_insert_sorted(mcl->mdls, mcap_mdl_ref(mdl), compare_mdl); mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl); return TRUE; }
static void mcap_notify_error(struct mcap_mcl *mcl, GError *err) { struct mcap_mdl_op_cb *con = mcl->priv_data; struct mcap_mdl *mdl; MDLState st; GSList *l; if (!con || !mcl->lcmd) return; switch (mcl->lcmd[0]) { case MCAP_MD_CREATE_MDL_REQ: st = MDL_WAITING; l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state); mdl = l->data; mcl->mdls = g_slist_remove(mcl->mdls, mdl); mcap_mdl_unref(mdl); update_mcl_state(mcl); con->cb.op_conf(NULL, 0, err, con->user_data); break; case MCAP_MD_ABORT_MDL_REQ: st = MDL_WAITING; l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state); shutdown_mdl(l->data); update_mcl_state(mcl); con->cb.notify(err, con->user_data); break; case MCAP_MD_DELETE_MDL_REQ: for (l = mcl->mdls; l; l = l->next) { mdl = l->data; if (mdl->state == MDL_DELETING) mdl->state = (mdl->dc) ? MDL_CONNECTED : MDL_CLOSED; } update_mcl_state(mcl); con->cb.notify(err, con->user_data); break; case MCAP_MD_RECONNECT_MDL_REQ: st = MDL_WAITING; l = g_slist_find_custom(mcl->mdls, &st, cmp_mdl_state); shutdown_mdl(l->data); update_mcl_state(mcl); con->cb.op(NULL, err, con->user_data); break; } free_mcl_priv_data(mcl); g_free(mcl->lcmd); mcl->lcmd = NULL; }
gboolean mcap_delete_mdl(struct mcap_mdl *mdl, mcap_mdl_notify_cb delete_cb, gpointer user_data, GDestroyNotify destroy, GError **err) { struct mcap_mcl *mcl= mdl->mcl; struct mcap_mdl_op_cb *con; GSList *l; l = g_slist_find(mcl->mdls, mdl); if (!l) { g_set_error(err, MCAP_ERROR, MCAP_ERROR_INVALID_MDL, "%s" , error2str(MCAP_INVALID_MDEP)); return FALSE; } if (mdl->state == MDL_WAITING) { g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, "Mdl is not created"); return FALSE; } mdl->state = MDL_DELETING; con = g_new0(struct mcap_mdl_op_cb, 1); con->mdl = mcap_mdl_ref(mdl); con->cb.notify = delete_cb; con->destroy = destroy; con->user_data = user_data; if (!send_delete_req(mcl, con, mdl->mdlid, err)) { mcap_mdl_unref(con->mdl); g_free(con); return FALSE; } return TRUE; }