--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/secman/secmanhci.cpp Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,456 @@
+// Copyright (c) 1999-2009 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:
+//
+
+#include <bluetooth/logger.h>
+
+#include "secman.h"
+#include "linkutil.h"
+
+#include <bluetooth/hcicommandqueue.h>
+
+#include <bluetooth/hci/event.h>
+#include <bluetooth/hci/writesimplepairingmodecommand.h>
+#include <bluetooth/hci/writesimplepairingdebugmodecommand.h>
+#include <bluetooth/hci/iocapabilityrequestreplycommand.h>
+#include <bluetooth/hci/iocapabilityrequestnegativereplycommand.h>
+#include <bluetooth/hci/iocapabilityrequestnegativereplycommand.h>
+#include <bluetooth/hci/userconfirmationrequestreplycommand.h>
+#include <bluetooth/hci/userconfirmationrequestnegativereplycommand.h>
+#include <bluetooth/hci/remoteoobdatarequestreplycommand.h>
+#include <bluetooth/hci/remoteoobdatarequestnegativereplycommand.h>
+#include <bluetooth/hci/readlocaloobdatacommand.h>
+
+#include <bluetooth/hci/commandcompleteevent.h>
+#include <bluetooth/hci/commandstatusevent.h>
+
+#include <bluetooth/hci/iocapabilityrequestevent.h>
+#include <bluetooth/hci/iocapabilityresponseevent.h>
+#include <bluetooth/hci/userconfirmationrequestevent.h>
+#include <bluetooth/hci/userpasskeynotificationevent.h>
+#include <bluetooth/hci/remoteoobdatarequestevent.h>
+#include <bluetooth/hci/simplepairingcompleteevent.h>
+#include <bluetooth/hci/keypressnotificationevent.h>
+#include <bluetooth/hci/remotehostsupportedfeaturesnotificationevent.h>
+
+#include <bluetooth/hci/writesimplepairingdebugmodecompleteevent.h>
+
+#include <bluetooth/hci/readlocaloobdatacompleteevent.h>
+#include <bluetooth/hci/remoteoobdatarequestreplycompleteevent.h>
+#include <bluetooth/hci/remoteoobdatarequestnegativereplycompleteevent.h>
+
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_SECMAN);
+#endif
+
+
+// ------------------------------------------------------------------------
+// class CSecManCommandController
+// ------------------------------------------------------------------------
+
+CSecManCommandController::CSecManCommandController(CBTSecMan& aSecMan)
+ : iSecMan(aSecMan)
+ {
+ LOG_FUNC
+ }
+
+CSecManCommandController* CSecManCommandController::NewL(CBTSecMan& aSecMan)
+ {
+ LOG_STATIC_FUNC
+ CSecManCommandController* self = CSecManCommandController::NewLC(aSecMan);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSecManCommandController* CSecManCommandController::NewLC(CBTSecMan& aSecMan)
+ {
+ LOG_STATIC_FUNC
+ CSecManCommandController* self = new(ELeave) CSecManCommandController(aSecMan);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+void CSecManCommandController::ConstructL()
+ {
+ LOG_FUNC
+ }
+
+CSecManCommandController::~CSecManCommandController()
+ {
+ LOG_FUNC
+ ClearHCICommandQueue();
+ }
+
+void CSecManCommandController::SetHCICommandQueue(MHCICommandQueue& aCommandQueue)
+ {
+ LOG_FUNC
+ __ASSERT_DEBUG(!iCommandQueue, PANIC(KBTSecPanic, EBTSecCommandQueueAlreadyProvided));
+ iCommandQueue = &aCommandQueue;
+ }
+
+void CSecManCommandController::ClearHCICommandQueue()
+ {
+ LOG_FUNC
+ if(iCommandQueue)
+ {
+ iCommandQueue->MhcqRemoveAllCommands(*this);
+ }
+ iCommandQueue = NULL;
+ }
+
+MHCICommandQueue& CSecManCommandController::CommandQueue() const
+ {
+ LOG_FUNC
+ __ASSERT_DEBUG(iCommandQueue, PANIC(KBTSecPanic, EBTSecCommandQueueNotAvailable));
+ return *iCommandQueue;
+ }
+
+void CSecManCommandController::WriteSimplePairingModeL(TUint8 aSimplePairingMode)
+ {
+ LOG_FUNC
+ // Ownership of cmd transfered
+ CWriteSimplePairingModeCommand* cmd = CWriteSimplePairingModeCommand::NewL(aSimplePairingMode);
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::WriteSimplePairingDebugModeL(TUint8 aSimplePairingDebugMode)
+ {
+ LOG_FUNC
+ // Ownership of cmd transfered
+ CWriteSimplePairingDebugModeCommand* cmd = CWriteSimplePairingDebugModeCommand::NewL(aSimplePairingDebugMode);
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::IOCapabilityRequestReplyL(const TBTDevAddr& aBDADDR,
+ THCIIoCapability aIOCapability,
+ THCIOobDataPresence aOOBDataPresent,
+ THCIAuthenticationRequirement aAuthenticationRequirements)
+ {
+ LOG_FUNC
+ // Ownership of cmd transfered
+ CIOCapabilityRequestReplyCommand* cmd = CIOCapabilityRequestReplyCommand::NewL(aBDADDR, aIOCapability, aOOBDataPresent, aAuthenticationRequirements);
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::IOCapabilityRequestNegativeReplyL(const TBTDevAddr& aBDADDR, TUint8 aReason)
+ {
+ // Ownership of cmd transfered
+ CIOCapabilityRequestNegativeReplyCommand* cmd = CIOCapabilityRequestNegativeReplyCommand::NewL(aBDADDR, aReason);
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::UserConfirmationRequestReplyL(const TBTDevAddr& aBDADDR)
+ {
+ LOG_FUNC
+ // Ownership of cmd transfered
+ CUserConfirmationRequestReplyCommand* cmd = CUserConfirmationRequestReplyCommand::NewL(aBDADDR);
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::UserConfirmationRequestNegativeReplyL(const TBTDevAddr& aBDADDR)
+ {
+ LOG_FUNC
+ // Ownership of cmd transfered
+ CUserConfirmationRequestNegativeReplyCommand* cmd = CUserConfirmationRequestNegativeReplyCommand::NewL(aBDADDR);
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::RemoteOOBDataRequestReplyL(const TBTDevAddr& aBDADDR,
+ const TBluetoothSimplePairingHash& aC,
+ const TBluetoothSimplePairingRandomizer& aR)
+ {
+ LOG_FUNC
+ // Ownership of cmd transfered
+ CRemoteOOBDataRequestReplyCommand* cmd = CRemoteOOBDataRequestReplyCommand::NewL(aBDADDR, aC, aR);
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::RemoteOOBDataRequestNegativeReplyL(const TBTDevAddr& aBDADDR)
+ {
+ LOG_FUNC
+ CRemoteOOBDataRequestNegativeReplyCommand* cmd = CRemoteOOBDataRequestNegativeReplyCommand::NewL(aBDADDR);
+ // Ownership of cmd transfered
+ CommandQueue().MhcqAddCommandL(cmd, *this);
+ }
+
+void CSecManCommandController::MhcqcCommandErrored(TInt IF_FLOGGING(aErrorCode), const CHCICommandBase* __DEBUG_ONLY(aCommand))
+ {
+ LOG_FUNC
+ __ASSERT_DEBUG(aCommand, PANIC(KBTSecPanic, EBTSecNoCommandAssociatedWithErrorEvent)); // this should never happen
+
+ #ifdef _DEBUG
+ LOG2(_L("error code:%d opcode:0x%04x"), aErrorCode, aCommand->Opcode());
+ #else
+ LOG1(_L("error code:%d"), aErrorCode);
+ #endif
+ }
+
+// -----------------------------------------------------------------------------------------
+
+// From MHCICommandQueueClient
+void CSecManCommandController::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
+ {
+ LOG_FUNC
+ switch(aEvent.EventCode())
+ {
+ case ECommandCompleteEvent:
+ {
+ CommandCompleteEvent(aEvent);
+ break;
+ }
+
+ case ECommandStatusEvent:
+ CommandStatusEvent(aEvent);
+ break;
+
+ case EIOCapabilityRequestEvent:
+ IOCapabilityRequestEvent(aEvent);
+ break;
+
+ case EIOCapabilityResponseEvent:
+ IOCapabilityResponseEvent(aEvent);
+ break;
+
+ case EUserConfirmationRequestEvent:
+ UserConfirmationRequestEvent(aEvent);
+ break;
+
+ case EUserPasskeyRequestEvent:
+ // Symbian devices are assumed to be DisplayYesNo statically.
+ __ASSERT_DEBUG(EFalse, PANIC(KBTSecPanic, EBTSecBadUserPasskeyRequest));
+ break;
+
+ case EUserPasskeyNotificationEvent:
+ UserPasskeyNotificationEvent(aEvent);
+ break;
+
+ case ERemoteOOBDataRequestEvent:
+ RemoteOOBDataRequestEvent(aEvent);
+ break;
+
+ case EKeypressNotificationEvent:
+ KeypressNotificationEvent(aEvent);
+ break;
+
+ case ESimplePairingCompleteEvent:
+ SimplePairingCompleteEvent(aEvent);
+ break;
+
+ default:
+ LOG1(_L("Warning!! Unknown Command Event Received (event code: %d)"), aEvent.EventCode());
+ __ASSERT_DEBUG(EFalse, PANIC(KBTSecPanic, EBTSecUnknownHCIEvent));
+ break;
+ }
+ }
+
+void CSecManCommandController::IOCapabilityRequestEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TIOCapabilityRequestEvent& event = TIOCapabilityRequestEvent::Cast(aEvent);
+ iSecMan.IOCapabilityRequestFromRemote(event.BDADDR());
+ }
+
+void CSecManCommandController::IOCapabilityResponseEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TIOCapabilityResponseEvent& event = TIOCapabilityResponseEvent::Cast(aEvent);
+ iSecMan.IOCapabilityAskForResponse(event.BDADDR(), CastToIoCapability(event.IOCapability()), CastToOobDataPresence(event.OOBDataPresent()), CastToAuthenticationRequirements(event.AuthenticationRequirements()));
+ }
+
+void CSecManCommandController::UserConfirmationRequestEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TUserConfirmationRequestEvent& event = TUserConfirmationRequestEvent::Cast(aEvent);
+ iSecMan.UserConfirmationRequest(event.BDADDR(), event.NumericValue());
+ }
+
+void CSecManCommandController::UserPasskeyNotificationEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TUserPasskeyNotificationEvent& event = TUserPasskeyNotificationEvent::Cast(aEvent);
+ iSecMan.PasskeyNotification(event.BDADDR(), event.Passkey());
+ }
+
+void CSecManCommandController::RemoteOOBDataRequestEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TRemoteOOBDataRequestEvent& event = TRemoteOOBDataRequestEvent::Cast(aEvent);
+ iSecMan.RemoteOOBDataRequest(event.BDADDR());
+ }
+
+void CSecManCommandController::SimplePairingCompleteEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TSimplePairingCompleteEvent& spevent = TSimplePairingCompleteEvent::Cast(aEvent);
+ iSecMan.SimplePairingComplete(spevent.BDADDR(), aEvent.ErrorCode());
+ }
+
+void CSecManCommandController::KeypressNotificationEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TKeypressNotificationEvent& event = TKeypressNotificationEvent::Cast(aEvent);
+ iSecMan.KeypressNotification(event.BDADDR(), event.NotificationType());
+ }
+
+
+void CSecManCommandController::CommandCompleteEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const THCICommandCompleteEvent& completeEvent = THCICommandCompleteEvent::Cast(aEvent);
+ THCIOpcode opcode = completeEvent.CommandOpcode();
+ THCIErrorCode hciErr = aEvent.ErrorCode();
+
+ switch (opcode)
+ {
+ case KWriteSimplePairingModeOpcode:
+ WriteSimplePairingModeOpcode(completeEvent);
+ break;
+
+ case KRemoteOOBDataRequestReplyOpcode:
+ RemoteOOBDataRequestReplyOpcode(completeEvent);
+ break;
+
+ case KRemoteOOBDataRequestNegativeReplyOpcode:
+ RemoteOOBDataRequestNegativeReplyOpcode(completeEvent);
+ break;
+
+ case KIOCapabilityRequestReplyOpcode:
+ // Check bdaddr
+ break;
+
+ case KWriteSimplePairingDebugModeOpcode:
+ WriteSimplePairingDebugModeOpcode(completeEvent);
+ break;
+
+ // Need to handle link key request reply...
+ // Need to complete link key request negative reply
+ // Pin code request reply
+ case KIOCapabilityRequestNegativeReplyOpcode:
+ case KUserConfirmationRequestReplyOpcode:
+ // check bdaddr.
+ case KUserConfirmationRequestNegativeReplyOpcode:
+ // check bdadrr
+ case KUserPasskeyRequestReplyOpcode:
+ case KUserPasskeyRequestNegativeReplyOpcode:
+ // Catch all the events we do not handle
+ LOG1(_L("Warning!! Unhandled Command Complete Event (opcode: %d)"), opcode);
+ break;
+
+ default:
+ LOG2(_L("Link [HCIFacade_Events.cpp]: Warning: Unknown Command complete event! Opcode %d error code %d"), opcode, hciErr);
+ __ASSERT_DEBUG(EFalse, PANIC(KBTSecPanic, EBTSecUnknownHCICommandCompleteOpcode));
+ break;
+ }
+ }
+
+void CSecManCommandController::CommandStatusEvent(const THCIEventBase& aEvent)
+ {
+ LOG_FUNC
+ const TCommandStatusEvent& commandStatusEvent = TCommandStatusEvent::Cast(aEvent);
+ THCIOpcode opcode = commandStatusEvent.CommandOpcode();
+ THCIErrorCode hciErr = commandStatusEvent.ErrorCode();
+ }
+
+void CSecManCommandController::WriteSimplePairingModeOpcode(const THCICommandCompleteEvent& aCompleteEvent)
+ {
+ LOG_FUNC
+ if(aCompleteEvent.ErrorCode() == EOK)
+ {
+ iSecMan.SetLocalSimplePairingMode(ETrue);
+ }
+ // if we got an error then we make the reasonable assumption that the local controller is not
+ // capable of secure simple pairing.
+ }
+
+void CSecManCommandController::RemoteOOBDataRequestReplyOpcode(const THCICommandCompleteEvent& aCompleteEvent)
+ {
+ LOG_FUNC
+ const TRemoteOOBDataRequestReplyCompleteEvent& event = TRemoteOOBDataRequestReplyCompleteEvent::Cast(aCompleteEvent);
+ iSecMan.RemoteOOBDataRequestComplete(event.BDADDR());
+ }
+
+void CSecManCommandController::RemoteOOBDataRequestNegativeReplyOpcode(const THCICommandCompleteEvent& aCompleteEvent)
+ {
+ LOG_FUNC
+ const TRemoteOOBDataRequestNegativeReplyCompleteEvent& event = TRemoteOOBDataRequestNegativeReplyCompleteEvent::Cast(aCompleteEvent);
+ iSecMan.RemoteOOBDataRequestComplete(event.BDADDR());
+ }
+
+void CSecManCommandController::WriteSimplePairingDebugModeOpcode(const THCICommandCompleteEvent& aCompleteEvent)
+ {
+ LOG_FUNC
+ const TWriteSimplePairingDebugModeCompleteEvent& event = TWriteSimplePairingDebugModeCompleteEvent::Cast(aCompleteEvent);
+ if(event.ErrorCode() == EOK)
+ {
+ iSecMan.DebugModeChanged(ETrue);
+ }
+ // ignore errors - debug mode remains the same
+ }
+
+THCIIoCapability CSecManCommandController::CastToIoCapability(TUint8 aIOCapability)
+ {
+ LOG_STATIC_FUNC
+ switch(aIOCapability)
+ {
+ case EIOCapsDisplayOnly:
+ case EIOCapsDisplayYesNo:
+ case EIOCapsKeyboardOnly:
+ case EIOCapsNoInputNoOutput:
+ // All valid understood values.
+ break;
+ default:
+ __ASSERT_DEBUG(EFalse, PANIC(KBTSecPanic, EBTSecUnexpectedIoCapability));
+ break;
+ }
+ return static_cast<THCIIoCapability>(aIOCapability);
+ }
+
+THCIOobDataPresence CSecManCommandController::CastToOobDataPresence(TUint8 aOOBDataPresent)
+ {
+ LOG_STATIC_FUNC
+ switch(aOOBDataPresent)
+ {
+ case EOOBDataNotPresent:
+ case EOOBDataPresent:
+ // All valid understood values.
+ break;
+ default:
+ __ASSERT_DEBUG(EFalse, PANIC(KBTSecPanic, EBTSecUnexpectedOobDataPresence));
+ break;
+ }
+ return static_cast<THCIOobDataPresence>(aOOBDataPresent);
+ }
+
+THCIAuthenticationRequirement CSecManCommandController::CastToAuthenticationRequirements(TUint8 aAuthenticationRequirements)
+ {
+ LOG_STATIC_FUNC
+ switch(aAuthenticationRequirements)
+ {
+ case EMitmNotReqNoBonding:
+ case EMitmReqNoBonding:
+ case EMitmNotReqDedicatedBonding:
+ case EMitmReqDedicatedBonding:
+ case EMitmNotReqGeneralBonding:
+ case EMitmReqGeneralBonding:
+ // All valid understood values.
+ break;
+ default:
+ __ASSERT_DEBUG(EFalse, PANIC(KBTSecPanic, EBTSecUnexpectedAuthenticationRequirements));
+ break;
+ }
+ return static_cast<THCIAuthenticationRequirement>(aAuthenticationRequirements);
+ }
+