1 /* 2 * Copyright (c) 2024 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #ifndef IOGCCircularDataQueue_h 30 #define IOGCCircularDataQueue_h 31 32 #if KERNEL 33 #include <IOKit/IOLib.h> 34 #else 35 #include <IOKit/IOKitLib.h> 36 #endif 37 38 __BEGIN_DECLS 39 40 struct IOCircularDataQueue; 41 typedef struct IOCircularDataQueue IOCircularDataQueue; 42 43 // IOCircularDataQueueCreate* options 44 typedef enum __OS_ENUM_ATTR IOCircularDataQueueCreateOptions { 45 kIOCircularDataQueueCreateConsumer = 0x00000001, 46 kIOCircularDataQueueCreateProducer = 0x00000002 47 } IOCircularDataQueueCreateOptions; 48 49 #if KERNEL 50 51 /*! 52 * @function IOCircularDataQueueCreateWithEntries 53 * @abstract Function that creates a new IOCircularDataQueue instance with the specified number of entries of the given 54 * size. 55 * @discussion This method will create a new IOCircularDataQueue instance with enough capacity for numEntries of 56 * entrySize each. It does account for the IOCircularDataQueueEntryHeader overhead for each entry. Note that the 57 * numEntries and entrySize are simply used to determine the data region size. They do not actually restrict the number 58 * of enqueues to the queue since its a circular buffer and will eventually overwrite old data. At any time, the 59 * allocated data region can hold a maximum of numEntries queue entries. <br> This method allocates a new 60 * IOCircularDataQueue instance with the given numEntries and entrySize parameters. 61 * @param options IOCircularDataQueueCreateOptions. 62 * @param numEntries Number of entries to allocate space for. 63 * @param entrySize Size of each entry. 64 * @param pQueue Pointer to a queue handle. On return, this holds a handle to the newly allocated queue. 65 * @return 66 * - `kIOReturnSuccess` if the queue was succesfully intialized. 67 * - `kIOReturnBadArgument` if the parameters passed were invalid. 68 * - `kIOReturnNoMemory` if there was a memory allocation failure. 69 */ 70 IOReturn IOCircularDataQueueCreateWithEntries(IOCircularDataQueueCreateOptions options, uint32_t numEntries, uint32_t entrySize, IOCircularDataQueue **pQueue); 71 72 /*! 73 * @function IOCircularDataQueueCopyMemoryDescriptor 74 * @abstract Returns a reference to the IOMemoryDescriptor for the queue's memory. 75 * @discussion Returns a reference to the IOMemoryDescriptor for the queue's memory. 76 * @param queue Queue handle. On return, this holds a handle to the newly allocated queue. 77 * @return IOMemoryDescriptor reference 78 */ 79 IOMemoryDescriptor * IOCircularDataQueueCopyMemoryDescriptor(IOCircularDataQueue *queue); 80 81 #else /* KERNEL */ 82 83 /*! 84 * @function IOCircularDataQueueCreateWithConnection 85 * @abstract Function that creates a new IOCircularDataQueue instance with an open IOUserClient connection. 86 * @discussion This method will create a new IOCircularDataQueue instance with a queue owned by the IOUserClient 87 * instance passed in. The memory and queue attributes are created from the IOMemoryDescriptor returned by the IOUC 88 * returned by clientMemoryForType() with the memoryType parameter passed to this function. This memory descriptor must 89 * be one returned by the kernel api IOCircularDataQueueCopyMemoryDescriptor(). 90 * @param options IOCircularDataQueueCreateOptions. 91 * @param connect An open IOUserClient connection created by the caller with IOServiceOpen(). The connection must be 92 * valid while the queue is in use. 93 * @param memoryType memoryType argument that will passed to the IOUC clientMemoryForType() function to obtain the queue memory. 94 * @param pQueue Pointer to a queue handle. On return, this holds a handle to the newly allocated queue. 95 * @return 96 * - `kIOReturnSuccess` if the queue was succesfully intialized. 97 * - `kIOReturnBadArgument` if the parameters passed were invalid. 98 * - `kIOReturnNoMemory` if there was a memory allocation failure. 99 */ 100 IOReturn IOCircularDataQueueCreateWithConnection(IOCircularDataQueueCreateOptions options, io_connect_t connect, uint32_t memoryType, IOCircularDataQueue **pQueue); 101 102 #endif /* !KERNEL */ 103 104 /*! 105 * @function IOCircularDataQueueDestroy 106 * @abstract Function that destroys a previously created IOCircularDataQueue instance (created with 107 * IOCircularDataQueueCreateWithEntries). 108 * @param pQueue Pointer to the queue handle. 109 * @return 110 * - `kIOReturnSuccess` if the queue was succesfully destroyed. 111 * - `kIOReturnBadArgument` if an invalid queue was provided. 112 */ 113 IOReturn IOCircularDataQueueDestroy(IOCircularDataQueue **pQueue); 114 115 116 /*! 117 * @function IOCircularDataQueueEnqueue 118 * @abstract Enqueues a new entry on the queue. 119 * @discussion This method adds a new data entry of dataSize to the queue. It sets the size parameter of the entry 120 * pointed to by the write index and copies the memory pointed to by the data parameter in place in the queue. Once 121 * that is done, it moves the write index to the next index. 122 * @param queue Handle to the queue. 123 * @param data Pointer to the data to be added to the queue. 124 * @param dataSize Size of the data pointed to by data. 125 * @return 126 * - `kIOReturnSuccess` on success. 127 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 128 * - `kIOReturnBadArgument` if an invalid queue was provided. 129 * - `kIOReturnBusy` if another thread is enqueing concurrently 130 * - `kIOReturnUnsupported` if the queue has not been configured to support fixed size entries. Variable size is 131 * currently not supported 132 * - Other values indicate an error. 133 */ 134 IOReturn IOCircularDataQueueEnqueue(IOCircularDataQueue *queue, const void *data, size_t dataSize); 135 136 /*! 137 * @function IOCircularDataQueueGetLatest 138 * Access the latest entry data, also update the cursor position to the latest. No copy is made of the data. <br> Caller 139 * is supposed to call IOCircularDataQueueIsCurrentDataValid() to check data integrity after reading the data is 140 * complete. 141 * @param queue Handle to the queue. 142 * @param data A pointer to the data memory region for the latest entry data in the queue. 143 * @param size A pointer to the size of the data parameter. On return, this contains the actual size of the data 144 * pointed to by data param. 145 * @return 146 * - `kIOReturnSuccess` if the cursor position was updated. 147 * - `kIOReturnUnderrun` if nothing has ever been enqueued into the queue 148 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 149 * - `kIOReturnBadArgument` if an invalid queue was provided. 150 * - `kIOReturnTimeout` if the reader timed out when trying to read. This is possible if the writer overwrites the 151 * latest index a reader is about to read. The function times out if the read is unsuccessful after multiple retries. 152 * - Other values indicate an error. 153 */ 154 IOReturn IOCircularDataQueueGetLatest(IOCircularDataQueue *queue, void **data, size_t *size); 155 156 /*! 157 * @function IOCircularDataQueueCopyLatest 158 * Access the latest entry data and copy into the provided buffer. Also update the cursor position to the latest. On a 159 * successful return, the function gaurantees that the latest data was successfully copied. In this case there is no 160 * need to call IOCircularDataQueueIsCurrentDataValid() after reading the data is complete, since the function returns a 161 * copy which cannot be overwritten by the writer. 162 * @param queue Handle to the queue. 163 * @param data Pointer to memory into which the latest data from the queue is copied. Lifetime of this memory is 164 * controlled by the caller. 165 * @param size Size of the data buffer provided for copying. On return, this contains the actual size of the data 166 * pointed to by data param. 167 * @return 168 * - `kIOReturnSuccess` if the cursor position was updated to latest and the data was successfully copied. 169 * - `kIOReturnUnderrun` if nothing has ever been enqueued into the queue 170 * - `kIOReturnBadArgument` if the buffer provided to copy the data is NULL or if an invalid queue was provided.. 171 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 172 * - `kIOReturnTimeout` if the reader timed out when trying to copy the latest data. This is possible if the writer 173 * overwrites the latest index a reader is about to copy. The function times out if the copy is unsuccessful after 174 * multiple retries. 175 * - Other values indicate an error. 176 * 177 */ 178 IOReturn IOCircularDataQueueCopyLatest(IOCircularDataQueue *queue, void *data, size_t *size); 179 180 /*! 181 * @function IOCircularDataQueueGetNext 182 * Access the data at the next cursor position and updates the cursor position to the next. No copy is made of the data. 183 * <br> Caller is supposed to call IOCircularDataQueueIsCurrentDataValid() to check data integrity after reading the 184 * data is complete. 185 * @param queue Handle to the queue. 186 * @param data A pointer to the data memory region for the next entry data in the queue. 187 * @param size A pointer to the size of the data parameter. On return, this contains the actual size of the data 188 * pointed to by data param. 189 * @return 190 * - `kIOReturnSuccess` if the cursor position was updated to the latest. 191 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 192 * - `kIOReturnUnderrun` if the cursor has reached the latest available data. 193 * - `kIOReturnOverrun` if the entry at the cursor position is no longer in 194 * the queue's buffer. Call IOCircularDataQueueGetLatest to get the latest data and cursor position. 195 * - `kIOReturnBadArgument` if an invalid argument is passsed. 196 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 197 * - Other values indicate an error. 198 * 199 */ 200 IOReturn IOCircularDataQueueGetNext(IOCircularDataQueue *queue, void **data, size_t *size); 201 202 /*! 203 * @function IOCircularDataQueueCopyNext 204 * Access the data at the next cursor position and copy into the provided buffer. Also update the cursor position to the 205 * next. On a successful return, the function gaurantees that the next entry data was successfully copied. In this case 206 * there is no need to call IOCircularDataQueueIsCurrentDataValid() after reading the data is complete, since the 207 * function returns a copy which cannot be overwritten by the writer. 208 * @param queue Handle to the queue. 209 * @param data Pointer to memory into which the next data from the queue is copied. Lifetime of this memory is 210 * controlled by the caller. 211 * @param size Size of the data buffer provided for copying. On return, this contains the actual size of the data 212 * pointed to by data param. 213 * @return 214 * - `kIOReturnSuccess` if the cursor position was updated to next and the data was successfully copied. 215 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 216 * - `kIOReturnUnderrun` if the cursor has reached the latest available data. 217 * - `kIOReturnOverrun` if the entry at the cursor position is no longer in 218 * the queue's buffer. Call IOCircularDataQueueCopyLatest to get the latest data and cursor position. 219 * - `kIOReturnBadArgument` if an invalid argument is passsed. 220 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 221 * - Other values indicate an error. 222 * 223 */ 224 IOReturn IOCircularDataQueueCopyNext(IOCircularDataQueue *queue, void *data, size_t *size); 225 226 /*! 227 * @function IOCircularDataQueueGetPrevious 228 * Access the data at the previous cursor position and updates the cursor position to the previous. No copy is made of 229 * the data. <br> Caller is supposed to call IOCircularDataQueueIsCurrentDataValid() to check data integrity after 230 * reading the data is complete. 231 * @param queue Handle to the queue. 232 * @param data A pointer to the data memory region for the previous entry data in the queue. 233 * @param size A pointer to the size of the data parameter. On return, this contains the actual size of the data 234 * pointed to by data param. 235 * @return 236 * - `kIOReturnSuccess` if the cursor position was updated to the previous. 237 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 238 * - `kIOReturnOverrun` if the entry at the cursor position is no longer in 239 * the queue's buffer. Call IOCircularDataQueueGetLatest to get the latest data and cursor position. 240 * - `kIOReturnBadArgument` if an invalid argument is passsed. 241 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 242 * - Other values indicate an error. 243 * 244 */ 245 IOReturn IOCircularDataQueueGetPrevious(IOCircularDataQueue *queue, void **data, size_t *size); 246 247 /*! 248 * @function IOCircularDataQueueCopyPrevious 249 * Access the data at the previous cursor position and copy into the provided buffer. Also update the cursor position to 250 * the previous. On a successful return, the function gaurantees that the previous entry data was successfully copied. 251 * In this case there is no need to call IOCircularDataQueueIsCurrentDataValid() after reading the data is complete, 252 * since the function returns a copy which cannot be overwritten by the writer. 253 * @param queue Handle to the queue. 254 * @param data Pointer to memory into which the previous data is copied. Lifetime of this memory is controlled by the 255 * caller. 256 * @param size Size of the data buffer provided for copying. On return, this contains the actual size of the data 257 * pointed to by data param. 258 * @return 259 * - `kIOReturnSuccess` if the cursor position was updated to the previous and the data was successfully copied. 260 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 261 * - `kIOReturnOverrun` if the entry at the cursor position is no longer in 262 * the queue's buffer. Call IOCircularDataQueueCopyLatest to get the latest data and cursor position. 263 * - `kIOReturnBadArgument` if an invalid argument is passsed. 264 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 265 * - Other values indicate an error. 266 * 267 */ 268 IOReturn IOCircularDataQueueCopyPrevious(IOCircularDataQueue *queue, void *data, size_t *size); 269 270 /*! 271 * @function IOCircularDataQueueIsCurrentDataValid 272 * Verify if the data at the current cursor position is the same as the data when the cursor was first updated to this 273 * position. Call this function after having read the data at the current cursor position from the queue, since the 274 * queue entry could potentially have been overwritten by the writer while being read by the caller. <br> 275 * @param queue Handle to the queue. 276 * @return 277 * - `kIOReturnSuccess` if the data at the cursor position is unchanged. 278 * - `kIOReturnOverrun` if the entry at the cursor position is no longer the same and is 279 * potentially overwritten. Call IOCircularDataQueueGetLatest to get the latest data and cursor position. 280 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 281 * - `kIOReturnBadArgument` if an invalid param was passed. 282 * - `kIOReturnBadMedia` if the queueMemory is corrupted. 283 * - Other values indicate an error. 284 * 285 */ 286 IOReturn IOCircularDataQueueIsCurrentDataValid(IOCircularDataQueue *queue); 287 288 /*! 289 * @function IOCircularDataQueueSetCursorLatest 290 * Set the current cursor position to the latest entry in the queue. This only updates the cursor and does not read the 291 * data from the queue. If nothing has been enqueued into the queue yet, this returns an error. 292 * @param queue Handle to the queue. 293 * @return 294 * - `kIOReturnSuccess` if the cursor position was updated to the latest. 295 * - `kIOReturnUnderrun` if nothing has ever been enqueued into the queue since there is no latest entry. 296 * - `kIOReturnAborted` if the queue is in an irrecoverable state. 297 * - `kIOReturnBadArgument` if an invalid argument is passsed. 298 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 299 * - Other values indicate an error. 300 * 301 */ 302 IOReturn IOCircularDataQueueSetCursorLatest(IOCircularDataQueue *queue); 303 304 /*! 305 * @function IOCircularDataQueueGetCurrent 306 * Access the data at the current cursor position. The cursor position is unchanged. No copy is made of the data. <br> 307 * Caller is supposed to call IOCircularDataQueueIsCurrentDataValid() to check data integrity after reading the data is 308 * complete. 309 * @param queue Handle to the queue. 310 * @param data A pointer to the data memory region for the next entry data in the queue. 311 * @param size A pointer to the size of the data parameter. On return, this contains the actual size of the data 312 * pointed to by data param. 313 * @return 314 * - `kIOReturnSuccess` if the cursor position was updated. 315 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 316 * - `kIOReturnUnderrun` if nothing has ever been enqueued into the queue hence there is no entry at the current 317 * position.. 318 * - `kIOReturnOverrun` if the entry at the current cursor position is no longer in 319 * the queue's buffer. Call IOCircularDataQueueGetLatest to get the latest data and cursor position. 320 * - `kIOReturnBadArgument` if an invalid argument is passsed. 321 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 322 * - Other values indicate an error. 323 * 324 */ 325 IOReturn IOCircularDataQueueGetCurrent(IOCircularDataQueue *queue, void **data, size_t *size); 326 327 /*! 328 * @function IOCircularDataQueueCopyCurrent 329 * Access the data at the current cursor position and copy into the provided buffer. The cursor position is unchanged. 330 * If successful, function gaurantees that the data returned is always valid, hence no need to call 331 * IOCircularDataQueueIsCurrentDataValid(). 332 * @param queue Handle to the queue. 333 * @param data Pointer to memory into which the previous data is copied. Lifetime of this memory is controlled by the 334 * caller. 335 * @param size Size of the data buffer provided for copying. On return, this contains the actual size of the data 336 * pointed to by data param. 337 * @return 338 * - `kIOReturnSuccess` if the cursor position was updated. 339 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 340 * - `kIOReturnUnderrun` if nothing has ever been enqueued into the queue hence there is no entry at the current 341 * position.. 342 * - `kIOReturnOverrun` if the entry at the current cursor position is no longer in 343 * the queue's buffer. Call IOCircularDataQueueCopyLatest to get the latest data and cursor position. 344 * - `kIOReturnBadArgument` if an invalid argument is passsed. 345 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 346 * - Other values indicate an error. 347 * 348 */ 349 IOReturn IOCircularDataQueueCopyCurrent(IOCircularDataQueue *queue, void *data, size_t *size); 350 351 /*! 352 * @function IOCircularDataQueueGetLatestWithBlock 353 * Access the latest entry data, also update the cursor position to the latest. Calls the provided block with the data 354 * at the cursor position. No copy is made of the data. <br> Optionally the caller can call 355 * IOCircularDataQueueIsCurrentDataValid() to check data integrity after reading the data is complete in the block. 356 * Additionally the function also returns an error if the data has been overwritten after the block completion 357 * @param queue Handle to the queue. 358 * @param handler Block to call 359 * -param data Pointer to the latest data in the queue that the block is called with. 360 * -param size Size of the data pointed to by data that the block is called with. 361 * @return 362 * - `kIOReturnSuccess` if the cursor position was updated to the latest. 363 * - `kIOReturnUnderrun` if nothing has ever been enqueued into the queue 364 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 365 * - `kIOReturnBadArgument` if an invalid queue was provided. 366 * - `kIOReturnAborted` if the queue was reset. 367 * - Other values indicate an error. 368 * 369 */ 370 IOReturn IOCircularDataQueueGetLatestWithBlock(IOCircularDataQueue * queue, void (^handler)(const void *data, size_t size)); 371 372 /*! 373 * @function IOCircularDataQueueGetNextWithBlock 374 * Access the data at the next cursor position and updates the cursor position to the next. Calls the provided block 375 * with the data at the cursor position. No copy is made of the data. <br> Optionally the caller can call 376 * IOCircularDataQueueIsCurrentDataValid() to check data integrity after reading the data is complete in the block. 377 * Additionally the function also returns an error if the data has been overwritten after the block completion. 378 * @param queue Handle to the queue. 379 * @param handler Block to call 380 * -param data A pointer to the data memory region for the next entry data in the queue that the block is called with. 381 * -param size Size of the data pointed to by data that the block is called with. 382 * @return 383 * - `kIOReturnSuccess` if the cursor position was updated to next. 384 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 385 * - `kIOReturnUnderrun` if the cursor has reached the latest available data. 386 * - `kIOReturnOverrun` if the entry at the cursor position is no longer in 387 * the queue's buffer. Call IOCircularDataQueueGetLatest to get the latest data and cursor position. 388 * - `kIOReturnBadArgument` if an invalid argument is passsed. 389 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 390 * - Other values indicate an error. 391 * 392 */ 393 IOReturn IOCircularDataQueueGetNextWithBlock(IOCircularDataQueue * queue, void (^handler)(const void *data, size_t size)); 394 395 /*! 396 * @function IOCircularDataQueueGetPreviousWithBlock 397 * Access the data at the previous cursor position and updates the cursor position to the previous. Calls the provided 398 * block with the data at the cursor position. No copy is made of the data. <br> Optionally the caller can call 399 * IOCircularDataQueueIsCurrentDataValid() to check data integrity after reading the data is complete in the block. 400 * Additionally the function also returns an error if the data has been overwritten after the block completion. 401 * @param queue Handle to the queue. 402 * @param handler Block to call 403 * -param data A pointer to the data memory region for the previous entry data in the queue that the block is called 404 * with. 405 * -param size Size of the data pointed to by data that the block is called with. 406 * @return 407 * - `kIOReturnSuccess` if the cursor position was updated to previous. 408 * - `kIOReturnAborted` if the cursor has become invalid, possibly due to a reset of the queue. 409 * - `kIOReturnUnderrun` if the entry at the cursor position is no longer in 410 * the queue's buffer. Call IOCircularDataQueueGetLatest to get the latest data and cursor position. 411 * - `kIOReturnBadArgument` if an invalid argument is passsed. 412 * - `kIOReturnBadMedia` if the queue shared memory has been compromised. 413 * - Other values indicate an error. 414 * 415 */ 416 IOReturn IOCircularDataQueueGetPreviousWithBlock(IOCircularDataQueue * queue, void (^handler)(const void *data, size_t size)); 417 418 __END_DECLS 419 420 #endif /* IOGCCircularDataQueue_h */ 421