Difference Analysis Generated by HtmlDiff on 10/26/2004 1:35 PM  

Base file: C:\CY4632_RDK_1_21\Software\Source Code\WirelessUSBSysTray\MainFrm.cpp

Modified file: C:\CY4632_RDK_1_3\Software\Source Code\WirelessUSBSysTray\MainFrm.cpp

//--------------------------------------------------------------------------
//
// Microsoft Visual C++ generated source file.
//
// Implementation of the CMainFrame class
//
//--------------------------------------------------------------------------
// $Archive: /WirelessUSB/WUSB Kits/CY4632 LS KBM RDK/DocSrc/CD_Root/Software/Source Code/WirelessUSBSysTray/MainFrm.cpp $
// $Modtime: 7/15/10/19/04 4:4359p $
// $Revision: 37 $
//--------------------------------------------------------------------------
//
// Copyright 2003-2004, Cypress Semiconductor Corporation.
//
// This software is owned by Cypress Semiconductor Corporation (Cypress)
// and is protected by and subject to worldwide patent protection (United
// States and foreign), United States copyright laws and international
// treaty provisions. Cypress hereby grants to licensee a personal,
// non-exclusive, non-transferable license to copy, use, modify, create
// derivative works of, and compile the Cypress Source Code and derivative
// works for the sole purpose of creating custom software in support of
// licensee product to be used only in conjunction with a Cypress integrated
// circuit as specified in the applicable agreement. Any reproduction,
// modification, translation, compilation, or representation of this
// software except as specified above is prohibited without the express
// written permission of Cypress.
//
// Disclaimer: CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// WITH REGARD TO THIS MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
// Cypress reserves the right to make changes without further notice to the
// materials described herein. Cypress does not assume any liability arising
// out of the application or use of any product or circuit described herein.
// Cypress does not authorize its products for use as critical components in
// life-support systems where a malfunction or failure may reasonably be
// expected to result in significant injury to the user. The inclusion of
// Cypress’ product in a life-support systems application implies that the
// manufacturer assumes all risk of such use and in doing so indemnifies
// Cypress against all charges.
//
// Use may be limited by and subject to the applicable Cypress software
// license agreement.
//
//--------------------------------------------------------------------------

#include "stdafx.h"
#include "WirelessUSBTray.h"

#include "MainFrm.h"
#include ".\mainfrm.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define STATUS_POLL_TIMER_MS            5000    // pull status every 5 seconds
#define REQUEST_BATTERY_MS              3600000 // request battery level every 1 hour
#define NUMBER_OF_POLLS_BEFORE_REQUEST  (REQUEST_BATTERY_MS/STATUS_POLL_TIMER_MS)

// CMainFrame

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    // Global help commands
    ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder)
    ON_COMMAND(ID_HELP, CFrameWnd::OnHelp)
    ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp)
    ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder)
    ON_WM_TIMER()
    ON_WM_DESTROY()
    ON_COMMAND(ID_APP_WIRELESSUSB_STATUS, OnAppWirelessUSBStatus)
    ON_WM_CREATE()
END_MESSAGE_MAP()


// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
    m_pWirelessUSBStatusPropertySheet = NULL;
}

CMainFrame::~CMainFrame()
{
}

// called when a new window is created for this frame
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    // set callback for notification of Hid devices, primarily
    // notification of addition or removal of a Hid device
    m_ExecuteHidCallback.SetCallback(this, &CMainFrame::HIDNotification);

    // setup device status property sheet 
    CString strTitle; 
    strTitle.LoadString(IDS_PROPSHEET_WIRELESSUSB_STATUS_TITLE); 
    m_pWirelessUSBStatusPropertySheet = new CWirelessUSBStatusPropertySheet(strTitle); 
    m_pWirelessUSBStatusPropertySheet->m_pHidTrayManager = &m_HidTrayManager;

    // initialize HID Manager
    m_HidTrayManager.Create(lpCreateStruct->hInstance, lpCreateStruct->hwndParent, (PHidCallback)HIDCallbackFunction, &m_ExecuteHidCallback);

    // start update timer
    OnStartTimer();

    //
    // setup the system tray icon
    //

    // create new icon
    m_SystemTrayIcon.Create(
                        NULL,                            // Let it handle
                        WM_SYSTEM_TRAY_ICON_NOTIFY,      // Icon notify message to use
                        (LPCTSTR)_T("WirelessUSB"),      // tooltip
                        NULL,                            // don't display icon yet
                        IDR_POPUP_MENU                   // ID of tray icon
                        );

    // set default double-click menu item
    m_SystemTrayIcon.SetMenuItem(ID_APP_WIRELESSUSB_STATUS);

    // set default tool tip text
    CString strToolTip;
    strToolTip.LoadString(AFX_IDS_APP_TITLE);
    m_SystemTrayIcon.SetToolTip(strToolTip);

    // if devices are found, append device count and display the tray icon
    if (m_HidTrayManager.GetDeviceCount())
    {
        if (m_HidTrayManager.GetDeviceCount() > 1)
        {
            strToolTip.AppendFormat("\n%d devices", m_HidTrayManager.GetDeviceCount());
        }
        else
        {
            strToolTip.AppendFormat("\n%d device", m_HidTrayManager.GetDeviceCount());
        }

        m_SystemTrayIcon.SetToolTip(strToolTip);

        // display tray icon
        m_SystemTrayIcon.SetIcon(AfxGetApp()->LoadIcon(IDI_WIRELESSUSB));
    }

    return 0;
}

// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
    CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
    CFrameWnd::Dump(dc);
}

#endif //_DEBUG


// CMainFrame message handlers

// frame window is destroyed
void CMainFrame::OnDestroy()
{
    CFrameWnd::OnDestroy();

    // stop timer
    OnStopTimer();

    // if wireless property sheet exists, remove it
    if (m_pWirelessUSBStatusPropertySheet)
    {
        delete m_pWirelessUSBStatusPropertySheet;
        m_pWirelessUSBStatusPropertySheet = NULL;
    }

    // remove icon
    m_SystemTrayIcon.RemoveIcon();
}

// called when a Hid device is added or removed
void CMainFrame::HIDNotification(CHidTrayDevice *pHidDevice, UINT uHidCode)
{

    // if a Hid device was added
    if (uHidCode == HIDCB_NOTIFY_DEVICE_ADDED)
    {
        // setup pointer to Hid device for the hid property page
        pHidDevice->m_DeviceStatusPropertyPage.m_pHidDevice = (CObject*)pHidDevice;

        // get product string for this HID device
        ZeroMemory(pHidDevice->m_szProductString, sizeof(pHidDevice->m_szProductString));
        if (!pHidDevice->GetProductString(pHidDevice->m_szProductString, sizeof(pHidDevice->m_szProductString)))
        {
            // if no product string, default to "WirelessUSB"
            strncpy(pHidDevice->m_szProductString, _T("WirelessUSB"), sizeof(pHidDevice->m_szProductString));
        }

        // get serial number string for this HID device
        ZeroMemory(pHidDevice->m_szSerialNumberString, sizeof(pHidDevice->m_szSerialNumberString));
        if (!pHidDevice->GetSerialNumberString(pHidDevice->m_szSerialNumberString, sizeof(pHidDevice->m_szSerialNumberString)))
        {
            // if no serial number, zero out string
            ZeroMemory(pHidDevice->m_szSerialNumberString, sizeof(pHidDevice->m_szSerialNumberString));
        }

        // append usageID description based on usage type (keyboard, mouse, ...)
        if (pHidDevice->m_HidCaps.Usage == WIRELESSUSB_USAGE_KEYBOARD)
        {
            // append "Keyboard" to product string
            strncat(pHidDevice->m_szProductString, _T(" Keyboard"), sizeof(pHidDevice->m_szProductString));
        }
        else if (pHidDevice->m_HidCaps.Usage == WIRELESSUSB_USAGE_MOUSE)
        {
            // append "Mouse" to product string
            strncat(pHidDevice->m_szProductString, _T(" Mouse"), sizeof(pHidDevice->m_szProductString));
        }
        else
        {
            // unknown usage type, just append "Device" to product string
            strncat(pHidDevice->m_szProductString, _T(" Device"), sizeof(pHidDevice->m_szProductString));
        }

        pHidDevice->m_DeviceStatusPropertyPage.m_psp.dwFlags |= PSP_USETITLE;
        pHidDevice->m_DeviceStatusPropertyPage.m_psp.pszTitle = pHidDevice->m_szProductString;

        // read the current Diable Warning Message state from the
        // registry, this is used to determine if warning messages 
        // (like battery low) should be displayed in the taskbar
        CString szValueName;
        DWORD   Type = REG_BINARY;
        UCHAR   Data;
        DWORD   Size = sizeof(Data);
        szValueName.Format("Usage%04d_DWM", pHidDevice->m_HidCaps.Usage);
        if (pHidDevice->RegQueryValue((LPCTSTR)szValueName, &Type, (LPBYTE)&Data, &Size))
        {
            // set based on registry value read
            pHidDevice->m_bDisableWarningMessages = Data ? true : false;
        }
        else
        {
            // default to false
            pHidDevice->m_bDisableWarningMessages = falstrue;
        }

        // if devices are found, update the tray icon text
        if (m_HidTrayManager.GetDeviceCount())
        {
            // update tool tip displayed
            CString strToolTip;
            strToolTip.LoadString(AFX_IDS_APP_TITLE);
            strToolTip.AppendFormat("\n%d devices", m_HidTrayManager.GetDeviceCount());
            m_SystemTrayIcon.SetToolTip(strToolTip);

            // display tray icon if hidden
            if (m_SystemTrayIcon.IsHidden())
                m_SystemTrayIcon.SetIcon(AfxGetApp()->LoadIcon(IDI_WIRELESSUSB));
        }
        else
        {
            // not sure how this could happen
            ASSERT(FALSE);
        }

        // update device information, create popup if needed
        pHidDevice->UpdateDeviceInfo(&m_SystemTrayIcon);

        // Hid device added, if propery sheet exists then 
        // add a page for this Hid device
        if (m_pWirelessUSBStatusPropertySheet) 
        { 
            // add device property page to property sheet and refresh property page
            m_pWirelessUSBStatusPropertySheet->AddPage(&pHidDevice->m_DeviceStatusPropertyPage);
        } 
    }
    // if a Hid device was removed
    else if (uHidCode == HIDCB_NOTIFY_DEVICE_REMOVED)
    {
        // if the property sheet exists, remove the Hid device from the page
        if (m_pWirelessUSBStatusPropertySheet)
        {
            m_pWirelessUSBStatusPropertySheet->RemovePage(&pHidDevice->m_DeviceStatusPropertyPage);
        }

        // if devices are found, update the tray icon text
        if (m_HidTrayManager.GetDeviceCount())
        {
            // update tool tip displayed
            CString strToolTip;
            strToolTip.LoadString(AFX_IDS_APP_TITLE);
            strToolTip.AppendFormat("\n%d devices", m_HidTrayManager.GetDeviceCount());
            m_SystemTrayIcon.SetToolTip(strToolTip);

            // display tray icon if hidden
            if (m_SystemTrayIcon.IsHidden())
                m_SystemTrayIcon.SetIcon(AfxGetApp()->LoadIcon(IDI_WIRELESSUSB));
        }
        else
        {
            // if no devices, just remove the icon
            if (!m_SystemTrayIcon.IsHidden())
                m_SystemTrayIcon.RemoveIcon();      

            // and remove status page if active
            if (m_pWirelessUSBStatusPropertySheet) 
            { 
                // check if active, if so then end the property sheet dialog
                if (m_pWirelessUSBStatusPropertySheet->m_bIsCreated)
                    m_pWirelessUSBStatusPropertySheet->EndDialog(IDCANCEL);
            } 
        }
    }
}

// HID callback function
void CMainFrame::HIDCallbackFunction(CHidCallback *pHidCallback, CHidTrayDevice *pHidDevice, UINT uHidCode)
{
    // if callback function is not NULL, execute callback
    if (pHidCallback) pHidCallback->Execute(pHidDevice, uHidCode);
}

// start timer
void CMainFrame::OnStartTimer() 
{
   m_nTimer = SetTimer(1, STATUS_POLL_TIMER_MS, 0);
}

// stop timer
void CMainFrame::OnStopTimer() 
{
   KillTimer(m_nTimer);   
}

// timer routine, called when timer expires
void CMainFrame::OnTimer(UINT nIDEvent)
{
    CHidTrayDevice* pHidDevice = (CHidTrayDevice*)m_HidTrayManager.GetFirstHidDevice();

    // loop through all hid devices
    while (pHidDevice)
    {
        // determine if we need to issue a request for new usages values (battery level)
        if (pHidDevice->m_ulNumberOfPollsSinceLastRequest++ > NUMBER_OF_POLLS_BEFORE_REQUEST)
        {
            // Request for new usage values (specifically Battery Level)
            // NOTE: we don't want to do this very often because
            //       over time it will drain the battery more if the 
            //       wireless device is used frequently
            pHidDevice->RequestNewUsageValues();

            // reset poll count to zero
            pHidDevice->m_ulNumberOfPollsSinceLastRequest = 0;
        }

        // update device info (display's popup if neccessary)
        pHidDevice->UpdateDeviceInfo(&m_SystemTrayIcon);

        // get next Hid device, if one exists
        pHidDevice = (CHidTrayDevice*)m_HidTrayManager.GetNextHidDevice();
    }

    // restart timer
    CFrameWnd::OnTimer(nIDEvent);
}

// initialize CHidTrayDevice
CHidTrayDevice::CHidTrayDevice(void)
{
    int i;

    m_ucBatteryLevel = 0;
    m_ucWirelessChannel = 0;
    m_ucWirelessPnCode = 0;
    m_ucSignalStrength = 0;
    m_ucDutyLoad = 0;

    m_wBadPackets.SetSize(WIRELESSUSB_MAX_SIGNAL_QUALITY_SAMPLES);
    for (i=0;i<m_wBadPackets.GetCount(); i++)
    {
        m_wBadPackets.SetAt(i, 0);
    }

    m_wGoodPackets.SetSize(WIRELESSUSB_MAX_SIGNAL_QUALITY_SAMPLES);
    for (i=0;i<m_wGoodPackets.GetCount(); i++)
    {
        m_wGoodPackets.SetAt(i, 0);
    }

    m_ucPrevBatteryLevel = 0;
    m_ucPrevSignalStrengthWirelessChannel = 0;

    m_ullTotalBadPackets = 0;
    m_ullTotalGoodPackets = 0;

    m_bCriticalBatteryLevelWarning = false;
    m_bCriticalSignalStrengthWarningbCriticalSignalQualityWarning = false;
    m_bDisableWarningMessages = falstrue;

    m_ctConnectTime = CTime::GetCurrentTime();

    m_ulNumberOfPollsSinceLastRequest = NUMBER_OF_POLLS_BEFORE_REQUEST+1;

}

// destruction
CHidTrayDevice::~CHidTrayDevice(void)
{
}

// extract Hid usage ID value 
ULONG CHidTrayDevice::GetUsageIDValue(USHORT usUsageID)
{
    PHID_DATA pData = m_pFeatureData;
    UINT i;

    // parse the feature data for usage id value
    for (i = 0; i < m_ulFeatureDataLength; i++, pData++) 
    {
        // check for matching usage ID
        if (usUsageID == pData->ValueData.Usage)
        {
            // found match, return data value
            return pData->ValueData.Value;
        }
    }

    return 0;
}

// set Hid usage ID value 
void CHidTrayDevice::SetUsageIDValue(USHORT usUsageID, ULONG ulValue)
{
    PHID_DATA pData = m_pFeatureData;
    UINT i;

    // parse the feature data for usage id value
    for (i = 0; i < m_ulFeatureDataLength; i++, pData++) 
    {
        // check for matching usage ID
        if (usUsageID == pData->ValueData.Usage)
        {
            // found match, set data value
            pData->ValueData.Value = ulValue;
        }
    }
}


// this requests that the wireless device return updated usage value, 
// which in this case just means updated battery level
bool CHidTrayDevice::RequestNewUsageValues()
{
    PHID_DATA pData = m_pFeatureData;
    UINT i;

    if (pData)
    {
        // zero out the feature data values
        for (i = 0; i < m_ulFeatureDataLength; i++, pData++) 
        {
            if (pData)
            {
                pData->ValueData.Value = 0;
            }
        }
    }


    // here we could modify the feature data value that is 
    // being sent if in the future it is required, but right now,
    // they should all just be set to zero


    // issue SetFeature
    return SetFeature();
}

// add value to good packet array
void CHidTrayDevice::AddGoodPacketValue(unsigned short goodValue)
{
    m_wGoodPackets.Add(goodValue);

    if (m_wGoodPackets.GetCount() > WIRELESSUSB_MAX_SIGNAL_QUALITY_SAMPLES)
    {
        m_wGoodPackets.RemoveAt(0, (m_wGoodPackets.GetCount()-WIRELESSUSB_MAX_SIGNAL_QUALITY_SAMPLES));
    }
    
    m_ullTotalGoodPackets += goodValue;
}

// add value to bad packet array
void CHidTrayDevice::AddBadPacketValue(unsigned short badValue)
{
    m_wBadPackets.Add(badValue);

    if (m_wBadPackets.GetCount() > WIRELESSUSB_MAX_SIGNAL_QUALITY_SAMPLES)
    {
        m_wBadPackets.RemoveAt(0, (m_wBadPackets.GetCount()-WIRELESSUSB_MAX_SIGNAL_QUALITY_SAMPLES));
    }

    m_ullTotalBadPackets += badValue;
}

// get specific good packet value
ULONG CHidTrayDevice::GetGoodPacketValue(int index)
{
    if (index < m_wGoodPackets.GetCount())
    {
        return m_wGoodPackets.GetAt(index);
    }

    return 0;
}

// set specific good packet value
void CHidTrayDevice::SetGoodPacketValue(int index, ULONG value)
{
    if (index < m_wGoodPackets.GetCount())
    {
        m_wGoodPackets.SetAt(index, (WORD)value);
    }
}

// get specific bad packet value
ULONG CHidTrayDevice::GetBadPacketValue(int index)
{
    if (index < m_wBadPackets.GetCount())
    {
        return m_wBadPackets.GetAt(index);
    }

    return 0;
}

// set specific bad packet value
void CHidTrayDevice::SetBadPacketValue(int index, ULONG value)
{
    if (index < m_wBadPackets.GetCount())
    {
        m_wBadPackets.SetAt(index, (WORD)value);
    }
}

// get total accumlative values of good packets
ULONG CHidTrayDevice::GetTotalGoodPacketValues(void)
{
    ULONG totalValues = 0;
    int i;

    for (i=0;i < m_wGoodPackets.GetCount(); i++)
    {
        totalValues += m_wGoodPackets.GetAt(i);
    }

    return totalValues;
}

// get total accumlative values of good packets
ULONG CHidTrayDevice::GetTotalBadPacketValues(void)
{
    ULONG totalValues = 0;
    int i;

    for (i=0;i < m_wBadPackets.GetCount(); i++)
    {
        totalValues += m_wBadPackets.GetAt(i);
    }

    return totalValues;
}

// adjust bad packets based detection of a channel change
// which indicates a link quality issue
void CHidTrayDevice::ChannelChangeAdjustment(void)
{
    int adjustedValue = 0;
    int i;

    for (i=0;i < m_wGoodPackets.GetCount(); i++)
    {
        adjustedValue = GetBadPacketValue(i);
        adjustedValue += (int)((m_wGoodPackets.GetAt(i) * WIRELESSUSB_MAX_SIGNAL_QUALITY_CC_ADJ)+1);
        SetBadPacketValue(i, adjustedValue);
    }
}

// get the current usage values from the USB dongle, this includes
// wireless channel, wireless pn code, last reported battery level, and 
// signal strengthquality
bool CHidTrayDevice::UpdateUsageValues()
{
    // issue get feature report to get current HID battery level, 
    // signal strengthgood packets, bad packets, and wireless channel/ pn code
    bool result = GetFeature();

    // if successful, validate and update data recieved
    if (result)
    {
        UCHAR ucUsageIDValue;

        // update all usage values
        
        // validate battery level
        ucUsageIDValue = (UCHAR) (GetUsageIDValue(WIRELESSUSB_USAGEID_BATTERYLEVEL)*WIRELESSUSB_BATTERY_LEVEL_MULTIPLIER);
        if (ucUsageIDValue >= WIRELESSUSB_MIN_BATTERY_LEVEL && 
            ucUsageIDValue <= WIRELESSUSB_MAX_BATTERY_LEVEL)
        {
            // NOTE: battery level can report inaccurate low values if battery requests happen 
            //       back-to-back, so filtering is neccessary
            if ((ucUsageIDValue < m_ucBatteryLevel) &&
                     ((m_ucBatteryLevel - ucUsageIDValue) > WIRELESSUSB_BATTERY_LEVEL_MAX_ADJUST))
            {
                // Limit it to maximum adjustment value
                ucUsageIDValue = m_ucBatteryLevel - WIRELESSUSB_BATTERY_LEVEL_MAX_ADJUST;
            }

            // save previous battery level
            m_ucPrevBatteryLevel = m_ucBatteryLevel;

            // update new battery level
            m_ucBatteryLevel = ucUsageIDValue;
        }

        // check for new connection
        if ((!m_ucPrevBatteryLevel) && (m_ucBatteryLevel))
        {
            // reset connect time
            m_ctConnectTime = CTime::GetCurrentTime();
        }

        // validate wireless channel
        ucUsageIDValue = (UCHAR) GetUsageIDValue(WIRELESSUSB_USAGEID_WIRELESSCHANNEL);
        if (ucUsageIDValue >= WIRELESSUSB_MIN_WIRELESS_CHANNEL && 
            ucUsageIDValue <= WIRELESSUSB_MAX_WIRELESS_CHANNEL)
        {
            // save previous channel
            m_ucPrevWirelessChannel = m_ucWirelessChannel;

            // update wireless channel
            m_ucWirelessChannel = ucUsageIDValue;
        }

        // validate wireless pn code
        ucUsageIDValue = (UCHAR) GetUsageIDValue(WIRELESSUSB_USAGEID_WIRELESSPNCODE);
        if (ucUsageIDValue >= WIRELESSUSB_MIN_WIRELESS_PNCODE && 
            ucUsageIDValue <= WIRELESSUSB_MAX_WIRELESS_PNCODE)
        {
            // update wireless pn code
            m_ucWirelessPnCode = ucUsageIDValue;
        }


        // validate signal strength
        // NOTE: because signal strength reporting is broken, filtering is neccessary
        ucUsageIDValue = (UCHAR) GetUsageIDValue(WIRELESSUSB_USAGEID_SIGNALSTRENGTH);
        if (ucUsageIDValue >= WIRELESSUSB_MIN_SIGNAL_STRENGTH && 
            ucUsageIDValue <= WIRELESSUSB_MAX_SIGNAL_STRENGTH &&
            ucUsageIDValue+WIRELESSUSB_SIGNAL_STRENGTH_FILTER >= m_ucSignalStrength)
        {
            // save previous signal strength
            m_ucPrevSignalStrength = m_ucSignalStrength;

            // update signal strength
            m_ucSignalStrength = ucUsageIDValue;
        }

        // get get duty cycle (not used right now)
        m_ucDutyLoad = (UCHAR) GetUsageIDValue(WIRELESSUSB_USAGEID_DUTYLOAD);

        // include latest good/bad packet values into array
        AddGoodPacketValue((USHORT)GetUsageIDValue(WIRELESSUSB_USAGEID_GOOD_PACKETS));
        AddBadPacketValue((USHORT)GetUsageIDValue(WIRELESSUSB_USAGEID_BAD_PACKETS));
    }

    return result;
}

// retrieve the current wireless device usage values and
// display any warning messages (if enabled)
bool CHidTrayDevice::UpdateDeviceInfo(CCySysTray* pSysTray)
{
    // issue input report to get current HID Device data
    bool result = UpdateUsageValues();

    if (result)
    {
        if (m_ucBatteryLevel && m_ucPrevBatteryLevel)
        {
            // critically low battery level, display warning message if so
            if (((m_ucBatteryLevel+m_ucPrevBatteryLevel)/2) <= WIRELESSUSB_MAX_BATTERY_LEVEL_CRITICAL)
            {
                // don't try to display warning if hidden or warning messages has been disabled
                if (!pSysTray->IsHidden() && !m_bDisableWarningMessages)
                {
                    if (!m_bCriticalBatteryLevelWarning)
                    {
                        // display critical battery warning
                        pSysTray->ShowBalloonTip(_T("Low Battery!"), m_szProductString, NIIF_WARNING);
                        m_bCriticalBatteryLevelWarning = true;
                    }
                }
            }
            else
            {
                // reset critically low battery warning if battery level now high
                if (m_ucBatteryLevel >= WIRELESSUSB_MAX_BATTERY_LEVEL_HIGH)
                {
                    // reset critical battery level warning
                    m_bCriticalBatteryLevelWarning = false;
                }
            }
        }

        if (m_ucSignalStrength)
        if (WIRELESSUSB_SIGNAL_QUALITY_REPORTED(GetTotalGoodPacketValues(), GetTotalBadPacketValues()))
        {
            // critically low signal strengthquality, display warning message if so
            if (((m_ucSignalStrength+m_ucPrevSignalStrength)/2) WIRELESSUSB_SIGNAL_QUALITY_REPORTED(GetTotalGoodPacketValues(), GetTotalBadPacketValues())) <= WIRELESSUSB_MAX_SIGNAL_STRENGTHQUALITY_CRITICAL)
            {
                // don't try to display warning if hidden or warning messages has been disabled
                if (!pSysTray->IsHidden() && !m_bDisableWarningMessages)
                {
                    if (!m_bCriticalSignalStrengthWarningbCriticalSignalQualityWarning)
                    {
                        // display critical signal strengthquality warning
                        pSysTray->ShowBalloonTip(_T("Low Signal StrengthQuality!"), m_szProductString, NIIF_WARNING);
                        m_bCriticalSignalStrengthWarningbCriticalSignalQualityWarning = true;
                    }
                }
            }
            else
            {
                // reset critically low signal strength quality warning if signal strengthquality now high
                if (m_ucSignalStrength >= WIRELESSUSB_MAX_SIGNAL_STRENGTH_HIGH)
                if (WIRELESSUSB_SIGNAL_QUALITY_REPORTED(GetTotalGoodPacketValues(), GetTotalBadPacketValues()) >= WIRELESSUSB_MAX_SIGNAL_QUALITY_HIGH)
                {
                    // reset critical signal strengthquality level warning
                    m_bCriticalSignalStrengthWarningbCriticalSignalQualityWarning = false;
                }
                }
            }

        if (m_ucPrevWirelessChannel && (m_ucPrevWirelessChannel != m_ucWirelessChannel))
        {
            ChannelChangeAdjustment();
        }
    }

    return result;
}

// verify that this is a valid Hid device we care about
bool CHidTrayDevice::VerifyHidDevice()
{
    // using m_HidAttributes, we could check for VID/PID
    // if this becomes a future requirement

    // look for vendor specific usage page
    if (m_HidCaps.UsagePage == WIRELESSUSB_USAGEPAGE)
    {
        // look for usage of either either WirelessUSB Keyboard (WIRELESSUSB_USAGE_KEYBOARD)
        // or WirelessUSB Mouse (WIRELESSUSB_USAGE_MOUSE)
        if (m_HidCaps.Usage == WIRELESSUSB_USAGE_KEYBOARD || m_HidCaps.Usage == WIRELESSUSB_USAGE_MOUSE)
        {
            // update usage values for this Hid device
            return UpdateUsageValues();
        }
    }

    return false;
}

CHidTrayManager::CHidTrayManager(void)
{
}

CHidTrayManager::~CHidTrayManager(void)
{
    // going away, remove all Hid devices
    RemoveAllHidDevices();
}

// new Hid device, initialize and add it to the list of Hid devices we support
CHidDevice* CHidTrayManager::NewHidDevice(PCHAR pDevicePath) // overriding to support new CHidTrayDevice
    { 
        CHidTrayDevice *pNewHidDevice = new CHidTrayDevice(); 

        if (pNewHidDevice)
            pNewHidDevice->InitializeHidDevice(pDevicePath, CreateUniqueDeviceID());

        return pNewHidDevice;
    }

// delete Hid device, remove it from the list of Hid devices we support
void CHidTrayManager::DeleteHidDevice(CHidDevice *pHidDevice) // overriding to remove CHidTrayDevice
{   
    FreeUniqueDeviceID(pHidDevice->m_uDeviceID);
    delete (CHidTrayDevice *)pHidDevice; 
}

// display wireless status property sheet, it is not already displayed
void CMainFrame::OnAppWirelessUSBStatus()
{
    if (m_pWirelessUSBStatusPropertySheet) 
    { 
        // if property sheet has not been created, then do so
        if (!m_pWirelessUSBStatusPropertySheet->m_bIsCreated)
        {
            m_pWirelessUSBStatusPropertySheet->Create();
        }
        else
        {
            m_pWirelessUSBStatusPropertySheet->SetForegroundWindow();
        }
    } 
}