1/** 2 * \file 3 * \brief Non-blocking I/O API for terminal client library. 4 */ 5 6/* 7 * Copyright (c) 2012, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich, 13 * Attn: Systems Group. 14 */ 15 16#include <barrelfish/barrelfish.h> 17#include <if/terminal_defs.h> 18#include <if/terminal_config_defs.h> 19#include <term/client/client.h> 20 21#include "filter_priv.h" 22 23#include <assert.h> 24 25/** 26 * \brief Change the waitset used for incoming characters. 27 * 28 * \param client Terminal client state. 29 * \param read_ws New waitset to use. 30 * 31 * \return SYS_ERR_OK if successful. 32 * TERM_ERR_CHANGE_WAITSET on error. 33 */ 34errval_t term_client_change_read_waitset(struct term_client *client, 35 struct waitset *read_ws) 36{ 37 errval_t err; 38 39 assert(client != NULL); 40 assert(read_ws != NULL); 41 42 client->read_ws = read_ws; 43 err = client->in_binding->change_waitset(client->in_binding, read_ws); 44 if (err_is_fail(err)) { 45 return err_push(err, TERM_ERR_CHANGE_WAITSET); 46 } 47 48 return SYS_ERR_OK; 49} 50 51/** 52 * \brief Change the waitset used for outgoing characters. 53 * 54 * \param client Terminal client state. 55 * \param write_ws New waitset to use. 56 * 57 * \return SYS_ERR_OK if successful. 58 * TERM_ERR_CHANGE_WAITSET on error. 59 */ 60errval_t term_client_change_write_waitset(struct term_client *client, 61 struct waitset *write_ws) 62{ 63 errval_t err; 64 65 assert(client != NULL); 66 assert(write_ws != NULL); 67 68 client->write_ws = write_ws; 69 err = client->out_binding->change_waitset(client->out_binding, write_ws); 70 if (err_is_fail(err)) { 71 return err_push(err, TERM_ERR_CHANGE_WAITSET); 72 } 73 74 return SYS_ERR_OK; 75} 76 77/** 78 * \brief Change the waitset used for configuration messages. 79 * 80 * \param client Terminal client state. 81 * \param conf_ws New waitset to use. 82 * 83 * \return SYS_ERR_OK if successful. 84 * TERM_ERR_CHANGE_WAITSET on error. 85 */ 86errval_t term_client_change_config_waitset(struct term_client *client, 87 struct waitset *conf_ws) 88{ 89 errval_t err; 90 91 assert(client != NULL); 92 assert(conf_ws != NULL); 93 94 client->conf_ws = conf_ws; 95 err = client->conf_binding->change_waitset(client->conf_binding, conf_ws); 96 if (err_is_fail(err)) { 97 return err_push(err, TERM_ERR_CHANGE_WAITSET); 98 } 99 100 return SYS_ERR_OK; 101} 102 103/** 104 * \brief Non-blocking write to a terminal. 105 * 106 * \param client Terminal client state. 107 * \param data Buffer holding characters to write. 108 * \param length The number of characters to write. 109 * \param cont Continuation invoked once the write completes. 110 * 111 * \return SYS_ERR_OK if successful. 112 * TERM_ERR_TX_BUSY if another message is buffered but not yet sent. 113 * TERM_ERR_IO if an I/O error occurred. 114 */ 115errval_t term_client_write(struct term_client *client, const char *data, 116 size_t length, struct event_closure cont) 117{ 118 errval_t err = SYS_ERR_OK; 119 char *outdata = NULL; 120 121 assert(client != NULL); 122 assert(data != NULL); 123 assert(length > 0); 124 125 /* Make a copy of the data, since the output filters might modify them. */ 126 outdata = malloc(length); 127 assert(outdata != NULL); 128 memcpy(outdata, data, length); 129 130 /* apply output filters */ 131 term_filter_apply(client->output_filters, &outdata, &length); 132 133 /* try to send characters */ 134 err = client->out_binding->tx_vtbl.characters(client->out_binding, cont, 135 outdata, length); 136 if (err_no(err) == FLOUNDER_ERR_TX_BUSY) { 137 err = err_push(err, TERM_ERR_TX_BUSY); 138 goto out; 139 } else if (err_is_fail(err)) { 140 err = err_push(err, TERM_ERR_IO); 141 goto out; 142 } 143 144out: 145 /* free data */ 146 free(outdata); 147 return err; 148} 149 150/** 151 * \brief Send a configuration command to the terminal server. 152 * 153 * \param client Terminal client state. 154 * \param opt Configuration option. 155 * \param arg Optional argument. 156 * \param cont Continuation invoked once the configuration message is sent. 157 * 158 * \return SYS_ERR_OK if successful. 159 * TERM_ERR_TX_BUSY if another message is buffered but not yet sent. 160 * TERM_ERR_UNKNOWN_CONFIG_OPT if opt is unknown. 161 */ 162errval_t term_client_config(struct term_client *client, 163 terminal_config_option_t opt, char *arg, 164 struct event_closure cont) 165{ 166 assert(!"NYI"); 167 return TERM_ERR_UNKNOWN_CONFIG_OPT; 168} 169 170/** 171 * \brief Set an error handler, called when an asynchronous error occurs. 172 * 173 * \param client Terminal client state. 174 * \param err_cb Error handler. 175 */ 176void term_client_set_err_handler(struct term_client *client, 177 term_async_err_handler_fn err_cb) 178{ 179 assert(client != NULL); 180 assert(err_cb != NULL); 181 182 client->err_cb = err_cb; 183} 184 185/** 186 * \brief Set handler that is called when new characters arrive. 187 * 188 * \param client Terminal client state. 189 * \param chars_cb Characters handler. 190 */ 191void term_client_set_chars_handler(struct term_client *client, 192 term_characters_handler_fn *chars_cb) 193{ 194 assert(client != NULL); 195 assert(chars_cb != NULL); 196 197 client->chars_cb = chars_cb; 198 client->non_blocking_read = true; 199} 200