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; }
gboolean mcap_mdl_abort(struct mcap_mdl *mdl, mcap_mdl_notify_cb abort_cb, gpointer user_data, GDestroyNotify destroy, GError **err) { struct mcap_mdl_op_cb *con; struct mcap_mcl *mcl = mdl->mcl; mcap_md_req *cmd; if (mdl->state != MDL_WAITING) { g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, "Mdl in invalid state"); return FALSE; } cmd = create_req(MCAP_MD_ABORT_MDL_REQ, mdl->mdlid); if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) { g_free(cmd); return FALSE; } con = g_new0(struct mcap_mdl_op_cb, 1); con->mdl = mcap_mdl_ref(mdl); con->cb.notify = abort_cb; con->destroy = destroy; con->user_data = user_data; mcl->priv_data = con; mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl); return TRUE; }
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 mcap_mdl_connected_cb(struct mcap_mdl *mdl, void *data) { struct health_channel *channel = data; int fd; if (!channel->mdl) channel->mdl = mcap_mdl_ref(mdl); DBG("Data channel connected: mdl %p channel %p", mdl, channel); fd = mcap_mdl_get_fd(channel->mdl); if (fd < 0) { error("health: error retrieving fd"); goto fail; } if (channel->mdep_id == MDEP_ECHO) { GIOChannel *io; io = g_io_channel_unix_new(fd); g_io_add_watch(io, G_IO_ERR | G_IO_HUP | G_IO_NVAL | G_IO_IN, serve_echo, channel); g_io_channel_unref(io); return; } send_channel_state_notify(channel, HAL_HEALTH_CHANNEL_CONNECTED, fd); return; fail: /* TODO: mcap_mdl_abort */ destroy_channel(channel); }
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; }
gboolean mcap_reconnect_mdl(struct mcap_mdl *mdl, mcap_mdl_operation_cb reconnect_cb, gpointer user_data, GDestroyNotify destroy, GError **err) { struct mcap_mdl_op_cb *con; struct mcap_mcl *mcl = mdl->mcl; mcap_md_req *cmd; if (mdl->state != MDL_CLOSED) { g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED, "MDL is not closed"); return FALSE; } cmd = create_req(MCAP_MD_RECONNECT_MDL_REQ, mdl->mdlid); if (!mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err)) { g_free(cmd); return FALSE; } mdl->state = MDL_WAITING; con = g_new0(struct mcap_mdl_op_cb, 1); con->mdl = mcap_mdl_ref(mdl); con->cb.op = reconnect_cb; con->destroy = destroy; con->user_data = user_data; mcl->state = MCL_ACTIVE; mcl->priv_data = con; mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer, mcl); return TRUE; }
static void process_md_create_mdl_req(struct mcap_mcl *mcl, void *cmd, uint32_t len) { mcap_md_create_mdl_req *req; struct mcap_mdl *mdl; uint16_t mdl_id; uint8_t mdep_id; uint8_t cfga, conf; uint8_t rsp; if (!check_cmd_req_length(mcl, cmd, len, sizeof(mcap_md_create_mdl_req), MCAP_MD_CREATE_MDL_RSP)) return; req = cmd; mdl_id = ntohs(req->mdl); if (mdl_id < MCAP_MDLID_INITIAL || mdl_id > MCAP_MDLID_FINAL) { mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDL, mdl_id, NULL, 0); return; } mdep_id = req->mdep; if (mdep_id > MCAP_MDEPID_FINAL) { mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_INVALID_MDEP, mdl_id, NULL, 0); return; } mdl = get_mdl(mcl, mdl_id); if (mdl && (mdl->state == MDL_WAITING || mdl->state == MDL_DELETING )) { /* Creation request arrives for a MDL that is being managed * at current moment */ mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_MDL_BUSY, mdl_id, NULL, 0); return; } cfga = conf = req->conf; /* Callback to upper layer */ rsp = mcl->cb->mdl_conn_req(mcl, mdep_id, mdl_id, &conf, mcl->cb->user_data); if (mcl->state == MCL_IDLE) { /* MCL has been closed int the callback */ return; } if (cfga != 0 && cfga != conf) { /* Remote device set default configuration but upper profile */ /* has changed it. Protocol Error: force closing the MCL by */ /* remote device using UNSPECIFIED_ERROR response */ mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_UNSPECIFIED_ERROR, mdl_id, NULL, 0); return; } if (rsp != MCAP_SUCCESS) { mcap_send_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, rsp, mdl_id, NULL, 0); return; } if (!mdl) { mdl = g_new0(struct mcap_mdl, 1); mdl->mcl = mcap_mcl_ref(mcl); mdl->mdlid = mdl_id; mcl->mdls = g_slist_insert_sorted(mcl->mdls, mcap_mdl_ref(mdl), compare_mdl); } else if (mdl->state == MDL_CONNECTED) {