/** * Query audio mixer for basic info (name and items count). * @param[in] exch IPC exchange connected to the device * @param[out] name Audio mixer string identifier * @param[out] items Number of items controlled by the mixer. * @return Error code. */ int audio_mixer_get_info(async_exch_t *exch, const char **name, unsigned *items) { if (!exch) return EINVAL; sysarg_t name_size, itemc; const int ret = async_req_1_2(exch, DEV_IFACE_ID(AUDIO_MIXER_IFACE), IPC_M_AUDIO_MIXER_GET_INFO, &name_size, &itemc); if (ret == EOK && name) { char *name_place = calloc(1, name_size); if (!name_place) { /* Make the other side fail * as it waits for read request */ async_data_read_start(exch, (void*)-1, 0); return ENOMEM; } const int ret = async_data_read_start(exch, name_place, name_size); if (ret != EOK) { free(name_place); return ret; } *name = name_place; } if (ret == EOK && items) *items = itemc; return ret; }
/** 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; }
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; }
/** 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; }
/** Retrieve current settings of multicast frames reception. * * Note: In case of mode != NIC_MULTICAST_LIST the contents of * address_list and address_count are undefined. * * @param[in] dev_sess * @param[out] mode Current operation mode * @param[in] max_count Maximal number of addresses that could * be written into the list buffer. * @param[out] address_list Buffer for the list (array). Can be NULL. * @param[out] address_count Number of addresses in the list before * possible truncation due to the max_count. * Can be NULL. * * @return EOK If the operation was successfully completed * */ int nic_multicast_get_mode(async_sess_t *dev_sess, nic_multicast_mode_t *mode, size_t max_count, nic_address_t *address_list, size_t *address_count) { assert(mode); sysarg_t _mode; if (!address_list) max_count = 0; async_exch_t *exch = async_exchange_begin(dev_sess); sysarg_t ac; int rc = async_req_2_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_MULTICAST_GET_MODE, max_count, &_mode, &ac); if (rc != EOK) { async_exchange_end(exch); return rc; } *mode = (nic_multicast_mode_t) _mode; if (address_count) *address_count = (size_t) ac; if ((max_count) && (ac)) rc = async_data_read_start(exch, address_list, max_count * sizeof(nic_address_t)); async_exchange_end(exch); return rc; }
/** Retrieve the currently blocked source MAC addresses. * * @param[in] dev_sess * @param[in] max_count Maximal number of addresses that could * be written into the list buffer. * @param[out] address_list Buffer for the list (array). Can be NULL. * @param[out] address_count Number of addresses in the list before * possible truncation due to the max_count. * * @return EOK If the operation was successfully completed * */ int nic_blocked_sources_get(async_sess_t *dev_sess, size_t max_count, nic_address_t *address_list, size_t *address_count) { if (!address_list) max_count = 0; async_exch_t *exch = async_exchange_begin(dev_sess); sysarg_t ac; int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_BLOCKED_SOURCES_GET, max_count, &ac); if (rc != EOK) { async_exchange_end(exch); return rc; } if (address_count) *address_count = (size_t) ac; if ((max_count) && (ac)) rc = async_data_read_start(exch, address_list, max_count * sizeof(nic_address_t)); async_exchange_end(exch); 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; }
/** Get information about virtue. * * @param[in] dev_sess * @param[in] id Virtue identifier * @param[out] type Type of the filter. Can be NULL. * @param[out] max_length Size of the data buffer. * @param[out] data Buffer for data used when the * virtue was created. Can be NULL. * @param[out] length Length of the data. Can be NULL. * * @return EOK If the operation was successfully completed * */ int nic_wol_virtue_probe(async_sess_t *dev_sess, nic_wv_id_t id, nic_wv_type_t *type, size_t max_length, void *data, size_t *length) { sysarg_t _type; sysarg_t _length; if (data == NULL) max_length = 0; async_exch_t *exch = async_exchange_begin(dev_sess); int rc = async_req_3_2(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_WOL_VIRTUE_PROBE, (sysarg_t) id, max_length, &_type, &_length); if (rc != EOK) { async_exchange_end(exch); return rc; } if (type) *type = _type; if (length) *length = _length; if ((max_length) && (_length != 0)) rc = async_data_read_start(exch, data, max_length); async_exchange_end(exch); return rc; }
/** 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; }
size_t loc_get_services(service_id_t ns_handle, loc_sdesc_t **data) { /* Loop until read is succesful */ while (true) { async_exch_t *exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER); size_t count = loc_count_services_internal(exch, ns_handle); loc_exchange_end(exch); if (count == 0) return 0; loc_sdesc_t *devs = (loc_sdesc_t *) calloc(count, sizeof(loc_sdesc_t)); if (devs == NULL) return 0; exch = loc_exchange_begin(LOC_PORT_CONSUMER); ipc_call_t answer; aid_t req = async_send_1(exch, LOC_GET_SERVICES, ns_handle, &answer); int rc = async_data_read_start(exch, devs, count * sizeof(loc_sdesc_t)); loc_exchange_end(exch); if (rc == EOVERFLOW) { /* * Number of services has changed since * the last call of LOC_GET_SERVICE_COUNT */ free(devs); continue; } if (rc != EOK) { async_forget(req); free(devs); return 0; } sysarg_t retval; async_wait_for(req, &retval); if (retval != EOK) return 0; *data = devs; return count; } }
int ahci_get_sata_device_name(async_sess_t *sess, size_t sata_dev_name_length, char *sata_dev_name) { async_exch_t *exch = async_exchange_begin(sess); if (!exch) return EINVAL; aid_t req = async_send_2(exch, DEV_IFACE_ID(AHCI_DEV_IFACE), IPC_M_AHCI_GET_SATA_DEVICE_NAME, sata_dev_name_length, NULL); async_data_read_start(exch, sata_dev_name, sata_dev_name_length); sysarg_t rc; async_wait_for(req, &rc); return rc; }
/** Request current VLAN filtering mask. * * @param[in] dev_sess * @param[out] stats Structure with the statistics * * @return EOK If the operation was successfully completed * */ int nic_vlan_get_mask(async_sess_t *dev_sess, nic_vlan_mask_t *mask) { assert(mask); async_exch_t *exch = async_exchange_begin(dev_sess); int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_VLAN_GET_MASK); if (rc != EOK) { async_exchange_end(exch); return rc; } rc = async_data_read_start(exch, mask, sizeof(nic_vlan_mask_t)); async_exchange_end(exch); return rc; }
/** Request the MAC address of the device * * @param[in] dev_sess * @param[out] address Structure with buffer for the address * * @return EOK If the operation was successfully completed * */ int nic_get_address(async_sess_t *dev_sess, nic_address_t *address) { assert(address); async_exch_t *exch = async_exchange_begin(dev_sess); aid_t aid = async_send_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_GET_ADDRESS, NULL); int rc = async_data_read_start(exch, address, sizeof(nic_address_t)); async_exchange_end(exch); sysarg_t res; async_wait_for(aid, &res); if (rc != EOK) return rc; return (int) res; }
/** Request information about the device. * * @see nic_device_info_t * * @param[in] dev_sess * @param[out] device_info Information about the device * * @return EOK If the operation was successfully completed * */ int nic_get_device_info(async_sess_t *dev_sess, nic_device_info_t *device_info) { assert(device_info); async_exch_t *exch = async_exchange_begin(dev_sess); int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_GET_DEVICE_INFO); if (rc != EOK) { async_exchange_end(exch); return rc; } rc = async_data_read_start(exch, device_info, sizeof(nic_device_info_t)); async_exchange_end(exch); return rc; }
/** Get ID of the new task. * * Retrieves the ID of the new task from the loader. * * @param ldr Loader connection structure. * @param task_id Points to a variable where the ID should be stored. * * @return Zero on success or negative error code. * */ int loader_get_task_id(loader_t *ldr, task_id_t *task_id) { /* Get task ID. */ async_exch_t *exch = async_exchange_begin(ldr->sess); ipc_call_t answer; aid_t req = async_send_0(exch, LOADER_GET_TASKID, &answer); sysarg_t rc = async_data_read_start(exch, task_id, sizeof(task_id_t)); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return (int) rc; } async_wait_for(req, &rc); return (int) rc; }
/** Request statistic data about NIC operation. * * @param[in] dev_sess * @param[out] stats Structure with the statistics * * @return EOK If the operation was successfully completed * */ int nic_get_stats(async_sess_t *dev_sess, nic_device_stats_t *stats) { assert(stats); async_exch_t *exch = async_exchange_begin(dev_sess); int rc = async_req_1_0(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_GET_STATS); if (rc != EOK) { async_exchange_end(exch); return rc; } rc = async_data_read_start(exch, stats, sizeof(nic_device_stats_t)); async_exchange_end(exch); return rc; }
/** Get scan results from IEEE 802.11 device * * @param[in] dev_sess Device session. * @param[out] results Structure where to put scan results. * * @return EOK If the operation was successfully completed, * negative error code otherwise. * */ int ieee80211_get_scan_results(async_sess_t *dev_sess, ieee80211_scan_results_t *results, bool now) { assert(results); async_exch_t *exch = async_exchange_begin(dev_sess); aid_t aid = async_send_2(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE), IEEE80211_GET_SCAN_RESULTS, now, NULL); int rc = async_data_read_start(exch, results, sizeof(ieee80211_scan_results_t)); async_exchange_end(exch); sysarg_t res; async_wait_for(aid, &res); if(res != EOK) return (int) res; return rc; }
int bd_read_toc(bd_t *bd, uint8_t session, void *buf, size_t size) { async_exch_t *exch = async_exchange_begin(bd->sess); ipc_call_t answer; aid_t req = async_send_1(exch, BD_READ_TOC, session, &answer); int rc = async_data_read_start(exch, 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; return EOK; }
/** Get disk information. */ int vbd_disk_info(vbd_t *vbd, service_id_t sid, vbd_disk_info_t *vinfo) { 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_DISK_INFO, sid, &answer); int rc = async_data_read_start(exch, vinfo, sizeof(vbd_disk_info_t)); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return EIO; } async_wait_for(req, &retval); if (retval != EOK) return EIO; return EOK; }
int vbd_part_get_info(vbd_t *vbd, vbd_part_id_t part, vbd_part_info_t *pinfo) { 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_GET_INFO, part, &answer); int rc = async_data_read_start(exch, pinfo, sizeof(vbd_part_info_t)); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return EIO; } async_wait_for(req, &retval); if (retval != EOK) return EIO; return EOK; }
int win_get_event(async_sess_t *sess, window_event_t *event) { async_exch_t *exch = async_exchange_begin(sess); ipc_call_t answer; aid_t req = async_send_0(exch, WINDOW_GET_EVENT, &answer); int rc = async_data_read_start(exch, event, sizeof(window_event_t)); async_exchange_end(exch); sysarg_t ret; async_wait_for(req, &ret); if (rc != EOK) { return rc; } else if (ret != EOK) { return ret; } else { return EOK; } }
/** Read part of received message. * * @param rmsg Received message * @param off Start offset * @param buf Buffer for storing data * @param bsize Buffer size * * @return EOK on success or negative error code. */ int udp_rmsg_read(udp_rmsg_t *rmsg, size_t off, void *buf, size_t bsize) { async_exch_t *exch; ipc_call_t answer; exch = async_exchange_begin(rmsg->udp->sess); aid_t req = async_send_1(exch, UDP_RMSG_READ, off, &answer); int rc = async_data_read_start(exch, buf, bsize); 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; }
/** Read the current time from the device * * @param sess Session of the device * @param t The current time that will be read from the device * * @return EOK on success or a negative error code */ int clock_dev_time_get(async_sess_t *sess, struct tm *t) { aid_t req; int ret; async_exch_t *exch = async_exchange_begin(sess); req = async_send_1(exch, DEV_IFACE_ID(CLOCK_DEV_IFACE), CLOCK_DEV_TIME_GET, NULL); ret = async_data_read_start(exch, t, sizeof(*t)); async_exchange_end(exch); sysarg_t rc; if (ret != EOK) { async_forget(req); return ret; } async_wait_for(req, &rc); return (int)rc; }
int bd_read_blocks(bd_t *bd, aoff64_t ba, size_t cnt, void *data, size_t size) { async_exch_t *exch = async_exchange_begin(bd->sess); ipc_call_t answer; aid_t req = async_send_3(exch, BD_READ_BLOCKS, LOWER32(ba), UPPER32(ba), cnt, &answer); int rc = async_data_read_start(exch, data, 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; }
/** Suggest partition type based on partition content. * * @param vbd Virtual Block Device * @param disk Disk on which the partition will be created * @param pcnt Partition content * @param ptype Place to store suggested partition type * * @return EOK on success or negative error code */ int vbd_suggest_ptype(vbd_t *vbd, service_id_t disk, label_pcnt_t pcnt, label_ptype_t *ptype) { async_exch_t *exch; sysarg_t retval; ipc_call_t answer; exch = async_exchange_begin(vbd->sess); aid_t req = async_send_2(exch, VBD_SUGGEST_PTYPE, disk, pcnt, &answer); int rc = async_data_read_start(exch, ptype, sizeof(label_ptype_t)); async_exchange_end(exch); if (rc != EOK) { async_forget(req); return EIO; } async_wait_for(req, &retval); if (retval != EOK) return EIO; return EOK; }
/** Read to or write from device. * * Helper function to read to or write from a device * using its character interface. * * @param sess Session to the device. * @param buf Buffer for the data read from or written to the device. * @param size Maximum size of data (in bytes) to be read or written. * @param read Read from the device if true, write to it otherwise. * * @return Non-negative number of bytes actually read from or * written to the device on success, negative error number * otherwise. * */ static ssize_t char_dev_rw(async_sess_t *sess, void *buf, size_t size, bool read) { ipc_call_t answer; aid_t req; int ret; async_exch_t *exch = async_exchange_begin(sess); if (read) { req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE), CHAR_DEV_READ, &answer); ret = async_data_read_start(exch, buf, size); } else { req = async_send_1(exch, DEV_IFACE_ID(CHAR_DEV_IFACE), CHAR_DEV_WRITE, &answer); ret = async_data_write_start(exch, buf, size); } async_exchange_end(exch); sysarg_t rc; if (ret != EOK) { async_wait_for(req, &rc); if (rc == EOK) return (ssize_t) ret; return (ssize_t) rc; } async_wait_for(req, &rc); ret = (int) rc; if (ret != EOK) return (ssize_t) ret; return (ssize_t) IPC_GET_ARG1(answer); }
/** Query the current interrupt/poll mode of the NIC * * @param[in] dev_sess * @param[out] mode Current poll mode * @param[out] period Period used in periodic polling. * Can be NULL. * * @return EOK If the operation was successfully completed * */ int nic_poll_get_mode(async_sess_t *dev_sess, nic_poll_mode_t *mode, struct timeval *period) { assert(mode); sysarg_t _mode; async_exch_t *exch = async_exchange_begin(dev_sess); int rc = async_req_2_1(exch, DEV_IFACE_ID(NIC_DEV_IFACE), NIC_POLL_GET_MODE, period != NULL, &_mode); if (rc != EOK) { async_exchange_end(exch); return rc; } *mode = (nic_poll_mode_t) _mode; if (period != NULL) rc = async_data_read_start(exch, period, sizeof(struct timeval)); async_exchange_end(exch); return rc; }
/** * Retrieve a list of server side actors. * @param[in] sess Valid audio session. * @param[out] ids list of string identifiers. * @param[out] count Number of elements int the @p ids list. * @param[in] flags list requirements. * @param[in] connection name of target actor. Used only if the list should * contain connected actors. * @retval Error code. */ int hound_service_get_list(hound_sess_t *sess, const char ***ids, size_t *count, int flags, const char *connection) { assert(sess); assert(ids); assert(count); if (connection && !(flags & HOUND_CONNECTED)) return EINVAL; async_exch_t *exch = async_exchange_begin(sess); if (!exch) return ENOMEM; ipc_call_t res_call; aid_t mid = async_send_3(exch, IPC_M_HOUND_GET_LIST, flags, *count, (bool)connection, &res_call); int ret = EOK; if (mid && connection) ret = async_data_write_start(exch, connection, str_size(connection)); if (ret == EOK) async_wait_for(mid, (sysarg_t*)&ret); if (ret != EOK) { async_exchange_end(exch); return ret; } unsigned name_count = IPC_GET_ARG1(res_call); /* Start receiving names */ const char **names = NULL; if (name_count) { size_t *sizes = calloc(name_count, sizeof(size_t)); names = calloc(name_count, sizeof(char *)); if (!names || !sizes) ret = ENOMEM; if (ret == EOK) ret = async_data_read_start(exch, sizes, name_count * sizeof(size_t)); for (unsigned i = 0; i < name_count && ret == EOK; ++i) { char *name = malloc(sizes[i] + 1); if (name) { memset(name, 0, sizes[i] + 1); ret = async_data_read_start(exch, name, sizes[i]); names[i] = name; } else { ret = ENOMEM; } } free(sizes); } async_exchange_end(exch); if (ret != EOK) { for (unsigned i = 0; i < name_count; ++i) free(names[i]); free(names); } else { *ids = names; *count = name_count; } return ret; }
/** * Read data from a stream. * @param exch IPC exchange in STREAM MODE. * @param data Audio data buffer. * @size size of the buffer * @return Error code. */ int hound_service_stream_read(async_exch_t *exch, void *data, size_t size) { return async_data_read_start(exch, data, size); }
/** Get a copy of clipboard contents. * * Returns a new string that can be deallocated with free(). * * @param str Here pointer to the newly allocated string is stored. * * @return Zero on success or negative error code. * */ int clipboard_get_str(char **str) { /* Loop until clipboard read succesful */ while (true) { async_exch_t *exch = clip_exchange_begin(); sysarg_t size; sysarg_t tag; sysarg_t rc = async_req_0_2(exch, CLIPBOARD_CONTENT, &size, &tag); clip_exchange_end(exch); if (rc != EOK) return (int) rc; char *sbuf; switch (tag) { case CLIPBOARD_TAG_NONE: sbuf = malloc(1); if (sbuf == NULL) return ENOMEM; sbuf[0] = 0; *str = sbuf; return EOK; case CLIPBOARD_TAG_DATA: sbuf = malloc(size + 1); if (sbuf == NULL) return ENOMEM; exch = clip_exchange_begin(); aid_t req = async_send_1(exch, CLIPBOARD_GET_DATA, tag, NULL); rc = async_data_read_start(exch, (void *) sbuf, size); clip_exchange_end(exch); if ((int) rc == EOVERFLOW) { /* * The data in the clipboard has changed since * the last call of CLIPBOARD_CONTENT */ break; } if (rc != EOK) { sysarg_t rc_orig; async_wait_for(req, &rc_orig); if (rc_orig == EOK) return (int) rc; else return (int) rc_orig; } async_wait_for(req, &rc); if (rc == EOK) { sbuf[size] = 0; *str = sbuf; } return rc; default: return EINVAL; } } }