static int answer_preprocess(call_t *answer, ipc_data_t *olddata) { int rc = EOK; if (!IPC_GET_RETVAL(answer->data)) { /* The recipient authorized the change of state. */ phone_t *recipient_phone; task_t *other_task_s; task_t *other_task_r; rc = phone_get(IPC_GET_ARG1(answer->data), &recipient_phone); if (rc != EOK) { IPC_SET_RETVAL(answer->data, ENOENT); return ENOENT; } mutex_lock(&recipient_phone->lock); if (recipient_phone->state != IPC_PHONE_CONNECTED) { mutex_unlock(&recipient_phone->lock); IPC_SET_RETVAL(answer->data, EINVAL); return EINVAL; } other_task_r = recipient_phone->callee->task; other_task_s = (task_t *) IPC_GET_ARG5(*olddata); /* * See if both the sender and the recipient meant the * same third party task. */ if (other_task_r != other_task_s) { IPC_SET_RETVAL(answer->data, EINVAL); rc = EINVAL; } else { rc = event_task_notify_5(other_task_r, EVENT_TASK_STATE_CHANGE, false, IPC_GET_ARG1(*olddata), IPC_GET_ARG2(*olddata), IPC_GET_ARG3(*olddata), LOWER32(olddata->task_id), UPPER32(olddata->task_id)); IPC_SET_RETVAL(answer->data, rc); } mutex_unlock(&recipient_phone->lock); } return rc; }
static int loc_category_get_ids_once(sysarg_t method, sysarg_t arg1, sysarg_t *id_buf, size_t buf_size, size_t *act_size) { async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER); ipc_call_t answer; aid_t req = async_send_1(exch, method, arg1, &answer); int rc = async_data_read_start(exch, id_buf, buf_size); loc_exchange_end(exch); if (rc != EOK) { async_forget(req); return rc; } sysarg_t retval; async_wait_for(req, &retval); if (retval != EOK) { return retval; } *act_size = IPC_GET_ARG1(answer); return EOK; }
/** Register new service. * * The @p interface is used when forwarding connection to the server. * If not 0, the first argument is the interface and the second argument * is the service ID. * * When the interface is zero (default), the first argument is directly * the handle (to ensure backward compatibility). * * @param fqsn Fully qualified service name * @param[out] sid Service ID of new service * @param interface Interface when forwarding * */ int loc_service_register_with_iface(const char *fqsn, service_id_t *sid, sysarg_t interface) { async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_SUPPLIER); ipc_call_t answer; aid_t req = async_send_2(exch, LOC_SERVICE_REGISTER, interface, 0, &answer); sysarg_t retval = async_data_write_start(exch, fqsn, str_size(fqsn)); loc_exchange_end(exch); if (retval != EOK) { async_forget(req); return retval; } async_wait_for(req, &retval); if (retval != EOK) { if (sid != NULL) *sid = -1; return retval; } if (sid != NULL) *sid = (service_id_t) IPC_GET_ARG1(answer); return retval; }
static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall, void *arg) { /* Ignore parameters, the connection is already opened */ while (true) { ipc_call_t call; ipc_callid_t callid = async_get_call(&call); int retval = EOK; if (!IPC_GET_IMETHOD(call)) { /* TODO: Handle hangup */ return; } switch (IPC_GET_IMETHOD(call)) { case ADB_REG_NOTIF: adb_kbd_reg0_data(IPC_GET_ARG1(call)); break; default: retval = ENOENT; } async_answer_0(callid, retval); } }
/** Handle one connection to APIC. * * @param iid Hash of the request that opened the connection. * @param icall Call data of the request that opened the connection. * @param arg Local argument. */ static void apic_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) { ipc_callid_t callid; ipc_call_t call; /* * Answer the first IPC_M_CONNECT_ME_TO call. */ async_answer_0(iid, EOK); while (true) { callid = async_get_call(&call); if (!IPC_GET_IMETHOD(call)) { /* The other side has hung up. */ async_answer_0(callid, EOK); return; } switch (IPC_GET_IMETHOD(call)) { case IRC_ENABLE_INTERRUPT: async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call))); break; case IRC_CLEAR_INTERRUPT: /* Noop */ async_answer_0(callid, EOK); break; default: async_answer_0(callid, EINVAL); break; } } }
static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call) { tcp_sockdata_t *sock; int sock_id; int rc; ipc_call_t answer; log_msg(LVL_DEBUG, "tcp_sock_socket()"); rc = tcp_sock_create(client, &sock); if (rc != EOK) { async_answer_0(callid, rc); return; } sock->laddr.ipv4 = TCP_IPV4_ANY; sock->lconn = NULL; sock->backlog = 0; sock_id = SOCKET_GET_SOCKET_ID(call); rc = tcp_sock_finish_setup(sock, &sock_id); if (rc != EOK) { tcp_sock_uncreate(sock); async_answer_0(callid, rc); return; } SOCKET_SET_SOCKET_ID(answer, sock_id); SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE); SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t)); async_answer_3(callid, EOK, IPC_GET_ARG1(answer), IPC_GET_ARG2(answer), IPC_GET_ARG3(answer)); }
static void kbdev_callback_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg) { kbdev_t *kbdev; int retval; int type, key; /* Kbdev device structure */ kbdev = arg; while (true) { ipc_call_t call; ipc_callid_t callid; callid = async_get_call(&call); if (!IPC_GET_IMETHOD(call)) { kbdev_destroy(kbdev); return; } switch (IPC_GET_IMETHOD(call)) { case KBDEV_EVENT: /* Got event from keyboard device */ retval = 0; type = IPC_GET_ARG1(call); key = IPC_GET_ARG2(call); kbd_push_event(kbdev->kbd_dev, type, key); break; default: retval = ENOTSUP; break; } async_answer_0(callid, retval); } }
int vbd_part_create(vbd_t *vbd, service_id_t disk, vbd_part_spec_t *pspec, vbd_part_id_t *rpart) { async_exch_t *exch; sysarg_t retval; ipc_call_t answer; exch = async_exchange_begin(vbd->sess); aid_t req = async_send_1(exch, VBD_PART_CREATE, disk, &answer); int rc = async_data_write_start(exch, pspec, sizeof(vbd_part_spec_t)); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return EIO; } async_wait_for(req, &retval); if (retval != EOK) return EIO; *rpart = (vbd_part_id_t)IPC_GET_ARG1(answer); return EOK; }
/** Add new Wake-On-LAN virtue. * * @param[in] dev_sess * @param[in] type Type of the virtue * @param[in] data Data required for this virtue * (depends on type) * @param[in] length Length of the data * @param[out] id Identifier of the new virtue * * @return EOK If the operation was successfully completed * */ int nic_wol_virtue_add(async_sess_t *dev_sess, nic_wv_type_t type, const void *data, size_t length, nic_wv_id_t *id) { assert(id); bool send_data = ((data != NULL) && (length != 0)); async_exch_t *exch = async_exchange_begin(dev_sess); ipc_call_t result; aid_t message_id = async_send_3(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_WOL_VIRTUE_ADD, (sysarg_t) type, send_data, &result); sysarg_t res; if (send_data) { int rc = async_data_write_start(exch, data, length); if (rc != EOK) { async_exchange_end(exch); async_wait_for(message_id, &res); return rc; } } async_exchange_end(exch); async_wait_for(message_id, &res); *id = IPC_GET_ARG1(result); return (int) res; }
/** Get information about the next received message from UDP service. * * @param udp UDP client * @param rmsg Place to store message information * * @return EOK on success or negative error code */ static int udp_rmsg_info(udp_t *udp, udp_rmsg_t *rmsg) { async_exch_t *exch; inet_ep_t ep; ipc_call_t answer; exch = async_exchange_begin(udp->sess); aid_t req = async_send_0(exch, UDP_RMSG_INFO, &answer); int rc = async_data_read_start(exch, &ep, sizeof(inet_ep_t)); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return rc; } sysarg_t retval; async_wait_for(req, &retval); if (retval != EOK) return retval; rmsg->udp = udp; rmsg->assoc_id = IPC_GET_ARG1(answer); rmsg->size = IPC_GET_ARG2(answer); rmsg->remote_ep = ep; return EOK; }
/** Get list of IDs into a buffer of fixed size. * * @param vbd Virtual Block Device * @param method IPC method * @param arg1 First argument * @param id_buf Buffer to store IDs * @param buf_size Buffer size * @param act_size Place to store actual size of complete data. * * @return EOK on success or negative error code. */ static int vbd_get_ids_once(vbd_t *vbd, sysarg_t method, sysarg_t arg1, sysarg_t *id_buf, size_t buf_size, size_t *act_size) { async_exch_t *exch = async_exchange_begin(vbd->sess); ipc_call_t answer; aid_t req = async_send_1(exch, method, arg1, &answer); int rc = async_data_read_start(exch, id_buf, buf_size); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return rc; } sysarg_t retval; async_wait_for(req, &retval); if (retval != EOK) { return retval; } *act_size = IPC_GET_ARG1(answer); return EOK; }
/** Handle data requests. * * @param fun ddf_fun_t function. * @param id callid * @param call IPC request. * */ void default_handler(ddf_fun_t *fun, ipc_callid_t id, ipc_call_t *call) { const sysarg_t method = IPC_GET_IMETHOD(*call); const size_t size = IPC_GET_ARG1(*call); switch (method) { case IPC_CHAR_READ: if (size <= 4 * sizeof(sysarg_t)) { sysarg_t message[4] = {}; i8042_read(fun, (char *) message, size); async_answer_4(id, size, message[0], message[1], message[2], message[3]); } else async_answer_0(id, ELIMIT); break; case IPC_CHAR_WRITE: if (size <= 3 * sizeof(sysarg_t)) { const sysarg_t message[3] = { IPC_GET_ARG2(*call), IPC_GET_ARG3(*call), IPC_GET_ARG4(*call) }; i8042_write(fun, (char *) message, size); async_answer_0(id, size); } else async_answer_0(id, ELIMIT); default: async_answer_0(id, EINVAL); } }
/** Default handler for IPC methods not handled by DDF. * * @param fun Device function handling the call. * @param icallid Call id. * @param icall Call data. * */ static void default_connection_handler(ddf_fun_t *fun, ipc_callid_t icallid, ipc_call_t *icall) { const sysarg_t method = IPC_GET_IMETHOD(*icall); xt_kbd_t *kbd = ddf_dev_data_get(ddf_fun_get_dev(fun)); switch (method) { case KBDEV_SET_IND: { /* * XT keyboards do not support setting mods, * assume AT keyboard with Scan Code Set 1. */ const unsigned mods = IPC_GET_ARG1(*icall); const uint8_t status = 0 | ((mods & KM_CAPS_LOCK) ? LI_CAPS : 0) | ((mods & KM_NUM_LOCK) ? LI_NUM : 0) | ((mods & KM_SCROLL_LOCK) ? LI_SCROLL : 0); uint8_t cmds[] = { KBD_CMD_SET_LEDS, status }; async_exch_t *exch = async_exchange_begin(kbd->parent_sess); const ssize_t size = chardev_write(exch, cmds, sizeof(cmds)); async_exchange_end(exch); async_answer_0(icallid, size < 0 ? size : EOK); break; } /* * This might be ugly but async_callback_receive_start makes no * difference for incorrect call and malloc failure. */ case IPC_M_CONNECT_TO_ME: { async_sess_t *sess = async_callback_receive_start(EXCHANGE_SERIALIZE, icall); /* Probably ENOMEM error, try again. */ if (sess == NULL) { ddf_msg(LVL_WARN, "Failed creating callback session"); async_answer_0(icallid, EAGAIN); break; } if (kbd->client_sess == NULL) { kbd->client_sess = sess; ddf_msg(LVL_DEBUG, "Set client session"); async_answer_0(icallid, EOK); } else { ddf_msg(LVL_ERROR, "Client session already set"); async_answer_0(icallid, ELIMIT); } break; } default: ddf_msg(LVL_ERROR, "Unknown method: %d.", (int)method); async_answer_0(icallid, EINVAL); break; } }
/** Character device connection handler */ static void cuda_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) { ipc_callid_t callid; ipc_call_t call; sysarg_t method; service_id_t dsid; int dev_addr, i; /* Get the device handle. */ dsid = IPC_GET_ARG1(*icall); /* Determine which disk device is the client connecting to. */ dev_addr = -1; for (i = 0; i < ADB_MAX_ADDR; i++) { if (adb_dev[i].service_id == dsid) dev_addr = i; } if (dev_addr < 0) { async_answer_0(iid, EINVAL); return; } /* Answer the IPC_M_CONNECT_ME_TO call. */ async_answer_0(iid, EOK); while (true) { callid = async_get_call(&call); method = IPC_GET_IMETHOD(call); if (!method) { /* The other side has hung up. */ async_answer_0(callid, EOK); return; } async_sess_t *sess = async_callback_receive_start(EXCHANGE_SERIALIZE, &call); if (sess != NULL) { if (adb_dev[dev_addr].client_sess == NULL) { adb_dev[dev_addr].client_sess = sess; /* * A hack so that we send the data to the session * regardless of which address the device is on. */ for (i = 0; i < ADB_MAX_ADDR; ++i) { if (adb_dev[i].service_id == dsid) adb_dev[i].client_sess = sess; } async_answer_0(callid, EOK); } else async_answer_0(callid, ELIMIT); } else async_answer_0(callid, EINVAL); } }
static void iplink_addr_remove_srv(iplink_srv_t *srv, ipc_callid_t callid, ipc_call_t *call) { int rc; iplink_srv_addr_t addr; addr.ipv4 = IPC_GET_ARG1(*call); rc = srv->ops->addr_remove(srv, &addr); async_answer_0(callid, rc); }
/** Callback when client connects to a telnet terminal. */ static void client_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) { /* Find the user. */ telnet_user_t *user = telnet_user_get_for_client_connection(IPC_GET_ARG1(*icall)); if (user == NULL) { async_answer_0(iid, ENOENT); return; } /* Handle messages. */ con_conn(iid, icall, &user->srvs); }
/** Interrupt handler routine. * * Write new data to the corresponding buffer. * * @param dev Device that caued the interrupt. * @param iid Call id. * @param call pointerr to call data. * */ static void i8042_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) { i8042_t *controller = dev_i8042(dev); const uint8_t status = IPC_GET_ARG1(*call); const uint8_t data = IPC_GET_ARG2(*call); buffer_t *buffer = (status & i8042_AUX_DATA) ? &controller->aux_buffer : &controller->kbd_buffer; buffer_write(buffer, data); }
static void notification_received(ipc_callid_t callid, ipc_call_t *call) { switch (IPC_GET_IMETHOD(*call)) { case VFS_TASK_STATE_CHANGE: if (IPC_GET_ARG1(*call) == VFS_PASS_HANDLE) vfs_pass_handle( (task_id_t) MERGE_LOUP32(IPC_GET_ARG4(*call), IPC_GET_ARG5(*call)), call->in_task_id, (int) IPC_GET_ARG2(*call)); break; default: break; } }
/** Forward a received call to another destination - slow version. * * This function is the slow verision of the sys_ipc_forward_fast interface. * It can copy all five new arguments and the new interface and method from * the userspace. It naturally extends the functionality of the fast version. * For system methods, it additionally stores the new value of arg3 to ARG4. * For non-system methods, it additionally stores the new value of arg3, arg4 * and arg5, respectively, to ARG3, ARG4 and ARG5, respectively. * * @param callid Hash of the call to forward. * @param phoneid Phone handle to use for forwarding. * @param data Userspace address of the new IPC data. * @param mode Flags that specify mode of the forward operation. * * @return 0 on succes, otherwise an error code. * */ sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t phoneid, ipc_data_t *data, unsigned int mode) { ipc_data_t newdata; int rc = copy_from_uspace(&newdata.args, &data->args, sizeof(newdata.args)); if (rc != 0) return (sysarg_t) rc; return sys_ipc_forward_common(callid, phoneid, IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata), IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata), IPC_GET_ARG4(newdata), IPC_GET_ARG5(newdata), mode, true); }
static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg) { ethip_nic_t *nic; service_id_t sid; sid = (service_id_t)IPC_GET_ARG1(*icall); log_msg(LOG_DEFAULT, LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid); nic = ethip_nic_find_by_iplink_sid(sid); if (nic == NULL) { log_msg(LOG_DEFAULT, LVL_WARN, "Uknown service ID."); return; } iplink_conn(iid, icall, &nic->iplink); }
static void connection_handler(ipc_callid_t iid, ipc_call_t *icall, void *arg) { logger_interface_t iface = IPC_GET_ARG1(*icall); switch (iface) { case LOGGER_INTERFACE_CONTROL: logger_connection_handler_control(iid); break; case LOGGER_INTERFACE_WRITER: logger_connection_handler_writer(iid); break; default: async_answer_0(iid, EINVAL); break; } }
/** Close the file in the endpoint FS server. */ static int vfs_file_close_remote(vfs_file_t *file) { assert(!file->refcnt); async_exch_t *exch = vfs_exchange_grab(file->node->fs_handle); ipc_call_t answer; aid_t msg = async_send_2(exch, VFS_OUT_CLOSE, file->node->service_id, file->node->index, &answer); vfs_exchange_release(exch); sysarg_t rc; async_wait_for(msg, &rc); return IPC_GET_ARG1(answer); }
static void inet_ev_recv(ipc_callid_t callid, ipc_call_t *call) { int rc; inet_dgram_t dgram; dgram.src.ipv4 = IPC_GET_ARG1(*call); dgram.dest.ipv4 = IPC_GET_ARG2(*call); dgram.tos = IPC_GET_ARG3(*call); rc = async_data_write_accept(&dgram.data, false, 0, 0, 0, &dgram.size); if (rc != EOK) { async_answer_0(callid, rc); return; } rc = inet_ev_ops->recv(&dgram); async_answer_0(callid, rc); }
static void iplink_send_srv(iplink_srv_t *srv, ipc_callid_t callid, ipc_call_t *call) { iplink_srv_sdu_t sdu; int rc; sdu.lsrc.ipv4 = IPC_GET_ARG1(*call); sdu.ldest.ipv4 = IPC_GET_ARG2(*call); rc = async_data_write_accept(&sdu.data, false, 0, 0, 0, &sdu.size); if (rc != EOK) { async_answer_0(callid, rc); return; } rc = srv->ops->send(srv, &sdu); free(sdu.data); async_answer_0(callid, rc); }
imagemap_handle_t fb_imagemap_create(async_sess_t *sess, imgmap_t *imgmap) { async_exch_t *exch = async_exchange_begin(sess); ipc_call_t answer; aid_t req = async_send_0(exch, FB_IMAGEMAP_CREATE, &answer); int rc = async_share_out_start(exch, imgmap, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE); async_exchange_end(exch); sysarg_t ret; async_wait_for(req, &ret); if ((rc != EOK) || (ret != EOK)) return 0; return (imagemap_handle_t) IPC_GET_ARG1(answer); }
/** Create new UDP association. * * Create a UDP association that allows sending and receiving messages. * * @a epp may specify remote address and port, in which case only messages * from that remote endpoint will be received. Also, that remote endpoint * is used as default when @c NULL is passed as destination to * udp_assoc_send_msg. * * @a epp may specify a local link or address. If it does not, the association * will listen on all local links/addresses. If @a epp does not specify * a local port number, a free dynamic port number will be allocated. * * The caller is informed about incoming data by invoking @a cb->recv_msg * * @param udp UDP client * @param epp Internet endpoint pair * @param cb Callbacks * @param arg Argument to callbacks * @param rassoc Place to store pointer to new association * * @return EOK on success or negative error code. */ int udp_assoc_create(udp_t *udp, inet_ep2_t *epp, udp_cb_t *cb, void *arg, udp_assoc_t **rassoc) { async_exch_t *exch; udp_assoc_t *assoc; ipc_call_t answer; assoc = calloc(1, sizeof(udp_assoc_t)); if (assoc == NULL) return ENOMEM; exch = async_exchange_begin(udp->sess); aid_t req = async_send_0(exch, UDP_ASSOC_CREATE, &answer); sysarg_t rc = async_data_write_start(exch, (void *)epp, sizeof(inet_ep2_t)); async_exchange_end(exch); if (rc != EOK) { sysarg_t rc_orig; async_wait_for(req, &rc_orig); if (rc_orig != EOK) rc = rc_orig; goto error; } async_wait_for(req, &rc); if (rc != EOK) goto error; assoc->udp = udp; assoc->id = IPC_GET_ARG1(answer); assoc->cb = cb; assoc->cb_arg = arg; list_append(&assoc->ludp, &udp->assoc); *rassoc = assoc; return EOK; error: free(assoc); return (int) rc; }
static void fault_event(ipc_callid_t callid, ipc_call_t *call) { const char *fname; char *s_taskid; int rc; task_id_t taskid; uintptr_t thread; taskid = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call)); thread = IPC_GET_ARG3(*call); if (asprintf(&s_taskid, "%" PRIu64, taskid) < 0) { printf("Memory allocation failed.\n"); return; } printf(NAME ": Task %" PRIu64 " fault in thread %p.\n", taskid, (void *) thread); fname = "/app/taskdump"; #ifdef CONFIG_WRITE_CORE_FILES char *dump_fname; if (asprintf(&dump_fname, "/data/core%" PRIu64, taskid) < 0) { printf("Memory allocation failed.\n"); return; } printf(NAME ": Executing %s -c %s -t %s\n", fname, dump_fname, s_taskid); rc = task_spawnl(NULL, fname, fname, "-c", dump_fname, "-t", s_taskid, NULL); #else printf(NAME ": Executing %s -t %s\n", fname, s_taskid); rc = task_spawnl(NULL, fname, fname, "-t", s_taskid, NULL); #endif if (rc != EOK) { printf("%s: Error spawning %s (%s).\n", NAME, fname, str_error(rc)); } }
frontbuf_handle_t fb_frontbuf_create(async_sess_t *sess, screenbuffer_t *frontbuf) { async_exch_t *exch = async_exchange_begin(sess); ipc_call_t answer; aid_t req = async_send_0(exch, FB_FRONTBUF_CREATE, &answer); int rc = async_share_out_start(exch, frontbuf, AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE); async_exchange_end(exch); sysarg_t ret; async_wait_for(req, &ret); if ((rc != EOK) || (ret != EOK)) return 0; return (frontbuf_handle_t) IPC_GET_ARG1(answer); }
/** Get category ID. * * Provided name of a category, return its ID. * * @param name Category name * @param cat_id Place to store ID * @param flags IPC_FLAG_BLOCKING to wait for location service to start * @return EOK on success or negative error code */ int loc_category_get_id(const char *name, category_id_t *cat_id, unsigned int flags) { async_exch_t *exch; if (flags & IPC_FLAG_BLOCKING) exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER); else { exch = loc_exchange_begin(LOC_PORT_CONSUMER); if (exch == NULL) return errno; } ipc_call_t answer; aid_t req = async_send_0(exch, LOC_CATEGORY_GET_ID, &answer); sysarg_t retval = async_data_write_start(exch, name, str_size(name)); loc_exchange_end(exch); if (retval != EOK) { async_forget(req); return retval; } async_wait_for(req, &retval); if (retval != EOK) { if (cat_id != NULL) *cat_id = (category_id_t) -1; return retval; } if (cat_id != NULL) *cat_id = (category_id_t) IPC_GET_ARG1(answer); return retval; }
/** * Register a named application context to the audio server. * @param sess Valid audio session. * @param name Valid string identifier * @param record True if the application context wishes to receive data. * @return Valid ID on success, Error code on failure. */ hound_context_id_t hound_service_register_context(hound_sess_t *sess, const char *name, bool record) { assert(sess); assert(name); ipc_call_t call; async_exch_t *exch = async_exchange_begin(sess); aid_t mid = async_send_1(exch, IPC_M_HOUND_CONTEXT_REGISTER, record, &call); int ret = mid ? EOK : EPARTY; if (ret == EOK) ret = async_data_write_start(exch, name, str_size(name)); else async_forget(mid); if (ret == EOK) async_wait_for(mid, (sysarg_t *)&ret); async_exchange_end(exch); return ret == EOK ? (hound_context_id_t)IPC_GET_ARG1(call) : ret; }