diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/linkmgr/VendorSAP.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/VendorSAP.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,382 @@ +// Copyright (c) 2005-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 "VendorSAP.h" +#include "vendorspecific.h" +#include "linkmgr.h" +#include "hcifacade.h" +#include "BTSec.h" + + +//Diagnostic string for security check failures, in builds without platsec +//diagnostics this will be NULL. +const char* const KVENDOR_SAP_NAME_DIAG = __PLATSEC_DIAGNOSTIC_STRING("Vendor SAP"); + +// only does IOCTLs + +CVendorSAP* CVendorSAP::NewL(CLinkMgrProtocol& aProtocol) + { + return new(ELeave) CVendorSAP(aProtocol); + } + +CVendorSAP::CVendorSAP(CLinkMgrProtocol& aProtocol) +: iDebugEventQueue(_FOFF(TVendorDebugEvent, iEventLink)), + iProtocol(aProtocol) + { + iProtocol.iVendorSpecificSAP = this; + } + +CVendorSAP::~CVendorSAP() + { + iProtocol.iVendorSpecificSAP = NULL; + + //need to empty the queue. + while (!(iDebugEventQueue.IsEmpty())) + { + TVendorDebugEvent* theEvent = iDebugEventQueue.First(); + theEvent->iEventLink.Deque(); + delete theEvent; + } + } + +void CVendorSAP::Ioctl(TUint aLevel,TUint aName,TDes8* aOption) +/** +**/ + { + __ASSERT_DEBUG(iIoctlLevel == 0, Panic(EVendorTwoIoctls)); + __ASSERT_DEBUG(iIoctlName == 0, Panic(EVendorTwoIoctls)); + + iIoctlLevel = aLevel; + iIoctlName = aName; + + //Do security check on following Ioctls + TInt rerr = KErrNone; + switch(aName) + { + case KHCIWaitForVendorSpecificDebugEventIoctl: + case KHCIWriteVendorSpecificFrameIoctl: + case KHCIWriteVendorSpecificFrameNoEventExpectedIoctl: + { + //The above Ioctl require additional security checking, NetworkControl + //in addition to the LocalServices that was required to create the SAP + __ASSERT_DEBUG(iSecurityChecker, User::Panic(KSECURITY_PANIC, EBTPanicNullSecurityChecker)); + rerr = iSecurityChecker->CheckPolicy(KNETWORK_CONTROL, KVENDOR_SAP_NAME_DIAG); + if (rerr != KErrNone) + { + NotifyIoctlComplete(rerr, + KSolBtHCI, + aName, + NULL); + } + break; + } + default: + // Other Ioctls require just LocalServices - effectively policed when BT socket is created/transferred + break; + } + if (rerr != KErrNone) + { + return; + } + + // have passed security check so continue to handle ioctl + switch(aName) + { + case KHCIWaitForVendorSpecificDebugEventIoctl: + { + + /* + If VendorSpecificWaitForDebugEvent ioctl + See if we can complete it synchronously + */ + TryToCompleteVendorDebugEventIoctl(); + break; + } + case KHCIWriteVendorSpecificFrameIoctl: + { + if(aOption->Length() != sizeof(THCIWriteVendorSpecificFrameIoctl)) + { + NotifyIoctlComplete(KErrBadDescriptor, + KSolBtHCI, + KHCIWriteVendorSpecificFrameIoctl, + NULL); + return; + } + const THCIWriteVendorSpecificFrameIoctl* ioctl = + reinterpret_cast(aOption->Ptr()); + + TRAPD(err,iProtocol.HCIFacade().VendorSpecificCommandL(ioctl->iOpcode, ioctl->iParams)); + if (err) + { + NotifyIoctlComplete(err, + KSolBtHCI, + KHCIWriteVendorSpecificFrameIoctl, + NULL); + } + // if no error wait for event before completing + + break; + } + case KHCIWriteVendorSpecificFrameNoEventExpectedIoctl: + { + if(aOption->Length() != sizeof(THCIWriteVendorSpecificFrameIoctl)) + { + NotifyIoctlComplete(KErrBadDescriptor, + KSolBtHCI, + KHCIWriteVendorSpecificFrameNoEventExpectedIoctl, + NULL); + return; + } + const THCIWriteVendorSpecificFrameIoctl* ioctl = + reinterpret_cast(aOption->Ptr()); + + TRAPD(err,iProtocol.HCIFacade().VendorSpecificCommandL(ioctl->iOpcode, ioctl->iParams)); + // notify completion now though really could wait until delivered from q + NotifyIoctlComplete(err, + KSolBtHCI, + KHCIWriteVendorSpecificFrameNoEventExpectedIoctl, + NULL); + break; + } + default: + NotifyIoctlComplete( + KErrNotSupported, + iIoctlLevel, + iIoctlName, + NULL + ); + break; + } // END Switch + } + + +void CVendorSAP::VendorCommandCompleteEvent(TInt aErr, const TDesC8* aEvent) + { + if(iIoctlName == KHCIWriteVendorSpecificFrameIoctl) + { + /* + A client is waiting for this. + */ + NotifyIoctlComplete(aErr, iIoctlLevel, KHCIWriteVendorSpecificFrameIoctl, aEvent); + } + } + +void CVendorSAP::VendorDebugEvent(TInt aErr, const TDesC8* aEvent) + { + // Some events will not contain an event descriptor. + TPtrC8 eventDesc = aEvent?*aEvent:KNullDesC8; + + // Holds the data from an *expected* event (expected as in conduit said so!). + TVendorDebugEvent* newEvent = NewDebugEventData(eventDesc, aErr); + + if(newEvent) + { + iDebugEventQueue.AddLast(*newEvent); // add this event to the end of the list of events already queued + } + else + { + NotifyIoctlComplete(KErrNoMemory, + iIoctlLevel, + iIoctlName, + NULL); + return; + } + TryToCompleteVendorDebugEventIoctl(); + } + + +TInt CVendorSAP::SecurityCheck(MProvdSecurityChecker *aSecurityChecker) + { + __ASSERT_ALWAYS(aSecurityChecker, User::Panic(KSECURITY_PANIC, EBTPanicNullSecurityChecker)); + + iSecurityChecker = aSecurityChecker; + return iSecurityChecker->CheckPolicy(KLOCAL_SERVICES, KVENDOR_SAP_NAME_DIAG); + } + +void CVendorSAP::NotifyIoctlComplete(TInt aErr, TUint aLevel, TUint aName, const TDesC8* aBuffer) + { + if (iIoctlLevel == aLevel && iIoctlName == aName) + { + if (aErr == KErrNone) + { + if(iSocket) + iSocket->IoctlComplete(const_cast(aBuffer)); + } + else + { + if(iSocket) + iSocket->Error(aErr, MSocketNotify::EErrorIoctl); + } + } + + iIoctlLevel=0; + iIoctlName=0; + } + + +CVendorSAP::TVendorDebugEvent* CVendorSAP::NewDebugEventData(const TDesC8& aBuf, TInt aError) +/** +@param aBuf The Vendor event buffer. Must not be NULL +**/ + { + TVendorDebugEvent* event = new TVendorDebugEvent; + if(!event) + { + return 0; + } + event->iEventBuf.Copy(aBuf.Left(Min(CHctlCommandFrame::KHCIMaxCommandLength, aBuf.Length()))); + event->iEventError = aError; + return event; + } + +void CVendorSAP::TryToCompleteVendorDebugEventIoctl() + { + // check to see if anyone expecting a debug event completion + if (iIoctlName != KHCIWaitForVendorSpecificDebugEventIoctl) + { + return; + } + + // nothing to do + if(iDebugEventQueue.IsEmpty()) + { + return; + } + + TVendorDebugEvent* theEvent = iDebugEventQueue.First(); + + // belt and braces! + if(theEvent == NULL) + { + return; + } + + // De-queue the event, as it is being consumed + theEvent->iEventLink.Deque(); + + // Complete the waiting ioctl, passing the the first appropriate + // event in the queue back up. + NotifyIoctlComplete( + theEvent->iEventError, + KSolBtHCI, + KHCIWaitForVendorSpecificDebugEventIoctl, + &(theEvent->iEventBuf) + ); + + // Event has been consumed, may now be deleted + delete theEvent; + + } + + +void CVendorSAP::Start() + { + // do nothing + } + +void CVendorSAP::LocalName(TSockAddr& /*aAddr*/) const + { + Panic(EVendorSAPBadCall); + } + +TInt CVendorSAP::SetLocalName(TSockAddr& /*aAddr*/) + { + Panic(EVendorSAPBadCall); + return KErrNotSupported; + } + +void CVendorSAP::RemName(TSockAddr& /*aAddr*/) const + { + Panic(EVendorSAPBadCall); + } + +TInt CVendorSAP::SetRemName(TSockAddr& /*aAddr*/) + { + Panic(EVendorSAPBadCall); + return KErrNotSupported; + } + +TInt CVendorSAP::GetOption(TUint /*aLevel*/,TUint /*aName*/,TDes8& /*aOption*/) const + { + Panic(EVendorSAPBadCall); + return KErrNotSupported; + } + +void CVendorSAP::CancelIoctl(TUint __DEBUG_ONLY(aLevel),TUint __DEBUG_ONLY(aName)) + { + __ASSERT_DEBUG(iIoctlLevel == aLevel, Panic(EVendorSAPBadIoctlCancel)); + __ASSERT_DEBUG(iIoctlName == aName, Panic(EVendorSAPBadIoctlCancel)); + + iIoctlName = 0; + iIoctlLevel = 0; + } + +TInt CVendorSAP::SetOption(TUint /*aLevel*/,TUint /*aName*/,const TDesC8& /*aOption*/) + { + Panic(EVendorSAPBadCall); + return KErrNotSupported; + } + +void CVendorSAP::ActiveOpen() + { + Panic(EVendorSAPBadCall); + } + +void CVendorSAP::ActiveOpen(const TDesC8& /*aConnectionData*/) + { + Panic(EVendorSAPBadCall); + } + +TInt CVendorSAP::PassiveOpen(TUint /*aQueSize*/) + { + Panic(EVendorSAPBadCall); + return KErrNotSupported; + } + +TInt CVendorSAP::PassiveOpen(TUint /*aQueSize*/,const TDesC8& /*aConnectionData*/) + { + Panic(EVendorSAPBadCall); + return KErrNotSupported; + } + +void CVendorSAP::AutoBind() + { + Panic(EVendorSAPBadCall); + } + +TUint CVendorSAP::Write(const TDesC8& /*aDesc*/, TUint /*aOptions*/, TSockAddr* /*aAddr*/) + { + Panic(EVendorSAPBadCall); + return 0; + } + +void CVendorSAP::GetData(TDes8& /*aDesc*/,TUint /*aOptions*/,TSockAddr* /*aAddr*/) + { + Panic(EVendorSAPBadCall); + } + +void CVendorSAP::Shutdown(TCloseType aCloseType) + { + if (aCloseType == ENormal) + { + iSocket->CanClose(); + } + } + +void CVendorSAP::Shutdown(TCloseType /*aOption*/,const TDesC8& /*aDisconnectionData*/) + { + Panic(EVendorSAPBadCall); + } +