//************************************************************************
// The Logitech LCD SDK, including all acompanying documentation,
// is protected by intellectual property laws. All use of the Logitech
// LCD SDK is subject to the License Agreement found in the
// "Logitech LCD SDK License Agreement" file and in the Reference Manual.
// All rights not expressly granted by Logitech are reserved.
//************************************************************************
//************************************************************************
//
// LCDConnection.cpp
//
// The CLCDConnection class manages connections to all LCD devices
// including color and monochrome
//
// Logitech LCD SDK
//
// Copyright 2010 Logitech Inc.
//************************************************************************
#include "LCDUI.h"
// Add the lgLcd.lib to the linker
#pragma comment(lib, "lgLcd.lib")
// to keep track of clients that use multiple CLCDOutput instances
// within the same app
LONG CLCDConnection::g_lInitCount = 0;
//************************************************************************
//
// CLCDConnection::CLCDConnection
//
//************************************************************************
CLCDConnection::CLCDConnection(void)
{
m_hConnection = LGLCD_INVALID_CONNECTION;
ZeroMemory(&m_AppletState, sizeof(m_AppletState));
m_plcdSoftButtonsChangedCtx = NULL;
InitializeCriticalSection(&m_csCallback);
}
//************************************************************************
//
// CLCDConnection::~CLCDConnection
//
//************************************************************************
CLCDConnection::~CLCDConnection(void)
{
Disconnect();
FreeMonoOutput();
FreeColorOutput();
if (m_AppletState.Mono.pGfx)
{
delete m_AppletState.Mono.pGfx;
m_AppletState.Mono.pGfx = NULL;
}
if (m_AppletState.Color.pGfx)
{
delete m_AppletState.Color.pGfx;
m_AppletState.Color.pGfx = NULL;
}
DeleteCriticalSection(&m_csCallback);
}
//************************************************************************
//
// CLCDConnection::Initialize
//
//************************************************************************
BOOL CLCDConnection::Initialize(lgLcdConnectContext & ConnectContext,
lgLcdSoftbuttonsChangedContext* pSoftButtonChangedContext)
{
// Assume only BW is supported
m_AppletState.Mono.pOutput = new CLCDOutput();
m_AppletState.Mono.pGfx = new CLCDGfxMono();
m_AppletState.Mono.pGfx->Initialize();
m_AppletState.Mono.pOutput->SetGfx(m_AppletState.Mono.pGfx);
lgLcdConnectContextEx ConnectContextEx;
memset(&ConnectContextEx, 0, sizeof(ConnectContextEx));
ConnectContextEx.appFriendlyName = ConnectContext.appFriendlyName;
ConnectContextEx.isPersistent = ConnectContext.isPersistent;
ConnectContextEx.isAutostartable = ConnectContext.isAutostartable;
ConnectContextEx.connection = LGLCD_INVALID_CONNECTION;
ConnectContextEx.onConfigure = ConnectContext.onConfigure;
ConnectContextEx.dwAppletCapabilitiesSupported = LGLCD_APPLET_CAP_BW;
return Initialize(ConnectContextEx, pSoftButtonChangedContext);
}
//************************************************************************
//
// CLCDConnection::Initialize
//
//************************************************************************
BOOL CLCDConnection::Initialize(lgLcdConnectContextEx & ConnectContext,
lgLcdSoftbuttonsChangedContext* pSoftButtonChangedContext)
{
DWORD res = ERROR_SUCCESS;
if ((LGLCD_APPLET_CAP_BASIC == ConnectContext.dwAppletCapabilitiesSupported) ||
ConnectContext.dwAppletCapabilitiesSupported & LGLCD_APPLET_CAP_BW)
{
m_AppletState.Mono.pOutput = AllocMonoOutput();
m_AppletState.Mono.pGfx = new CLCDGfxMono();
m_AppletState.Mono.pGfx->Initialize();
m_AppletState.Mono.pOutput->SetGfx(m_AppletState.Mono.pGfx);
}
if (ConnectContext.dwAppletCapabilitiesSupported & LGLCD_APPLET_CAP_QVGA)
{
m_AppletState.Color.pOutput = AllocColorOutput();
m_AppletState.Color.pGfx = new CLCDGfxColor();
m_AppletState.Color.pGfx->Initialize();
m_AppletState.Color.pOutput->SetGfx(m_AppletState.Color.pGfx);
}
//Assure we only call the lib's init once
LCDUIASSERT(g_lInitCount >= 0);
if(1 == InterlockedIncrement(&g_lInitCount))
{
// need to call lgLcdInit once
res = lgLcdInit();
if (ERROR_SUCCESS != res)
{
InterlockedDecrement(&g_lInitCount);
LCDUITRACE(_T("WARNING: lgLcdInit failed\n"));
return FALSE;
}
}
memset(&m_lcdConnectCtxEx, 0, sizeof(m_lcdConnectCtxEx));
m_lcdConnectCtxEx.appFriendlyName = NULL;
m_lcdConnectCtxEx.isPersistent = FALSE;
m_lcdConnectCtxEx.isAutostartable = FALSE;
m_lcdConnectCtxEx.connection = LGLCD_INVALID_CONNECTION;
// Initialize the added version 3.0 API fields
m_lcdConnectCtxEx.dwAppletCapabilitiesSupported = LGLCD_APPLET_CAP_BASIC;
m_lcdConnectCtxEx.dwReserved1 = 0;
m_lcdConnectCtxEx.onNotify.notificationCallback = NULL;
m_lcdConnectCtxEx.onNotify.notifyContext = NULL;
memcpy(&m_lcdConnectCtxEx, &ConnectContext, sizeof(lgLcdConnectContextEx));
m_plcdSoftButtonsChangedCtx = pSoftButtonChangedContext;
// Add internal callback handlers if not specified
if (NULL == m_lcdConnectCtxEx.onNotify.notificationCallback)
{
m_lcdConnectCtxEx.onNotify.notificationCallback = _OnNotificationCallback;
m_lcdConnectCtxEx.onNotify.notifyContext = this;
}
Connect();
if (LGLCD_INVALID_CONNECTION != m_hConnection)
{
// At this point, the asynchronous events have already been sent.
// Let's allow a small amount of time for the callback thread to insert the events
// into the shared queue.
// If you don't care about knowing about devices after Initialize
// completes, you can remove these 2 lines
Sleep(50);
Update();
}
return TRUE;
}
//************************************************************************
//
// CLCDConnection::Shutdown
//
//************************************************************************
void CLCDConnection::Shutdown(void)
{
Disconnect();
if(0 == InterlockedDecrement(&g_lInitCount))
{
lgLcdDeInit();
}
m_plcdSoftButtonsChangedCtx = NULL;
}
//************************************************************************
//
// CLCDConnection::Connect
//
// This will attempt a connection to LCDMon
//************************************************************************
void CLCDConnection::Connect(void)
{
//Close previous connections
Disconnect();
if (LGLCD_INVALID_CONNECTION == m_hConnection)
{
DWORD retval = lgLcdConnectEx(&m_lcdConnectCtxEx);
if (ERROR_SUCCESS == retval)
{
m_hConnection = m_lcdConnectCtxEx.connection;
}
else
{
if( ERROR_SERVICE_NOT_ACTIVE == retval )
{
LCDUITRACE( _T("lgLcdConnectEx ---> ERROR_INVALID_PARAMETER\n") );
m_hConnection = LGLCD_INVALID_CONNECTION;
}
m_hConnection = LGLCD_INVALID_CONNECTION;
}
}
}
//************************************************************************
//
// CLCDConnection::Disconnect
//
//************************************************************************
void CLCDConnection::Disconnect(void)
{
//Close your devices, too
if (m_AppletState.Color.pOutput)
{
m_AppletState.Color.pOutput->Close();
}
if (m_AppletState.Mono.pOutput)
{
m_AppletState.Mono.pOutput->Close();
}
if( LGLCD_INVALID_CONNECTION != m_hConnection )
{
lgLcdDisconnect(m_hConnection);
m_hConnection = LGLCD_INVALID_CONNECTION;
}
}
//************************************************************************
//
// CLCDConnection::IsConnected
//
//************************************************************************
BOOL CLCDConnection::IsConnected(void)
{
return LGLCD_INVALID_CONNECTION != m_hConnection;
}
//************************************************************************
//
// CLCDConnection::GetConnectionId
//
//************************************************************************
int CLCDConnection::GetConnectionId(void)
{
return m_hConnection;
}
//************************************************************************
//
// CLCDConnection::ColorOutput
//
//************************************************************************
CLCDOutput *CLCDConnection::ColorOutput(void)
{
return m_AppletState.Color.pOutput;
}
//************************************************************************
//
// CLCDConnection::MonoOutput
//
//************************************************************************
CLCDOutput *CLCDConnection::MonoOutput(void)
{
return m_AppletState.Mono.pOutput;
}
//************************************************************************
//
// CLCDConnection::_OnNotificationCallback
//
//************************************************************************
DWORD CALLBACK CLCDConnection::_OnNotificationCallback(
IN int connection,
IN const PVOID pContext,
IN DWORD notificationCode,
IN DWORD notifyParm1,
IN DWORD notifyParm2,
IN DWORD notifyParm3,
IN DWORD notifyParm4)
{
UNREFERENCED_PARAMETER(connection);
UNREFERENCED_PARAMETER(notifyParm3);
UNREFERENCED_PARAMETER(notifyParm4);
CLCDConnection* pThis = (CLCDConnection*)pContext;
CB_EVENT Event;
memset(&Event, 0, sizeof(Event));
EnterCriticalSection(&pThis->m_csCallback);
Event.Type = CBT_NOTIFICATION;
Event.CallbackCode = notificationCode;
Event.CallbackParam1 = notifyParm1;
Event.CallbackParam2 = notifyParm2;
pThis->m_CallbackEventQueue.push(Event);
LeaveCriticalSection(&pThis->m_csCallback);
pThis->OnCallbackEvent();
return 0;
}
//************************************************************************
//
// CLCDConnection::_OnSoftButtonsCallback
//
//************************************************************************
DWORD CALLBACK CLCDConnection::_OnSoftButtonsCallback(
IN int device,
IN DWORD dwButtons,
IN const PVOID pContext)
{
CLCDConnection* pThis = (CLCDConnection*)pContext;
CB_EVENT Event;
memset(&Event, 0, sizeof(Event));
EnterCriticalSection(&pThis->m_csCallback);
Event.Type = CBT_BUTTON;
Event.CallbackCode = device;
Event.CallbackParam1 = dwButtons;
pThis->m_CallbackEventQueue.push(Event);
LeaveCriticalSection(&pThis->m_csCallback);
pThis->OnCallbackEvent();
return 0;
}
//************************************************************************
//
// CLCDConnection::_OnConfigureCallback
//
//************************************************************************
DWORD CALLBACK CLCDConnection::_OnConfigureCallback(
IN int connection,
IN const PVOID pContext)
{
UNREFERENCED_PARAMETER(connection);
CLCDConnection* pThis = (CLCDConnection*)pContext;
CB_EVENT Event;
memset(&Event, 0, sizeof(Event));
EnterCriticalSection(&pThis->m_csCallback);
Event.Type = CBT_CONFIG;
pThis->m_CallbackEventQueue.push(Event);
LeaveCriticalSection(&pThis->m_csCallback);
return 0;
}
//************************************************************************
//
// CLCDConnection::GetNextCallbackEvent
//
//************************************************************************
BOOL CLCDConnection::GetNextCallbackEvent(CB_EVENT& rEvent)
{
memset(&rEvent, 0, sizeof(rEvent));
EnterCriticalSection(&m_csCallback);
if(0 < m_CallbackEventQueue.size())
{
std::swap(rEvent, m_CallbackEventQueue.front());
m_CallbackEventQueue.pop();
LeaveCriticalSection(&m_csCallback);
return TRUE;
}
LeaveCriticalSection(&m_csCallback);
return FALSE;
}
//************************************************************************
//
// CLCDConnection::Update
//
//************************************************************************
void CLCDConnection::Update(void)
{
// If we're not connected, connect
if (LGLCD_INVALID_CONNECTION == m_hConnection)
{
Connect();
}
// Get events
CB_EVENT Event;
while(GetNextCallbackEvent(Event))
{
switch(Event.Type)
{
case CBT_NOTIFICATION:
OnNotification(Event.CallbackCode, Event.CallbackParam1);
break;
case CBT_CONFIG:
OnConfigure();
break;
case CBT_BUTTON:
OnSoftButtonEvent(Event.CallbackCode, Event.CallbackParam1);
break;
default:
break;
}
}
// For each display type
for (int i = 0; i < 2; i++)
{
LCD_DEVICE_STATE* pDevice = (i == 0) ? &m_AppletState.Mono : &m_AppletState.Color;
if (NULL == pDevice->pOutput)
{
// Output not supported
continue;
}
if (pDevice->pOutput->IsOpened())
{
pDevice->pOutput->OnUpdate(GetTickCount());
pDevice->pOutput->OnDraw();
}
// If the device is closed, but it was opened by OpenByType(),
// we can try to open it again...
if (!pDevice->pOutput->IsOpened() && pDevice->pOutput->HasBeenOpenedByDeviceType())
{
pDevice->pOutput->ReOpenDeviceType();
}
}
}
//************************************************************************
//
// CLCDConnection::OnConfigure
//
//************************************************************************
void CLCDConnection::OnConfigure(void)
{
LCDUITRACE(_T("OnConfigure\n"));
}
//************************************************************************
//
// CLCDConnection::OnDeviceArrival
//
//************************************************************************
void CLCDConnection::OnDeviceArrival(DWORD dwDisplayType)
{
LCD_DEVICE_STATE* pDevice = NULL;
switch(dwDisplayType)
{
case LGLCD_DEVICE_BW:
pDevice = &m_AppletState.Mono;
break;
case LGLCD_DEVICE_QVGA:
pDevice = &m_AppletState.Color;
break;
default:
LCDUITRACE(_T("Unhandled DisplayType in OnDeviceArrival()!\n"));
return;
}
// Ensure that we have a valid output
if (NULL == pDevice->pOutput)
{
LCDUITRACE(_T("Device arrival on unsupported device\n"));
return;
}
lgLcdOpenByTypeContext OpenCtx;
memset(&OpenCtx, 0, sizeof(OpenCtx));
OpenCtx.connection = m_hConnection;
OpenCtx.deviceType = dwDisplayType;
OpenCtx.onSoftbuttonsChanged.softbuttonsChangedCallback = _OnSoftButtonsCallback;
OpenCtx.onSoftbuttonsChanged.softbuttonsChangedContext = this;
OpenCtx.device = LGLCD_INVALID_DEVICE;
// If user has specified the soft button context, allow user to override
if (NULL != m_plcdSoftButtonsChangedCtx)
{
OpenCtx.onSoftbuttonsChanged = *m_plcdSoftButtonsChangedCtx;
}
pDevice->pOutput->OpenByType(OpenCtx);
}
//************************************************************************
//
// CLCDConnection::OnDeviceRemoval
//
//************************************************************************
void CLCDConnection::OnDeviceRemoval(DWORD dwDisplayType)
{
LCD_DEVICE_STATE* pDevice = NULL;
switch(dwDisplayType)
{
case LGLCD_DEVICE_BW:
pDevice = &m_AppletState.Mono;
break;
case LGLCD_DEVICE_QVGA:
pDevice = &m_AppletState.Color;
break;
default:
LCDUITRACE(_T("Unhandled DisplayType in OnDeviceArrival()!\n"));
return;
}
if (pDevice->pOutput)
{
pDevice->pOutput->StopOpeningByDeviceType();
pDevice->pOutput->Close();
}
}
//************************************************************************
//
// CLCDConnection::OnAppletEnabled
//
//************************************************************************
void CLCDConnection::OnAppletEnabled(void)
{
}
//************************************************************************
//
// CLCDConnection::OnAppletDisabled
//
//************************************************************************
void CLCDConnection::OnAppletDisabled(void)
{
}
//************************************************************************
//
// CLCDConnection::OnNotification
//
//************************************************************************
void CLCDConnection::OnNotification(DWORD dwNotification, DWORD dwParam1)
{
switch(dwNotification)
{
case LGLCD_NOTIFICATION_DEVICE_ARRIVAL:
LCDUITRACE(_T("LGLCD_NOTIFICATION_DEVICE_ARRIVAL\n"));
OnDeviceArrival(dwParam1);
break;
case LGLCD_NOTIFICATION_DEVICE_REMOVAL:
LCDUITRACE(_T("LGLCD_NOTIFICATION_DEVICE_REMOVAL\n"));
OnDeviceRemoval(dwParam1);
break;
case LGLCD_NOTIFICATION_CLOSE_CONNECTION:
LCDUITRACE(_T("LGLCD_NOTIFICATION_CLOSE_CONNECTION\n"));
Disconnect();
break;
case LGLCD_NOTIFICATION_APPLET_DISABLED:
LCDUITRACE(_T("LGLCD_NOTIFICATION_APPLET_DISABLED\n"));
OnAppletDisabled();
break;
case LGLCD_NOTIFICATION_APPLET_ENABLED:
LCDUITRACE(_T("LGLCD_NOTIFICATION_APPLET_ENABLED\n"));
OnAppletEnabled();
break;
case LGLCD_NOTIFICATION_TERMINATE_APPLET:
break;
}
}
//************************************************************************
//
// CLCDConnection::OnSoftButtonEvent
//
//************************************************************************
void CLCDConnection::OnSoftButtonEvent(int nDeviceId, DWORD dwButtonState)
{
// Forward this to the appropriate display
if (m_AppletState.Mono.pOutput && (nDeviceId == m_AppletState.Mono.pOutput->GetDeviceId()))
{
m_AppletState.Mono.pOutput->OnSoftButtonEvent(dwButtonState);
}
else if (m_AppletState.Color.pOutput && (nDeviceId == m_AppletState.Color.pOutput->GetDeviceId()))
{
m_AppletState.Color.pOutput->OnSoftButtonEvent(dwButtonState);
}
}
//************************************************************************
//
// CLCDConnection::AllocMonoOutput
//
//************************************************************************
CLCDOutput* CLCDConnection::AllocMonoOutput(void)
{
return new CLCDOutput();
}
//************************************************************************
//
// CLCDConnection::AllocColorOutput
//
//************************************************************************
CLCDOutput* CLCDConnection::AllocColorOutput(void)
{
return new CLCDOutput();
}
//************************************************************************
//
// CLCDConnection::FreeMonoOutput
//
//************************************************************************
void CLCDConnection::FreeMonoOutput(void)
{
if (NULL != m_AppletState.Mono.pOutput)
{
delete m_AppletState.Mono.pOutput;
m_AppletState.Mono.pOutput = NULL;
}
}
//************************************************************************
//
// CLCDConnection::FreeColorOutput
//
//************************************************************************
void CLCDConnection::FreeColorOutput(void)
{
if (NULL != m_AppletState.Color.pOutput)
{
delete m_AppletState.Color.pOutput;
m_AppletState.Color.pOutput = NULL;
}
}
//** end of LCDConnection.cpp ********************************************
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: m_lcdConnectCtxEx.
↑ V519 The 'm_hConnection' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 228, 231.