--- a/kernel/eka/drivers/usbcsc/d_usbcsc.cpp Wed Jun 23 12:58:21 2010 +0100
+++ b/kernel/eka/drivers/usbcsc/d_usbcsc.cpp Thu Jul 01 17:57:33 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2000-2010 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
@@ -98,7 +98,6 @@
TUsbcScChunkInfo::TUsbcScChunkInfo(DLogicalDevice* aLdd)
: iChunk(NULL),
- iCleanup((TDfcFn)&DfcChunkCleanup,this,Kern::SvMsgQue(),0),
iChunkMem(NULL),
iLdd(aLdd)
{
@@ -121,7 +120,7 @@
chunkInfo.iMaxSize = aTotalSize;
chunkInfo.iMapAttr = EMapAttrCachedMax;
chunkInfo.iOwnsMemory = EFalse;
- chunkInfo.iDestroyedDfc = &iCleanup;
+ chunkInfo.iDestroyedDfc = NULL;
TLinAddr chunkMem;
r = Kern::ChunkCreate(chunkInfo, iChunk, chunkMem, iChunkMapAttr);
@@ -138,7 +137,14 @@
// Note that nothing may happen immediately, as something else may have the chunk open.
void TUsbcScChunkInfo::Close()
{
- Kern::ChunkClose(iChunk);
+ __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::Close %d", iChunk->AccessCount()));
+
+ if (Kern::ChunkClose(iChunk))
+ {
+ __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::Close1"));
+ ChunkCleanup();
+ __KTRACE_OPT(KUSB, Kern::Printf("TUsbcScChunkInfo::Close2"));
+ }
}
@@ -342,6 +348,19 @@
}
}
+
+TBool TUsbcScBuffer::IsRequestPending()
+ {
+ return iStatusList.IsRequestPending();
+ }
+
+TBool TUsbcScStatusList::IsRequestPending()
+ {
+ return (iLength != 0);
+ }
+
+
+
/*
TUsbcScBuffer::StartEndpoint
@@ -881,6 +900,13 @@
iHead = ((iHead+1) & (iSize-1));
}
+
+void TUsbcScStatusList::SetClient(DThread& aThread)
+ {
+ iClient = &aThread;
+ }
+
+
// End TUsbcScStatusList
/*****************************************************************************\
@@ -1240,12 +1266,14 @@
if (iRealizeCalled)
{
// Close Chunk
+ __KTRACE_OPT(KUSB, Kern::Printf("iChunkInfo->Close()"));
iChunkInfo->Close();
// ChunkInfo will delete itself with DFC, but the pointer here is no longer needed.
iChunkInfo=NULL;
}
__KTRACE_OPT(KUSB, Kern::Printf("about to SafeClose"));
Kern::SafeClose((DObject*&)iClient, NULL);
+ __KTRACE_OPT(KUSB, Kern::Printf("about to SafeClose1"));
}
@@ -1326,6 +1354,13 @@
}
TInt r;
+
+ if (aMsg->Client() != iClient)
+ {
+ m.Complete(KErrAccessDenied, ETrue);
+ return;
+ }
+
if (id < 0)
{
// DoRequest
@@ -2255,18 +2290,50 @@
TInt DLddUsbcScChannel::RequestUserHandle(DThread* aThread, TOwnerType /*aType*/)
{
__KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::RequestUserHandle"));
- // The USB client LDD is not designed for a channel to be shared between
- // threads. It saves a pointer to the current thread when it is opened, and
- // uses this to complete any asynchronous requests.
- // It is therefore not acceptable for the handle to be duplicated and used
- // by another thread:
+ // The USB client LDD can share across process, but can't use simultanously.
+ // This mean if transfer the handle to another process, can't access this channel
+ // in the origin process and any call to the channel will return with KErrAccessDenied.
+ // If there is async request scheduled, can't transfer channel handle to another process
+ // and return KErrAccessDenied.
if (aThread == iClient)
{
return KErrNone;
}
else
{
- return KErrAccessDenied;
+ //check if async request has been called
+ for (TInt i = 1; i < KUsbcMaxRequests; i++)
+ {
+ if (iRequestStatus[i] != NULL)
+ {
+ return KErrAccessDenied;
+ }
+ }
+
+ if (iBuffers)
+ {
+ for (TInt i=0; i<(iNumBuffers+2); i++)
+ {
+ if (iBuffers[i].IsRequestPending())
+ {
+ return KErrAccessDenied;
+ }
+ }
+ }
+
+
+ Kern::SafeClose((DObject*&)iClient, NULL);
+ iClient = aThread;
+ iClient->Open();
+ if (iBuffers)
+ {
+ for (TInt i=0; i<(iNumBuffers+2); i++)
+ {
+ iBuffers[i].iStatusList.SetClient(*iClient);
+ }
+ }
+ __KTRACE_OPT(KUSB, Kern::Printf("DLddUsbcScChannel::handle %d", iChunkInfo->iChunk->AccessCount()));
+ return KErrNone;
}
}