#ifndef YEALINKSDK_H
#define YEALINKSDK_H

/****************************************************************************
*
*   yealinksdk.h
*
*   FreeType high-level API and common types (specification only).
*
* Copyright (c) 2020 Yealink ltd.
*
* This file defines the  interface for the Yealink SDK to control Yealink devices.
*
*/





#if defined _WIN32 || defined __CYGWIN___
#ifdef  BUILD_SDK
#define YEALINK_API extern "C" __declspec(dllexport)
#else
#define YEALINK_API extern "C" __declspec(dllimport)
#endif
#else
#ifdef __APPLE__
#ifdef __cplusplus
#define YEALINK_API extern "C" __attribute__ ((visibility ("default")))
#else
#define YEALINK_API __attribute__ ((visibility ("default")))
#endif
#include <stdbool.h>
#elif __linux__
#ifdef __cplusplus
#define YEALINK_API extern "C" __attribute__ ((visibility ("default")))
#else
#define YEALINK_API __attribute__ ((visibility ("default")))
#include <stdbool.h>
#endif
#endif
#endif

#if defined _WIN32 || defined __CYGWIN___
#define Yealink_VAR extern "C" __declspec(dllexport)
#else
#ifdef __cplusplus
#define Yealink_VAR extern "C" __attribute__ ((visibility ("default")))
#else
#define Yealink_VAR extern __attribute__ ((visibility ("default")))
#endif
#endif

#include "yealinksdkcommon.h"
#include "yealinkrccmulticall.h"


/**
* @brief Get the SDK version.
* @param[in,out] version Pointer to buffer used to hold the SDK version. The
* buffer must be allocated by the caller prior to calling this function.
* @param[in,out] count Character count, at time of call count must the size
* of the version buffer, at return count hols the count of the actual
* characters written to the version buffer.
* @return Return_Ok if get version is successful.
* @return Return_ParameterFail if version is NULL or too small to contain
* result.
* @note This function can be called without #Yealink_Initialize being called.
*/
YEALINK_API Yealink_ReturnCode Yealink_GetVersion(char* const version, int count);

/**
* @brief Sets the Application ID. The application ID must be set before
* #Yealink_Initialize is called. The application ID can requested via the
* Yealink Developer Zone https://developer.Yealink.com
* @param[in] inAppID ID for the application.
*/
YEALINK_API void Yealink_SetAppID(const char* inAppID);

/**
* @brief Library initialization - only intended to be called once.
* @param[in] FirstScanForDevicesDoneFunc Callback method, called when USB scan
* is done. Can be NULL if not used.
* @param[in] DeviceAttachedFunc Callback method, called when a device is
* attached. Can be NULL if not used. Callee must call #Yealink_FreeDeviceInfo to
* free memory.
* @param[in] DeviceRemovedFunc Callback method, called when a device is
* removed. Can be NULL if not used.
* @param[in] ButtonInDataRawHidFunc Callback method, called on new input data.
* HID Events will (default) NOT be triggered for standard HID to avoid conflicts
* Raw HID. Low-level. Can be NULL if not used.
* @param[in] ButtonInDataTranslatedFunc Callback method, called on new input
* data. High-level. Can be NULL if not used.
* @param[in] configParams Optional configuration of various SDK library
* behavior. Can be NULL if not used.Not support in current version,will support in next release version.
* @return True if library initialization is successful.
* @return False if library initialization is not successful. One reason could
* be that the library is already initialized or that #Yealink_SetAppID has not
* been called prior to calling this function.
* @note AppID must be set using #Yealink_SetAppID before the library
* initialization is called. If not the initialization fails.
*/
YEALINK_API bool Yealink_Initialize(void(*FirstScanForDevicesDoneFunc)(void),
                                    void(*DeviceAttachedFunc)(Yealink_DeviceInfo deviceInfo),
                                    void(*DeviceRemovedFunc)(unsigned short deviceID),
                                    void(*ButtonInDataRawHidFunc)(unsigned short deviceID, unsigned short usagePage, unsigned short usage, bool buttonInData),
                                    void(*ButtonInDataTranslatedFunc)(unsigned short deviceID, Yealink_HidInput translatedInData, bool buttonInData),
                                    Config_params* configParams
                                   );


/**
* @brief Library uninitialize.
* @return True if library uninitialization is successful, false if library
* initialization is not successful (for example if called when not
* initialized).
*/
YEALINK_API bool Yealink_Uninitialize(void);

/**
 * @brief Check if Firmware update available for device.
 * @param[in] deviceID ID for specific device.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Firmware_UpToDate if device has latest firmware version.
 * @return Firmware_Available if new firmware version is available for the
 * device.
 * @return No_Information if firmware file is not available.
 * @return NetworkRequest_Fail if request to the server fails.
 * @return Invalid_Authorization if authorization is invalid.
 * @return Not_Supported if check is not supported for given device.
 */
YEALINK_API Yealink_ReturnCode Yealink_CheckForFirmwareUpdate(unsigned short uDeviceId);

/**
 * @brief Gets details of the latest firmware present in cloud.
 * @param[in] deviceID ID for specific device.
 * @return #Yealink_FirmwareInfo structure pointer for details of the latest
 * firmware, nullptr if the device is unknown,or there was a request error.
 * @note As memory is allocated through SDK, memory needs to be freed by
 * calling #Yealink_FreeFirmwareInfo.
 */
YEALINK_API Yealink_FirmwareInfo* Yealink_GetLatestFirmwareInformation(unsigned short uDeviceId);


/**
 * @brief Frees the firmware information structure members.
 * @param[in] firmwareInfo #Yealink_FirmwareInfo structure to be freed.
 */
YEALINK_API bool Yealink_FreeFirmwareInfo(Yealink_FirmwareInfo* pInfo);

/**
 * @brief Gets information of all the firmware present in cloud for the
 * specific device.
 * @param[in] uDeviceId ID for the specific device.
 * @return A list of information about all firmware versions. If no information
 * is available or the device is unknown , nullptr
 * is returned.
 * @note The list must be freed by calling #Yealink_FreeFirmwareInfoList.
 */
YEALINK_API Yealink_FirmwareInfoList* Yealink_GetAllFirmwareInformation(unsigned short uDeviceId);

/**
 * @brief Frees the list of firmware information structure.
 * @param[in] firmwareInfolist #Yealink_FirmwareInfoList structure to be freed.
 */
YEALINK_API bool Yealink_FreeFirmwareInfoList(Yealink_FirmwareInfoList* firmwareInfolist);

/**
 * @brief Downloads the specified firmware version file.
 * @param[in] deviceID ID for specific device.
 * @param[in] version Version for which file download needs to be initiated.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_Invalid if deviceID is wrong.
 * @return Return_ParameterFail if version  is incorrect.
 * @return Return_Async if firmware download is in progress and will be
 * returned asynchronously using the callback.
 */
YEALINK_API Yealink_ReturnCode Yealink_DownloadFirmware(unsigned short uDeviceId, const char* version);

/**
 * @brief Downloads the latest FW updater relevant for this device.
 * @param[in] deviceID ID for specific device.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_Invalid if deviceID is wrong.
 * @return Return_ParameterFail if version  is incorrect.
 * @return Return_Async if firmware download is in progress and will be
 * returned asynchronously using the callback.
 */
YEALINK_API Yealink_ReturnCode Yealink_DownloadLatestFirmware(unsigned short uDeviceId);

/**
 * @brief Upgrades/Updates the firmware for the target device with specified
 * version.
 * @param[in] deviceID ID for specific device.
 * @param[in] filepath Firmware file path.
 * @return Return_Ok Successfully updated firmware.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_Invalid if deviceID is wrong.
 * @return File_Not_Accessible if firmware file path is incorrect.
 * @return Return_ParameterFail if filepath is incorrect.
 * @return Return_Async firmware update is in progress. Use FWU progress
 * callback to determine when update is done.
 */
YEALINK_API Yealink_ReturnCode Yealink_UpdateFirmware(unsigned short uDeviceId, const char* filepath);

/**
 * @brief Cancels the firmware download.
 * @param[in] deviceID ID for specific device.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_Invalid if deviceID is wrong.
 * @return Return_Ok cancels firmware download.
 */
YEALINK_API Yealink_ReturnCode Yealink_CancelFirmwareDownload(unsigned short uDeviceId);

/**
 * @brief Get the file path of the downloaded file.
 * @param[in] deviceID ID for specific device.
 * @param[in] version Version for which the path is required.
 * @return firmwareFilePath firmware file path of the device, nullptr
 * if the device is unknown or version is a nullptr.
 * @note Call #Yealink_DownloadFirmware first to ensure that data is current
 * @note As memory is allocated through SDK for firmwareFilePath, it must be
 * freed by calling #Yealink_FreeString.
 */
YEALINK_API char* Yealink_GetFirmwareFilePath(unsigned short uDeviceId, const char* version);

/**
 * @brief Registration for firmware progress event.
 * @param[in] callback Callback method, called when firmwareProgress event is
 * received from device. Can be NULL if not used.
 */
YEALINK_API void Yealink_RegisterFirmwareProgressCallBack(void(*CallBackFirmwareProgress)(unsigned short deviceID,
        Yealink_FirmwareEventType type, Yealink_FirmwareEventStatus status,
        unsigned short percentage));


/**
* @brief Check if device scan is done.
* @return True if USB device scan is done, false if USB device scan is not
* done.
* @note Library initialization must be performed before calling this function.
*/
YEALINK_API bool Yealink_IsFirstScanForDevicesDone(void);

/**
* @brief Check if a device is attached.
* @param[in] deviceID Id for specific device.
* @return True if device is attached, false if device is not attached.
*/
YEALINK_API bool Yealink_IsDeviceAttached(unsigned short deviceID);



/**
* @brief Get number of all attached devices.
*/
YEALINK_API int Yealink_GetAttachedYealinkDeviceNumber(void);


/**
* @brief Get information of all attached devices.
* @param[in] count Pointer to an integer that has the number of
* #Yealink_DeviceInfo structures allocated before calling this function.
* On return this pointer has the value of how many devices that was added.
* @param[in] deviceInfoList Pointer to an array of #Yealink_DeviceInfo to be
* populated.
* @note call #Yealink_FreeDeviceInfo on each object in the list when done do
* avoid a memory leak.
* @see Yealink_FreeDeviceInfo
*/
YEALINK_API void Yealink_GetAttachedYealinkDevices(int* count, Yealink_DeviceInfo* deviceInfoList);

/**
* @brief Get information of attached devices.
* @param[in] deviceID ID for a specific device.
* @note call #Yealink_FreeDeviceInfo when done do avoid a memory leak.
* @see Yealink_FreeDeviceInfo
*/
YEALINK_API Yealink_DeviceInfo Yealink_GetAttachedYealinkDevicesById(unsigned short deviceID);

/**
* Frees the #Yealink_DeviceInfo structure members.
* @param[in] info #Yealink_DeviceInfo structure to be freed.
*/
YEALINK_API void Yealink_FreeDeviceInfo(Yealink_DeviceInfo info);

/**
* @brief Get device ESN (electronic serial number).
* @param[in] deviceID ID for a specific device.
* @param[in] esn Pointer to buffer location where the ESN is written. The
* buffer must be allocated by the caller.
* @param[in] count Maximum number of characters to copy to serialNumber.
* @return Return_Ok if get serial number is successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Return_ParameterFail if esn or count is incorrect.
*/
YEALINK_API Yealink_ReturnCode Yealink_GetESN(unsigned short deviceID, char* const esn, int count);

/**
* @brief Get firmware version of the device.
* @param[in] deviceID ID for a specific device.
* @param[in] firmwareVersion Pointer to a location where the firmware version
* is written. Must be allocated by the caller.
* @param[in] count Maximum number of characters to copy to firmwareVersion.
* @param[out] firmwareVersion Firmware version of device.
* @return Return_Ok if get serial number is successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Not_Supported if the functionality is not supported.
*/
YEALINK_API Yealink_ReturnCode Yealink_GetFirmwareVersion(unsigned short deviceID, char* const firmwareVersion, int count);

/**
* @brief Upload device log to cloud
* @param[in] deviceID ID for a specific device.
* @return Return_Ok if that is successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Other_Error if something wrong.
* @return NetworkRequest_Fail request fail or network is block.
*/
YEALINK_API Yealink_ReturnCode Yealink_UploadDevLogToCloud(unsigned short deviceID);

/**
* @brief Export device log to path
* @param[in] deviceID ID for a specific device.
* @param[in] path log to be exported.
* @return Return_Ok if that is successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Other_Error if something wrong.
* @return Return_ParameterFail if path is incorrect.
*/
YEALINK_API Yealink_ReturnCode Yealink_ExportDevLog(unsigned short deviceID,  const char* path);

/**
 * @brief Registration for log progress event.
 * @param[in] callback Callback method, called when log event is
 * received from device. Can be NULL if not used.
 */
YEALINK_API void Yealink_RegisterLogProgressCallBack(void(*CallBackLogProgress)(unsigned short deviceID,
        Yealink_LogEventType type, bool bSuccess));

/**
 * @brief Check for offhook command support by the device.
 * @param[in] deviceID Id for a specific device.
 * @return Returns True if offhook is supported for a specific Yealink device.
 * @see Yealink_SetOffHook
 */
YEALINK_API bool Yealink_IsOffHookSupported(unsigned short deviceID);

/**
 * @brief Set off-hook.
 * @param[in] deviceID Id for a specific device.
 * @param[bool] bOffHook Boolean value to set off-hook/on-hook.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if HID is not supported.
 * @see Yealink_IsOffHookSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_SetOffHook(unsigned short deviceID, bool bOffHook);

/**
 * @brief Checks for the hold support by the device.
 * @param[in] deviceID Id for a specific device.
 * @return Returns True if hold is supported for the Yealink device.
 * @see Yealink_SetHold
 */
YEALINK_API bool Yealink_IsHoldSupport(unsigned short deviceID);

/**
 * @brief Set call on hold/resume.
 * @param[in] deviceID Id for a specific device.
 * @param[bool] bHold Boolean value to set device on hold/resume.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if HID is not supported.
 * @see Yealink_IsHoldSupport
 */
YEALINK_API Yealink_ReturnCode Yealink_SetHold(unsigned short deviceID, bool bHold);

/**
 * @brief Checks for Mute command support by the device.
 * @param[in] deviceID Id for a specific device.
 * @return Returns True if mute is supported for the Yealink device.
 * @see Yealink_SetMute
 */
YEALINK_API bool Yealink_IsMuteSupported(unsigned short deviceID);

/**
 * @brief Set mute on or off.
 * @param[in] deviceID Id for a specific device.
 * @param[bool] bMute Boolean value to set mute on/off.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if HID is not supported.
 * @see Yealink_IsMuteSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_SetMute(unsigned short deviceID, bool bMute);

/**
 * @brief Check for ringer command support by the device.
 * @param[in] deviceID Id for a specific device.
 * @return Returns True if ringer is supported for a specific Yealink device.
 * @see Yealink_SetRing
 */
YEALINK_API bool Yealink_IsRingSupported(unsigned short deviceID);

/**
 * @brief Set ringer (ringtone in headset) and ringing (ringing LED if available).
 * @param[in] deviceID Id for a specific device.
 * @param[bool] bRing Boolean value to set ringer on/off and ringing LED on/off,
 * not all device have a LED for ringing.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if HID is not supported.
 * @see Yealink_IsRingSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_SetRing(unsigned short deviceID, bool bRing);

/**
 * @brief Checks for the online mode support by the device.
 * @param[in] deviceID Id for a specific device.
 * @return Returns True if online mode is supported for a specific Yealink device.
 * @see Yealink_SetOnline
 */
YEALINK_API bool Yealink_IsOnlineSupported(unsigned short deviceID);

/**
 * @brief Set device online i.e. open radio link between base/dongle and device.
 * @param[in] deviceID Id for a specific device.
 * @param[bool] bOnline Boolean value to set online On/Off.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if HID is not supported.
 * @see Yealink_IsOnlineSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_SetOnline(unsigned short deviceID, bool bOnline);

/**
 * @brief Is the device supporting YL HID and Std HID and are able to switch
 * between them.
 * @param[in] deviceID ID for a specific device.
 * @return True Supports YL HID and STD HID.
 * @see Yealink_GetHidWorkingState
 * @see Yealink_SetHidWorkingState
 */
YEALINK_API bool Yealink_IsYlHidStdHidSupported(unsigned short deviceID);

/**
 * @brief Gets the HID working state.
 * @param[in] deviceID ID for a specific device.
 * @param[out] state HID working state.
 * @return Return_Ok working state has been set successfully.
 * @return Not_Supported the device does not support.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_ReadFail if it fails to get the state from the device.
 * @return Return_ParameterFail in case of an incorrect parameter.
 * @see Yealink_IsYlHidStdHidSupported
 * @see Yealink_SetHidWorkingState
 */
YEALINK_API Yealink_ReturnCode Yealink_GetHidWorkingState(unsigned short deviceID, Yealink_HidState* state);

/**
 * @brief Sets the HID working state to either standard HID (usb.org HID
 * specification) or YL HID.
 * @param[in] deviceID ID for a specific device.
 * @param[in] state HID working state.
 * @return Return_Ok working state has been set successfully.
 * @return Not_Supported the device does not support.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_WriteFail if it fails to write to the device.
 * @return Return_ParameterFail in case of an incorrect parameter.
 * @see Yealink_IsYlHidStdHidSupported
 * @see Yealink_GetHidWorkingState
 */
YEALINK_API Yealink_ReturnCode Yealink_SetHidWorkingState(unsigned short deviceID, Yealink_HidState state);

/**
 * @brief Enable Hid events from Yealink devices.
 * @param[in] hidEvents true HID events are send to app, false HID events are discarded
 */
YEALINK_API void Yealink_SetStdHidEventsFromYealinkDevices(bool hidEvents);

/**
 * @brief Is Hid events from Yealink devices enabled. default is false.
 * @return true HID events are enabled, false HID events are not enabled
 */
YEALINK_API bool Yealink_IsStdHidEventsFromYealinkDevicesEnabled();

/**
* @brief Register for button data with call id. DTMF and so on.
* @param[in] ButtonInDataTranslatedFunc Callback method, called on new input data
* @see Yealink_EnterDialCall
* @see Yealink_RingBackCall
* @see Yealink_IncomingCall
* @see Yealink_OutgoingCall
* @see Yealink_TerminateCall
* @see Yealink_AnswerCall
* @see Yealink_HoldCall
* @see Yealink_ResumeCall
* @see Yealink_MuteCall
* @see Yealink_UnmuteCall
*/
YEALINK_API void Yealink_RegButtonInDataTranslatedWithCid(void(*ButtonInDataTranslatedFunc)(unsigned short deviceID, int cid, Yealink_HidInput translatedInData, bool buttonInData));

/**
 * @brief Check if a feature is supported by a device.
 * @param[in] deviceID ID for the specific device.
 * @param[in] feature The feature to check.
 * @return True if specified feature is supported.
 * @see Yealink_GetSupportedFeatures
 * @see Yealink_FreeSupportedFeatures
 */
YEALINK_API bool Yealink_IsFeatureSupported(unsigned short deviceID, DeviceFeature feature);

/**
 * @brief Get the support url of the device.
 * @param[in] deviceID ID for specific device.
 * @return support url of the device, nullptr
 * if the device is unknown or url is empty.
 * @note As memory is allocated through SDK for url, it must be
 * freed by calling #Yealink_FreeString.
 */
YEALINK_API char* Yealink_GetSupportUrl(unsigned short uDeviceID);

/**
 * @brief Get array of features supported by a device.
 * @param[in] deviceID ID for the specific device.
 * @param[out] count Number of items in result.
 * @return Array of supported features, may be null. Shall be freed by calling
 * #Yealink_FreeSupportedFeatures.
 * @see Yealink_IsFeatureSupported
 * @see Yealink_FreeSupportedFeatures
 */
YEALINK_API const DeviceFeature* Yealink_GetSupportedFeatures(unsigned short deviceID, unsigned int* count);

/**
 * @brief Free a list of features obtained by calling
 * #Yealink_GetSupportedFeatures.
 * @param[in] features List to delete.
 * @see Yealink_GetSupportedFeatures
 * @see Yealink_FreeSupportedFeatures
 */
YEALINK_API void Yealink_FreeSupportedFeatures(const DeviceFeature* features);


/**
Device Settings
* @brief The proposed design is to have the memory allocated at the SDK level
* as the user may not aware of how much memory needs to be allocated. Settings
* vary up on connected devices. So it is good SDK to decide how much memory
* to allocate for settings.
*/

/**
* @brief Gets the unique setting identified by a GUID of a device.
* @param[in] deviceID Device ID of the device to read/get the setting from.
* @param[in] guid The unique setting identifier, the string must be zero
* terminated.
* @return Pointer to the structure containing the requested setting. In case
* the device is not found or could not be accessed a NULL pointer is returned.
* @note As memory is allocated through the SDK it needs to be freed by calling
* #Yealink_FreeDeviceSettings.
*/
YEALINK_API DeviceSettings* Yealink_GetSetting(unsigned short deviceID, const char* guid);

/**
* @brief Gets the complete settings details (all groups and its settings) for
* a device.
* @param[in] deviceID ID for specific device.
* @return Pointer to the structure containing all settings for the deviceID.
* In case device is not found/ could not be access, NULL pointer is returned.
* @note As memory is allocated through SDK, need to be freed by calling
* #Yealink_FreeDeviceSettings.
*/
YEALINK_API DeviceSettings* Yealink_GetSettings(unsigned short deviceID);

/**
* @brief Sets all the settings( including all groups and its settings) for a
* device.
* @param[in] deviceID ID for a specific device.
* @param[in] setting Dynamic settings for the device.
* @return Return_Ok if setting is successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Return_ParameterFail if setting parameter is wrong.
* @return Device_Rebooted if the device rebooted after applying settings that
* required rebooting.
* @return Device_WriteFail if it fails to write to the device.
*/
YEALINK_API Yealink_ReturnCode Yealink_SetSettings(unsigned short deviceID, DeviceSettings* setting);



/**
* @brief Free #DeviceSettings structure.
* @param[in] setting #DeviceSettings structure pointer, which needs to be freed.
*/
YEALINK_API void Yealink_FreeDeviceSettings(DeviceSettings* setting);


/**
* @brief Add a listener for changes to the device settings. The listener will
* be called when a setting is changed in the device, regardless of who
* changed it (this instance, another instance, or the user through MMI).
* @param deviceID ID for a specific device.
* @param listener The function to receive callbacks. Set to null to cancel
* listening.
* @param settings The settings which the client is interested in. Remains
* owned by the caller. Set to null to cancel listening.
* @return Return_Ok if successful.
* @return Not_Supported if feature is not supported.
* @return Device_Unknown if device not known.
*/
YEALINK_API Yealink_ReturnCode Yealink_SetSettingsChangeListener(unsigned short deviceID, SettingsListener listener, const DeviceSettings* settings);


/**
* Free char pointer.
* @param[in] strPtr Char pointer, which needs to be freed.
*/
YEALINK_API void Yealink_FreeString(char* strPtr);


/**
* Reboot Device
* @param[in] deviceID ID for a specific device.
* @return Return_Ok if successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Not_Supported if device does not support factory reset.
*/
YEALINK_API Yealink_ReturnCode Yealink_Reboot(unsigned short deviceID);


/**
* @brief Restore factory settings to device. Note that if used on a device
* connected via dongle (or directly via BT), the pairing list in the device
* will be cleared, and the connection to the device will be lost.
* @param[in] deviceID ID for a specific device.
* @return Return_Ok if successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return No_FactorySupported if device does not support factory reset.
* @return Device_WriteFail if it fails to write to the device.
* @return ProtectedSetting_Write if a setting is write protected.
*/
YEALINK_API Yealink_ReturnCode Yealink_FactoryReset(unsigned short deviceID);


/**
* @brief Checks if date and time synchronization is supported by the device.
* @param[in] deviceID ID for a device.
* @return True if date and time synchronization is supported otherwise false.
* @see Yealink_SetDateTime
*/
YEALINK_API bool Yealink_IsSetDateTimeSupported(unsigned short deviceID);

/**
* @brief Sets (synchronizes) the date and time in the device.
* @param[in] deviceID ID of the device to operate on.
* @param[in] dateTime Date and time to set. If this parameter is set to NULL
* the date and time is set to the current time of the platform.
* @return Return_Ok if time and date is set successfully.
* @return Device_Unknown if the deviceID specified is not known.
* @see Yealink_IsSetDateTimeSupported
*/
YEALINK_API Yealink_ReturnCode Yealink_SetDateTime(unsigned short deviceID, const timedate_t* const dateTime);

/**
 * @brief Set the Bluetooth device in pairing mode.
 * @param[in] deviceID ID for a BT adapter.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_ScanNewDevices
 * @see Yealink_GetSearchDeviceList
 * @see Yealink_StopBTScan
 * @see Yealink_SetAutoConnecting
 * @see Yealink_GetAutoConnecting
 */
YEALINK_API Yealink_ReturnCode Yealink_SetBTDiscoverable(unsigned short uDeviceId);

/**
 * @brief Search for available Bluetooth devices which are switched on, within
 * range and ready to connect.
 * @param[in] deviceID ID for the BT adapter.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_SetBTDiscoverable
 * @see Yealink_GetSearchDeviceList
 * @see Yealink_StopBTScan
 * @see Yealink_SetAutoConnecting
 * @see Yealink_GetAutoConnecting
 */
YEALINK_API Yealink_ReturnCode Yealink_ScanNewDevices(unsigned short uDeviceId);

/**
 * @brief Stop search for available Bluetooth devices.
 * @param[in] deviceID ID for a BT adapter.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_SetBTDiscoverable
 * @see Yealink_GetSearchDeviceList
 * @see Yealink_ScanNewDevices
 * @see Yealink_SetAutoConnecting
 * @see Yealink_GetAutoConnecting
 */
YEALINK_API Yealink_ReturnCode Yealink_StopBTScan(unsigned short uDeviceId);

/**
 * @brief Gets the list of new devices which are available to pair & connect.
 * @param[in] deviceID ID for specific device.
 * @return Returns pointer to the structure #Yealink_PairingList contains
 * available devices ready to pair.
 * @note As memory is allocated through SDK, it must be freed by calling
 * #Yealink_FreePairingList.
 * @see Yealink_SetBTDiscoverable
 * @see Yealink_StopBTScan
 * @see Yealink_ScanNewDevices
 * @see Yealink_SetAutoConnecting
 * @see Yealink_GetAutoConnecting
 */
YEALINK_API Yealink_PairingList* Yealink_GetSearchDeviceList(unsigned short uDeviceId);

/**
 * @brief When Bluetooth adapter is plugged into the PC it will attempt to
 * connect with the last connected Bluetooth device.
 * @param[in] deviceID ID for a BT adapter.
 * @param[in] value Enable or disable for auto connect.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_SetBTDiscoverable
 * @see Yealink_StopBTScan
 * @see Yealink_ScanNewDevices
 * @see Yealink_GetSearchDeviceList
 * @see Yealink_GetAutoConnecting
 */
YEALINK_API Yealink_ReturnCode Yealink_SetAutoConnecting(unsigned short uDeviceId, bool bValue);

/**
 * @brief Get Auto connect mode enable or disable.
 * @param[in] deviceID ID for a BT adapter.
 * @return True if auto pairing mode is enabled, false otherwise.
 * @see Yealink_SetBTDiscoverable
 * @see Yealink_StopBTScan
 * @see Yealink_ScanNewDevices
 * @see Yealink_GetSearchDeviceList
 * @see Yealink_SetAutoConnecting
 */
YEALINK_API bool Yealink_GetAutoConnecting(unsigned short uDeviceId);

/**
 * @brief Through this interface, the audio stream channel for
 * playing media audio can be closed to save power.
 * @param[in] deviceID ID for a BT adapter.
 * @param[in] value Enable or disable for audio stream channel.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_GetMediaAudioStatus
 */
YEALINK_API Yealink_ReturnCode Yealink_SetMediaAudioStatus(unsigned short uDeviceId, bool bValue);

/**
 * @brief Get the audio stream channel mode enable or disable.
 * @param[in] deviceID ID for a BT adapter.
 * @return True if the channel is open, false otherwise.
 * @see Yealink_SetMediaAudioStatus
 */
YEALINK_API bool Yealink_GetMediaAudioStatus(unsigned short uDeviceId);

/**
 * @brief Connect/Reconnect Bluetooth device to the Yealink Bluetooth adapter.
 * Ensure the Bluetooth device is switched on and within range.
 * @param[in] deviceID ID for a BT adapter.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_ConnectNewDevice
 * @see Yealink_DisconnectBTDevice
 * @see Yealink_ConnectPairedDevice
 * @see Yealink_DisConnectPairedDevice
 * @see Yealink_GetConnectedBTDeviceName
 */
YEALINK_API Yealink_ReturnCode Yealink_ConnectBTDevice(unsigned short uDeviceId);

/**
 * @brief Connect a new device.
 * @param[in] deviceID ID for specific device.
 * @param[in] device pointer to structure #Yealink_PairedDevice.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_AlreadyConnected if the device is already connected.
 * @return Device_WriteFail if it fails to write to the device.
 * @return Return_ParameterFail if device pointer is null or BTAddr is wrong.
 * @return Not_Supported if the functionality is not supported.
 * @see Yealink_ConnectBTDevice
 * @see Yealink_DisconnectBTDevice
 * @see Yealink_ConnectPairedDevice
 * @see Yealink_DisConnectPairedDevice
 * @see Yealink_GetConnectedBTDeviceName
 */
YEALINK_API Yealink_ReturnCode Yealink_ConnectNewDevice(unsigned short uDeviceId, Yealink_PairedDevice* device);

/**
 * @brief Disconnect Bluetooth device from Bluetooth adapter.
 * @param[in] deviceID ID for a BT adapter.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_ConnectBTDevice
 * @see Yealink_ConnectNewDevice
 * @see Yealink_ConnectPairedDevice
 * @see Yealink_DisConnectPairedDevice
 * @see Yealink_GetConnectedBTDeviceName
 */
YEALINK_API Yealink_ReturnCode Yealink_DisconnectBTDevice(unsigned short uDeviceId);

/**
 * @brief Connect a device which was already paired.
 * @param[in] deviceID ID for specific device.
 * @param[in] device Pointer to structure #Yealink_PairingList.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_AlreadyConnected if the device is already connected.
 * @return Device_WriteFail if it fails to write the value to the device.
 * @return Return_ParameterFail if device pointer is null or BTAddr is wrong.
 * @return Not_Supported if the functionality is not supported.
 * @note After device connection, #Yealink_GetPairedList api has to be called
 * to get updated connection status. In order to connect to a device from the
 * list of paired devices, make sure that there is no paired device currently
 * connected. Any paired device currently connected has to be disconnected by
 * calling #Yealink_DisconnectPairedDevice before using
 * #Yealink_ConnectPairedDevice.
 * @see Yealink_ConnectBTDevice
 * @see Yealink_ConnectNewDevice
 * @see Yealink_DisconnectBTDevice
 * @see Yealink_DisConnectPairedDevice
 * @see Yealink_GetConnectedBTDeviceName
 */
YEALINK_API Yealink_ReturnCode Yealink_ConnectPairedDevice(unsigned short uDeviceId, Yealink_PairedDevice* device);

/**
 * @brief Disconnect a paired device.
 * @param[in] deviceID ID for specific device.
 * @param[in] device pointer to structure #Yealink_PairingList.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Device_NotConnected if the device is not connected.
 * @return Device_WriteFail if it fails to write the value to the device.
 * @return Return_ParameterFail if device pointer is null or BTAddr is wrong.
 * @return Not_Supported if the functionality is not supported.
 * @note After device disconnection, #Yealink_GetPairedList api has to be called
 * to get updated connection status.
 * @see Yealink_ConnectBTDevice
 * @see Yealink_ConnectNewDevice
 * @see Yealink_DisconnectBTDevice
 * @see Yealink_ConnectPairedDevice
 * @see Yealink_GetConnectedBTDeviceName
 */
YEALINK_API Yealink_ReturnCode Yealink_DisConnectPairedDevice(unsigned short uDeviceId, Yealink_PairedDevice* device);

/**
 * @brief Get name of connected BT device with BT Adapter.
 * @param[in] deviceID ID for a BT adapter.
 * @return Name of connected BT device if successful, otherwise return NULL.
 * @note As memory is allocated through SDK, it must be freed by calling
 * #Yealink_FreeString.
 * @see Yealink_ConnectBTDevice
 * @see Yealink_ConnectNewDevice
 * @see Yealink_DisconnectBTDevice
 * @see Yealink_ConnectPairedDevice
 * @see Yealink_DisConnectPairedDevice
 */
YEALINK_API char* Yealink_GetConnectedBTDeviceName(unsigned short uDeviceId);

/**
 * @brief Checks if pairing list is supported by the device.
 * @param[in] deviceID ID for a device.
 * @return True if pairing list is supported, false if device does not support
 * pairing list.
 * @see Yealink_GetPairedList
 * @see Yealink_ClearPairedList
 * @see Yealink_FreePairingList
 * @see Yealink_ClearPairedDevice
 * @see Yealink_RegisterPairingListCallback
 */
YEALINK_API bool Yealink_IsPairedListSupported(unsigned short uDeviceId);

/**
 * @brief Gets the list of devices which are paired previously.
 * @param[in] deviceID ID for specific device.
 * @return Returns pointer to the structure #Yealink_PairingList contains all
 * paired device details.
 * @note As memory is allocated through SDK, it must be freed by calling
 * #Yealink_FreePairingList.
 * @see Yealink_IsPairedListSupported
 * @see Yealink_ClearPairedList
 * @see Yealink_FreePairingList
 * @see Yealink_ClearPairedDevice
 * @see Yealink_RegisterPairingListCallback
 */
YEALINK_API Yealink_PairingList* Yealink_GetPairedList(unsigned short uDeviceId);

/**
 * @brief Clear list of paired BT devices from BT adaptor.
 * @param[in] deviceID ID for a BT adapter.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_WriteFail if it fails to write to the device.
 * @see Yealink_IsPairedListSupported
 * @see Yealink_GetPairedList
 * @see Yealink_FreePairingList
 * @see Yealink_ClearPairedDevice
 * @see Yealink_RegisterPairingListCallback
 */
YEALINK_API Yealink_ReturnCode Yealink_ClearPairedList(unsigned short uDeviceId);

/**
 * @brief Clear devices from the paired device list.
 * @param[in] deviceID ID for specific device.
 * @param[in] device Pointer to structure #Yealink_PairingList.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return CannotClear_DeviceConnected if the device has an active connection.
 * @return Device_WriteFail if it fails to write the value to the device.
 * @return Return_ParameterFail if device pointer is null or BTAddr is wrong.
 * @see Yealink_IsPairedListSupported
 * @see Yealink_GetPairedList
 * @see Yealink_FreePairingList
 * @see Yealink_ClearPairedList
 * @see Yealink_RegisterPairingListCallback
 */
YEALINK_API Yealink_ReturnCode Yealink_ClearPairedDevice(unsigned short uDeviceId, Yealink_PairedDevice* device);

/**
 * @brief Frees the memory allocated for the list of paired devices.
 * @param[in] deviceList #Yealink_PairingList structure pointer, which needs to
 * be freed.
 * @see Yealink_IsPairedListSupported
 * @see Yealink_GetPairedList
 * @see Yealink_ClearPairedDevice
 * @see Yealink_ClearPairedList
 * @see Yealink_RegisterPairingListCallback
 */
YEALINK_API void Yealink_FreePairingList(Yealink_PairingList* deviceList);

/**
 * @brief Register callback for Pairing list.
 * @param[in] PairingList Callback method, will be called when paired devices
 * changed event received from device.
 * @see Yealink_IsPairedListSupported
 * @see Yealink_GetPairedList
 * @see Yealink_ClearPairedDevice
 * @see Yealink_ClearPairedList
 * @see Yealink_FreePairingList
 */
YEALINK_API void Yealink_RegisterPairingListCallback(void(*PairingList)(unsigned short deviceID, Yealink_PairingList *lst));

/**
* @brief Gets a list of supported remote MMIs.
* @param[in] deviceID ID for the specific device.
* @param[in,out] types Pointer to allocated memory area containing count of
* structures of #RemoteMmiDefinition. The memory area must be freed by calling
* #Yealink_FreeRemoteMmiTypes.
* @param[out] count Number of items passed via types.
* @return Return_Ok list and count is valid.
* @return Return_ParameterFail in case of an incorrect parameter.
* @return Not_Supported the device does not support remote MMIv2.
* @return Device_Unknown if the deviceID specified is not known.
* @see Yealink_FreeRemoteMmiTypes
* @see Yealink_IsRemoteMmiInFocus
* @see Yealink_GetRemoteMmiFocus
* @see Yealink_ReleaseRemoteMmiFocus
* @see Yealink_SetRemoteMmiAction
* @see Yealink_RegisterRemoteMmiCallback
*/
YEALINK_API Yealink_ReturnCode Yealink_GetRemoteMmiTypes(unsigned short deviceID, RemoteMmiDefinition** const types, int* count);

/**
* @brief Frees the memory area allocated by #Yealink_GetRemoteMmiTypes.
* @param[in] types Pointer to the memory area to free.
* @see Yealink_GetRemoteMmiTypes
* @see Yealink_IsRemoteMmiInFocus
* @see Yealink_GetRemoteMmiFocus
* @see Yealink_ReleaseRemoteMmiFocus
* @see Yealink_SetRemoteMmiAction
* @see Yealink_RegisterRemoteMmiCallback
*/
YEALINK_API void Yealink_FreeRemoteMmiTypes(RemoteMmiDefinition* types);

/**
* @brief Gets the status of the remote MMI focus.
* @param[in] deviceID ID for the specific device.
* @param[in] type Type of remote MMI to get focus status of.
* @param[out] isInFocus True if in focus, false if not.
* @return Return_Ok if status has been gotten successfully.
* @return Return_ParameterFail in case of an incorrect parameter.
* @return Not_Supported the device does not support remote MMI.
* @return Device_Unknown if the deviceID specified is not known.
* @see Yealink_GetRemoteMmiTypes
* @see Yealink_FreeRemoteMmiTypes
* @see Yealink_GetRemoteMmiFocus
* @see Yealink_ReleaseRemoteMmiFocus
* @see Yealink_SetRemoteMmiAction
* @see Yealink_RegisterRemoteMmiCallback
*/
YEALINK_API Yealink_ReturnCode Yealink_IsRemoteMmiInFocus(unsigned short deviceID, RemoteMmiType type, bool* isInFocus);

/**
* @brief Gets the focus of the remote MMI specified. Once a remote MMI has
* focus, the normal functionality of the MMI (button/LED) is suppressed until
* #Yealink_ReleaseRemoteMmiFocus or #Yealink_ReleaseRemoteMmiFocusAll is called.
* If only the LED output MMI functionality is required, action can be
* specified as MMI_ACTION_NONE.
* @param[in] deviceID ID for the specific device.
* @param[in] type Type of remote MMI to get focus of.
* @param[in] action Action to get focus of, acts as a filter/mask for the
* actions on the RemoteMmiCallback callback. Note that several actions can be
* OR'ed together e.g. (RemoteMmiInput)(MMI_ACTION_TAP | MMI_ACTION_DOWN).
* @param[in] priority Priority of focus.
* @return Return_Ok focus has been gotten successfully.
* @return Not_Supported the device does not support remote MMI.
* @return Device_Unknown if the deviceID specified is not known.
* @return Device_WriteFail if it fails to write to the device.
* @see Yealink_GetRemoteMmiTypes
* @see Yealink_FreeRemoteMmiTypes
* @see Yealink_IsRemoteMmiInFocus
* @see Yealink_ReleaseRemoteMmiFocus
* @see Yealink_SetRemoteMmiAction
* @see Yealink_RegisterRemoteMmiCallback
*/
YEALINK_API Yealink_ReturnCode Yealink_GetRemoteMmiFocus(unsigned short deviceID, RemoteMmiType type, RemoteMmiInput action, RemoteMmiPriority priority);

/**
* @brief Releases the focus of the remote MMI specified. Note that focus on
* all actions are removed.
* @param[in] deviceID ID for the specific device.
* @param[in] type Type of remote MMI to release focus of.
* @return Return_Ok focus has been release successfully.
* @return Not_Supported the device does not support remote MMI.
* @return Device_Unknown if the deviceID specified is not known.
* @return Device_WriteFail if it fails to write to the device.
* @see Yealink_GetRemoteMmiTypes
* @see Yealink_FreeRemoteMmiTypes
* @see Yealink_IsRemoteMmiInFocus
* @see Yealink_GetRemoteMmiFocus
* @see Yealink_SetRemoteMmiAction
* @see Yealink_RegisterRemoteMmiCallback
*/
YEALINK_API Yealink_ReturnCode Yealink_ReleaseRemoteMmiFocus(unsigned short deviceID, RemoteMmiType type);

/**
* @brief Sets an output action on the remote MMI. Note that
* #Yealink_GetRemoteMmiFocus must be called once for the RemoteMmiType in
* question prior to setting the output action, else Return_ParameterFail is
* returned.
* @param[in] deviceID ID for the specific device.
* @param[in] type Type of remote MMI to set action of.
* @param[in] outputAction Output LED action to set.
* @return Return_Ok action has been set successfully.
* @return Not_Supported the device does not support remote MMI.
* @return Device_Unknown if the deviceID specified is not known.
* @return Device_WriteFail if it fails to write to the device e.g. if
* #Yealink_GetRemoteMmiFocus has not called prior to calling.
* #Yealink_SetRemoteMmiAction.
* @return Return_ParameterFail if an incorrect/unsupported parameter has been
* passed or #Yealink_GetRemoteMmiFocus has not been called for the
* #RemoteMmiType in question.
* @see Yealink_GetRemoteMmiTypes
* @see Yealink_FreeRemoteMmiTypes
* @see Yealink_IsRemoteMmiInFocus
* @see Yealink_GetRemoteMmiFocus
* @see Yealink_ReleaseRemoteMmiFocus
* @see Yealink_RegisterRemoteMmiCallback
*/
YEALINK_API Yealink_ReturnCode Yealink_SetRemoteMmiAction(unsigned short deviceID, RemoteMmiType type, RemoteMmiActionOutput outputAction);


/**
* @brief Register for remote MMI event callback.
* @param[in] callback RemoteMmiCallback callback method, called when a remote
* MMI input event is generated.
* @see Yealink_GetRemoteMmiTypes
* @see Yealink_FreeRemoteMmiTypes
* @see Yealink_IsRemoteMmiInFocus
* @see Yealink_GetRemoteMmiFocus
* @see Yealink_ReleaseRemoteMmiFocus
* @see Yealink_SetRemoteMmiAction
*/
YEALINK_API void Yealink_RegisterRemoteMmiCallback(RemoteMmiCallback callback);

/**
* @brief Integrates softphone app to Yealink applications like Yealink Connecter
* @param[in] guid Client unique ID.
* @param[in] softphoneName Name of the application to be shown in Yealink Connecter.
* @return True if softphone app integrates to Yealink Connecter, false if it fails or already connected
* otherwise.
* @see Yealink_DisconnectFromYealinkConnecter
*/
YEALINK_API bool Yealink_ConnectToYealinkConnecter(const char* guid, const char* softphoneName);

/**
* @brief Disconnects connected from Yealink Connecter.
* @see Yealink_ConnectToYealinkConnecter
*/
YEALINK_API void Yealink_DisconnectFromYealinkConnecter(void);

/**
* @brief Sets the softphone to Ready.
* @param[in] isReady Sets the softphone readiness state.
* @see Yealink_IsSoftphoneInFocus
*/
YEALINK_API void Yealink_SetSoftphoneReady(bool isReady);

/**
* @brief Indicates whether the softphone is in focus.
* @return True if softphone is in focus, false otherwise.
* @see Yealink_SetSoftphoneReady
*/
YEALINK_API bool Yealink_IsSoftphoneInFocus(void);

/**
* @brief Register for focus status change callback.
* @see Yealink_RegisterFocusChangeCallback
*/
YEALINK_API void Yealink_RegisterFocusChangeCallback(void(*FocusChangeCallback)(bool bInfocus));


/**
 * @brief Gets the device image path.
 * @param[in] deviceID ID for a specific device.
 * @return The path of the device image.
 * @note As memory is allocated through SDK, needs to be freed by calling
 * #Yealink_FreeString.
 */
YEALINK_API char* Yealink_GetDeviceImagePath(unsigned short deviceID);

/**
 * @brief Get battery status, if supported by device.
 * @param[in] deviceID ID for a specific device.
 * @param[out] levelInPercent Battery level in percent (0 - 100).
 * @param[out] charging Indicates if battery is being charged.
 * @param[out] batteryLow Indicates if battery level is low.
 * @return Return_Ok if get battery information is returned.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if device does not have battery information.
 * @note Since dongle does not have battery, SDK returns Not_Supported when
 * battery status is requested for dongle device.
 * @see Yealink_RegisterBatteryStatusUpdateCallback
 */
YEALINK_API Yealink_ReturnCode Yealink_GetBatteryStatus(unsigned short deviceID, int *levelInPercent, bool *charging, bool *batteryLow);

/**
 * @brief Register for battery status update callback.
 * @param[in] callback Callback method called when the battery status changes.
 * @see Yealink_GetBatteryStatus
 */
YEALINK_API void Yealink_RegisterBatteryStatusUpdateCallback(void(*BatteryStatusUpdateCallback)(unsigned short deviceID,
        int levelInPercent, bool charging, bool batteryLow));

/**
 * @brief Set Contact List to device.
 * @param[in] deviceID ID for a specific device.
 * @param[in] Yealink_ContactInfoList for contact list.
 * @return Return_Ok if set success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if device does not have Contact information.
 * @return Return_ParameterFail if pInfoList have something wrong.
 * @see Yealink_SetCurrentTalkContact
 */
YEALINK_API Yealink_ReturnCode Yealink_SetContactInfoList(unsigned short uDeviceId, Yealink_ContactInfoList* pInfoList);

/**
 * @brief Set Current Talk Contact to device.
 * @param[in] deviceID ID for a specific device.
 * @param[in] Yealink_ContactInfo for contact list.
 * @return Return_Ok if set success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if device does not have Contact information.
 * @return Return_ParameterFail if pInfo has something wrong.
 * @see Yealink_SetContactInfoList
 */
YEALINK_API Yealink_ReturnCode Yealink_SetCurrentTalkContact(unsigned short uDeviceId, Yealink_ContactInfo* pInfo);

/**
 * @brief Checks if ringtone upload is supported by the device.
 * @param[in] deviceID ID for a device.
 * @return True if upload ringtone is supported otherwise false.
 * @see Yealink_UploadRingtone
 * @see Yealink_PlayRingtone
 */
YEALINK_API bool Yealink_IsUploadRingtoneSupported(unsigned short uDeviceId);

/**
 * @brief Upload ringtone to device
 * @param[in] deviceID ID for a specific device.
 * @param[in] pFilePath is the ringtone file.
 * @return Return_Ok.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Return_ParameterFail if the file has wrong path.
 * @see Yealink_IsUploadRingtoneSupported
 * @see Yealink_PlayRingtone
 */
YEALINK_API Yealink_ReturnCode Yealink_UploadRingtone(unsigned short uDeviceId, const char* pFilePath);

/**
 * @brief Play ringtone in device.
 * @param[in] deviceID ID for a specific device.
 * @param[in] iType Type of ringtone to Play.
 * @return Return_Ok if success.
 * @return Device_Unknown if the deviceID specified is not known.
 * @return Not_Supported if device is not supporting ringtones or input
 * parameters are wrong.
 */
YEALINK_API Yealink_ReturnCode Yealink_PlayRingtone(unsigned short uDeviceId, int iType);

/**
 * @brief Get the device's region version.
 * @param[in] deviceID ID for a specific device.
 * @return it maybe return null, if the device is not supported.
 * @note As memory is allocated through SDK, needs to be freed by calling
 * #Yealink_FreeString.
 */
YEALINK_API char* Yealink_GetRegionVersion(unsigned short uDeviceId);

/**
 * @brief Check has dect in docked state
 * @param[in] uDeviceId ID for a specific device.
 * @return true it has.
 * @return false doesn't has.
 */
YEALINK_API bool Yealink_HasDectInDocked(unsigned short uDeviceId);

/**
 * @brief Checks if equalizer is supported by the device.
 * @param[in] deviceID ID for a device.
 * @return True if equalizer is supported, false if device does not support
 * equalizer.
 * @see Yealink_GetEqualizerMode
 * @see Yealink_SetEqualizerMode
 */
YEALINK_API bool Yealink_IsEqualizerSupported(unsigned short uDeviceId);

/**
 * @brief Get the current Equalizer mode.
 * @param[in] deviceID ID for a specific device.
 * @param[out] EqualizerMode Current Equalizer mode.
 * @return Return_Ok if the current equalizer mode was retrieved successfully.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown id the device is not known.
 * @return Return_ParameterFail if param is wrong
 * @see Yealink_IsEqualizerSupported
 * @see Yealink_SetEqualizerMode
 */
YEALINK_API Yealink_ReturnCode Yealink_GetEqualizerMode(unsigned short uDeviceId, int* iOutMode);

/**
 * @brief set the current Equalizer mode.
 * @param[in] deviceID ID for a specific device.
 * @param[in] Equalizer mode.
 * @return Return_Ok if the current Equalizer mode was retrieved successfully.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown id the device is not known.
 * @return Return_ParameterFail if param is wrong
 * @see Yealink_GetEqualizerMode
 * @see Yealink_IsEqualizerSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_SetEqualizerMode(unsigned short uDeviceId, EqualizerMode eMode);

/**
 * @brief Checks if WizardMode is supported by the device.
 * @param[in] deviceID ID for a device.
 * @return True if WizardMode is supported otherwise false.
 * @see Yealink_SetWizardMode
 * @see Yealink_GetWizardMode
 */
YEALINK_API bool Yealink_IsWizardModeSupported(unsigned short uDeviceId);

/**
 * @brief set the current wizard mode.
 * @param[in] deviceID ID for a specific device.
 * @param[in] wizard mode (one of WizardModes).
 * @return Return_Ok if the current wizard mode was retrieved successfully.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown id the device is not known.
 * @return Return_ParameterFail if param is wrong
 * @see Yealink_GetWizardMode
 * @see Yealink_IsWizardModeSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_SetWizardMode(unsigned short uDeviceId, WizardModes eMode);

/**
 * @brief Reads the current wizard mode.
 * @param[in] deviceID ID for a specific device.
 * @param[out] iOutMode Current wizard mode (one of WizardModes).
 * @return Return_Ok if the current wizard mode was retrieved successfully.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown id the device is not known.
 * @return Return_ParameterFail if param is wrong
 * @see Yealink_SetWizardMode
 * @see Yealink_IsWizardModeSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_GetWizardMode(unsigned short uDeviceId, int* iOutMode);

/**
 * @brief Checks if busylight is supported by the device.
 * @param[in] deviceID ID for a device.
 * @return True if busylight is supported, false if device does not support
 * busylight.
 * @see Yealink_SetBusylightStatus
 * @see Yealink_GetBusylightStatus
 * @see Yealink_RegisterBusylightEvent
 */
YEALINK_API bool Yealink_IsBusylightSupported(unsigned short uDeviceId);

/**
 * @brief set the status of busylight.
 * @param[in] deviceID ID for a device.
 * @param[in] eStatus, the busylight status.
 * @return Return_Ok if the current busylight mode was write successfully.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown id the device is not known.
 * @return Return_ParameterFail if param is wrong
 * @see Yealink_IsBusylightSupported
 * @see Yealink_GetBusylightStatus
 * @see Yealink_RegisterBusylightEvent
 */
YEALINK_API Yealink_ReturnCode Yealink_SetBusylightStatus(unsigned short uDeviceId, UsbBusylight eStatus);

/**
 * @brief get the status of busylight.
 * @param[in] deviceID ID for a device.
 * @param[out] eStatus, the busylight status.
 * @return Return_Ok if the current busylight mode was return successfully.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown id the device is not known.
 * @return Return_ParameterFail if param is wrong
 * @see Yealink_IsBusylightSupported
 * @see Yealink_SetBusylightStatus
 * @see Yealink_RegisterBusylightEvent
 */
YEALINK_API Yealink_ReturnCode Yealink_GetBusylightStatus(unsigned short uDeviceId, int* eStatus);

/**
 * @brief Registration for busylight event.
 * @param[in] BusylightFunc Callback method, called when busylight event is
 * received from device. Can be NULL if not used.
 * @see Yealink_IsBusylightSupported
 * @see Yealink_SetBusylightStatus
 * @see Yealink_RegisterBusylightEvent
 */
YEALINK_API void Yealink_RegisterBusylightEvent(void(*BusylightFunc)(unsigned short uDeviceId, UsbBusylight eStatus));

/**
 * @brief Checks if AudioMode is supported by the device.
 * @param[in] uDeviceId ID for a device.
 * @return True if AudioMode is supported, false if device does not support
 * AudioMode.
 * @see Yealink_ChangeAudioMode
 */
YEALINK_API bool Yealink_IsAudioModeSupported(unsigned short uDeviceId);

/**
 * @brief get the status of busylight.
 * @param[in] uDeviceId ID for a device.
 * @param[in] eType, the audio mode you want to set.
 * @return Return_Ok if the current busylight mode was return successfully.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown id the device is not known.
 * @return Return_ParameterFail if param is wrong
 * @see Yealink_IsAudioModeSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_ChangeAudioMode(unsigned short uDeviceId, AudioMode eType);

/**
* @brief Start export device Audio to path
* @param[in] deviceID ID for a specific device.
* @param[in] path to be exported.
* @return Return_Ok if that is successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Device_WriteFail export wrong.
* @return Not_Supported if the functionality is not supported.
* @return Return_ParameterFail if path is incorrect.
*/
YEALINK_API Yealink_ReturnCode Yealink_StartExportAudio(unsigned short uDeviceId, const char* path);

/**
* @brief Stop export device Audio to path
* @param[in] deviceID ID for a specific device.
* @return Return_Ok if that is successful.
* @return Device_Unknown if the deviceID specified is not known.
* @return Device_WriteFail write wrong.
* @return Not_Supported if the functionality is not supported.
*/
YEALINK_API Yealink_ReturnCode Yealink_StopExportAudio(unsigned short uDeviceId);

/**
 * @brief Check is camera ready.
 * @param[in] uDeviceId ID for a specific device.
 * @return true camera is ready.
 * @return false camera is not ready.
 */
YEALINK_API bool Yealink_CameraIsReady(unsigned short uDeviceId);

/**
 * @brief Register for camera ready callback.
 * @param[in] callback CallBackCameraReady callback method, called when a camera ready
 * @return true camera is ready.
 * @return false camera is not ready.
 */
YEALINK_API void Yealink_RegisterCameraReadyCallBack(void(*CallBackCameraReady)(unsigned short uDeviceId));

/**
 * @brief Camera direction control
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] eDirCmd control cmd, CAMERA_DIR_STOP to stop ctrl.
 * @return Return_Ok if that is successful.
 * @return Device_Unknown if the device is not found.
 * @return Not_Supported if the functionality is not supported.
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Operation_Fail_SmartTracking_Enabled if auto-framing is enabled.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraZoomCtrl
 * @see Yealink_CameraPTZReset
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraDirectionCtrl(unsigned short uDeviceId, CameraDirectionCmd eDirCmd);

/**
 * @brief Camera zoom control
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] eZoomCmd control cmd, CAMERA_ZOOM_STOP to stop.
 * @return Return_Ok if that is successful.
 * @return Device_Unknown if the device is not found.
 * @return Not_Supported if the functionality is not supported.
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Operation_Fail_SmartTracking_Enabled if auto-framing is enabled.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraDirectionCtrl
 * @see Yealink_CameraPTZReset
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraZoomCtrl(unsigned short uDeviceId, CameraZoomCmd eZoomCmd);

/**
 * @brief Camera reset PTZ
 * @param[in] uDeviceId ID for a specific device.
 * @return Return_Ok if that is successful.
 * @return Device_Unknown if the device is not found.
 * @return Not_Supported if the functionality is not supported.
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Operation_Fail_SmartTracking_Enabled if auto-framing is enabled.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraDirectionCtrl
 * @see Yealink_CameraZoomCtrl
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraPTZReset(unsigned short uDeviceId);

/**
 * @brief Camera add preset
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] picPath path for preset picture.
 * @return Return_Ok if that is successful.
 * @return Device_Unknown if the device is not found.
 * @Return ParameterFail if the path of picture unexpected
 * @return Camera_Not_Ready if the camera is not ready.Preset_Count_Limit
 * @return Not_Supported if the functionality is not supported.
 * @return Preset_Count_Limit if count of preset is reach limit.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraIsInIdle
 * @see Yealink_CameraGetAllPreset
 * @see Yealink_CameraDelPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraUpdatePreset
 * @see Yealink_CameraApplyPreset
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraAddPreset(unsigned short uDeviceId, const char* picPath);

/**
 * @brief Camera get all preset info
 * @param[in] uDeviceId ID for a specific device.
 * @return Returns pointer to the structure #Yealink_CameraPresetList contains all
 * camera preset details.
 * @see Yealink_CameraIsReady
 * @see Yealink_FreeCameraPresetInfo
 * @see Yealink_CameraAddPreset
 * @see Yealink_CameraDelPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraUpdatePreset
 * @see Yealink_CameraApplyPreset
 */
YEALINK_API Yealink_CameraPresetList* Yealink_CameraGetAllPreset(unsigned short uDeviceId);

/**
 * @brief Camera delete one preset
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] uPresetIndex index for preset.
 * @return Return_Ok if that is successful.
 * @return Device_Unknown if the device is not found.
 * @Return Preset_Not_Exist if the index of preset not exist
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Not_Supported if the functionality is not supported.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraAddPreset
 * @see Yealink_CameraGetAllPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraUpdatePreset
 * @see Yealink_CameraApplyPreset
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraDelPreset(unsigned short uDeviceId, unsigned short uPresetIndex);

/**
 * @brief Camera delete all preset
 * @param[in] uDeviceId ID for a specific device.
 * @return Return_Ok if that is successful.
 * @return Device_Unknown if the device is not found.
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Not_Supported if the functionality is not supported.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraAddPreset
 * @see Yealink_CameraGetAllPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraUpdatePreset
 * @see Yealink_CameraApplyPreset
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraDelAllPreset(unsigned short uDeviceId);

/**
 * @brief Camera update preset info
 * @param[in] uDeviceId ID for a specific device.
 * @return Return_Ok if that is successful.
 * @return Device_Unknown if the device is not found.
 * @return Camera_Not_Ready if the camera is not ready.
 * @Return Preset_Not_Exist if the index of preset not exist
 * @return Not_Supported if the functionality is not supported.
 * @Return ParameterFail if the path of picture unexpected.
 * @return Operation_Fail_SmartTracking_Enabled if auto-framing is enabled.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraAddPreset
 * @see Yealink_CameraGetAllPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraApplyPreset
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraUpdatePreset(unsigned short uDeviceId, unsigned short uPresetIndex, const char* picPath);

/**
 * @brief Camera apply preset to device
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] uPresetIndex index for preset.
 * @return Return_Ok if that is successful.
 * @return Not_Supported if the functionality is not supported.
 * @return Device_Unknown if the device is not found.
 * @return Camera_Not_Ready if the camera is not ready.
 * @Return Preset_Not_Exist if the index of preset not exist Preset_Apply_Time_Out
 * @return Operation_Fail_SmartTracking_Enabled if auto-framing is enabled.
 * @return Preset_Apply_Time_Out The camera cannot rotate to the specified position, check position timeout timeout.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraAddPreset
 * @see Yealink_CameraGetAllPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraDelAllPreset
 * @see Yealink_CameraUpdatePreset
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraApplyPreset(unsigned short uDeviceId, unsigned short uPresetIndex);

/**
 * @brief Camera get smart tracking opt info
 * @param[in] uDeviceId ID for a specific device.
 * @return Returns pointer to the structure #Yealink_CameraSmartTrackingOptList contains all
 * @see Yealink_CameraIsReady
 * @see Yealink_GetSamrtTrackingOpt
 * @see Yealink_SetSmartTrackingOpt
 */
YEALINK_API Yealink_CameraSmartTrackingOptList* Yealink_GetSmartTrackingOptInfo(unsigned short uDeviceId);

/**
 * @brief Camera set smart tracking opt
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] smart tracking opt.
 * @return Return_Ok if that is successful.
 * @return Not_Supported if the functionality is not supported.
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Device_Unknown if the device is not found.
 * @see Yealink_CameraIsReady
 * @see Yealink_GetSmartTrackingOptInfo
 * @see Yealink_GetSamrtTrackingOpt
 */
YEALINK_API Yealink_ReturnCode Yealink_SetSmartTrackingOpt(unsigned short uDeviceId, CameraSmartTrackingOpt eType);

/**
 * @brief Camera get smart tracking opt
 * @param[in] uDeviceId ID for a specific device.
 * @param[out] smart tracking opt.
 * @return Return_Ok if that is successful.
 * @return Not_Supported if the functionality is not supported.
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Device_Unknown if the device is not found.
 * @see Yealink_CameraIsReady
 * @see Yealink_GetSmartTrackingOptInfo
 * @see Yealink_SetSmartTrackingOpt
 */
YEALINK_API Yealink_ReturnCode Yealink_GetSamrtTrackingOpt(unsigned short uDeviceId, CameraSmartTrackingOpt* eType);

/**
 * @brief Register for camera smart tracking opt changed.
 * @param[in] callback CallBack callback method, called when a camera smart tracking opt changed
 * @see Yealink_GetSmartTrackingOptInfo
 * @see Yealink_GetSamrtTrackingOpt
 * @see Yealink_SetSmartTrackingOpt
 */
YEALINK_API void Yealink_RegisterCameraSmartTrackingOptCallBack(void(*CallBack)(unsigned short uDeviceId, CameraSmartTrackingOpt eType));

/**
 * @brief Camera set face detection switch state
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] bEnable switch state.
 * @return Return_Ok if that is successful.
 * @return Not_Supported if the functionality is not supported.
 * @return Camera_Not_Ready if the camera is not ready.
 * @return Device_Unknown if the device is not found.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraIsFaceDetectionEnable
 */
YEALINK_API Yealink_ReturnCode Yealink_CameraSetFaceDetection(unsigned short uDeviceId, bool bEnable);

/**
 * @brief Camera get face detection switch state
 * @param[in] uDeviceId ID for a specific device.
 * @return true switch state enable.
 * @return false switch state disable.
 * @see Yealink_CameraIsReady
 * @see Yealink_CameraSetFaceDetection
 */
YEALINK_API bool Yealink_CameraIsFaceDetectionEnable(unsigned short uDeviceId);

/**
 * @brief Check is camera in idle state
 * @param[in] uDeviceId ID for a specific device.
 * @return true camera is in idle.
 * @return false camera is busy now.
 * @see Yealink_CameraIsReady
 */
YEALINK_API bool Yealink_CameraIsInIdle(unsigned short uDeviceId);

/**
 * Frees the #Yealink_CameraPresetList structure members.
 * @param[in] info #Yealink_CameraPresetList structure to be freed.
 */
YEALINK_API void Yealink_FreeCameraPresetInfo(Yealink_CameraPresetList* pPresetInfo);

/**
 * Frees the #Yealink_CameraSmartTrackingOptList structure members.
 * @param[in] info #Yealink_CameraSmartTrackingOptList structure to be freed.
 */
YEALINK_API void Yealink_FreeSmartTackingOptInfo(Yealink_CameraSmartTrackingOptList* pSmartTrackingOptInfo);

/**
 * @brief change the camera layout, FeaMultiCameraMng feature is needed
 * @param[in] uDeviceId ID for a specific device.
 * @param[in] pLayoutList layoutinfo.
 * @return Return_Ok, success.
 * @return Device_WriteFail, please try again.
 * @return Not_Supported, check the device have FeaMultiCameraMng feature
 * @return Device_Unknown if the device is not found.
 */
YEALINK_API Yealink_ReturnCode Yealink_SetCameraLayout(unsigned short uDeviceId, Yealink_CameraLayoutList* pLayoutList);

/**
 * @brief Checks if AEC is supported by the device.
 */
YEALINK_API bool Yealink_IsAECSupported(unsigned short uDeviceId);

/**
 * @brief Register for sdk log call back.
 */
YEALINK_API void Yealink_RegisterSdkLogCallBack(void(*LogCallBack)(int iLevel, const char* pStr, int iLen));

/**
 * @brief Checks if call extend is supported by the device.
 * @param[in] deviceID ID for a device.
 * @return True if busylight is supported, false if device does not support
 * call extend.
 * @see Yealink_SetCallExtend
 */
YEALINK_API bool Yealink_IsCallExtendSupported(unsigned short uDeviceId);

/**
 * @brief set call extend enable
 * call extend.
 * @see Yealink_IsCallExtendSupported
 */
YEALINK_API Yealink_ReturnCode Yealink_SetCallExtend(unsigned short uDeviceId, bool bEnable);

/**
* @brief Register for device request contact callback.
* @param[in] callback Callback method called when the device requestes contact.
* @see Yealink_SyncContactList
*/
YEALINK_API void Yealink_RegisterSyncContactCallBack(void(*CallBackSyncContact)(unsigned short uDeviceId));

/**
* @brief Send contact data to the device.
* @param[in] uDeviceId ID for a specific device, and  contact data.
* @see Yealink_SyncContactList
* @see Yealink_RegisterSyncContactCallBack
*/
YEALINK_API void Yealink_SyncContactList(unsigned short uDeviceId, Yealink_ContactDataList* Contact);

#endif
