Changes in uspace/lib/c/generic/io/chardev.c [19ea61d:75751db6] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/chardev.c
r19ea61d r75751db6 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2017 Jiri Svoboda4 3 * All rights reserved. 5 4 * … … 28 27 */ 29 28 30 /** @addtogroup libc31 * @{32 */33 /**34 * @file35 * @brief Character device client interface36 */37 38 29 #include <errno.h> 39 30 #include <mem.h> 40 31 #include <io/chardev.h> 41 32 #include <ipc/chardev.h> 42 #include <stddef.h>43 #include <stdlib.h>44 33 45 /** Open character device. 46 * 47 * @param sess Session with the character device 48 * @param rchardev Place to store pointer to the new character device structure 49 * 50 * @return EOK on success, ENOMEM if out of memory, EIO on I/O error 51 */ 52 int chardev_open(async_sess_t *sess, chardev_t **rchardev) 34 ssize_t chardev_read(async_exch_t *exch, void *data, size_t size) 53 35 { 54 chardev_t *chardev; 36 if (!exch) 37 return EBADMEM; 38 if (size > 4 * sizeof(sysarg_t)) 39 return ELIMIT; 55 40 56 chardev = calloc(1, sizeof(chardev_t)); 57 if (chardev == NULL) 58 return ENOMEM; 59 60 chardev->sess = sess; 61 *rchardev = chardev; 62 63 /* EIO might be used in a future implementation */ 64 return EOK; 41 sysarg_t message[4] = { 0 }; 42 const ssize_t ret = async_req_1_4(exch, CHARDEV_READ, size, 43 &message[0], &message[1], &message[2], &message[3]); 44 if (ret > 0 && (size_t)ret <= size) 45 memcpy(data, message, size); 46 return ret; 65 47 } 66 48 67 /** Close character device. 68 * 69 * Frees the character device structure. The underlying session is 70 * not affected. 71 * 72 * @param chardev Character device or @c NULL 73 */ 74 void chardev_close(chardev_t *chardev) 49 ssize_t chardev_write(async_exch_t *exch, const void *data, size_t size) 75 50 { 76 free(chardev); 51 if (!exch) 52 return EBADMEM; 53 if (size > 3 * sizeof(sysarg_t)) 54 return ELIMIT; 55 56 sysarg_t message[3] = { 0 }; 57 memcpy(message, data, size); 58 return async_req_4_0(exch, CHARDEV_WRITE, size, 59 message[0], message[1], message[2]); 77 60 } 78 79 /** Read from character device.80 *81 * Read as much data as is available from character device up to @a size82 * bytes into @a buf. On success EOK is returned and at least one byte83 * is read (if no byte is available the function blocks). The number84 * of bytes read is stored in @a *nread.85 *86 * On error a non-zero error code is returned and @a *nread is filled with87 * the number of bytes that were successfully transferred.88 *89 * @param chardev Character device90 * @param buf Destination buffer91 * @param size Maximum number of bytes to read92 * @param nread Place to store actual number of bytes read93 *94 * @return EOK on success or non-zero error code95 */96 int chardev_read(chardev_t *chardev, void *buf, size_t size, size_t *nread)97 {98 async_exch_t *exch = async_exchange_begin(chardev->sess);99 100 if (size > DATA_XFER_LIMIT) {101 /* This should not hurt anything. */102 size = DATA_XFER_LIMIT;103 }104 105 ipc_call_t answer;106 aid_t req = async_send_0(exch, CHARDEV_READ, &answer);107 int rc = async_data_read_start(exch, buf, size);108 async_exchange_end(exch);109 110 if (rc != EOK) {111 async_forget(req);112 *nread = 0;113 return rc;114 }115 116 sysarg_t retval;117 async_wait_for(req, &retval);118 119 if (retval != EOK) {120 *nread = 0;121 return retval;122 }123 124 *nread = IPC_GET_ARG2(answer);125 /* In case of partial success, ARG1 contains the error code */126 return IPC_GET_ARG1(answer);127 128 }129 130 /** Write up to DATA_XFER_LIMIT bytes to character device.131 *132 * Write up to @a size or DATA_XFER_LIMIT bytes from @a data to character133 * device. On success EOK is returned, bytes were written and @a *nwritten134 * is set to min(@a size, DATA_XFER_LIMIT)135 *136 * On error a non-zero error code is returned and @a *nwritten is filled with137 * the number of bytes that were successfully transferred.138 *139 * @param chardev Character device140 * @param buf Destination buffer141 * @param size Maximum number of bytes to read142 * @param nwritten Place to store actual number of bytes written143 *144 * @return EOK on success or non-zero error code145 */146 static int chardev_write_once(chardev_t *chardev, const void *data,147 size_t size, size_t *nwritten)148 {149 async_exch_t *exch = async_exchange_begin(chardev->sess);150 ipc_call_t answer;151 aid_t req;152 int rc;153 154 /* Break down large transfers */155 if (size > DATA_XFER_LIMIT)156 size = DATA_XFER_LIMIT;157 158 req = async_send_0(exch, CHARDEV_WRITE, &answer);159 rc = async_data_write_start(exch, data, size);160 async_exchange_end(exch);161 162 if (rc != EOK) {163 async_forget(req);164 *nwritten = 0;165 return rc;166 }167 168 sysarg_t retval;169 async_wait_for(req, &retval);170 if (retval != EOK) {171 *nwritten = 0;172 return retval;173 }174 175 *nwritten = IPC_GET_ARG2(answer);176 /* In case of partial success, ARG1 contains the error code */177 return IPC_GET_ARG1(answer);178 }179 180 /** Write to character device.181 *182 * Write @a size bytes from @a data to character device. On success EOK183 * is returned, all bytes were written and @a *nwritten is set to @a size.184 *185 * On error a non-zero error code is returned and @a *nwritten is filled with186 * the number of bytes that were successfully transferred.187 *188 * @param chardev Character device189 * @param buf Destination buffer190 * @param size Maximum number of bytes to read191 * @param nwritten Place to store actual number of bytes written192 *193 * @return EOK on success or non-zero error code194 */195 int chardev_write(chardev_t *chardev, const void *data, size_t size,196 size_t *nwritten)197 {198 size_t nw;199 size_t p;200 int rc;201 202 p = 0;203 while (p < size) {204 rc = chardev_write_once(chardev, data + p, size - p, &nw);205 /* nw is always valid, we can have partial success */206 p += nw;207 208 if (rc != EOK) {209 /* We can return partial success */210 *nwritten = p;211 return rc;212 }213 }214 215 *nwritten = p;216 return EOK;217 }218 219 /** @}220 */
Note:
See TracChangeset
for help on using the changeset viewer.