localconnectivityservice/generichid/src/hidgeneric.cpp
branchRCL_3
changeset 19 0aa8cc770c8a
--- /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;
+    }