//!
//! \file view.h
//!
//! \author Platform Architecture Engineering (PAE)
//!
//! \date 17 July 2015
//!
//! \copyright Copyright (c) 2015-2016 Apple Inc. All rights reserved.
//!
//! \brief VIEW API documentation.
//!
//! The VIEW API provides a single interface for both VIEW and VIEW2 devices.
//!
//! The VIEW API relies on 'callback' blocks and GCD to provide sample data and handle
//! errors. The various viewAdd[Data|Error] functions are used to register the specific
//! 'callback' blocks. By default dispatch_get_main_queue() is used, but can be
//! individually set by block.
//!
//! To connect to a device, the viewOpenDevice() function is used. Once a device
//! is connected, information about it can be queried using various functions.
//! Channel configuration can also be changed once a device is connected.
//!
//! Once a device is configured sampling can be controlled using the
//! viewStartSampling() and viewStopSampling() functions.
//! Various triggers can also be used to begin sampling.
//!
//! Multiple device sampling is also supported (providing all devices
//! are of the same version). In these cases, viewSetMaster() is
//! needed to designate the master device.
//!
//! View2 supports CFNotifications for connect and disconnect events. To utilize this,
//! CFObservers must be added in the user application that pay attention to object \link kViewNotificationObject \endlink
//! and listen for events \link kViewNotificationConnect \endlink/\link kViewNotificationDisconnect \endlink.
//! Users can provide their own programmed callback function to the observer. A simple example for only the connect event is shown below:
//!
//! \code
//! #include <stdio.h>
//! #include <CoreFoundation/CoreFoundation.h>
//! #include <view/view.h>
//!
//! // Callback function when connect notification occurs
//! void connectEventCallback(  CFNotificationCenterRef center,
//!                             void                    *observer,
//!                             CFStringRef             name,
//!                             const void              *object,
//!                             CFDictionaryRef         userInfo    )
//!{
//!    CFStringRef deviceIdCFStr = CFDictionaryGetValue(userInfo, kViewNotificationKey);
//!    const char * deviceIdStr = CFStringGetCStringPtr(deviceIdCFStr, kCFStringEncodingASCII);
//!    printf("%s connected\n", deviceIdStr);
//!}
//!
//!int main(int argc, const char * argv[])
//!{
//!    // Decare/define CF distributed notification center
//!    CFNotificationCenterRef distributedCenter = CFNotificationCenterGetDistributedCenter();
//!
//!    // Declare/define CF Observer
//!    CFStringRef observer = CFSTR("Connection CF Observer");
//!
//!    // Add observer/configure notification parameters/arguments
//!    CFNotificationCenterAddObserver(
//!                                    distributedCenter,
//!                                    observer,
//!                                    connectEventCallback,
//!                                    kViewNotificationConnect,
//!                                    kViewNotificationObject,
//!                                    CFNotificationSuspensionBehaviorDrop
//!                                    );
//!    // Should never exit run loop
//!    CFRunLoopRun();
//!
//!    return 0;
//!}
//! \endcode

#pragma once

#include <CoreFoundation/CoreFoundation.h>
#include <view/viewKeys.h>
#include <math.h>

#if defined(__cplusplus)
extern "C" {
#endif

// In this header, you should import all the public headers of your framework using statements like #import <view/PublicHeader.h>

typedef const void				* view_t;				//!< View device reference TODO: Test typedef void * with char *
typedef const void				* viewSampleData_t;		//!< View sample data reference
typedef float					viewFloat_t;			//!< Analog value in either volts or amps
typedef uint16_t				viewFlags_t;			//!< View sample flag data
typedef uint32_t				channelNum_t;			//!< Channel number
typedef uint64_t				viewTime_t;				//!< Timestamp in nanoseconds
typedef uint64_t				viewSampleRate_t;		//!< Sample period in Hz
typedef void					viewCalibrationInfo_t;	//!< Pointer to view calibration info. TODO

//! Trigger type enum
typedef enum {
	viewTriggerNone        = 0,		//!< No trigger enabled
	viewTriggerRisingEdge  = 1,		//!< Rising edge trigger
	viewTriggerFallingEdge = 2,		//!< Falling edge trigger
	viewTriggerAnyEdge     = 3,		//!< Trigger on both rising and falling edges
} viewTriggerType_t;

typedef enum {
	viewModeNormal    = 0,			//!< Start sampling and receiving data immediately
	viewModeTriggered = 1,			//!< Wait until trigger event before receiving data (can also be triggered manually)
} viewSamplingMode_t;

typedef enum {
	viewChannelModeVoltage     = 0,
	viewChannelModeCurrent     = 1,
    viewChannelModeTemperature = 2,
    viewChannelModeDigital     = 3
} viewChannelMode_t;

enum {
	viewFlagMissedSample = (1 << 0),	//!< Samples from a missed packet (VIEW 1). Invalid data.
	viewFlagClipped      = (1 << 1),    //!< Sample was at or exceed the the range for the channel.
	viewFlagLowSignal    = (1 << 2),	//!< Sample was close to zero. For VIEW1 this indicates that the measurement has increased error
};

typedef enum {
	viewErrorNone            =  0,           //!< Everything is OK
	viewErrorMisc            = -1,           //!< Undefined error
	viewErrorNoMem           = -2,           //!< Out of memory error
    viewErrorNoDevice        = -3,           //!< Returned when the requested device is not present
    viewErrorInvalidOption   = -4,           //
    viewErrorI2C             = -5,           //
    viewErrorTimeout         = -6,           //
    viewErrorOvertemp        = -7,           //
    viewErrorNoSamples       = -8,           //!< View2, no DMA interrupt, so stopped receiving data
    viewErrorCardExtracted   = -9,           //!< View2, card extracted, so stopped receiving data
	viewErrorAlreadyOpen     = -10,          //!< Device is already opened
	viewErrorNoCalStub       = -11,
    viewErrorCalDataInvalid  = -12,
    viewErrorLateStart       = -13,
    viewErrorCalFailToSettle = -14,
    viewErrorClockSync       = -15,          //!<View2 not sync'd to TBT clock
    viewErrorNoAuth         = -17,           //!<Could not authenticate through AppleConnect for authorization to download board file.
    viewErrorNotFound       = -18            //!<Board config file with given DUT parameters not found
} viewError_t;

//! Channel info structure
typedef struct {
	char name[128];					//!< Channel name
	float senseResistorInOhms;		//!< Sense resistor value
	float gain;						//!< Pre-amp gain
	viewChannelMode_t mode;			//!< Current/Voltage
    float offset;                   //!< Channel offset - Always zero
} viewChannelInfo_t;

typedef enum {
    VIEW_TYPE_NONE = 0,
    VIEW_TYPE_1    = 1,
    VIEW_TYPE_2    = 2,
    VIEW_TYPE_DEMO = 3,
    VIEW_TYPE_2_TEMP = 4,
    VIEW_TYPE_2_HS   = 5,
    VIEW_TYPE_2_DAC  = 6,
    VIEW_TYPE_2_GPIO = 7,
    VIEW_TYPE_MAX
} viewType_t;

typedef enum {
    VIEW_DAC_CHANNEL_0 = 0,
    VIEW_DAC_CHANNEL_1 = 1,
    VIEW_NUM_DAC_CHANNELS
} viewDAC_ChannelNum_t;
//!
//! \brief New Data available block definition.
//! \param samples Abstract pointer to sample buffer. Use viewGetSamples() to get the actual sample data and viewGetTimestamp() to get the timestamp.
//!
typedef void (^viewSampleBlock_t)(viewSampleData_t samples);

typedef void (^viewDataBlock_t)(view_t view, viewTime_t timeStamp, int32_t numRows, viewSampleData_t samples);

//!
//! \brief DAC samples block definition.
//!
typedef void (^viewDacBlock_t)(void);


//!
//! \brief Error block definition
//!
//! \param view View device sending the data
//! \param error Error code
//! \param errorMsg String description of error if available, NULL otherwise.
//!
typedef void (^viewErrorBlock_t)(view_t view, viewError_t error, const char *errorMsg);

#pragma mark -
#pragma mark Version Information

//!
//! \name Version Information
//! Functions dealing with the Framework/Kext version
//!
//! \{

//!
//! \brief Get Framework/Kext version information
//!
//! \return CFDictionaryRef with versions for various things. See viewKeys.h for more information
//!
__attribute__((cf_returns_retained))
CFDictionaryRef viewGetVersions(void);

//! \}

#pragma mark -
#pragma mark Device Information

//!
//! \name Device Information
//! Functions to get device information
//!
//! \{

//!
//! \brief Get number of channels
//! \param device View device to query
//! \param numChannels pointer where the number of channels is returned
//!
//! \return viewErrorNone on success. viewErrorMisc if functions is not supported on passed in device or the passed in device is not valid.
//!
viewError_t viewGetNumChannels(view_t device, uint32_t *numChannels);

//!
//! \brief Get channel information
//! \param device View device to query
//! \param channel Channel number
//! \param info pointer to viewChannelInfo_t structure
//! TODO: - more info
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewGetChannelInfo(view_t device, channelNum_t channel, viewChannelInfo_t *info);

//!
//! \brief Query what type of data the a specific channel contains.
//! \param device View device to query. Must not be NULL.
//! \param channel Channel number. If the channel index is out of range viewErrorInvalidOption is returned.
//! \param mode pointer to viewChannelMode_t. Must not be NULL.
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewGetChannelMode(view_t device, channelNum_t channel, viewChannelMode_t *mode);

//!
//! \brief Get view device
//! \param device View device to query
//!
//! \return CFDictionaryRef with device information. See viewKeys.h for more information
//!
__attribute__((cf_returns_retained))
CFDictionaryRef viewGetInfo(view_t device);

//!
//! \brief Get device sampleRate
//! \param device View device
//!
//! \return sample rate in Hz
//!
viewSampleRate_t viewGetSampleRate(view_t device);

//!
//! \brief Get device type
//! \param device View device
//!
//! \return enumrated type corresponding to what type of view this object corresponds to.
//!
viewType_t viewGetType(view_t device);

//! \}

#pragma mark -
#pragma mark Channel Buffer/sampling functions

//!
//! \name Channel Buffer/sampling functions
//! Functions dealing with sample data/buffers, information about them, and memory management
//!
//! \{

//!
//! \brief Get pointer to interleaved sample data
//! The sample data is organized in memory as follows:
//!   samples:
//!   t0         | ch0, ch1, ch2, ch3, ..., chN
//!   t1         | ch0, ch1, ch2, ch3, ..., chN
//!   .          |
//!   .          |
//!   .          |
//!   tnumRows-1 | ch0, ch1, ch2, ch3, ..., chN
//! Where each ch is ChannelX as a float. So its an array of numRows long, where
//! each item in the array is an array of N floats. Each row is the set of all
//! channel samples for a particular sample time.
//! \param sampleData abstract pointer to sample buffer
//! \param samples address of a pointer which will point to a array of viewFloat_ts after this call.
//!
//! \return viewErrorNone on Success or viewErrorInvalidOption if a bad parameter was passed
//!
viewError_t viewGetSamples(viewSampleData_t sampleData, viewFloat_t **samples);

//!
//! \brief Get pointer to interleaved flag data
//! \param sampleData abstract pointer to sample buffer
//! \param flags address of a pointer which will point to a array of viewFlags_t after this call.
//!
//! \return viewErrorNone on Success or viewErrorInvalidOption if a bad parameter was passed
//!
viewError_t viewGetFlags(viewSampleData_t sampleData, viewFlags_t **flags);

//!
//! \brief Get number of samples (per channel) in sample data
//! \param sampleData pointer to sample data
//!
//! \return number of samples per channel in sample data
//!
int32_t viewGetNumSamples(viewSampleData_t sampleData);

//!
//! \brief Get timestamp for the first sample in sample data
//! \param sampleData pointer to sample data
//!
//! \return Timestamp
//!
viewTime_t viewGetTimestamp(viewSampleData_t sampleData);

//!
//! \brief Get sampleRate for viewSampleData
//! \param samples pointer to sample data
//!
//! \return sample rate in Hz
//!
viewSampleRate_t viewGetSampleRateFromSamples(viewSampleData_t samples);

//!
//! \brief Get the reference to the view device that is associated with this sample buffer.
//! \param sampleData abstract pointer to sample buffer
//! \param view abstract pointer to view device
//!
//! \return viewErrorNone on Success or viewErrorInvalidOption if a bad parameter was passed
//!
viewError_t viewGetDeviceFromSamples(viewSampleData_t sampleData, view_t *view);

//!
//! \brief Increase retain count on viewSampleData
//! \param samples pointer to sample data
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewSampleDataRetain(viewSampleData_t samples);

//!
//! \brief Decrease retain count on viewSampleData
//! \param samples pointer to sample data
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewSampleDataRelease(viewSampleData_t samples);

//! \}

#pragma mark -
#pragma mark Device Setup/Configuration

//!
//! \name Device Setup/Configuration
//! Device add/remove/configure and pin configuration functions
//!
//! \{

//!
//! \brief Get list of connected view devices connected to the system. Does not include IP based VIEW1 systems.
//!
//! \return CFArray containing CFStrings of all the available view devices attached to the system
//!
CFArrayRef viewCreateListOfDevices(void);

//!
//! \brief Add new view device
//! \param deviceID String with device ID (can be ip address or pci device name)
//!
//! \return view_t device (or NULL if not sucessfull)
//!
view_t viewOpenDevice(const char *deviceID); // deviceID can be ip address or pci device name

//!
//! \brief Remove view device
//! \param device View device to be removed
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewCloseDevice(view_t device);

//!
//! \brief Set device sampleRate
//! \param device View device
//! \param sampleRate Sample rate in Hz
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewSetSampleRate(view_t device, viewSampleRate_t sampleRate);

//!
//! \brief Set channel name
//!
//! \param device View device to be configured
//! \param channel Channel number
//! \param name Channel name
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewSetChannelName(view_t device, channelNum_t channel, const char *name);

//!
//! \brief Automatic channel configuration
//! Function will automatically set an appropriate gain based on senseResistorInOhms and maxCurrent
//!
//! \param device View device to be configured
//! \param channel Channel number
//! \param senseResistorInOhms Sense resistor value
//! \param maxCurrent Maximum expected current
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewConfigureChannel(view_t device, channelNum_t channel, double senseResistorInOhms, double maxCurrent);


//!
//! \brief Configures the view using a boardcfg.xml file
//!
//! \param device View device to be configured
//! \param boardXmlFileData The boardxml.cfg file
//! \param medusaheaderTagC The specific slot(medusaheader) tag to use in the boardcfg.xml file
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewConfigureUsingBoardXMLFile(view_t device, CFDataRef boardXmlFileData, const char *medusaheaderTagC);


//!
//! \brief Manual channel configuration
//! \param device View device to be configured
//! \param channel Channel number
//! \param senseResistorInOhms Sense resistor value
//! \param gain Pre-amp gain
//!
//! \return 0 on success, nonzero for error
//! }
//!
// TODO: rdar://22766014 Get rid of this
viewError_t viewConfigureChannelManual(view_t device, channelNum_t channel, double senseResistorInOhms, double gain);

//!
//! \brief Flag configuration
//! Enable/disable sample flags. Note: Enabling flags will have a negative effect on performance.
//!
//! \param device View device to be configured
//! \param flagsEnabled Should sample flags be stored?
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewConfigureFlags(view_t device, bool flagsEnabled);

//!
//! \brief Set device specific configuration
//! Diferent VIEW device families might have device-specific configuration. This function allows for
//! the setting of various parameters using a CFDictionary and key-value pairs.
//!
//! \param device View device to be configured
//! \param config Dictionary with key-value pairs for configuration
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewDeviceSpecificConfigurationSet(view_t device, CFDictionaryRef config);

//! \}

#pragma mark -
#pragma mark Calibration

//!
//! \name Calibration
//! Calibration functions
//!
//! \{

//!
//! \brief Check if View device needs calibration
//! \param device View device to be checked
//!
//! \return True if calibration is needed, false if calibration is still current
//!
viewError_t viewNeedsCalibration(view_t device, bool *calibrationNeeded);

//!
//! \brief Get device calibration information
//! \param device View device to get calibration info from
//! \param info Pointer to calibration info. Client must free after using.
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewGetCalibrationInfo(view_t device, viewCalibrationInfo_t *info);

//!
//! \brief Calibrate view device
//! \param device View device to be calibrated ( This might take a while)
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewCalibrate(view_t device);

//!
//! \brief Calibrate all view2 device
//! \param view2Devices Array of View2 devices to be calibrated (This might take a while)
//!
//! \return 0 on success, nonzero for error
//!
viewError_t view2CalibrateAll(view_t view2Devices[], uint32_t numViews);

//! \}

#pragma mark -
#pragma mark Blocks/callbacks

//!
//! \name Blocks/callbacks
//! Functions dealing with events
//!
//! \{

//!
//! \brief Register new sample processing block that wil be called for each set of samples caputred by the view device.
//! \param device View device to be configured
//! \param queue GCD queue on which the block will be called, can be NULL in which case the view framework will create a queue
//! \param sampleBlock block to be called when new data is available
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewRegisterSampleHandler(view_t device, dispatch_queue_t queue, viewSampleBlock_t sampleBlock);

//!
//! \deprecated Should use viewRegisterSampleHandler
//! \brief Add new data processing block
//! \param device View device to be configured
//! \param dataBlock block to be called when new data is available
//! \param queue GCD queue on which the block will be called
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewRegisterDataHandler(view_t device, viewDataBlock_t dataBlock, dispatch_queue_t queue) __attribute__((deprecated));

//!
//! \brief Add error processing/handling block
//! \param device View device to be configured
//! \param errorBlock block to be called when errors occur
//! \param queue GCD queue on which the block will be called
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewRegisterErrorMsgHandler(view_t device, dispatch_queue_t queue, viewErrorBlock_t errorBlock);

//!
//! \deprecated Should use viewRegisterErrorMsgHandler
//! \brief Add error processing/handling block
//! \param device View device to be configured
//! \param errorBlock block to be called when errors occur
//! \param queue GCD queue on which the block will be called
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewRegisterErrorHandler(view_t device, viewErrorBlock_t errorBlock, dispatch_queue_t queue) __attribute__((deprecated));

//!
//! \brief Get the data queue that the handler events are processed on
//! \param device View device to be configured
//! \param queue GCD queue on which the data handler block is called on
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewGetDataHandlerQueue(view_t device, dispatch_queue_t *queue);

//!
//! \brief Get the error queue that the handler events are processed on
//! \param device View device to be configured
//! \param queue GCD queue on which the data handler block is called on
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewGetErrorHandlerQueue(view_t device, dispatch_queue_t *queue);

//! \}

#pragma mark -
#pragma mark Sampling/Triggers

//!
//! \name Sampling/Triggers
//! Sampling start/stop as well as trigger functions
//!
//! \{

//!
//! \brief Start sampling data on all connected devices
//! \param mode View sampling mode
//! TODO: explain start/stop for changing
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewStartSampling(viewSamplingMode_t mode);
// TODO: rdar://22766263
// TODO: individual start/stop, multiple masters?
// TODO: pass list of devices?, viewGroup_t?
// TODO: viewGetSamplingMode()

//!
//! \brief Stop sampling data on all connected devices
//! This function will tell all connected VIEW devices to stop sampling and then return. There still might be outstanding data callbacks to be processed. If you need to know when all data callbacks are complete use: viewStopSamplingWithCallback().
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewStopSampling(void);

//!
//! \brief Stop sampling data on all connected devices with completion callback when all data callbacks have executed.
//! This function will tell all connected VIEW devices to stop sampling and then return and once all data callbacks are processed will execute the passed in completion block on the specified queue.
//! \param queue The queue the completion callback is called on. Can be NULL in which case the framework will choose the default main queue.
//! \param stopCompletionCallback Block to be called when all the devices have stopped and all data callbacks are processed.
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewStopSamplingWithCallback(dispatch_queue_t queue, void (^stopCompletionCallback)(void));

//!
//! \brief Add trigger to channel
//! \param device View device to be configured
//! \param channel Channel for the trigger
//! \param type Trigger type
//! \param level Trigger level (ignored if not applicable)
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewAddTrigger(view_t device, channelNum_t channel, viewTriggerType_t type, viewFloat_t level);

//!
//! \brief Remove all triggers from channel
//! \param device View device to be configured
//! \param channel Channel to remove triggers from
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewClearTriggers(view_t device, channelNum_t channel);

//!
//! \brief Manually generate trigger event
//! Useful when sampling in triggered mode and need samples to start coming in.
//! \param device View device to be triggered
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewForceTrigger(view_t device);

//!
//! \brief Set view device as master for synchronized captures
//! \param device View device to be set as master
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewSetMaster(view_t device);

//! \}


#pragma mark -
#pragma mark View2 Specific Functions

//!
//! \brief Sets the callback function for DAC data
//! \param device View device
//! \param queue target queue
//! \param sampleBlock callback block
//!
//! \return 0 on success, nonzero for error
//!
//! Note that you will get two callbacks, one for each channel.
//! Also note that the block callback is done directly in our ISR context so you must be pretty snappy with your code and
//! not do anything that could be blocking. Once we get some other issues resolved, we will be calling it from the dispatch_queue
//! context.
viewError_t viewRegisterDACHandler(view_t device, dispatch_queue_t queue, viewDacBlock_t sampleBlock);


//!
//! \brief Starts DAC conversions. Currently the conversion rate is fixed at 9.94 KHz.
//! \param device View device
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewStartDACConversions(view_t device);


//!
//! \brief Stops DAC conversions
//! \param device View device
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewStopDACConversions(view_t device);


//!
//! \brief Write DAC samples
//! \param device View device
//! \param channel Channel to write to
//! \param sample Pointer to array at least numSamples long, of data to write
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewWriteDACSample(view_t device, viewDAC_ChannelNum_t channel, float sample);


//!
//! \brief Returns the number of samples that could be written to DAC output buffer
//! \param device View device
//! \param channel Channel
//! \param numFreeSamplesLeftInBuffer Number of samples that could be written
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewGetNumFreeSamplesLeftInDACOutputQueue(view_t device, viewDAC_ChannelNum_t channel, size_t *numFreeSamplesLeftInBuffer);


#pragma mark -
#pragma mark Utility Functions

//!
//! \name Utility Functions
//!
//! \{

//!
//! \brief Convert a viewSampleRate_t value to a viewTime_t which is in nanoseconds
//! \param rate View device to be set as master
//!
//! \return 0 on success, nonzero for error
static inline viewTime_t viewConvertRateToPeriodInNs( viewSampleRate_t rate ) {
    return 1000000000ull / rate;
}


//!
//! \brief Returns the DUT ID, as read from the one wire EEPROM attached to the Preamp
//! \param device View device
//! \param dutID The DUT ID read from the device
//! \return error code indicating if could read
//!
viewError_t viewGetDUTId(view_t device, CFStringRef *dutID);


//!
//! \brief Writes the DUT ID to the one wire EEPROM attached to the Preamp.
//!        WARNING THIS WILL OVERWRITE THE EXISTING DUT ID
//! \param device View device
//! \param dutID The ID to write to the DUT
//! \return error code indicating if could write
//!
viewError_t viewSetDUTId(view_t device, CFStringRef dutID);

//!
//! \brief Fetches a board XML file for the specified DUT.
//! \param dutID The ID containing board parameters used to look up the file.
//! \param boardXmlFile Data object containing the XML file contents.
//! \return Possible return status codes:
//!                     viewError_None - File was either dowloaded from the server, or a current copy was already present in the cache.
//!                     ---- For the following download errors, the contents of a stale cache file will still be returned if present, and the app can decide whether to allow sampling or not.
//!                     viewError_Offline - File not present in the cache or expired, and the Knox server could not be contacted. App should prompt user to check their network/VPN settings.
//!                     viewError_AuthExpired - File not present or in the cache or expired, and the user is not authenticated with AC auth. App should prompt user to authenticate.
//!                     viewError_NotFound - File not present in the cache or expired, and no files could be located on the server for the specified DUT ID.
viewError_t viewGetBoardXmlFile(CFStringRef dutID, CFDataRef *boardXmlFile);

//!
//! \brief Clears the XML board file cache, resulting in a fresh download on the next call to viewGetBoardXmlFile()
//!
bool viewClearBoardXmlCache(void);

//! \}

#pragma mark -
#pragma mark Debugging Functions

#define VIEW_DBG_UNMASKABLE (1 << 31)   //!< Messages to always print - Calibration and some power messages
#define VIEW_DBG_VIEW		(1 << 0)	//!< VIEW API Basic Debug
#define VIEW_DBG_VIEW1		(1 << 4)	//!< VIEW1 Specific Debug
#define VIEW_DBG_VIEW2		(1 << 5)	//!< VIEW2 Specific Debug
#define VIEW_DBG_VIEW2_DMA	(1 << 6)	//!< Samples the VIEW DMA related registers to help debug any starvation
#define VIEW_DBG_ASTRIS		(1 << 8)	//!< VIEW1-Astris Debug
#define VIEW_DBG_POWER      VIEW_DBG_VIEW2

#define VIEW_DBG_ALL		(0xFFFFFFFF) //!< All debug flags are set

//!
//! \name Debugging Functions
//!
//! \{

//!
//! \brief Set debug level for view API
//! \param level Debug level (bitmask)
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewDebugSetLevel(uint32_t level);

//!
//! \brief Set debug output file for view API (stderr is default)
//! \param file output FILE*
//!
//! \return 0 on success, nonzero for error
//!
viewError_t viewDebugSetFile(FILE *file);

//!
//! \brief Run board level diagnotics. Will print out a report to the specified FILE*.
//! \param device View device to run diagnostics on
//! \param file file pointer to where the diagnotics report should be written. Can be NULL, in which case no report is generated.
//!
//! \return viewErrorNone if diagnotics pass, nonzero for failure or error
//!
viewError_t viewDebugDiagnostics(view_t device, FILE *file);


//!
//!\brief Downloads and decrypts a file from a Knox repo and saves the data to a file. CF entries are not transferred in - caller must release. 
//!\param downloadConfig Dictionary containing the following values:
//!     kViewKnoxQuery - Contains the metadata tags to search as key/value pairs. Required.
//!                     Example: { device-class: iPhone, device-model: D10, revision: 1 }
//!     kViewKnoxURL - URL of Knox Endpoint - Optional. If not specified, will default to PI repo.
//!     kViewKnoxSpace - Space to search - Optional. If not specified will default to space for View board config files
//!     kViewKnoxPointerType - Pointer type - Optional. If not specified will default to View board config file type.
//!     kViewKnoxDownloadDirectory - Local destination directory for the downloaded file. Optional. If not specified, will default ot ~/Library/View
//!     kViewKnoxDownloadFilename - Local filename for the downloaded file. Optional. If not specified, will default ot the name of the file on the Knox repo.
//!\param downloadedFilePath Pointer to a CFStringRef that will contain the full path to the downloaded and decrypted file on success, or NULL on failure. Caller must release.
//!
//!\return viewKnoxStatus - viewKnoxStatus_Success, or an error value.
viewError_t viewGetFileFromKnox(CFDictionaryRef downloadConfig, CFStringRef* downloadedFilePath);



#if defined(__cplusplus)
}
#endif
