--- /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);
+ }
+ }
+