bluetoothengine/bthid/bthidserver/src/hidsdpclient.cpp
changeset 0 f63038272f30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/bthid/bthidserver/src/hidsdpclient.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,438 @@
+/*
+* Copyright (c) 2008 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:  This is the implementation of application class
+ *
+*/
+
+
+#include <btdevice.h>
+#include <bt_sock.h>
+#include "hidsdpclient.h"
+#include "bthiddevice.h"
+#include "hidsdpobserver.h"
+#include "bthidtypes.h"
+#include "bthidserver.pan"
+#include "descriptorlistparser.h"
+
+class TServiceAttribute
+    {
+public:
+    TSdpAttributeID iID;
+    };
+
+// HID Service Attributes
+static const TServiceAttribute gHIDServiceAttributes[] =
+    {
+        {
+        KHIDAttrDevRelNum
+        },
+        {
+        KHIDAttrDevSubClass
+        },
+        {
+        KHIDAttrCountryCode
+        },
+        {
+        KHIDAttrVirtuallyCabled
+        },
+        {
+        KHIDAttrReconnectInitiate
+        },
+        {
+        KHIDAttrDescriptorList
+        },
+        {
+        KHIDAttrProfileVersion
+        },
+        {
+        KHIDAttrNormallyConnectable
+        }
+    };
+
+// HID Service Attribute count 
+static const TUint gHIDServAttrCount = sizeof(gHIDServiceAttributes) / sizeof(TServiceAttribute);
+
+// PnP Service Attributes
+static const TServiceAttribute gBTPnPServiceAttributes[] =
+    {
+        {
+        KPnPAttrVendorID
+        },
+        {
+        KPnPAttrProductID
+        }
+    };
+
+// PnP Service Attribute count 
+static const TUint gBTPnPAttrCount = sizeof(gBTPnPServiceAttributes)
+        / sizeof(TServiceAttribute);
+
+// Bit Mask flags for the mandatory fields value
+const TUint KDevSubClassMandFlag = 1;
+const TUint KCountryCodeMandFlag = 2;
+const TUint KVirtuallyCabledMandFlag = 4;
+const TUint KReconnectInitMandFlag = 8;
+const TUint KDescriptorListMandFlag = 16;
+const TUint KProfileVersionMandFlag = 32;
+const TUint KVendorIDMandFlag = 64;
+const TUint KProductIDMandFlag = 128;
+
+// Expected mandatory fields value after the hid service record.
+const TUint KHidServiceMandValue = KDevSubClassMandFlag
+        | KCountryCodeMandFlag | KVirtuallyCabledMandFlag
+        | KReconnectInitMandFlag | KDescriptorListMandFlag
+        | KProfileVersionMandFlag;
+
+// Expected mandatory fields value after the bt pnp service record.
+const TUint KPnPServiceMandValue = KHidServiceMandValue | KVendorIDMandFlag
+        | KProductIDMandFlag;
+
+CHidSdpClient* CHidSdpClient::NewL(CBTHidDevice& aDevice,
+        MHidSdpObserver& aObserver)
+    {
+    CHidSdpClient* self = NewLC(aDevice, aObserver);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CHidSdpClient* CHidSdpClient::NewLC(CBTHidDevice& aDevice,
+        MHidSdpObserver& aObserver)
+    {
+    CHidSdpClient* self = new (ELeave) CHidSdpClient(aDevice, aObserver);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+CHidSdpClient::CHidSdpClient(CBTHidDevice& aDevice,
+        MHidSdpObserver& aObserver) :
+    CActive(EPriorityStandard), iDevice(aDevice), iObserver(aObserver),
+            iParserState(EIdle)
+    {
+    }
+
+CHidSdpClient::~CHidSdpClient()
+    {
+    delete iAgent;
+
+    delete iHIDMatchList;
+
+    delete iPNPMatchList;
+
+    delete iSdpSearchPattern;
+    }
+
+void CHidSdpClient::ConstructL()
+    {
+    // Create the service search pattern object.
+    iSdpSearchPattern = CSdpSearchPattern::NewL();
+
+    // Create the attribute match list for HIDP Service.
+    iHIDMatchList = CSdpAttrIdMatchList::NewL();
+
+    TUint i;
+
+    // Populate the list with the attributes we want to find.
+    for (i = 0; i < gHIDServAttrCount; i++)
+        {
+        iHIDMatchList->AddL(TAttrRange(gHIDServiceAttributes[i].iID));
+        }
+
+    //Create the attribute match list for the BT PnP Service.
+    iPNPMatchList = CSdpAttrIdMatchList::NewL();
+
+    // Populate the list with the attributes we want to find.
+    for (i = 0; i < gBTPnPAttrCount; i++)
+        {
+        iPNPMatchList->AddL(TAttrRange(gBTPnPServiceAttributes[i].iID));
+        }
+    }
+
+void CHidSdpClient::Finish(TInt aError)
+    {
+    iParserState = EIdle;
+    iObserver.HidSdpSearchComplete(aError);
+    }
+
+void CHidSdpClient::StartL()
+    {
+    // Delete any current agent.
+    delete iAgent;
+    iAgent = 0;
+
+    // Reset the mandatory value bitmask.
+    iMandAttrValue = 0;
+
+    // Create a SDP Agent for the given BT Address.
+    iAgent = CSdpAgent::NewL(*this, iDevice.iAddress);
+
+    // Fill the record filter with the UUID of the HIDP Service.
+    iSdpSearchPattern->AddL(KHidPServiceUUID);
+
+    // Set the initial record filter.
+    iAgent->SetRecordFilterL(*iSdpSearchPattern);
+
+    // Request the next record.
+    iAgent->NextRecordRequestL();
+
+    // Set that we are inquiring for the HIDP Service.
+    iParserState = EHIDService;
+    }
+
+void CHidSdpClient::Kill()
+    {
+    CActiveScheduler::Add(this);
+    iStatus = KRequestPending;
+    SetActive(); // Wait to be completed...
+    TRequestStatus* status = &iStatus;
+    User::RequestComplete(status, KErrNone); // ...which we do ourself
+    }
+
+void CHidSdpClient::NextRecordRequestComplete(TInt aError,
+        TSdpServRecordHandle aHandle, TInt /*aTotalRecordsCount*/)
+    {
+
+    TInt error = aError;
+
+    if (aError == KErrNone)
+        {
+        switch (iParserState)
+            {
+            // If this is supposed to be the HIDP Service Record.
+            case EHIDService:
+                // Request the attributes from the HIDP Service.
+            TRAP( error,
+                    iAgent->AttributeRequestL(aHandle, *iHIDMatchList);
+            )
+                break;
+
+                // If this is supposed to be the BT Pnp Service Record.
+            case EBTPnPService:
+                // Request the attributes from the BT Pnp Service.
+            TRAP( error,
+                    iAgent->AttributeRequestL(aHandle, *iPNPMatchList);
+            )
+                error = KErrNone; //PNP not found but we don't care! FOR RUNNING WITH IAR TESTER!
+                break;
+
+            default:
+                User::Panic(KBTHIDServer, EBadState);
+                break;
+            }
+        }
+
+    // If we have had any error, inform the observer as we have finished.
+    if (error != KErrNone)
+        {
+        Finish(error);
+        }
+    }
+
+void CHidSdpClient::AttributeRequestResult(TSdpServRecordHandle /*aHandle*/,
+        TSdpAttributeID aAttrID, CSdpAttrValue* aAttrValue)
+    {
+    switch (iParserState)
+        {
+        // If this is supposed to be a HIDP Service Attribute.
+        case EHIDService:
+            // Check its type and assign to the appropriate member in the 
+            // device object.
+            switch (aAttrValue->Type())
+                {
+                case ETypeUint:
+                    switch (aAttrID)
+                        {
+                        case KHIDAttrDevRelNum:
+                            iDevice.iDeviceReleaseNumber = aAttrValue->Uint();
+                            break;
+                        case KHIDAttrDevSubClass:
+                            iDevice.iDeviceSubClass = aAttrValue->Uint();
+                            // Record that this mandatory item was found
+                            iMandAttrValue |= KDevSubClassMandFlag;
+                            break;
+                        case KHIDAttrCountryCode:
+                            iDevice.iCountryCode = aAttrValue->Uint();
+                            iMandAttrValue |= KCountryCodeMandFlag;
+                            break;
+                        case KHIDAttrProfileVersion:
+                            iDevice.iProfileVersion = aAttrValue->Uint();
+                            iMandAttrValue |= KProfileVersionMandFlag;
+                            break;
+                        default:
+                            // This is an attribute we didn't request,
+                            // or wrong type.
+                            break;
+                        }
+                    break;
+
+                case ETypeBoolean:
+                    switch (aAttrID)
+                        {
+                        case KHIDAttrVirtuallyCabled:
+                            iDevice.iVirtuallyCabled = aAttrValue->Bool();
+                            iMandAttrValue |= KVirtuallyCabledMandFlag;
+                            break;
+                        case KHIDAttrReconnectInitiate:
+                            iDevice.iReconnectInit = aAttrValue->Bool();
+                            iMandAttrValue |= KReconnectInitMandFlag;
+                            break;
+                        case KHIDAttrNormallyConnectable:
+                            iDevice.iNormallyConnectable = aAttrValue->Bool();
+                            break;
+                        default:
+                            // This is an attribute we didn't request 
+                            // or wrong type.
+                            break;
+                        }
+                    break;
+
+                case ETypeDES:
+                    switch (aAttrID)
+                        {
+                        case KHIDAttrDescriptorList:
+                            {
+                                TRAP_IGNORE(
+                                        CDescriptorListParser* visitor = new CDescriptorListParser(*(iDevice.iDescList));
+                                        if( visitor )
+                                            {
+                                            CleanupStack::PushL(visitor);
+                                            aAttrValue->AcceptVisitorL(*visitor);
+                                            CleanupStack::PopAndDestroy(visitor);
+                                            }
+                                )
+                            // Don't care about any error that could occur
+                            iMandAttrValue |= KDescriptorListMandFlag;
+                            }
+                            break;
+                        default:
+                            // This is an attribute we didn't request 
+                            // or wrong type.
+                            break;
+                        }
+                    break;
+
+                default:
+                    // This is an attribute we didn't request or wrong type.
+                    break;
+                }
+
+            break;
+
+            // If this is supposed to be a BT Pnp Service Attribute.
+        case EBTPnPService:
+            // Check its type and assign to the appropriate member in the 
+            // device object.
+            switch (aAttrValue->Type())
+                {
+                case ETypeUint:
+                    switch (aAttrID)
+                        {
+                        case KPnPAttrVendorID:
+                            iDevice.iVendorID = aAttrValue->Uint();
+                            iMandAttrValue |= KVendorIDMandFlag;
+                            break;
+                        case KPnPAttrProductID:
+                            iDevice.iProductID = aAttrValue->Uint();
+                            iMandAttrValue |= KProductIDMandFlag;
+                            break;
+                        default:
+                            // This is an attribute we didn't request,
+                            // or wrong type.
+                            break;
+                        }
+                    break;
+
+                default:
+                    // This is an attribute we didn't request or wrong type.
+                    break;
+                }
+
+            break;
+
+        default:
+            // We shouldn't get this state.
+            User::Panic(KBTHIDServer, EBadState);
+            break;
+        }
+
+    // Ownership has been transferred
+    delete aAttrValue;
+    }
+
+void CHidSdpClient::AttributeRequestComplete(
+        TSdpServRecordHandle /*aHandle*/, TInt aError)
+    {
+    if (aError == KErrNone)
+        {
+        switch (iParserState)
+            {
+            // If this is supposed to be the HIDP Service Record.
+            case EHIDService:
+                // If we found all the attributes we requested.
+                if (iMandAttrValue == KHidServiceMandValue)
+                    {
+                    // Start a new sdp agent to request the BT Pnp 
+                    // Service Record.
+                    delete iAgent;
+                    iAgent = 0;
+                    TRAPD( res,
+                            iAgent = CSdpAgent::NewL(*this, iDevice.iAddress);
+                            iSdpSearchPattern->Reset();
+                            iSdpSearchPattern->AddL(KPnPServiceUUID);
+                            iAgent->SetRecordFilterL(*iSdpSearchPattern);
+                            iAgent->NextRecordRequestL();
+                            iParserState = EBTPnPService;
+                    )
+
+                    // If we failed, inform the observer of the error.
+                    if (res != KErrNone)
+                        {
+                        Finish(res);
+                        }
+                    }
+                else
+                    {
+                    // Not all attributes were found so inform the observer.
+                    Finish(KErrNotFound);
+                    }
+                break;
+
+                // If this is supposed to be the BT PnP Service Record.
+            case EBTPnPService:
+                // If we found all the attributes we requested.
+                if (iMandAttrValue == KPnPServiceMandValue)
+                    {
+                    // Report success to the observer.
+                    Finish(KErrNone);
+                    }
+                else
+                    {
+                    // Not all attributes were found so inform the observer.
+                    Finish(KErrNone); //We don't care if all info wasn't found!
+                    }
+                break;
+
+            default:
+                // We shouldn't get this state.
+                User::Panic(KBTHIDServer, EBadState);
+                break;
+            }
+        }
+    else
+        {
+        // Inform the observer of the error.
+        Finish(aError);
+        }
+    }
+