/** Get a list of all virtues of the specified type. * * When NIC_WV_NONE is specified as the virtue type the function * lists virtues of all types. * * @param[in] dev_sess * @param[in] type Type of the virtues * @param[in] max_count Maximum number of ids that can be * written into the list buffer. * @param[out] id_list Buffer for to the list of virtue ids. * Can be NULL. * @param[out] id_count Number of virtue identifiers in the list * before possible truncation due to the * max_count. Can be NULL. * * @return EOK If the operation was successfully completed * */ int nic_wol_virtue_list(async_sess_t *dev_sess, nic_wv_type_t type, size_t max_count, nic_wv_id_t *id_list, size_t *id_count) { if (id_list == NULL) max_count = 0; async_exch_t *exch = async_exchange_begin(dev_sess); sysarg_t count; int rc = async_req_3_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_WOL_VIRTUE_LIST, (sysarg_t) type, max_count, &count); if (id_count) *id_count = (size_t) count; if ((rc != EOK) || (!max_count)) { async_exchange_end(exch); return rc; } rc = async_data_read_start(exch, id_list, max_count * sizeof(nic_wv_id_t)); async_exchange_end(exch); return rc; }
/** Send formatted message to the logger service. * * @param session Initialized IPC session with the logger. * @param log Log to use. * @param level Verbosity level of the message. * @param message The actual message. * @return Error code of the conversion or EOK on success. */ static int logger_message(async_sess_t *session, log_t log, log_level_t level, char *message) { async_exch_t *exchange = async_exchange_begin(session); if (exchange == NULL) { return ENOMEM; } if (log == LOG_DEFAULT) log = default_log_id; // FIXME: remove when all USB drivers use libc logging explicitly str_rtrim(message, '\n'); aid_t reg_msg = async_send_2(exchange, LOGGER_WRITER_MESSAGE, log, level, NULL); int rc = async_data_write_start(exchange, message, str_size(message)); sysarg_t reg_msg_rc; async_wait_for(reg_msg, ®_msg_rc); async_exchange_end(exchange); /* * Getting ENAK means no-one wants our message. That is not an * error at all. */ if (rc == ENAK) rc = EOK; if (rc != EOK) { return rc; } return reg_msg_rc; }
/** Set current working directory for the loaded task. * * Sets the current working directory for the loaded task. * * @param ldr Loader connection structure. * * @return Zero on success or negative error code. * */ int loader_set_cwd(loader_t *ldr) { char *cwd = (char *) malloc(MAX_PATH_LEN + 1); if (!cwd) return ENOMEM; if (!getcwd(cwd, MAX_PATH_LEN + 1)) str_cpy(cwd, MAX_PATH_LEN + 1, "/"); size_t len = str_length(cwd); async_exch_t *exch = async_exchange_begin(ldr->sess); ipc_call_t answer; aid_t req = async_send_0(exch, LOADER_SET_CWD, &answer); sysarg_t rc = async_data_write_start(exch, cwd, len); async_exchange_end(exch); free(cwd); if (rc != EOK) { async_forget(req); return (int) rc; } async_wait_for(req, &rc); return (int) rc; }
/** Set pathname of the program to load. * * Sets the name of the program file to load. The name can be relative * to the current working directory (it will be absolutized before * sending to the loader). * * @param ldr Loader connection structure. * @param path Pathname of the program file. * * @return Zero on success or negative error code. * */ int loader_set_pathname(loader_t *ldr, const char *path) { size_t pa_len; char *pa = absolutize(path, &pa_len); if (!pa) return ENOMEM; /* Send program pathname */ async_exch_t *exch = async_exchange_begin(ldr->sess); ipc_call_t answer; aid_t req = async_send_0(exch, LOADER_SET_PATHNAME, &answer); sysarg_t rc = async_data_write_start(exch, (void *) pa, pa_len); async_exchange_end(exch); free(pa); if (rc != EOK) { async_forget(req); return (int) rc; } async_wait_for(req, &rc); return (int) rc; }
/** Connect the device to the virtual host controller. * * @param dev The virtual device to be (virtually) plugged in. * @param vhc_path Devman path to the virtual host controller. * @return Error code. */ int usbvirt_device_plug(usbvirt_device_t *dev, const char *vhc_path) { if (DEV != NULL) return ELIMIT; devman_handle_t handle; int rc = devman_fun_get_handle(vhc_path, &handle, 0); if (rc != EOK) return rc; async_sess_t *hcd_sess = devman_device_connect(handle, 0); if (!hcd_sess) return ENOMEM; DEV = dev; dev->vhc_sess = hcd_sess; async_exch_t *exch = async_exchange_begin(hcd_sess); port_id_t port; rc = async_create_callback_port(exch, INTERFACE_USBVIRT_CB, 0, 0, callback_connection, NULL, &port); async_exchange_end(exch); if (rc != EOK) DEV = NULL; return rc; }
/** 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; }
/** Send message via UDP association. * * @param assoc Association * @param dest Destination endpoint or @c NULL to use association's remote ep. * @param data Message data * @param bytes Message size in bytes * * @return EOK on success or negative error code */ int udp_assoc_send_msg(udp_assoc_t *assoc, inet_ep_t *dest, void *data, size_t bytes) { async_exch_t *exch; exch = async_exchange_begin(assoc->udp->sess); aid_t req = async_send_1(exch, UDP_ASSOC_SEND_MSG, assoc->id, NULL); sysarg_t rc = async_data_write_start(exch, (void *)dest, sizeof(inet_ep_t)); if (rc != EOK) { async_exchange_end(exch); async_forget(req); return rc; } rc = async_data_write_start(exch, data, bytes); if (rc != EOK) { async_forget(req); return rc; } async_exchange_end(exch); if (rc != EOK) { async_forget(req); return rc; } async_wait_for(req, &rc); return rc; }
/** Set preset files for the program. * * Sets the vector of preset files to be passed to the loaded * program. By convention, the first three files represent stdin, * stdout and stderr respectively. * * @param ldr Loader connection structure. * @param files NULL-terminated array of pointers to files. * * @return Zero on success or negative error code. * */ int loader_set_files(loader_t *ldr, int * const files[]) { /* Send serialized files to the loader */ async_exch_t *exch = async_exchange_begin(ldr->sess); async_exch_t *vfs_exch = vfs_exchange_begin(); int i; for (i = 0; files[i]; i++); ipc_call_t answer; aid_t req = async_send_1(exch, LOADER_SET_FILES, i, &answer); sysarg_t rc = EOK; for (i = 0; files[i]; i++) { rc = async_state_change_start(exch, VFS_PASS_HANDLE, *files[i], 0, vfs_exch); if (rc != EOK) break; } vfs_exchange_end(vfs_exch); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return (int) rc; } async_wait_for(req, &rc); return (int) rc; }
static void emit_event(const isdv4_event_t *event) { fibril_mutex_lock(&client_mutex); async_sess_t *sess = client_sess; fibril_mutex_unlock(&client_mutex); if (!sess) return; async_exch_t *exch = async_exchange_begin(sess); if (exch) { unsigned int max_x = state.stylus_max_x; unsigned int max_y = state.stylus_max_y; if (event->source == TOUCH) { max_x = state.touch_max_x; max_y = state.touch_max_y; } async_msg_4(exch, MOUSEEV_ABS_MOVE_EVENT, event->x, event->y, max_x, max_y); if (event->type == PRESS || event->type == RELEASE) { async_msg_2(exch, MOUSEEV_BUTTON_EVENT, event->button, event->type == PRESS); } } async_exchange_end(exch); }
/** Load the frame that issued the wakeup. * * The NIC can support only matched_type, only part of the frame * can be available or not at all. Sometimes even the type can be * uncertain -- in this case the matched_type contains NIC_WV_NONE. * * Frame_length can be greater than max_length, but at most max_length * bytes will be copied into the frame buffer. * * Note: Only the type of the filter can be detected, not the concrete * filter, because the driver is probably not running when the wakeup * is issued. * * @param[in] dev_sess * @param[out] matched_type Type of the filter that issued wakeup. * @param[in] max_length Size of the buffer * @param[out] frame Buffer for the frame. Can be NULL. * @param[out] frame_length Length of the stored frame. Can be NULL. * * @return EOK If the operation was successfully completed * */ int nic_wol_load_info(async_sess_t *dev_sess, nic_wv_type_t *matched_type, size_t max_length, uint8_t *frame, size_t *frame_length) { assert(matched_type); sysarg_t _matched_type; sysarg_t _frame_length; if (frame == NULL) max_length = 0; async_exch_t *exch = async_exchange_begin(dev_sess); int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_WOL_LOAD_INFO, max_length, &_matched_type, &_frame_length); if (rc != EOK) { async_exchange_end(exch); return rc; } *matched_type = (nic_wv_type_t) _matched_type; if (frame_length) *frame_length = (size_t) _frame_length; if ((max_length != 0) && (_frame_length != 0)) rc = async_data_read_start(exch, frame, max_length); async_exchange_end(exch); return rc; }
int iplink_ev_recv(iplink_srv_t *srv, iplink_srv_sdu_t *sdu) { if (srv->client_sess == NULL) return EIO; async_exch_t *exch = async_exchange_begin(srv->client_sess); ipc_call_t answer; aid_t req = async_send_2(exch, IPLINK_EV_RECV, sdu->lsrc.ipv4, sdu->ldest.ipv4, &answer); int rc = async_data_write_start(exch, sdu->data, sdu->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; return EOK; }
static int adb_port_init(kbd_dev_t *kdev) { kbd_dev = kdev; const char *dev = "adb/kbd"; service_id_t service_id; int rc = loc_service_get_id(dev, &service_id, 0); if (rc != EOK) return rc; dev_sess = loc_service_connect(EXCHANGE_ATOMIC, service_id, 0); if (dev_sess == NULL) { printf("%s: Failed to connect to device\n", NAME); return ENOENT; } async_exch_t *exch = async_exchange_begin(dev_sess); if (exch == NULL) { printf("%s: Failed starting exchange with device\n", NAME); async_hangup(dev_sess); return ENOMEM; } rc = async_connect_to_me(exch, 0, 0, 0, kbd_port_events, NULL); async_exchange_end(exch); if (rc != EOK) { printf("%s: Failed to create callback from device\n", NAME); async_hangup(dev_sess); return rc; } return EOK; }
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; }
/** 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; }
/** 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; } }
int fb_pointer_update(async_sess_t *sess, sysarg_t x, sysarg_t y, bool visible) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_3_0(exch, FB_POINTER_UPDATE, x, y, visible); async_exchange_end(exch); return ret; }
int fb_claim(async_sess_t *sess) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_0_0(exch, FB_CLAIM); async_exchange_end(exch); return ret; }
int fb_yield(async_sess_t *sess) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_0_0(exch, FB_YIELD); async_exchange_end(exch); return ret; }
int fb_get_resolution(async_sess_t *sess, sysarg_t *maxx, sysarg_t *maxy) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_0_2(exch, FB_GET_RESOLUTION, maxx, maxy); async_exchange_end(exch); return ret; }
static void tcp_sock_notify_aconn(socket_core_t *lsock_core) { log_msg(LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id); async_exch_t *exch = async_exchange_begin(lsock_core->sess); async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id, TCP_SOCK_FRAGMENT_SIZE, 0, 0, 0); async_exchange_end(exch); }
static void tcp_sock_notify_data(socket_core_t *sock_core) { log_msg(LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id); async_exch_t *exch = async_exchange_begin(sock_core->sess); async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id, TCP_SOCK_FRAGMENT_SIZE, 0, 0, 1); async_exchange_end(exch); }
/** Request the driver to poll the NIC. * * @param[in] dev_sess * * @return EOK If the operation was successfully completed * */ int nic_poll_now(async_sess_t *dev_sess) { async_exch_t *exch = async_exchange_begin(dev_sess); int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_NOW); async_exchange_end(exch); return rc; }
int win_grab(async_sess_t *sess, sysarg_t pos_id, sysarg_t grab_flags) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_2_0(exch, WINDOW_GRAB, pos_id, grab_flags); async_exchange_end(exch); return ret; }
int graph_dev_connect(async_sess_t *sess) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_1_0(exch, DEV_IFACE_ID(GRAPH_DEV_IFACE), GRAPH_DEV_CONNECT); async_exchange_end(exch); return ret; }
/** Instruct loader to load the program. * * If this function succeeds, the program has been successfully loaded * and is ready to be executed. * * @param ldr Loader connection structure. * * @return Zero on success or negative error code. * */ int loader_load_program(loader_t *ldr) { async_exch_t *exch = async_exchange_begin(ldr->sess); int rc = async_req_0_0(exch, LOADER_LOAD); async_exchange_end(exch); return rc; }
int win_close_request(async_sess_t *sess) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_0_0(exch, WINDOW_CLOSE_REQUEST); async_exchange_end(exch); return ret; }
static int inet_set_proto(uint8_t protocol) { async_exch_t *exch = async_exchange_begin(inet_sess); int rc = async_req_1_0(exch, INET_SET_PROTO, protocol); async_exchange_end(exch); return rc; }
/** Connect to specified network. * * @param[in] dev_sess Device session. * @param[in] ssid_start Network SSID prefix. * @param[in] password Network password (pass empty string if not needed). * * @return EOK If the operation was successfully completed, * negative error code otherwise. * */ int ieee80211_connect(async_sess_t *dev_sess, char *ssid_start, char *password) { assert(ssid_start); sysarg_t rc_orig; async_exch_t *exch = async_exchange_begin(dev_sess); aid_t aid = async_send_1(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE), IEEE80211_CONNECT, NULL); sysarg_t rc = async_data_write_start(exch, ssid_start, str_size(ssid_start) + 1); if (rc != EOK) { async_exchange_end(exch); async_wait_for(aid, &rc_orig); if (rc_orig == EOK) return (int) rc; return (int) rc_orig; } // FIXME: Typecasting string literal if (password == NULL) password = (char *) ""; rc = async_data_write_start(exch, password, str_size(password) + 1); if (rc != EOK) { async_exchange_end(exch); async_wait_for(aid, &rc_orig); if (rc_orig == EOK) return (int) rc; return (int) rc_orig; } async_exchange_end(exch); async_wait_for(aid, &rc); if (rc != EOK) return rc; /* Send DHCP discover. */ nic_address_t wifi_mac; rc = nic_get_address(dev_sess, &wifi_mac); if (rc != EOK) return rc; sysarg_t link_id = get_link_id(wifi_mac.address); if (link_id == ((sysarg_t) -1)) return EINVAL; rc = dhcp_discover(link_id); return (int) rc; }
/** Start an async exchange on the loc session (blocking). * * @param iface Location service interface to choose * * @return New exchange. * */ async_exch_t *loc_exchange_begin_blocking(loc_interface_t iface) { switch (iface) { case LOC_PORT_SUPPLIER: fibril_mutex_lock(&loc_supp_block_mutex); while (loc_supp_block_sess == NULL) { clone_session(&loc_supplier_mutex, loc_supplier_sess, &loc_supp_block_sess); if (loc_supp_block_sess == NULL) loc_supp_block_sess = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOC, LOC_PORT_SUPPLIER, 0); } fibril_mutex_unlock(&loc_supp_block_mutex); clone_session(&loc_supplier_mutex, loc_supp_block_sess, &loc_supplier_sess); return async_exchange_begin(loc_supp_block_sess); case LOC_PORT_CONSUMER: fibril_mutex_lock(&loc_cons_block_mutex); while (loc_cons_block_sess == NULL) { clone_session(&loc_consumer_mutex, loc_consumer_sess, &loc_cons_block_sess); if (loc_cons_block_sess == NULL) loc_cons_block_sess = service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_LOC, LOC_PORT_CONSUMER, 0); } fibril_mutex_unlock(&loc_cons_block_mutex); clone_session(&loc_consumer_mutex, loc_cons_block_sess, &loc_consumer_sess); return async_exchange_begin(loc_cons_block_sess); default: return NULL; } }
int win_damage(async_sess_t *sess, sysarg_t x, sysarg_t y, sysarg_t width, sysarg_t height) { async_exch_t *exch = async_exchange_begin(sess); int ret = async_req_4_0(exch, WINDOW_DAMAGE, x, y, width, height); async_exchange_end(exch); return ret; }