kernel/eka/drivers/display/display.cpp
changeset 0 a41df078684a
child 31 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\drivers\display\display.cpp  
       
    15 // LDD for a Display driver with GCE support
       
    16 // LDD for a Display driver with GCE support
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file
       
    22  @internalTechnology
       
    23  @prototype
       
    24 */
       
    25 
       
    26 
       
    27 #include <drivers/display.h>
       
    28 #include <kernel/kern_priv.h>
       
    29 
       
    30 
       
    31 
       
    32 static const char KDisplayLddPanic[]="DISPLAY/GCE LDD";
       
    33 
       
    34 
       
    35 /************************************************************************************
       
    36  *            DDisplayLdd LDD class implementation
       
    37  ************************************************************************************/
       
    38 DDisplayLdd::DDisplayLdd()		
       
    39 	{	
       
    40 	__DEBUG_PRINT("DDisplayLdd::DDisplayLdd()\n");
       
    41 	// store the pointer to the current thread for request completion
       
    42   	iClient = &Kern::CurrentThread();
       
    43     __NK_ASSERT_DEBUG(iClient);
       
    44 	// Open a reference on the client thread so it's control block can't disappear until the driver has finished with it.
       
    45     iClient->Open();
       
    46     iCurrentPostCount   = 0;
       
    47     iRequestedPostCount = 0;
       
    48     iCompositionBuffIdx = 0;
       
    49     iUnit				= -1;
       
    50     iThreadOpenCount    = 0;	
       
    51 	}
       
    52 
       
    53 
       
    54 DDisplayLdd::~DDisplayLdd()
       
    55 	{
       
    56 	__DEBUG_PRINT("DDisplayLdd::~DDisplayLdd()  \n"); 
       
    57      // cancel outstanding requests
       
    58     for(TInt k = 0; k < KPendingReqArraySize ; k++)
       
    59     	{
       
    60         if(iPendingReq[k].iStatus)
       
    61         	{
       
    62      		CompleteRequest(iPendingReq[k].iOwningThread,iPendingReq[k].iStatus,KErrCancel);        	
       
    63         	}
       
    64     	}
       
    65     
       
    66     //Close User Buffer chunks not yet destroyed.
       
    67 	for(TInt i = 0; i < KDisplayUBMax; i++)
       
    68 		{
       
    69 		if(iUserBuffer[i].iChunk != 0)
       
    70 			{
       
    71     		Kern::ChunkClose(iUserBuffer[i].iChunk);
       
    72     		iUserBuffer[i].iChunk= NULL;
       
    73 			}
       
    74 		}
       
    75     	
       
    76     Kern::SafeClose((DObject*&)iClient, NULL);  
       
    77     
       
    78     __ASSERT_DEBUG(iThreadOpenCount==0,Kern::Fault(KDisplayLddPanic,__LINE__)); 
       
    79     	
       
    80     // Clear the 'units open mask' in the LDD factory.
       
    81 	if (iUnit>=0)
       
    82 		((DDisplayLddFactory*)iDevice)->SetUnitOpen(iUnit,EFalse);	 	
       
    83 	}
       
    84  
       
    85 
       
    86 /**
       
    87 	LDD second stage constructor
       
    88 */
       
    89 TInt DDisplayLdd::DoCreate(TInt aUnit, const TDesC8* /* anInfo*/, const TVersion& aVer)
       
    90 	{ 
       
    91 	
       
    92 	__DEBUG_PRINT("DDisplayLdd::DoCreate()\n"); 
       
    93 
       
    94 	if(    !Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,      __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
       
    95 		&& !Kern::CurrentThreadHasCapability(ECapabilityReadDeviceData, __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
       
    96 		&& !Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") )
       
    97 		&& !Kern::CurrentThreadHasCapability(ECapabilityProtServ,       __PLATSEC_DIAGNOSTIC_STRING("Checked by DISPLAY.LDD (GCE Driver)") ) )
       
    98 		{
       
    99 		return KErrPermissionDenied;
       
   100 		}
       
   101 		  
       
   102 	// Check that the display driver version specified by the client is compatible.
       
   103 	if (!Kern::QueryVersionSupported(RDisplayChannel::VersionRequired(),aVer))
       
   104 		{
       
   105 		return(KErrNotSupported);		
       
   106 		}
       
   107 				
       
   108 	// Check that a channel hasn't already been opened on this unit.
       
   109 	TInt r=((DDisplayLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
       
   110 	if (r!=KErrNone)
       
   111 		{
       
   112 		return r;
       
   113 		}
       
   114 				   	       
       
   115  	Pdd()->iLdd	= this;
       
   116  	
       
   117  	r		= Pdd()->CreateChannelSetup(aUnit); 	
       
   118  	if ( r!= KErrNone)
       
   119  		{
       
   120  		return r; 		
       
   121  		}
       
   122  
       
   123      // set up user buffer nodes
       
   124     for (TInt node = 0; node < KDisplayUBMax; node++)
       
   125     	{
       
   126         iUserBuffer[node].iType 	= EBufferTypeUser;
       
   127         iUserBuffer[node].iBufferId = (node + 1);
       
   128         iUserBuffer[node].iFree 	= ETrue;
       
   129         iUserBuffer[node].iState 	= EBufferFree;
       
   130         iUserBuffer[node].iAddress  = 0;
       
   131         iUserBuffer[node].iSize  	= 0;
       
   132         iUserBuffer[node].iHandle  	= 0;
       
   133         iUserBuffer[node].iChunk  	= 0;
       
   134         iUserBuffer[node].iOffset 	= 0;
       
   135         iUserBuffer[node].iPendingRequest = 0;
       
   136     	}
       
   137 
       
   138     //Initialise pending queue for asynchronous requests
       
   139     for(int k = 0; k < KPendingReqArraySize; k++) 
       
   140     	{
       
   141       	iPendingReq[k].iStatus = 0;
       
   142       	iPendingReq[k].iOwningThread = 0;
       
   143     	}
       
   144           
       
   145     Pdd()->SetGceMode();	
       
   146 	SetDfcQ(Pdd()->DfcQ(aUnit));	   
       
   147     iMsgQ.Receive();
       
   148     
       
   149     return KErrNone;		
       
   150 }
       
   151 
       
   152 
       
   153 /**
       
   154  * All driver's client requests (synchronous and asynchronous) are sent as
       
   155  * kernel messages by generic kernel to logical channel. This function
       
   156  * catches messages sent by the generic kernel
       
   157  *
       
   158  * @param aMsg KErnel side thread messaging
       
   159  */ 
       
   160 void DDisplayLdd::HandleMsg(TMessageBase* aMsg)
       
   161 	{
       
   162     TThreadMessage& m	= *(TThreadMessage*)aMsg ;
       
   163 	TInt id 			= m.iValue ;
       
   164     DThread* client 	= m.Client();
       
   165 
       
   166     // close message
       
   167     if (id == (TInt)ECloseMsg)
       
   168     	{
       
   169     	//Device specific cleanup operations
       
   170     	Pdd()->CloseMsg();
       
   171     	
       
   172         // cancel outstanding requests
       
   173         for(int k = 0; k < KPendingReqArraySize; k++)
       
   174         	{
       
   175             if(iPendingReq[k].iStatus) 
       
   176             	{
       
   177             	CompleteRequest(iPendingReq[k].iOwningThread,iPendingReq[k].iStatus,KErrCancel);
       
   178             	}
       
   179         	}
       
   180         Pdd()->SetLegacyMode();
       
   181 		m.Complete(KErrNone, EFalse);
       
   182 		return;
       
   183 		}
       
   184     // cancel
       
   185     if (id == KMaxTInt)
       
   186 		{
       
   187 		// DoCancel
       
   188 		TInt req = m.Int0() >> 1;
       
   189 		DoCancel(req);
       
   190 		m.Complete(KErrNone,ETrue);
       
   191     	return;
       
   192 		}
       
   193     // asynchronous request
       
   194 	else if (id < 0)
       
   195 		{
       
   196 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   197 		TInt r = DoRequest(~id,pS,m.Ptr1(),m.Ptr2(), client);
       
   198 		m.Complete(r, ETrue);
       
   199 		}
       
   200     // synchronous request
       
   201 	else
       
   202 		{
       
   203 	   	TInt r = DoControl(id,m.Ptr0(),m.Ptr1(), client);
       
   204 		m.Complete(r,ETrue);
       
   205 		}
       
   206 	} 
       
   207 
       
   208 
       
   209 /**
       
   210 	Cancel outstanding request.
       
   211 	
       
   212 	@param  aReqNumber	Any value from the RDisplayChannel::TRequest enumeration.
       
   213 */
       
   214 void DDisplayLdd::DoCancel(TUint aReqNumber)
       
   215 	{
       
   216       __DEBUG_PRINT2("DDisplayLdd::DoCancel %d\n",aReqNumber);
       
   217 
       
   218        switch (aReqNumber)
       
   219 		 {
       
   220 		 case RDisplayChannel::ECtrlCancelGetCompositionBuffer:
       
   221 		 case RDisplayChannel::ECtrlCancelPostUserBuffer:
       
   222 		 case RDisplayChannel::ECtrlCancelWaitForPost:
       
   223 	        if(iPendingReq[aReqNumber].iStatus)
       
   224 	        	{
       
   225         		CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,KErrCancel);
       
   226         		
       
   227         		iPendingReq[aReqNumber].iStatus 	  = 0;
       
   228         		iPendingReq[aReqNumber].iOwningThread = 0;
       
   229             	}
       
   230 			break;
       
   231 		}	
       
   232 	
       
   233 	}
       
   234 
       
   235 /**
       
   236 	Asynchronous request processing.
       
   237 	
       
   238 	@param aFunction    request function number
       
   239     @param apRqStat     pointer to the user's request status object.
       
   240     @param apArg1       pointer to the 1st parameter
       
   241     @param apArg2       pointer to the 2nd parameter
       
   242 	
       
   243 	@return request scheduling result, system-wide error code.
       
   244 */
       
   245 TInt DDisplayLdd::DoRequest(TInt aReqNumber, TRequestStatus* aRqStat, TAny* aArg1, TAny* aArg2, DThread* aClient)
       
   246 	{	
       
   247     TUint count;
       
   248     TInt pack[2];
       
   249     TInt r 				= KErrNone;
       
   250     TBufferNode* node 	= 0;
       
   251     TInt buffer_id  	= 0;
       
   252         
       
   253     // Open a reference on the client thread while the request is pending so it's control block can't disappear until this driver has finished with it.
       
   254 	r=aClient->Open();
       
   255 	__ASSERT_ALWAYS(r==KErrNone,Kern::Fault(KDisplayLddPanic,__LINE__));
       
   256 #ifdef _DEBUG
       
   257 	__e32_atomic_add_ord32(&iThreadOpenCount, 1);
       
   258 #endif	
       
   259     
       
   260     // check if this request is valid
       
   261     if(aReqNumber >= 0 && aReqNumber <= RDisplayChannel::EReqWaitForPost)
       
   262     	{
       
   263         // cancel outstanding request
       
   264         if(iPendingReq[aReqNumber].iStatus)
       
   265 			{
       
   266             CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,KErrCancel);
       
   267             iPendingReq[aReqNumber].iStatus 	  = 0;
       
   268             iPendingReq[aReqNumber].iOwningThread = 0;
       
   269         	}
       
   270         	
       
   271     	// store request and client
       
   272     	iPendingReq[aReqNumber].iStatus = aRqStat;
       
   273     	iPendingReq[aReqNumber].iOwningThread = aClient;
       
   274     	}
       
   275 
       
   276     switch (aReqNumber)
       
   277 		{
       
   278 	     case RDisplayChannel::EReqGetCompositionBuffer:
       
   279 
       
   280 			if(aArg1 == 0 )
       
   281 	              {
       
   282 	               r = KErrGeneral;
       
   283 	               CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,r);
       
   284 	               iPendingReq[aReqNumber].iStatus 		 = 0;
       
   285 	               iPendingReq[aReqNumber].iOwningThread = 0;
       
   286 	              }			
       
   287 			else
       
   288             	  {	 	
       
   289 	              TInt  index;
       
   290 	              TBool found = EFalse;
       
   291 	              
       
   292 	              for(index =0; index< KDisplayCBMax; index++)
       
   293 		              	{
       
   294 		              	if(iCompositionBuffer[index].iState == EBufferFree || iCompositionBuffer[index].iState == EBufferCompose )
       
   295 							{
       
   296 							__DEBUG_PRINT2("EReqGetCompositionBuffer: Getting iCompositionBuffer[%d] \n", index);
       
   297 
       
   298 			                 iCompositionBuffIdx = index;
       
   299 			                 r = Kern::ThreadRawWrite(aClient, aArg1, &iCompositionBuffIdx, sizeof(TInt), aClient);
       
   300 							 if ( r == KErrNone)
       
   301 								{   
       
   302 								 iCompositionBuffer[iCompositionBuffIdx].iState = EBufferCompose;
       
   303 								 CompleteRequest(iPendingReq[aReqNumber].iOwningThread,iPendingReq[aReqNumber].iStatus,r);
       
   304 								 iPendingReq[aReqNumber].iStatus 	   = 0;
       
   305 								 iPendingReq[aReqNumber].iOwningThread = 0;
       
   306 								 found = ETrue;
       
   307 								 break;
       
   308 								}
       
   309 							 }
       
   310 		              	}				
       
   311 				  if(!found)  	//There are no free buffers schedule request for completion
       
   312 					 	{	
       
   313 						//Case of a single composition buffer. 
       
   314 						if (iDisplayInfo.iNumCompositionBuffers == 1)
       
   315 							{
       
   316 							iCompositionBuffIdx = 0;
       
   317 			             	 r = Kern::ThreadRawWrite(aClient, aArg1, &iCompositionBuffIdx, sizeof(TInt), aClient);
       
   318 		                     __DEBUG_PRINT("EReqGetCompositionBuffer  The single Composition buffer is currently being used\n");
       
   319 		                     break;													
       
   320 							}
       
   321 								
       
   322 				 	 
       
   323 		              	for( index=0; index< KDisplayCBMax; index++)
       
   324 			                 {
       
   325 			                 if(iCompositionBuffer[index].iState == EBufferActive)
       
   326 								 {	
       
   327 		                         iCompositionBuffIdx = index;
       
   328 			                  	 r = Kern::ThreadRawWrite(aClient, aArg1,&iCompositionBuffIdx, sizeof(TInt), aClient);
       
   329 			                     __DEBUG_PRINT2("EReqGetCompositionBuffer  No composition buffer available. Next available is iCompositionBuffIdx  %d.\n",iCompositionBuffIdx );
       
   330 			                     break;
       
   331 								 }
       
   332 			                 }
       
   333 				 	 	}			 	 		
       
   334 	            }
       
   335           	break;
       
   336 
       
   337          case RDisplayChannel::EReqPostUserBuffer:			
       
   338             r= Kern::ThreadRawRead(aClient, aArg1, &pack, (sizeof(TInt)*2));
       
   339 			if ( r == KErrNone)
       
   340 				{
       
   341 				r = KErrArgument;
       
   342 	            buffer_id = pack[0];
       
   343 	            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
       
   344 	             	{
       
   345 	                node = FindUserBufferNode(buffer_id);
       
   346 	                if(node  && (!(node->iFree) && node->iChunk ) ) 
       
   347 	                	{
       
   348 	                  	__DEBUG_PRINT2("EReqPostUserBuffer Posting buffer id: %d \n",buffer_id );
       
   349 	                  	r = Pdd()->PostUserBuffer(node);
       
   350 	                  	if(r == KErrNone)
       
   351 		                  	 {
       
   352 		     		    	 ++iCurrentPostCount;
       
   353 		                	 r=Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);	           		     
       
   354 		           		     break;
       
   355 		                  	 }
       
   356 	                	}
       
   357 	             	}
       
   358 	            RequestComplete(RDisplayChannel::EReqPostUserBuffer,  r); 
       
   359 				}
       
   360             break; 	        
       
   361 
       
   362          case RDisplayChannel::EReqWaitForPost:
       
   363             r= Kern::ThreadRawRead(aClient, aArg1,  &count, sizeof(RDisplayChannel::TPostCount));
       
   364 			if ( r == KErrNone)
       
   365 				{   
       
   366 			    iRequestedPostCount = count;
       
   367 	    	    //Any post operation increases iCurrentPostCount instantly but the actual post completes later on.
       
   368 	    	    if( ! Pdd()->PostPending() )
       
   369 	    	    	 {
       
   370 	    	    	 RequestComplete(RDisplayChannel::EReqWaitForPost,  KErrNone);
       
   371 	    	    	 } 
       
   372 				}	 
       
   373          	break;
       
   374 
       
   375         default:
       
   376 			r = KErrNotSupported;
       
   377 			break;
       
   378 		}
       
   379     return r;	
       
   380 	}
       
   381 
       
   382 
       
   383 /**
       
   384 	Synchronous requests processing.
       
   385 	
       
   386 	@param aFunction    request function number,
       
   387 	@param apArg1       pointer to the 1st parameter
       
   388 	@param apArg2       pointer to the 2n parameter
       
   389     
       
   390     @return request processing result
       
   391 */
       
   392 TInt DDisplayLdd::DoControl(TInt aFunction, TAny* aArg1, TAny* aArg2, DThread* aClient)
       
   393  {
       
   394 	TInt r 			  = KErrNotSupported;
       
   395     TBool changedRot  = ETrue;
       
   396     TBufferNode* node = 0;
       
   397 	TInt buffer_id;
       
   398     TInt pack[2]      = {0,0};
       
   399     TInt handle, offset;
       
   400     TInt index        = 0;
       
   401 
       
   402     TPckgBuf<RDisplayChannel::TDisplayInfo> pckgInfo(iDisplayInfo);
       
   403 
       
   404     switch (aFunction)
       
   405 		{
       
   406 	    case RDisplayChannel::ECtrlGetDisplayInfo:
       
   407             r=Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&pckgInfo, sizeof(pckgInfo), aClient);
       
   408     	    break;
       
   409 
       
   410 	    case RDisplayChannel::ECtrlPostCompositionBuffer:
       
   411 	        node =  &iCompositionBuffer[iCompositionBuffIdx];
       
   412             r = Pdd()->PostCompositionBuffer(node);
       
   413 		    if(r == KErrNone)
       
   414 		    	{
       
   415     		    ++iCurrentPostCount;
       
   416                 r=Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);
       
   417     			}
       
   418             else 
       
   419             	{
       
   420             	r = KErrGeneral;	
       
   421             	}            	    	            	
       
   422 			break;
       
   423 
       
   424         case RDisplayChannel::ECtrlPostLegacyBuffer:
       
   425             r= Pdd()->PostLegacyBuffer();
       
   426             if ( r == KErrNone)
       
   427             	{
       
   428              	++iCurrentPostCount;
       
   429             	r = Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&iCurrentPostCount, sizeof(RDisplayChannel::TPostCount), aClient);           	
       
   430             	}            
       
   431 			break;
       
   432 
       
   433 	    case RDisplayChannel::ECtrlRegisterUserBuffer:
       
   434             node = FindUserBufferNode(0);
       
   435 			if(node)
       
   436 				{
       
   437                 r= Kern::ThreadRawRead(aClient, aArg1, &pack, (sizeof(TInt)*2));
       
   438 				if(r == KErrNone)
       
   439 					{
       
   440 	                handle  = pack[0]; 
       
   441 	                offset  = pack[1];
       
   442 	                r 		= CheckAndOpenUserBuffer(node, handle, offset, aClient);
       
   443 	                
       
   444 	                if(r == KErrNone)
       
   445 	                	{
       
   446 	                     r= Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&node->iBufferId, sizeof(TInt), aClient);
       
   447 	                	}
       
   448 					}
       
   449 				}
       
   450             else
       
   451             	{
       
   452     			r = KErrTooBig;
       
   453             	}
       
   454 			break;
       
   455 
       
   456 	    case RDisplayChannel::ECtrlDeregisterUserBuffer:
       
   457             r= Kern::ThreadRawRead(aClient, aArg1, &buffer_id, sizeof(TInt));
       
   458             if ( r == KErrNone)
       
   459 				{
       
   460 				r = KErrArgument;          
       
   461 	            if ( (buffer_id > 0) && (buffer_id <= KDisplayUBMax) )
       
   462 	            	{
       
   463 		            node = FindUserBufferNode(buffer_id);	            
       
   464 		            if(node  && (!(node->iFree) && node->iChunk ) ) 
       
   465 		            	{	                
       
   466 		                if(node->iState==EBufferFree  || node->iState==EBufferCompose )
       
   467 		                	{
       
   468 		                	r = FreeUserBufferNode(node);	                	
       
   469 		                	}
       
   470 		                else
       
   471 		                	{
       
   472 		                	r = KErrInUse;
       
   473 		                	}
       
   474 		            	}               	                                    
       
   475 	            	}
       
   476 				}
       
   477 			break;
       
   478 
       
   479 	    case RDisplayChannel::ECtrlPostCount:
       
   480             r= Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&iCurrentPostCount, sizeof(TUint), aClient);
       
   481 			break;
       
   482 
       
   483 	    case RDisplayChannel::ECtrlSetRotation:	    
       
   484 	    	{	    			    
       
   485             RDisplayChannel::TDisplayRotation rot;
       
   486             TInt previousRot = iCurrentRotation;
       
   487             r= Kern::ThreadRawRead(aClient, aArg1, &rot, sizeof(RDisplayChannel::TDisplayRotation));
       
   488             if ( r == KErrNone)
       
   489 				{               	
       
   490                 r = Pdd()->SetRotation((TInt)rot);                  
       
   491                 changedRot=(previousRot!=iCurrentRotation);              
       
   492                 if( r == KErrNone)
       
   493         	        {
       
   494                    	 r= Kern::ThreadRawWrite(aClient, aArg2, (const TAny *)&changedRot, sizeof(TBool), aClient);                       
       
   495                	    }
       
   496 				}
       
   497 	    	}
       
   498     	    break;
       
   499 
       
   500 	    case RDisplayChannel::ECtrlCurrentRotation:
       
   501 			r=Kern::ThreadRawWrite(aClient, aArg1, (const TAny *)&iCurrentRotation, sizeof(RDisplayChannel::TDisplayRotation), aClient);
       
   502 			break;
       
   503 
       
   504 	    case RDisplayChannel::ECtrlGetCompositionBufferInfo:
       
   505     	    {
       
   506             r= Kern::ThreadRawRead(aClient, aArg1, &index, sizeof(TInt));                     
       
   507             if ( r == KErrNone)
       
   508 				{   
       
   509 				if( (index >= KDisplayCBMax ) || (index < 0 ) )
       
   510 	            	{
       
   511 	            	r = KErrArgument;
       
   512 	            	break;	
       
   513 	            	}
       
   514 				r = Kern::MakeHandleAndOpen(aClient, iCompositionBuffer[index].iChunk);
       
   515 
       
   516 				if(r >= KErrNone)
       
   517 					{
       
   518 					pack[0] = r;
       
   519 					pack[1] = iCompositionBuffer[index].iOffset;
       
   520 					r=Kern::ThreadRawWrite(aClient, aArg2, &pack, (sizeof(TInt)*2), aClient);
       
   521 					}
       
   522 				}	
       
   523 		 	break;
       
   524 			}
       
   525     	   
       
   526         default:
       
   527 			r = KErrNotSupported;
       
   528 			break;
       
   529 		};
       
   530     return r;	
       
   531 	}
       
   532 
       
   533 
       
   534 /**
       
   535     Open a shared Chunk for the User buffer and then set the appropriate values for the
       
   536     User buffer node attributes.
       
   537 	
       
   538 */
       
   539 TInt DDisplayLdd::CheckAndOpenUserBuffer(TBufferNode* aNode, TInt aHandle, TInt aOffset, DThread* aClient)
       
   540  {
       
   541  
       
   542   TInt     	size 				= 0;
       
   543   DChunk*  	chunk 				= 0;
       
   544   TLinAddr 	kernelAddress 		= 0;
       
   545   TUint32  	mapAttr 			= 0;
       
   546   TUint32  	physicalAddress 	= 0;
       
   547   TUint32  	*physicalPageList 	= 0;
       
   548   TInt 		r 					= KErrBadHandle;
       
   549 	
       
   550   NKern::ThreadEnterCS();
       
   551   chunk = Kern::OpenSharedChunk(aClient, aHandle, EFalse);
       
   552   NKern::ThreadLeaveCS();
       
   553   if(chunk)
       
   554 		{
       
   555 		// Using iOffsetBetweenLines rather than iWidth as the controller may be using stride
       
   556 		size = iDisplayInfo.iNormal.iOffsetBetweenLines * iDisplayInfo.iNormal.iHeight;
       
   557                 
       
   558         r = Kern::ChunkPhysicalAddress(chunk, aOffset, size, kernelAddress, mapAttr, physicalAddress, physicalPageList);
       
   559         if( r == KErrNone )
       
   560         	{
       
   561             aNode->iChunk 			= chunk;
       
   562             aNode->iFree  			= EFalse;
       
   563             aNode->iState 			= EBufferCompose;
       
   564             aNode->iAddress 		= (TUint32)kernelAddress;
       
   565             aNode->iHandle 			= aHandle;
       
   566             aNode->iPhysicalAddress = physicalAddress;
       
   567         	}
       
   568         else
       
   569         	{ // we have an error here, close the chunk
       
   570         	r = KErrArgument;  
       
   571             Kern::ChunkClose(chunk);
       
   572         	}
       
   573     }
       
   574   return (r);
       
   575   }
       
   576 
       
   577 
       
   578 /**
       
   579     Return any free buffer when trying to register a User buffer( aBufferId ==0 )
       
   580     or return the specified User buffer( used by Deregister and PostUserBuffer).
       
   581     In the second case checks about the state of the user buffer are specific to 
       
   582     each case. 
       
   583     
       
   584 */
       
   585 TBufferNode* DDisplayLdd::FindUserBufferNode(TInt aBufferId)
       
   586 	{
       
   587     TBufferNode* node = 0;
       
   588 
       
   589     if(aBufferId == 0)
       
   590 		{
       
   591 		for(TInt i = 0; i < KDisplayUBMax; i++)
       
   592 			{
       
   593 			if(iUserBuffer[i].iFree)
       
   594 				{
       
   595 				node = &iUserBuffer[i];
       
   596 				break;
       
   597 				}
       
   598 			}
       
   599 		}
       
   600 	else
       
   601 		{		 
       
   602 		 node = &iUserBuffer[aBufferId-1];
       
   603 		}
       
   604     return (node);
       
   605 	}
       
   606 
       
   607 
       
   608 /**
       
   609     Free user buffer by reseting all the appropriate fields and closing the corresponding chunk.
       
   610 */ 
       
   611 TInt DDisplayLdd::FreeUserBufferNode(TBufferNode* aNode)
       
   612 	{
       
   613 	__DEBUG_PRINT2("FreeUserBufferNode with aNode->iAddress %08x.\n",aNode->iAddress );
       
   614 	TInt r = KErrNone;
       
   615 	NKern::ThreadEnterCS();
       
   616     if(aNode->iChunk != 0)
       
   617     	{
       
   618     	r= Kern::ChunkClose(aNode->iChunk);
       
   619     	}    	
       
   620     if( r== KErrNone)
       
   621     	{
       
   622     	aNode->iState 	= EBufferFree;
       
   623     	aNode->iFree 	= ETrue;
       
   624     	aNode->iAddress = 0;
       
   625     	aNode->iSize 	= 0;
       
   626     	aNode->iHandle 	= 0;
       
   627     	aNode->iChunk 	= 0;
       
   628     	}
       
   629     else
       
   630     	{
       
   631     	__DEBUG_PRINT("Failed to close chunk\n");    	
       
   632     	}
       
   633 	NKern::ThreadLeaveCS();	
       
   634     
       
   635     return r;
       
   636 	}	
       
   637 
       
   638 
       
   639 /**    
       
   640    Calls CompleteRequest( which internally sends a Kern::RequestComplete message )for the specified request and with the reason passed, 
       
   641    in case such an asynchronous request is pending. Also resets the pending queue fields for that request if it was actually pending. 
       
   642    Called by both the LDD and PDD.
       
   643    
       
   644 */ 
       
   645 TInt DDisplayLdd::RequestComplete(TInt aRequest, TInt aReason)
       
   646 	{
       
   647 	TBool flag = EFalse;
       
   648 			
       
   649 	switch (aRequest)
       
   650 		{
       
   651 	    case RDisplayChannel::EReqGetCompositionBuffer:	
       
   652 			{
       
   653 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqGetCompositionBuffer request and reason %d\n",aReason );
       
   654 			
       
   655 	        if(iPendingReq[RDisplayChannel::EReqGetCompositionBuffer].iStatus)
       
   656 				{
       
   657 				__DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqGetCompositionBuffer \n");
       
   658 	            flag = ETrue;
       
   659 	        	}
       
   660 	        break;											
       
   661 			}
       
   662 
       
   663 		 case RDisplayChannel::EReqWaitForPost:		        
       
   664 			{
       
   665 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqWaitForPost request and reason %d\n",aReason );
       
   666 			
       
   667 	 		if((iPendingReq[RDisplayChannel::EReqWaitForPost].iStatus != 0) && (iCurrentPostCount >= iRequestedPostCount) )
       
   668 	    	    {
       
   669 	    	    __DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqWaitForPost \n");
       
   670 				flag = ETrue;
       
   671 	            }
       
   672 	        break;    												
       
   673 			}
       
   674  		
       
   675 		case RDisplayChannel::EReqPostUserBuffer:	
       
   676 			{
       
   677 			__DEBUG_PRINT2("RequestComplete() called with a RDisplayChannel::EReqPostUserBuffer request and reason %d\n",aReason );
       
   678 				
       
   679 			if((iPendingReq[RDisplayChannel::EReqPostUserBuffer].iStatus != 0) )
       
   680 	    		{
       
   681 	    	    __DEBUG_PRINT("RequestComplete(): Calling CompleteRequest EReqPostUserBuffer \n");
       
   682 				flag = ETrue;
       
   683 	            }
       
   684 	        break;			
       
   685 			}
       
   686 		default:
       
   687 			__DEBUG_PRINT("RequestComplete() called for an unknown request\n");
       
   688 			return KErrGeneral;
       
   689 		
       
   690 		}
       
   691 		
       
   692 	if (flag)
       
   693 		{
       
   694 		CompleteRequest(iPendingReq[aRequest].iOwningThread,iPendingReq[aRequest].iStatus,aReason);
       
   695 		iPendingReq[aRequest].iStatus 		= 0;
       
   696 		iPendingReq[aRequest].iOwningThread = 0;			
       
   697 		}
       
   698 				
       
   699 	return KErrNone;	
       
   700 	}
       
   701 
       
   702 
       
   703 /** 
       
   704 Complete an asynchronous request back to the client.
       
   705 @param aThread The client thread which issued the request.
       
   706 @param aStatus The TRequestStatus instance that will receive the request status code. 
       
   707 @param aReason The request status code.  
       
   708 @pre The thread must be in a critical section. 
       
   709 */
       
   710 void DDisplayLdd::CompleteRequest(DThread* aThread, TRequestStatus*& aStatus, TInt aReason)
       
   711 	{		
       
   712 	Kern::RequestComplete(aThread,aStatus,aReason);		// Complete the request back to the client.
       
   713 	
       
   714 	aThread->AsyncClose();	// Asynchronously close our reference on the client thread - don't want to be blocked if this is final reference. 
       
   715 
       
   716 #ifdef _DEBUG	
       
   717 	__e32_atomic_add_ord32(&iThreadOpenCount, TUint32(-1));
       
   718 #endif	
       
   719 			
       
   720 	}
       
   721 
       
   722 
       
   723 
       
   724 /**
       
   725 	static factory function for the LDD.
       
   726 	
       
   727 	@return pointer to the created (or existing) instance of the class
       
   728 */
       
   729 DDisplayLdd* DDisplayLdd::CreateInstance()
       
   730 	{
       
   731 	__DEBUG_PRINT("DDisplayLdd::CreateInstance()\n");
       
   732 	 // create LDD channel instance
       
   733     DDisplayLdd* obj = new DDisplayLdd();
       
   734     return obj;
       
   735 	
       
   736 	}
       
   737 
       
   738 
       
   739 /************************************************************************************
       
   740  *            LDD factory, DDisplayLddFactory class implementation
       
   741  ************************************************************************************/
       
   742  
       
   743 /**
       
   744 	Constructor
       
   745 */  
       
   746 DDisplayLddFactory::DDisplayLddFactory()
       
   747 	{
       
   748 	__DEBUG_PRINT("DDisplayLddFactory::DDisplayLddFactory() \n");
       
   749 	
       
   750 	iParseMask 	= KDeviceAllowPhysicalDevice | KDeviceAllowUnit ;
       
   751 	
       
   752     iVersion	= TVersion( KDisplayChMajorVersionNumber,
       
   753                       	    KDisplayChMinorVersionNumber,
       
   754                       	    KDisplayChBuildVersionNumber);
       
   755                       	    
       
   756 	iUnitsOpenMask =0;                      	    
       
   757 	}
       
   758 
       
   759 
       
   760 /**
       
   761     Destructor
       
   762 */
       
   763 DDisplayLddFactory::~DDisplayLddFactory()
       
   764 	{
       
   765 	}
       
   766 
       
   767 
       
   768 /**
       
   769 	static factory function for the LDD factory.
       
   770 	
       
   771 	@return pointer to the created instance of the class
       
   772 */
       
   773 DDisplayLddFactory* DDisplayLddFactory::CreateInstance()
       
   774 
       
   775 	{
       
   776 	__DEBUG_PRINT("DDisplayLddFactory::CreateInstance() \n");
       
   777 	 
       
   778 	 DDisplayLddFactory* obj = new DDisplayLddFactory;
       
   779     return obj;
       
   780 	}
       
   781 
       
   782 
       
   783 /**
       
   784     Set our name and return error code
       
   785 */
       
   786 TInt DDisplayLddFactory::Install()
       
   787 
       
   788 	{
       
   789 	__DEBUG_PRINT("DDisplayLddFactory::Install() \n");
       
   790     return SetName(&RDisplayChannel::Name());
       
   791 	}
       
   792 
       
   793 
       
   794 void DDisplayLddFactory::GetCaps(TDes8& /*aDes*/) const
       
   795 
       
   796 	{
       
   797 	//No action.
       
   798 	}
       
   799 
       
   800 
       
   801 /**
       
   802 	LDD factory function. Creates LDD object.
       
   803 	
       
   804 	@param  aChannel  A pointer to an LDD channel object which will be initialised on return.
       
   805 	
       
   806 	@return KErrNone  if object successfully allocated, KErrNoMemory if not.			
       
   807 */
       
   808 TInt DDisplayLddFactory::Create(DLogicalChannelBase*& aChannel)
       
   809 	{
       
   810 	__DEBUG_PRINT("DDisplayLddFactory::Create \n");
       
   811     aChannel = DDisplayLdd::CreateInstance();
       
   812     return (!aChannel)? KErrNoMemory : KErrNone;
       
   813 	}
       
   814 
       
   815 
       
   816 
       
   817 /**
       
   818 Check whether a channel is currently open on the specified unit.
       
   819 @param aUnit The number of the unit to be checked.
       
   820 @return ETrue if a channel is open on the specified channel, EFalse otherwise.
       
   821 @pre The unit info. mutex must be held.
       
   822 */
       
   823 TBool DDisplayLddFactory::IsUnitOpen(TInt aUnit)
       
   824 	{
       
   825 	return(iUnitsOpenMask&(1<<aUnit));
       
   826 	}
       
   827 
       
   828 
       
   829 /**
       
   830 Attempt to change the state of the channel open status for a particular channel.
       
   831 @param aUnit The number of the unit to be updated.
       
   832 @param aIsOpenSetting The required new state for the channel open status: either ETrue to set the status to open or 
       
   833 	EFalse to set the status to closed.
       
   834 @return KErrNone if the status was updated successfully, KErrInUse if an attempt has been made to set the channnel status
       
   835 	to open while it is already open.
       
   836 */		
       
   837 TInt DDisplayLddFactory::SetUnitOpen(TInt aUnit,TBool aIsOpenSetting)
       
   838 	{
       
   839 		
       
   840 	NKern::FMWait(&iUnitInfoMutex); // Acquire the unit info. mutex.
       
   841 		
       
   842 	// Fail a request to open an channel that is already open
       
   843 	if (aIsOpenSetting && IsUnitOpen(aUnit))
       
   844 		{
       
   845 		NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
       
   846 		return(KErrInUse);
       
   847 		}
       
   848 	
       
   849 	// Update the open status as requested
       
   850 	if (aIsOpenSetting)
       
   851 		iUnitsOpenMask|=(1<<aUnit);
       
   852 	else
       
   853 		iUnitsOpenMask&=~(1<<aUnit);
       
   854 	
       
   855 	NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.	
       
   856 	return(KErrNone);
       
   857 	}
       
   858 
       
   859 
       
   860 /**
       
   861 	"Standard LDD" entrypoint.
       
   862 	
       
   863 	Is called on CreateLogicalDevice() if the user calls LoadLogicalDevice(). Creates LDD factory.
       
   864 	
       
   865 	@return pointer to the LDD factory object.
       
   866 */
       
   867 DECLARE_STANDARD_LDD()
       
   868 	{
       
   869 	__DEBUG_PRINT("DECLARE_STANDARD_LDD() \n");
       
   870      DDisplayLddFactory* pLDDFactory = DDisplayLddFactory::CreateInstance();
       
   871     return  pLDDFactory;
       
   872 	}
       
   873 
       
   874 
       
   875 
       
   876