Changes in uspace/lib/c/generic/io/chardev.c [75751db6:19ea61d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/chardev.c
r75751db6 r19ea61d 1 1 /* 2 2 * Copyright (c) 2011 Jan Vesely 3 * Copyright (c) 2017 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 27 28 */ 28 29 30 /** @addtogroup libc 31 * @{ 32 */ 33 /** 34 * @file 35 * @brief Character device client interface 36 */ 37 29 38 #include <errno.h> 30 39 #include <mem.h> 31 40 #include <io/chardev.h> 32 41 #include <ipc/chardev.h> 33 34 ssize_t chardev_read(async_exch_t *exch, void *data, size_t size) 35 { 36 if (!exch) 37 return EBADMEM; 38 if (size > 4 * sizeof(sysarg_t)) 39 return ELIMIT; 40 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; 47 } 48 49 ssize_t chardev_write(async_exch_t *exch, const void *data, size_t size) 50 { 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]); 60 } 42 #include <stddef.h> 43 #include <stdlib.h> 44 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) 53 { 54 chardev_t *chardev; 55 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; 65 } 66 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) 75 { 76 free(chardev); 77 } 78 79 /** Read from character device. 80 * 81 * Read as much data as is available from character device up to @a size 82 * bytes into @a buf. On success EOK is returned and at least one byte 83 * is read (if no byte is available the function blocks). The number 84 * of bytes read is stored in @a *nread. 85 * 86 * On error a non-zero error code is returned and @a *nread is filled with 87 * the number of bytes that were successfully transferred. 88 * 89 * @param chardev Character device 90 * @param buf Destination buffer 91 * @param size Maximum number of bytes to read 92 * @param nread Place to store actual number of bytes read 93 * 94 * @return EOK on success or non-zero error code 95 */ 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 character 133 * device. On success EOK is returned, bytes were written and @a *nwritten 134 * 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 with 137 * the number of bytes that were successfully transferred. 138 * 139 * @param chardev Character device 140 * @param buf Destination buffer 141 * @param size Maximum number of bytes to read 142 * @param nwritten Place to store actual number of bytes written 143 * 144 * @return EOK on success or non-zero error code 145 */ 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 EOK 183 * 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 with 186 * the number of bytes that were successfully transferred. 187 * 188 * @param chardev Character device 189 * @param buf Destination buffer 190 * @param size Maximum number of bytes to read 191 * @param nwritten Place to store actual number of bytes written 192 * 193 * @return EOK on success or non-zero error code 194 */ 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.