--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/localconnectivityservice/generichid/src/hidgeneric.cpp Tue Aug 31 16:03:15 2010 +0300
@@ -0,0 +1,533 @@
+/*
+* Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Generic hid implementation
+*
+*/
+
+#include <e32std.h>
+
+#include "debug.h"
+#include "hidgeneric.h"
+#include "hidreportroot.h"
+#include "hidparser.h"
+#include "hiddriveritem.h"
+#include "hidconnectioninfo.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// NewLC
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CGenericHid* CGenericHid::NewLC(MTransportLayer* aTransportLayer)
+ {
+ TRACE_INFO((_L("[HID]\tCGenericHid::NewLC(0x%08x)"), aTransportLayer));
+ CGenericHid* self = new (ELeave) CGenericHid(aTransportLayer);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CGenericHid* CGenericHid::NewL(MTransportLayer* aTransportLayer)
+ {
+ TRACE_INFO((_L("[HID]\tCGenericHid::NewL(0x%08x)"), aTransportLayer));
+ CGenericHid* self = NewLC(aTransportLayer);
+ CleanupStack::Pop();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::ConstructL()
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::ConstructL()"));
+ TRACE_INFO(_L("[HID]\tCGenericHid::ConstructL(): Creating Parser..."));
+ iParser = CParser::NewL();
+ iInputHandlingReg = CHidInputDataHandlingReg::NewL();
+ }
+
+// ---------------------------------------------------------------------------
+// CGenericHid()
+// ---------------------------------------------------------------------------
+//
+CGenericHid::CGenericHid(MTransportLayer* aTransportLayer) :
+ iDriverList(_FOFF(CDriverListItem, iSlink)),
+ iTransportLayer(aTransportLayer)
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CGenericHid::~CGenericHid()
+ {
+ TRACE_FUNC_ENTRY
+ RemoveDrivers();
+ iConnectionInfo.ResetAndDestroy();
+ iConnectionInfo.Close();
+ delete iInputHandlingReg;
+ delete iParser;
+ REComSession::FinalClose();
+ TRACE_FUNC_EXIT
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// CountryCodeL
+// ---------------------------------------------------------------------------
+//
+TUint CGenericHid::CountryCodeL(TInt aConnID)
+ {
+ // Pass the request through to the transport layer.
+ return (iTransportLayer->CountryCodeL(aConnID));
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// VendorIdL
+// ---------------------------------------------------------------------------
+//
+TUint CGenericHid::VendorIdL(TInt aConnID)
+ {
+ // Pass the request through to the transport layer.
+ return (iTransportLayer->VendorIdL(aConnID));
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// ProductIdL()
+// ---------------------------------------------------------------------------
+//
+TUint CGenericHid::ProductIdL(TInt aConnID)
+ {
+ // Pass the request through to the transport layer.
+ return iTransportLayer->ProductIdL(aConnID);
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// SetProtocol
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::SetProtocolL(TInt aConnectionId, TUint16 aInterface,
+ MDriverAccess::TProtocols aProtocol,
+ CHidDriver* aDriver)
+ {
+ iTransportLayer->SetProtocolL(aConnectionId, static_cast<TUint16>(aProtocol),
+ aInterface);
+ CConnectionInfo* conninfo = SeekConnectionInfo( aConnectionId );
+ if ( conninfo )
+ {
+ conninfo->SetLastCommandHandler(aDriver);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// GetProtocol
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::GetProtocolL(TInt aConnectionId,TUint16 aInterface)
+ {
+ iTransportLayer->GetProtocolL(aConnectionId, aInterface);
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// GetReport
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::GetReportL(TInt aConnectionId,
+ TUint8 aReportId, TUint16 aInterface, TUint16 aLength)
+ {
+ iTransportLayer->GetReportL(aConnectionId, MDriverAccess::EInput, aReportId,
+ aInterface, aLength);
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// SetReport()
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::SetReportL(TInt aConnectionId, TUint8 aReportId,
+ MDriverAccess::TReportType aReportType, const TDesC8& aPayload,
+ TUint16 aInterface, CHidDriver* aDriver)
+ {
+ iTransportLayer->SetReportL(aConnectionId, static_cast<TUint8>(aReportType),
+ aReportId, aInterface, aPayload);
+ CConnectionInfo* conninfo = SeekConnectionInfo( aConnectionId );
+ if ( conninfo )
+ {
+ conninfo->SetLastCommandHandler(aDriver);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// DataOut()
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::DataOutL(TInt aConnectionId, TUint8 aReportId,
+ const TDesC8& aPayload,
+ TUint16 aInterface)
+ {
+ iTransportLayer->DataOutL(aConnectionId, aReportId, aInterface, aPayload);
+ }
+
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// GetIdle()
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::GetIdleL(TInt aConnectionId, TUint8 aReportId,
+ TUint16 aInterface )
+ {
+ iTransportLayer->GetIdleL(aConnectionId, aReportId, aInterface);
+ }
+
+// ---------------------------------------------------------------------------
+// From MDriverAccess
+// SetIdle()
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::SetIdleL(TInt aConnectionId, TUint8 aDuration,
+ TUint8 aReportId, TUint16 aInterface, CHidDriver* aDriver)
+ {
+ iTransportLayer->SetIdleL(aConnectionId, aDuration, aReportId, aInterface);
+ CConnectionInfo* conninfo = SeekConnectionInfo( aConnectionId );
+ if ( conninfo )
+ {
+ conninfo->SetLastCommandHandler(aDriver);
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// RemoveDrivers()
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::RemoveDrivers()
+ {
+ TRACE_FUNC
+ // Driver instances
+ CDriverListItem* driverItem;
+ while ( !iDriverList.IsEmpty() )
+ {
+ driverItem = iDriverList.Last();
+ iDriverList.Remove( *driverItem );
+ delete driverItem;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// From CHidTransport
+// Disconnected()
+// ---------------------------------------------------------------------------
+//
+TInt CGenericHid::Disconnected( TInt aConnectionId )
+ {
+ TRACE_FUNC_ENTRY
+ TInt retVal = KErrNone;
+
+ TSglQueIter<CDriverListItem> driverIter( iDriverList );
+ driverIter.SetToFirst();
+
+ CDriverListItem* driverItem = driverIter;
+ while ( driverItem )
+ {
+ driverIter++;
+ if ( driverItem->ConnectionId() == aConnectionId )
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::Disconnected driver"));
+ if (driverItem->Driver())
+ {
+ driverItem->Driver()->Disconnected(0);
+ }
+ // Remove it from the list of driver instances
+
+ iDriverList.Remove(*driverItem);
+ delete driverItem;
+ driverItem = NULL;
+ retVal = KErrNone;
+ }
+ driverItem = driverIter;
+
+ TRACE_INFO(_L("[HID]\tCGenericHid::Disconnected next driver"));
+ }
+ TRACE_INFO(_L("[HID]\tCGenericHid::Disconnected remove connection info"));
+ TInt count = iConnectionInfo.Count();
+ for (TInt i = count-1 ; i>=0; i--)
+ {
+ TRACE_INFO((_L("[HID]\tCGenericHid::Disconnected remove connection info %d"),i));
+ CConnectionInfo* conninfo = iConnectionInfo[i];
+ TRACE_INFO((_L("[HID]\tCGenericHid::Disconnected remove connection info %d"),i));
+ if ( conninfo->ConnectionID() == aConnectionId )
+ {
+ iConnectionInfo.Remove(i);
+ delete conninfo;
+ TRACE_INFO((_L("[HID]\tCGenericHid::Disconnected remove connection info %d removed"),i));
+ }
+ }
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// From CHidTransport
+// ConnectedL
+// HID device has been connected. Attempt to find a driver that can
+// handle reports in the format specified by the report descriptor.
+// ---------------------------------------------------------------------------
+//
+TInt CGenericHid::ConnectedL( TInt aConnectionId, const TDesC8& aDescriptor )
+ {
+ TRACE_INFO((_L("[HID]\tCGenericHid::ConnectedL(%d, ...)"), aConnectionId))
+
+ // Place the parsed report descriptor in the driver list item:
+
+ TBool found = EFalse;
+ CConnectionInfo* conninfo = SeekConnectionInfo( aConnectionId );
+ if ( conninfo )
+ {
+ return KErrInUse;
+ }
+
+ CReportRoot* reportRoot = iParser->ParseL( aDescriptor );
+ CleanupStack::PushL(reportRoot);
+
+ TRACE_INFO(_L("[HID]\tCGenericHid::ConnectedL: evaluate driver array"));
+ // Implementation info array
+ RImplInfoPtrArray implInfoArray;
+ REComSession::ListImplementationsL( KHidDriverPluginInterfaceUid, implInfoArray );
+ CleanupClosePushL(implInfoArray);
+
+ TRACE_INFO((_L("[HID]\tCGenericHid::ConnectedL: %d implementations found"), implInfoArray.Count()));
+ TInt index = 0;
+ TInt retVal = KErrHidNoDriver;
+ TInt supportedfields = 0;
+ CHidDriver* driver = NULL;
+ for ( index = 0; index < implInfoArray.Count(); index++ )
+ {
+ // parse implementation UID
+ CImplementationInformation* info = implInfoArray[ index ];
+ TUid implUid = info->ImplementationUid();
+ TRACE_INFO((_L("[HID]\tCGenericHid::ConnectedL: load plugin 0x%08x"),implUid ));
+ // load driver
+ // Trap so other drivers will be enumerated even if
+ // this fails:
+
+ TRAPD(retTrap, driver = CHidDriver::NewL( implUid, this ));
+ if ( retTrap != KErrNone)
+ {
+ continue;
+ }
+ CleanupStack::PushL(driver);
+ TRACE_INFO((_L("[HID]\tCGenericHid::ConnectedL: init plugin 0x%08x"),implUid ));
+ driver->InitialiseL( aConnectionId );
+ TInt ret = driver->CanHandleReportL( reportRoot );
+ if (ret == KErrNone)
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::ConnectedL(): found driver"));
+
+ // Make a new driver list item:
+ CDriverListItem* driverItem = new ( ELeave ) CDriverListItem( aConnectionId );
+ CleanupStack::PushL( driverItem );
+ driver->SetInputHandlingReg( iInputHandlingReg );
+ supportedfields += driver->SupportedFieldCount();
+ iDriverList.AddLast( *driverItem );
+ CleanupStack::Pop( driverItem );
+ driverItem->SetDriver( driver );
+ CleanupStack::Pop( driver );
+ retVal = KErrNone;
+ found = ETrue;
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy( driver );
+ }
+ }
+ TRACE_INFO((_L("[HID]\tCGenericHid::ConnectedL Partial supported hid device supported %d in report %d&"),supportedfields,iParser->FieldCount()));
+ if (supportedfields < iParser->FieldCount() && found )
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::ConnectedL Partial supported hid device"));
+ }
+ implInfoArray.ResetAndDestroy();
+ CleanupStack::PopAndDestroy(); // info
+ if ( found )
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::ConnectedL append connection info"));
+ conninfo = CConnectionInfo::NewL(aConnectionId, reportRoot);
+ CleanupStack::Pop(reportRoot); // ownership transfered to conninfo
+ CleanupStack::PushL(conninfo);
+ iConnectionInfo.AppendL(conninfo);
+ CleanupStack::Pop(conninfo);
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(reportRoot);
+ }
+
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// From CHidTransport
+// DataIn
+// Determine which driver is handling this connection ID and pass the payload
+// reference to it
+// ---------------------------------------------------------------------------
+//
+TInt CGenericHid::DataIn(TInt aConnectionId,
+ CHidTransport::THidChannelType aChannel, const TDesC8& aPayload)
+ {
+ TRACE_FUNC_ENTRY
+ TInt retVal = KErrHidNoDriver;
+ TInt ret = KErrNone;
+
+ TSglQueIter<CDriverListItem> driverIter( iDriverList );
+ driverIter.SetToFirst();
+
+ CDriverListItem* item = driverIter;
+ TBool found = EFalse;
+ while ( item )
+ {
+ if ( item->ConnectionId() == aConnectionId )
+ {
+ ret = item->Driver()->DataIn( aChannel, aPayload );
+ if (ret == KErrNone)
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::DataIn command handled"));
+ found = ETrue;
+ retVal = KErrNone;
+ }
+ }
+ TRACE_INFO(_L("[HID]\tCGenericHid::DataIn next driver"));
+ driverIter++;
+ item = driverIter;
+ }
+ if ( !found && aChannel == CHidTransport::EHidChannelCtrl )
+ {
+ retVal = KErrNone;
+ }
+ iInputHandlingReg->Reset();
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+
+// ---------------------------------------------------------------------------
+// ReportDescriptor
+// Provides access to the parsed results to the factory
+// ---------------------------------------------------------------------------
+//
+CReportRoot* CGenericHid::ReportDescriptor(TInt aConnectionId)
+ {
+ CConnectionInfo* conninfo = SeekConnectionInfo( aConnectionId );
+ if ( conninfo )
+ {
+ return conninfo->ReportRoot();
+ }
+ return NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// From CHidTransport
+// DriverActive()
+// ---------------------------------------------------------------------------
+//
+TInt CGenericHid::DriverActive(TInt aConnectionId,
+ CHidTransport::TDriverState aActive)
+ {
+ TRACE_FUNC_ENTRY
+ TInt retVal = KErrHidNoDriver;
+ // Find the driver handling the connection and stop it
+ TSglQueIter<CDriverListItem> driverIter( iDriverList );
+ driverIter.SetToFirst();
+ CDriverListItem* item = driverIter;
+
+ while ( item )
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::DriverActive"));
+ if ( item->ConnectionId() == aConnectionId && item->Driver() )
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::DriverActive driver found"));
+ if ( aActive == CHidTransport::EActive )
+ {
+ TRAP(retVal, item->Driver()->StartL( aConnectionId ));
+ if (retVal != KErrNone)
+ {
+ break;
+ }
+ }
+ else if ( aActive == CHidTransport::ESuspend)
+ {
+ item->Driver()->Stop();
+ retVal = KErrNone;
+ }
+ }
+ driverIter++;
+ item = driverIter;
+ }
+ TRACE_FUNC_EXIT
+ return retVal;
+ }
+
+// ---------------------------------------------------------------------------
+// CommandResult()
+// ---------------------------------------------------------------------------
+//
+void CGenericHid::CommandResult(TInt aConnectionId, TInt aCmdAck)
+ {
+ // Get the driver handling this connection
+ CConnectionInfo* conninfo = SeekConnectionInfo( aConnectionId );
+ if ( conninfo )
+ {
+ CHidDriver* hiddriver = conninfo->ReturnLastCommandHandler();
+ if (hiddriver)
+ {
+ hiddriver->CommandResult(aCmdAck);
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// SeekConnectionInfo()
+// ---------------------------------------------------------------------------
+//
+CConnectionInfo* CGenericHid::SeekConnectionInfo(TInt aConnectionId)
+ {
+ TRACE_FUNC
+ CConnectionInfo* conninfo = NULL;
+ TInt count = iConnectionInfo.Count();
+ TRACE_INFO((_L("[HID]\tCGenericHid::SeekConnectionInfo count %d"), count));
+ for (TInt i = 0 ; i < count; i++)
+ {
+ conninfo = iConnectionInfo[i];
+ TRACE_INFO((_L("[HID]\tCGenericHid::SeekConnectionInfo connection info check %d %d"),aConnectionId, conninfo->ConnectionID()));
+ if ( conninfo->ConnectionID() == aConnectionId)
+ {
+ TRACE_INFO(_L("[HID]\tCGenericHid::SeekConnectionInfo connection info found"));
+ return conninfo;
+ }
+ }
+ return NULL;
+ }