/*
- * @APPLE_LICENSE_HEADER_START@
- *
- * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved.
+ * Copyright (c) 2012-2014 Apple Computer, Inc. All Rights Reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
- *
+ *
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#define _IOREPORT_MACROS_H_
#include "IOReportTypes.h"
+#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
+#ifndef IOREPORT_ABORT
+#define IOREPORT_ABORT panic
+#endif
+
/*
Background
appropriate macro.
*/
+
+/* ----- Reporting Single Integers (SimpleReport) ----- */
+
/*
- * Returns the buffer size required for a Simple report.
+ * The buffer size required for a SimpleReport.
*/
+
#define SIMPLEREPORT_BUFSIZE (sizeof(IOReportElement))
+
/*
- * Initialize a buffer to hold a Simple (integer) report.
+ * Initialize a buffer to hold a SimpleReport.
*
* void* buffer - ptr to SIMPLEREPORT_BUFSIZE bytes
* size_t bufSize - sanity check of buffer's size
* uint64_t channelID - the report's channel ID
* IOReportCategories categories - categories of this channel
*
- * If the buffer is not of sufficient size, the macro performs a
- * null pointer reference to trigger a segfault. Then, the buffer is
- * filled with 0xbadcafe.
+ * If the buffer is not of sufficient size, the macro calls IOREPORT_ABORT().
+ * If that returns, the buffer is left full of '&'.
*/
-#define SIMPLEREPORT_INIT(buffer, bufSize, providerID, channelID, cats) \
+
+#define SIMPLEREPORT_INIT(buf, bufSize, providerID, channelID, cats) \
do { \
- IOReportElement *__elem = (IOReportElement *)(buffer); \
+ memset((buf), '&', (bufSize)); \
+ IOReportElement *__elem = (IOReportElement *)(buf); \
IOSimpleReportValues *__vals; \
if ((bufSize) >= SIMPLEREPORT_BUFSIZE) { \
- __elem->channel_id = (channelID); \
__elem->provider_id = (providerID); \
+ __elem->channel_id = (channelID); \
__elem->channel_type.report_format = kIOReportFormatSimple; \
__elem->channel_type.reserved = 0; \
__elem->channel_type.categories = (cats); \
__elem->channel_type.nelements = 1; \
__elem->channel_type.element_idx = 0; \
__elem->timestamp = 0; \
- __vals = (IOSimpleReportValues*)&__elem->values; \
- __vals->simple_value = kIOReportInvalidValue; \
+ __vals = (IOSimpleReportValues*)&__elem->values; \
+ __vals->simple_value = kIOReportInvalidIntValue; \
} \
else { \
- uint32_t *__nptr = NULL; \
- *__nptr = 1; \
- POLLUTE_BUF((buffer), (bufSize)); \
+ IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
} \
} while(0)
/*
- * Sets the SimpleReport channel to a new value.
+ * Set a SimpleReport to a new value.
*
- * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
- * uint64_t new_value - new value for the channel
+ * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
+ * int64_t new_value - new value for the report
*/
+
#define SIMPLEREPORT_SETVALUE(simp_buf, new_value) \
do { \
IOReportElement *__elem = (IOReportElement *)(simp_buf); \
__vals->simple_value = (new_value); \
} while(0)
+
+/*
+ * Increment the value of a SimpleReport.
+ *
+ * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
+ * int64_t increment - amount by which to increment the value
+ */
+#define SIMPLEREPORT_INCREMENTVALUE(simp_buf, new_value) \
+do { \
+ IOReportElement *__elem = (IOReportElement *)(simp_buf); \
+ IOSimpleReportValues *__vals; \
+ __vals = (IOSimpleReportValues*)&__elem->values; \
+ __vals->simple_value += (new_value); \
+} while(0)
+
+
/*
- * Prepare simple report buffer for
+ * Prepare a SimpleReport for
* IOService::updateReport(kIOReportCopyChannelData...)
*
* void* simp_buf - Ptr to memory updated by SIMPLEREPORT_SETVALUE()
* size_t size2cpy - On return, 'size2cpy' is set to the size of the report
* data that needs to be copied for kIOReportCopyChannelData.
*/
+
#define SIMPLEREPORT_UPDATEPREP(simp_buf, ptr2cpy, size2cpy) \
do { \
(ptr2cpy) = (simp_buf); \
/*
- * Updates the result field received as a parameter for
+ * Update the result field received as a parameter for
* kIOReportGetDimensions & kIOReportCopyChannelData actions.
*
* IOReportConfigureAction action - configure/updateReport() 'action' param
} while (0)
-
/*
- * Returns the channel id from the buffer previously initialized by
- * SIMPLEREPORT_INIT().
+ * Get the 64-bit channel ID of a SimpleReport.
*
* void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
*/
#define SIMPLEREPORT_GETCHID(simp_buf) \
- (((IOReportElement *)(simp_buf))->channel_id); \
+ (((IOReportElement *)(simp_buf))->channel_id)
+
+/*
+ * Get the IOReportChannelType of a SimpleReport.
+ *
+ * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
+ */
+
+#define SIMPLEREPORT_GETCHTYPE(simp_buf) \
+ (*(uint64_t*)&(((IOReportElement *)(simp_buf))->channel_type))
+
+
+/*
+ * Get the integer value of a SimpleReport.
+ *
+ * void* simp_buf - memory initialized by SIMPLEREPORT_INIT()
+ */
+#define SIMPLEREPORT_GETVALUE(simp_buf) \
+ (((IOSimpleReportValues*)&(((IOReportElement*)(simp_buf))->values)) \
+ ->simple_value)
-// Internal struct for State report buffer
+/* ----- State Machine Reporting (StateReport) ----- */
+
+// Internal struct for StateReport
typedef struct {
uint16_t curr_state;
uint64_t update_ts;
} IOStateReportInfo;
/*
- * Returns the size required to be allocated for using STATEREPORT_*()
+ * Determine the size required for a StateReport buffer.
*
- * int nstates - number of states for the intended channel
+ * int nstates - number of states to be reported
*/
#define STATEREPORT_BUFSIZE(nstates) \
(sizeof(IOStateReportInfo) + (nstates) * sizeof(IOReportElement))
/*
- * Initializes a buffer so it can be used with STATEREPORT_*().
+ * Initialize a StateReport buffer.
*
* int nstates - number of states to be reported
* void* buffer - ptr to STATEREPORT_BUFSIZE(nstates) bytes
* uint64_t channelID - ID of this channel, see IOREPORT_MAKEID()
* IOReportCategories categories - categories of this channel
*
- * If the buffer is not of sufficient size, the macro performs a
- * null pointer reference to trigger a segfault. Then, the buffer is
- * filled with 0xbadcafe.
+ * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT.
+ * If that returns, the buffer is left full of '&'.
*/
#define STATEREPORT_INIT(nstates, buf, bufSize, providerID, channelID, cats) \
do { \
+ memset((buf), '&', (bufSize)); \
IOStateReportInfo *__info = (IOStateReportInfo *)(buf); \
IOStateReportValues *__rep; \
IOReportElement *__elem; \
for (unsigned __no = 0; __no < (nstates); __no++) { \
__elem = &(__info->elem[__no]); \
__rep = (IOStateReportValues *) &(__elem->values); \
- __elem->channel_id = (channelID); \
__elem->provider_id = (providerID); \
+ __elem->channel_id = (channelID); \
__elem->channel_type.report_format = kIOReportFormatState; \
__elem->channel_type.reserved = 0; \
__elem->channel_type.categories = (cats); \
__rep->state_id = __no; \
__rep->intransitions = 0; \
__rep->upticks = 0; \
+ __rep->last_intransition = 0; \
} \
__info->curr_state = 0; \
__info->update_ts = 0; \
} \
else { \
- int *__nptr = NULL; \
- *__nptr = 1; \
- POLLUTE_BUF((buf), (bufSize)); \
+ IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
} \
} while(0)
/*
- * Initializes the state id field of a state with the specified value. By
- * default, STATEREPORT_INIT initializes the state id with the index of
+ * Initialize the state id field of a state with the specified value. By
+ * default, STATEREPORT_INIT() initializes the state IDs with the index of
* that state. This macro can be used to provide a more descriptive state id.
*
* void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
/*
- * Set the state of a State report.
+ * Set the state of a StateReport.
*
* void* state_buf - pointer to memory initialized by STATEREPORT_INIT()
* unsigned newStateIdx - index of new state, out of bounds -> no-op
} while(0)
/*
- * Prepare StateReport for UpdateReport call
+ * Prepare a StateReport for
+ * IOService::updateReport(kIOReportCopyChannelData...)
*
* void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
* uint64_t currentTime - current timestamp
} while(0)
/*
- * Updates the result field received as a parameter for kIOReportGetDimensions &
+ * Update the result field received as a parameter for kIOReportGetDimensions &
* kIOReportCopyChannelData actions.
*
* void* state_buf - memory initialized by STATEREPORT_INIT()
} while (0)
-
/*
- * Returns the channel id from the buffer previously initialized by STATEREPORT_INIT().
+ * Get the 64-bit channel ID of a StateReport.
*
* void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
*/
-
#define STATEREPORT_GETCHID(state_buf) \
(((IOStateReportInfo *)(state_buf))->elem[0].channel_id)
/*
- * Returns number of transitions occurred from the given state
+ * Get the IOReportChannelType of a StateReport.
+ *
+ * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
+ */
+#define STATEREPORT_GETCHTYPE(state_buf) \
+ (*(uint64_t*)&(((IOStateReportInfo *)(state_buf))->elem[0].channel_type))
+
+/*
+ * Get the number of transitions into a given state.
*
* void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
* unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue
*
*/
-
#define STATEREPORT_GETTRANSITIONS(state_buf, stateIdx) \
(((stateIdx) < ((IOStateReportInfo *)(state_buf))->elem[0].channel_type.nelements) \
? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->intransitions \
: kIOReportInvalidValue)
/*
- * Returns the total number of ticks spent in the given state.
+ * Get the total number of ticks spent in a given state.
*
* void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
* unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue
*/
-
#define STATEREPORT_GETTICKS(state_buf, stateIdx) \
(((stateIdx) < ((IOStateReportInfo*)(state_buf))->elem[0].channel_type.nelements) \
? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->upticks \
: kIOReportInvalidValue)
-#define POLLUTE_BUF(buf, bufSize) \
+/* ----- Reporting an Array of Integers (SimpleArrayReport) ----- */
+
+/*
+ * Determine the buffer size for a SimpleArrayReport.
+ *
+ * int nValues - number of values to be reported
+ */
+
+#define SIMPLEARRAY_BUFSIZE(nValues) \
+ ((((nValues)/IOR_VALUES_PER_ELEMENT) + (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1:0)) \
+ * sizeof(IOReportElement))
+
+/*
+ * Initialize a buffer for use as a SimpleArrayReport.
+ *
+ * int nValues - number of elements to be reported
+ * void* buf - ptr to SIMPLEARRAY_BUFSIZE(nValues) bytes
+ * size_t bufSize - sanity check of buffer's size
+ * uint64_t providerID - registry Entry ID of the reporting service
+ * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID()
+ * IOReportCategories categories - categories of this channel
+ *
+ * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT().
+ * If that returns, the buffer is left full of '&'.
+ */
+
+#define SIMPLEARRAY_INIT(nValues, buf, bufSize, providerID, channelID, cats) \
+do { \
+ memset((buf), '&', (bufSize)); \
+ IOSimpleArrayReportValues *__rep; \
+ IOReportElement *__elem; \
+ uint32_t __nElems = (((nValues) / IOR_VALUES_PER_ELEMENT) + \
+ (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1 : 0)); \
+ if ((bufSize) >= SIMPLEARRAY_BUFSIZE(nValues)) { \
+ for (unsigned __no = 0; __no < __nElems; __no++) { \
+ __elem = &(((IOReportElement *)(buf))[__no]); \
+ __rep = (IOSimpleArrayReportValues *) &(__elem->values); \
+ __elem->provider_id = (providerID); \
+ __elem->channel_id = (channelID); \
+ __elem->channel_type.report_format = kIOReportFormatSimpleArray; \
+ __elem->channel_type.reserved = 0; \
+ __elem->channel_type.categories = (cats); \
+ __elem->channel_type.nelements = (__nElems); \
+ __elem->channel_type.element_idx = __no; \
+ __elem->timestamp = 0; \
+ __rep->simple_values[0] = kIOReportInvalidIntValue; \
+ __rep->simple_values[1] = kIOReportInvalidIntValue; \
+ __rep->simple_values[2] = kIOReportInvalidIntValue; \
+ __rep->simple_values[3] = kIOReportInvalidIntValue; \
+ } \
+ } \
+ else { \
+ IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
+ } \
+} while(0)
+
+
+/* SimpleArrayReport helpers */
+
+ #define __SA_FINDREP(array_buf, idx) \
+ IOSimpleArrayReportValues *__rep; \
+ IOReportElement *__elem; \
+ unsigned __elemIdx = (idx) / IOR_VALUES_PER_ELEMENT; \
+ unsigned __valueIdx = (idx) % IOR_VALUES_PER_ELEMENT; \
+ __elem = &(((IOReportElement *)(array_buf))[0]); \
+ if (__elemIdx < __elem->channel_type.nelements) { \
+ __elem = &(((IOReportElement *)(array_buf))[__elemIdx]); \
+ __rep = (IOSimpleArrayReportValues *) &(__elem->values); \
+
+ #define __SA_MAXINDEX(array_buf) \
+ ((((IOReportElement*)(array_buf))->channel_type.nelements) \
+ * IOR_VALUES_PER_ELEMENT) - 1
+
+/*
+ * Set a value at a specified index in a SimpleArrayReport.
+ *
+ * void* array_bufbuf - ptr to memory initialized by SIMPLEARRAY_INIT()
+ * unsigned idx - array index, out of bounds -> no-op
+ * uint64_t newValue - new value to be stored at array[idx]
+ */
+#define SIMPLEARRAY_SETVALUE(array_buf, idx, newValue) \
+do { \
+ __SA_FINDREP((array_buf), (idx)) \
+ __rep->simple_values[__valueIdx] = (newValue); \
+ } \
+} while(0)
+
+/*
+ * Increment an array value within a SimpleArrayReport.
+ *
+ * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
+ * unsigned idx - array index to increment, out of bounds -> no-op
+ * int64_t value - amount by which to increment array[idx]
+ */
+#define SIMPLEARRAY_INCREMENTVALUE(array_buf, idx, value) \
+do { \
+ __SA_FINDREP((array_buf), (idx)) \
+ __rep->simple_values[__valueIdx] += (value); \
+ } \
+} while(0)
+
+
+/*
+ * Prepare a SimpleArrayReport for
+ * IOService::updateReport(kIOReportCopyChannelData...)
+ *
+ * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
+ * void* ptr2cpy - filled in with pointer to buffer to be copied out
+ * size_t size2cpy - filled in with the size of the buffer to copy out
+ */
+
+#define SIMPLEARRAY_UPDATEPREP(array_buf, ptr2cpy, size2cpy) \
+do { \
+ IOReportElement *__elem; \
+ __elem = &(((IOReportElement *)(array_buf))[0]); \
+ (ptr2cpy) = (void *) (array_buf); \
+ (size2cpy) = __elem->channel_type.nelements * sizeof(IOReportElement); \
+} while(0)
+
+
+/*
+ * Update the result field received as a parameter for kIOReportGetDimensions &
+ * kIOReportCopyChannelData actions.
+ *
+ * void* array_buf - memory initialized by SIMPLEARRAY_INIT()
+ * IOReportConfigureAction action - configure/updateReport() 'action'
+ * void* result - configure/updateReport() 'result'
+ */
+
+#define SIMPLEARRAY_UPDATERES(array_buf, action, result) \
+do { \
+ IOReportElement *__elem; \
+ int *__nElements = (int *)(result); \
+ __elem = &(((IOReportElement *)(array_buf))[0]); \
+ if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
+ *__nElements += __elem->channel_type.nelements; \
+ } \
+} while (0)
+
+
+/*
+ * Get the 64-bit channel ID of a SimpleArrayReport.
+ *
+ * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
+ */
+#define SIMPLEARRAY_GETCHID(array_buf) \
+ (((IOReportElement *)(array_buf))->channel_id)
+
+
+/*
+ * Get the IOReportChannelType of a SimpleArrayReport.
+ *
+ * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
+ */
+#define SIMPLEARRAY_GETCHTYPE(array_buf) \
+ (*(uint64_t*)&(((IOReportElement *)(array_buf))->channel_type))
+
+/*
+ * Get a value from a SimpleArrayReport.
+ *
+ * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
+ * unsigned idx - index of the value, out of bounds -> kIOReportInvalidValue
+ */
+#define SIMPLEARRAY_GETVALUE(array_buf, idx) \
+ (((idx) > __SA_MAXINDEX(array_buf) || (idx) < 0) ? kIOReportInvalidIntValue : \
+ ((IOSimpleArrayReportValues*)&( \
+ ((IOReportElement*)(array_buf))[(idx) / IOR_VALUES_PER_ELEMENT].values)) \
+ ->simple_values[(idx) % IOR_VALUES_PER_ELEMENT])
+
+
+/* ----- Histogram Reporting (HistogramReport) ----- */
+
+// Internal struct for HistogramReport
+typedef struct {
+ int bucketWidth;
+ IOReportElement elem[]; // Array of elements
+} IOHistReportInfo;
+
+/*
+ * Determine the size required for a HistogramReport buffer.
+ *
+ * int nbuckets - number of buckets in the histogram
+ */
+#define HISTREPORT_BUFSIZE(nbuckets) \
+ (sizeof(IOHistReportInfo) + ((nbuckets) * sizeof(IOReportElement)))
+
+/*
+ * Initialize a HistogramReport buffer. Supports only linear scale histogram.
+ *
+ * int nbuckets - number of buckets data is combined into
+ * uint32_t bucketWidth - size of each bucket
+ * void* buffer - ptr to HISTREPORT_BUFSIZE(nbuckets) bytes
+ * size_t bufSize - sanity check of buffer's size
+ * uint64_t providerID - registry Entry ID of the reporting service
+ * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID()
+ * IOReportCategories categories - categories of this channel
+ *
+ * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT.
+ * If that returns, the buffer is left full of '&'.
+ */
+#define HISTREPORT_INIT(nbuckets, bktSize, buf, bufSize, providerID, channelID, cats) \
+do { \
+ memset((buf), '&', (bufSize)); \
+ IOHistReportInfo *__info = (IOHistReportInfo *)(buf); \
+ IOReportElement *__elem; \
+ IOHistogramReportValues *__rep; \
+ if ((bufSize) >= HISTREPORT_BUFSIZE(nbuckets)) { \
+ __info->bucketWidth = (bktSize); \
+ for (unsigned __no = 0; __no < (nbuckets); __no++) { \
+ __elem = &(__info->elem[__no]); \
+ __rep = (IOHistogramReportValues *) &(__elem->values); \
+ __elem->provider_id = (providerID); \
+ __elem->channel_id = (channelID); \
+ __elem->channel_type.report_format = kIOReportFormatHistogram; \
+ __elem->channel_type.reserved = 0; \
+ __elem->channel_type.categories = (cats); \
+ __elem->channel_type.nelements = (nbuckets); \
+ __elem->channel_type.element_idx = __no; \
+ __elem->timestamp = 0; \
+ memset(__rep, '\0', sizeof(IOHistogramReportValues)); \
+ } \
+ } \
+ else { \
+ IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
+ } \
+} while (0)
+
+/*
+ * Update histogram with a new value.
+ *
+ *
+ * void* hist_buf - pointer to memory initialized by HISTREPORT_INIT()
+ * int64_t value - new value to add to the histogram
+ */
+#define HISTREPORT_TALLYVALUE(hist_buf, value) \
+do { \
+ IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \
+ IOReportElement *__elem; \
+ IOHistogramReportValues *__rep; \
+ for (unsigned __no = 0; __no < __info->elem[0].channel_type.nelements; __no++) { \
+ if ((value) <= __info->bucketWidth * (__no+1)) { \
+ __elem = &(__info->elem[__no]); \
+ __rep = (IOHistogramReportValues *) &(__elem->values); \
+ if (__rep->bucket_hits == 0) { \
+ __rep->bucket_min = __rep->bucket_max = (value); \
+ } \
+ else if ((value) < __rep->bucket_min) { \
+ __rep->bucket_min = (value); \
+ } \
+ else if ((value) > __rep->bucket_max) { \
+ __rep->bucket_max = (value); \
+ } \
+ __rep->bucket_sum += (value); \
+ __rep->bucket_hits++; \
+ break; \
+ } \
+ } \
+} while (0)
+
+/*
+ * Prepare a HistogramReport for
+ * IOService::updateReport(kIOReportCopyChannelData...)
+ *
+ * void* array_buf - ptr to memory initialized by HISTREPORT_INIT()
+ * void* ptr2cpy - filled in with pointer to buffer to be copied out
+ * size_t size2cpy - filled in with the size of the buffer to copy out
+ */
+
+#define HISTREPORT_UPDATEPREP(hist_buf, ptr2cpy, size2cpy) \
+do { \
+ IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \
+ (size2cpy) = __info->elem[0].channel_type.nelements * sizeof(IOReportElement); \
+ (ptr2cpy) = (void *) &__info->elem[0]; \
+} while(0)
+
+
+/*
+ * Update the result field received as a parameter for kIOReportGetDimensions &
+ * kIOReportCopyChannelData actions.
+ *
+ * void* array_buf - memory initialized by HISTREPORT_INIT()
+ * IOReportConfigureAction action - configure/updateReport() 'action'
+ * void* result - configure/updateReport() 'result'
+ */
+
+#define HISTREPORT_UPDATERES(hist_buf, action, result) \
do { \
- int __cnt = (bufSize)/sizeof(uint32_t); \
- while (--__cnt >= 0) \
- ((uint32_t*)(buf))[__cnt] = 0xbadcafe; \
+ IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \
+ int *__nElements = (int *)(result); \
+ if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
+ *__nElements += __info->elem[0].channel_type.nelements; \
+ } \
} while (0)
+/*
+ * Get the 64-bit channel ID of a HistogramReport.
+ *
+ * void* hist_buf - ptr to memory initialized by HISTREPORT_INIT()
+ */
+#define HISTREPORT_GETCHID(hist_buf) \
+ (((IOHistReportInfo *)(hist_buf))->elem[0].channel_id)
+
+/*
+ * Get the IOReportChannelType of a HistogramReport.
+ *
+ * void* hist_buf - ptr to memory initialized by HISTREPORT_INIT()
+ */
+#define HISTREPORT_GETCHTYPE(hist_buf) \
+ (*(uint64_t*)&(((IOHistReportInfo *)(hist_buf))->elem[0].channel_type))
+
#ifdef __cplusplus
}
#endif