44
+ − 1
// Copyright (c) 2008-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/camerasc/cameraldd.cpp
+ − 15
//
+ − 16
//
+ − 17
+ − 18
#include <drivers/camerasc.h>
+ − 19
#include <kernel/kern_priv.h>
+ − 20
#include <kernel/cache.h>
+ − 21
+ − 22
//#define __KTRACE_CAM(s) s;
+ − 23
#define __KTRACE_CAM(s)
+ − 24
+ − 25
#define DISCARD_COMPLETED_TO_AVOID_OVERFLOW
+ − 26
+ − 27
static const char KCameraLddPanic[]="CameraSc LDD";
+ − 28
+ − 29
/**
+ − 30
Standard export function for LDDs. This creates a DLogicalDevice derived object,
+ − 31
in this case, DSoundScLddFactory.
+ − 32
*/
+ − 33
DECLARE_STANDARD_LDD()
+ − 34
{
+ − 35
return new DCameraScLddFactory;
+ − 36
}
+ − 37
+ − 38
/**
+ − 39
Constructor for the camera driver factory class.
+ − 40
*/
+ − 41
DCameraScLddFactory::DCameraScLddFactory()
+ − 42
{
+ − 43
// iUnitsOpenMask=0;
+ − 44
+ − 45
__KTRACE_CAM(Kern::Printf(">DCameraScLddFactory::DCameraScLddFactory"));
+ − 46
+ − 47
// Set version number for this device.
+ − 48
iVersion=RDevCameraSc::VersionRequired();
+ − 49
+ − 50
// Indicate that units / PDD are supported.
+ − 51
iParseMask=KDeviceAllowUnit|KDeviceAllowPhysicalDevice;
+ − 52
+ − 53
// Leave the units decision to the PDD
+ − 54
iUnitsMask=0xffffffff;
+ − 55
}
+ − 56
+ − 57
/**
+ − 58
Second stage constructor for the camera driver factory class.
+ − 59
This must at least set a name for the driver object.
+ − 60
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 61
*/
+ − 62
TInt DCameraScLddFactory::Install()
+ − 63
{
+ − 64
return(SetName(&KDevCameraScName));
+ − 65
}
+ − 66
+ − 67
/**
+ − 68
Return the 'capabilities' of the camera driver in general.
+ − 69
Called in the response to an RDevice::GetCaps() request.
+ − 70
@param aDes A user-side descriptor to write the capabilities information into.
+ − 71
*/
+ − 72
void DCameraScLddFactory::GetCaps(TDes8 &aDes) const
+ − 73
{
+ − 74
// Create a capabilities object
+ − 75
TCapsDevCameraV01 caps;
+ − 76
caps.iVersion=iVersion;
+ − 77
+ − 78
// Write it back to user memory
+ − 79
Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
+ − 80
}
+ − 81
+ − 82
/**
+ − 83
Called by the kernel's device driver framework to create a logical channel.
+ − 84
This is called in the context of the client thread which requested the creation of a logical
+ − 85
channel - through a call to RBusLogicalChannel::DoCreate().
+ − 86
The thread is in a critical section.
+ − 87
@param aChannel Set by this function to point to the created logical channel.
+ − 88
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 89
*/
+ − 90
TInt DCameraScLddFactory::Create(DLogicalChannelBase*& aChannel)
+ − 91
{
+ − 92
__KTRACE_CAM(Kern::Printf(">DCameraScLddFactory::Create"));
+ − 93
+ − 94
aChannel=new DCameraScLdd;
+ − 95
if (!aChannel)
+ − 96
return(KErrNoMemory);
+ − 97
+ − 98
return(KErrNone);
+ − 99
}
+ − 100
+ − 101
/**
+ − 102
Check whether a channel has is currently open on the specified unit.
+ − 103
@param aUnit The number of the unit to be checked.
+ − 104
@return ETrue if a channel is open on the specified channel, EFalse otherwise.
+ − 105
@pre The unit info. mutex must be held.
+ − 106
*/
+ − 107
TBool DCameraScLddFactory::IsUnitOpen(TInt aUnit)
+ − 108
{
+ − 109
return(iUnitsOpenMask&(1<<aUnit));
+ − 110
}
+ − 111
+ − 112
/**
+ − 113
Attempt to change the state of the channel open status for a particular channel.
+ − 114
@param aUnit The number of the unit to be updated.
+ − 115
@param aIsOpenSetting The required new state for the channel open status: either ETrue to set the status to open or
+ − 116
EFalse to set the status to closed.
+ − 117
@return KErrNone if the status was updated successfully;
+ − 118
KErrInUse if an attempt has been made to set the channnel status to open while it is already open.
+ − 119
*/
+ − 120
TInt DCameraScLddFactory::SetUnitOpen(TInt aUnit,TBool aIsOpenSetting)
+ − 121
{
+ − 122
NKern::FMWait(&iUnitInfoMutex); // Acquire the unit info. mutex.
+ − 123
+ − 124
// Fail a request to open an channel that is already open
+ − 125
if (aIsOpenSetting && IsUnitOpen(aUnit))
+ − 126
{
+ − 127
NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
+ − 128
return(KErrInUse);
+ − 129
}
+ − 130
+ − 131
// Update the open status as requested
+ − 132
if (aIsOpenSetting)
+ − 133
iUnitsOpenMask|=(1<<aUnit);
+ − 134
else
+ − 135
iUnitsOpenMask&=~(1<<aUnit);
+ − 136
+ − 137
NKern::FMSignal(&iUnitInfoMutex); // Release the unit info. mutex.
+ − 138
return(KErrNone);
+ − 139
}
+ − 140
+ − 141
/**
+ − 142
Constructor for the camera driver logical channel.
+ − 143
*/
+ − 144
DCameraScLdd::DCameraScLdd()
+ − 145
: iRequestQueue(&iMutex),
+ − 146
iRestartDfc(DCameraScLdd::RestartDfc,this,5),
+ − 147
iPowerDownDfc(DCameraScLdd::PowerDownDfc,this,3),
+ − 148
iPowerUpDfc(DCameraScLdd::PowerUpDfc,this,3)
+ − 149
{
+ − 150
iState=EOpen;
+ − 151
// iCaptureMode=ECaptureModeImage;
+ − 152
// iFrameHeight=0;
+ − 153
// iFrameWidth=0;
+ − 154
// iBufManager=NULL;
+ − 155
// iPowerHandler=NULL;
+ − 156
// iImageGatherCount=0;
+ − 157
+ − 158
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DCameraScLdd"));
+ − 159
+ − 160
iUnit=-1; // Invalid unit number
+ − 161
+ − 162
// Get pointer to client thread's DThread object
+ − 163
iOwningThread=&Kern::CurrentThread();
+ − 164
+ − 165
// Open a reference on client thread so it's control block can't dissapear until
+ − 166
// this driver has finished with it. Note, this call to Open() can't fail since
+ − 167
// it is the thread we are currently running in
+ − 168
iOwningThread->Open();
+ − 169
}
+ − 170
+ − 171
/**
+ − 172
Destructor for the camera driver logical channel.
+ − 173
This is called in the context of the client thread once a 'ECloseMsg' message has been
+ − 174
sent to the device driver DFC thread.
+ − 175
*/
+ − 176
DCameraScLdd::~DCameraScLdd()
+ − 177
{
+ − 178
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::~DCameraScLdd"));
+ − 179
+ − 180
TInt captureMode;
+ − 181
+ − 182
// Remove and delete the power handler.
+ − 183
if (iPowerHandler)
+ − 184
{
+ − 185
iPowerHandler->Remove();
+ − 186
delete iPowerHandler;
+ − 187
}
+ − 188
+ − 189
if (iCaptureModeConfig)
+ − 190
{
+ − 191
// Delete any buffers and shared chunk we created.
+ − 192
for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
+ − 193
{
+ − 194
if (iCaptureModeConfig[captureMode].iBufManager)
+ − 195
delete iCaptureModeConfig[captureMode].iBufManager;
+ − 196
}
+ − 197
+ − 198
// Delete the buffer config. info. structure.
+ − 199
for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
+ − 200
{
+ − 201
if (iCaptureModeConfig[captureMode].iBufConfig)
+ − 202
Kern::Free(iCaptureModeConfig[captureMode].iBufConfig);
+ − 203
}
+ − 204
+ − 205
if (iCaptureModeConfig)
+ − 206
delete[] iCaptureModeConfig;
+ − 207
}
+ − 208
// Close our reference on the client thread
+ − 209
Kern::SafeClose((DObject*&)iOwningThread,NULL);
+ − 210
+ − 211
// Clear the 'units open mask' in the LDD factory.
+ − 212
if (iUnit>=0)
+ − 213
((DCameraScLddFactory*)iDevice)->SetUnitOpen(iUnit,EFalse);
+ − 214
}
+ − 215
+ − 216
/**
+ − 217
Second stage constructor for the camera driver - called by the kernel's device driver framework.
+ − 218
This is called in the context of the client thread which requested the creation of a logical channel
+ − 219
(e.g. through a call to RBusLogicalChannel::DoCreate()).
+ − 220
The thread is in a critical section.
+ − 221
@param aUnit The unit argument supplied by the client. This is checked by the PDD and not used here.
+ − 222
@param aInfo The info argument supplied by the client. Always NULL in this case.
+ − 223
@param aVer The version argument supplied by the client.
+ − 224
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 225
*/
+ − 226
TInt DCameraScLdd::DoCreate(TInt aUnit, const TDesC8* /*aInfo*/, const TVersion& aVer)
+ − 227
{
+ − 228
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoCreate"));
+ − 229
+ − 230
// Check the client has EMultimediaDD capability.
+ − 231
if (!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ECAMERA.LDD (Camera driver)")))
+ − 232
return(KErrPermissionDenied);
+ − 233
+ − 234
// Check that the camera driver version specified by the client is compatible.
+ − 235
if (!Kern::QueryVersionSupported(RDevCameraSc::VersionRequired(),aVer))
+ − 236
return(KErrNotSupported);
+ − 237
+ − 238
// Check that a channel hasn't already been opened on this unit.
+ − 239
TInt r=((DCameraScLddFactory*)iDevice)->SetUnitOpen(aUnit,ETrue); // Try to update 'units open mask' in the LDD factory.
+ − 240
if (r!=KErrNone)
+ − 241
return(r);
+ − 242
iUnit=aUnit;
+ − 243
+ − 244
// Create the power handler
+ − 245
iPowerHandler=new DCameraScPowerHandler(this);
+ − 246
if (!iPowerHandler)
+ − 247
return(KErrNoMemory);
+ − 248
iPowerHandler->Add();
+ − 249
+ − 250
// Create the pending capture request list
+ − 251
r=iRequestQueue.Create(iOwningThread);
+ − 252
if (r!=KErrNone)
+ − 253
return(r);
+ − 254
+ − 255
// Initialise the PDD
+ − 256
((DCameraScPdd*)iPdd)->iLdd=this;
+ − 257
+ − 258
// Setup the default camera config
+ − 259
iCaptureMode=ECamCaptureModeImage;
+ − 260
+ − 261
iCaptureModeConfig = new TCaptureModeConfig[ECamCaptureModeMax];
+ − 262
if(!iCaptureModeConfig)
+ − 263
return KErrNoMemory;
+ − 264
TInt capsSize = Pdd()->CapsSize();
+ − 265
TInt captureMode;
+ − 266
TAny* capsBuf;
+ − 267
capsBuf = Kern::Alloc(capsSize);
+ − 268
if(!capsBuf)
+ − 269
return KErrNoMemory;
+ − 270
+ − 271
// Query the driver for its capabilities and set a default pixel format
+ − 272
// and frame size for each available capture mode.
+ − 273
TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
+ − 274
Pdd()->Caps(capsPtr);
+ − 275
+ − 276
TCameraCapsV02* caps = (TCameraCapsV02*) capsPtr.Ptr();
+ − 277
SDevCamPixelFormat* pixelFormat = (SDevCamPixelFormat*) (caps + 1);
+ − 278
SDevCamFrameSize* frameSize;
+ − 279
TAny* frameSizeCapsBuf=0;
+ − 280
TPtr8 frameSizeCapsPtr(0,0,0);
+ − 281
+ − 282
// Set the cache to hold the default dynamic attribute values.
+ − 283
iBrightnessValue = caps->iDynamicRange[ECamAttributeBrightness].iDefault;
+ − 284
iContrastValue = caps->iDynamicRange[ECamAttributeContrast].iDefault;
+ − 285
iColorEffectValue = caps->iDynamicRange[ECamAttributeColorEffect].iDefault;
+ − 286
+ − 287
for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
+ − 288
{
+ − 289
if ((captureMode==ECamCaptureModeImage) && (caps->iNumImagePixelFormats==0))
+ − 290
continue;
+ − 291
+ − 292
if ((captureMode==ECamCaptureModeVideo) && (caps->iNumVideoPixelFormats==0))
+ − 293
continue;
+ − 294
+ − 295
if ((captureMode==ECamCaptureModeViewFinder) && (caps->iNumViewFinderPixelFormats==0))
+ − 296
continue;
+ − 297
+ − 298
iCaptureModeConfig[captureMode].iCamConfig.iPixelFormat=*pixelFormat;
+ − 299
frameSizeCapsBuf = Kern::Alloc(pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize));
+ − 300
new (&frameSizeCapsPtr) TPtr8((TUint8*)frameSizeCapsBuf, pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize), pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize));
+ − 301
r=Pdd()->FrameSizeCaps((TDevCamCaptureMode)captureMode, pixelFormat->iPixelFormat, frameSizeCapsPtr);
+ − 302
if(r!=KErrNone)
+ − 303
{
+ − 304
Kern::Free(frameSizeCapsBuf);
+ − 305
return r;
+ − 306
}
+ − 307
frameSize=(SDevCamFrameSize*) frameSizeCapsPtr.Ptr();
+ − 308
iCaptureModeConfig[captureMode].iCamConfig.iFrameSize = *frameSize;
+ − 309
iCaptureModeConfig[captureMode].iCamConfig.iFrameRate = frameSize->iMinFrameRate;
+ − 310
Kern::Free(frameSizeCapsBuf);
+ − 311
+ − 312
iCaptureModeConfig[captureMode].iCamConfig.iFlashMode = ECamFlashNone;
+ − 313
iCaptureModeConfig[captureMode].iCamConfig.iExposureMode = ECamExposureAuto;
+ − 314
iCaptureModeConfig[captureMode].iCamConfig.iWhiteBalanceMode = ECamWBAuto;
+ − 315
iCaptureModeConfig[captureMode].iCamConfig.iZoom = 0;
+ − 316
iCaptureModeConfig[captureMode].iCamConfig.iPixelWidthInBytes = 0;
+ − 317
}
+ − 318
Kern::Free(capsBuf);
+ − 319
// Setup the default buffer config.
+ − 320
r=ReAllocBufferConfigInfo(0); // Zeros the structure
+ − 321
if (r!=KErrNone)
+ − 322
return(r);
+ − 323
for (captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
+ − 324
{
+ − 325
iCaptureModeConfig[captureMode].iBufConfig->iNumBuffers=KDefaultNumClientBuffers;
+ − 326
}
+ − 327
+ − 328
// Set up the correct DFC queue and enable the reception of client messages.
+ − 329
TDfcQue* dfcq=((DCameraScPdd*)iPdd)->DfcQ(aUnit);
+ − 330
SetDfcQ(dfcq);
+ − 331
iRestartDfc.SetDfcQ(dfcq);
+ − 332
iPowerDownDfc.SetDfcQ(dfcq);
+ − 333
iPowerUpDfc.SetDfcQ(dfcq);
+ − 334
iMsgQ.Receive();
+ − 335
+ − 336
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoCreate"));
+ − 337
+ − 338
return(KErrNone);
+ − 339
}
+ − 340
+ − 341
/**
+ − 342
Shutdown the camera device.
+ − 343
Terminate all device activity and power down the hardware.
+ − 344
*/
+ − 345
void DCameraScLdd::Shutdown()
+ − 346
{
+ − 347
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Shutdown"));
+ − 348
+ − 349
iState=EOpen;
+ − 350
+ − 351
// Power down the hardware
+ − 352
Pdd()->PowerDown();
+ − 353
+ − 354
// Cancel any requests that we may be handling
+ − 355
DoCancel(RDevCameraSc::EAllRequests);
+ − 356
+ − 357
// Make sure DFCs are not queued.
+ − 358
iRestartDfc.Cancel();
+ − 359
iPowerDownDfc.Cancel();
+ − 360
iPowerUpDfc.Cancel();
+ − 361
}
+ − 362
+ − 363
/**
+ − 364
Notification to the driver that a handle to it has been requested by a user thread.
+ − 365
The use of a camera driver channel is restricted here to a single thread (that has
+ − 366
EMultimediaDD capability).
+ − 367
@param aThread A pointer to thread which is requesting the handle.
+ − 368
@param aType Whether the requested handle is thread or process relative.
+ − 369
@return KErrNone, if the request is for a thread relative handle - originating from
+ − 370
the same the thread that created the channel object;
+ − 371
KErrAccessDenied, otherwise.
+ − 372
*/
+ − 373
TInt DCameraScLdd::RequestUserHandle(DThread* aThread, TOwnerType aType)
+ − 374
{
+ − 375
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::RequestUserHandle"));
+ − 376
+ − 377
// Ensure that each channel can only be used by a single thread.
+ − 378
if (aType!=EOwnerThread || aThread!=iOwningThread)
+ − 379
return(KErrAccessDenied);
+ − 380
return(KErrNone);
+ − 381
}
+ − 382
+ − 383
/**
+ − 384
Process a request on this logical channel
+ − 385
Called in the context of the client thread.
+ − 386
@param aReqNo The request number:
+ − 387
==KMaxTInt: a 'DoCancel' message;
+ − 388
>=0: a 'DoControl' message with function number equal to value.
+ − 389
<0: a 'DoRequest' message with function number equal to ~value.
+ − 390
@param a1 The first request argument. For DoRequest(), this is a pointer to the TRequestStatus.
+ − 391
@param a2 The second request argument. For DoRequest(), this is a pointer to the 2 actual TAny* arguments.
+ − 392
@return The result of the request. This is ignored by device driver framework for DoRequest().
+ − 393
*/
+ − 394
TInt DCameraScLdd::Request(TInt aReqNo, TAny* a1, TAny* a2)
+ − 395
{
+ − 396
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Request(%d)",aReqNo));
+ − 397
TInt r;
+ − 398
if (aReqNo<RDevCameraSc::EMsgControlMax && aReqNo>(~RDevCameraSc::EMsgRequestMax))
+ − 399
{
+ − 400
// Implement in the context of the kernel thread - prepare and issue a kernel message.
+ − 401
r=DLogicalChannel::Request(aReqNo,a1,a2);
+ − 402
}
+ − 403
else
+ − 404
{
+ − 405
// Implement in the context of the client thread.
+ − 406
// Decode the message type and dispatch it to the relevent handler function.
+ − 407
if ((TUint)aReqNo<(TUint)KMaxTInt)
+ − 408
r=DoControl(aReqNo,a1,a2); // DoControl - process the request.
+ − 409
+ − 410
else if (aReqNo==KMaxTInt)
+ − 411
{
+ − 412
r=DoCancel((TInt)a1); // DoCancel - cancel the request.
+ − 413
}
+ − 414
+ − 415
else
+ − 416
{
+ − 417
// DoRequest
+ − 418
TInt func=~aReqNo;
+ − 419
+ − 420
// NotifyNewImage() during image capture mode is another case which must be handled in the kernel thread.
+ − 421
if (iCaptureMode==ECamCaptureModeImage && func==RDevCameraSc::ERequestNotifyNewImage)
+ − 422
r=DLogicalChannel::Request(aReqNo,a1,a2);
+ − 423
else
+ − 424
{
+ − 425
// Read the arguments from the client thread and process the request.
+ − 426
TAny* a[2];
+ − 427
kumemget32(a,a2,sizeof(a));
+ − 428
TRequestStatus* status=(TRequestStatus*)a1;
+ − 429
r=DoRequest(func,status,a[0],a[1]);
+ − 430
+ − 431
// Complete request if there was an error
+ − 432
if (r!=KErrNone)
+ − 433
Kern::RequestComplete(iOwningThread,status,r);
+ − 434
r=KErrNone;
+ − 435
}
+ − 436
}
+ − 437
}
+ − 438
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::Request - %d",r));
+ − 439
return(r);
+ − 440
}
+ − 441
+ − 442
/**
+ − 443
Process a message for this logical channel.
+ − 444
This function is called in the context of the DFC thread.
+ − 445
@param aMsg The message to process.
+ − 446
The iValue member of this distinguishes the message type:
+ − 447
iValue==ECloseMsg, channel close message.
+ − 448
iValue==KMaxTInt, a 'DoCancel' message.
+ − 449
iValue>=0, a 'DoControl' message with function number equal to iValue.
+ − 450
iValue<0, a 'DoRequest' message with function number equal to ~iValue.
+ − 451
*/
+ − 452
void DCameraScLdd::HandleMsg(TMessageBase* aMsg)
+ − 453
{
+ − 454
TThreadMessage& m=*(TThreadMessage*)aMsg;
+ − 455
TInt id=m.iValue;
+ − 456
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::HandleMsg(%d)",id));
+ − 457
+ − 458
// Decode the message type and dispatch it to the relevent handler function.
+ − 459
if (id==(TInt)ECloseMsg)
+ − 460
{
+ − 461
// Channel close.
+ − 462
Shutdown();
+ − 463
m.Complete(KErrNone,EFalse);
+ − 464
return;
+ − 465
}
+ − 466
else if (id<0) // The only DoRequest handled in the kernel thread is NotifyNewImage(ECamCaptureModeImage).
+ − 467
{
+ − 468
// DoRequest
+ − 469
TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+ − 470
TInt r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
+ − 471
if (r!=KErrNone)
+ − 472
Kern::RequestComplete(iOwningThread,pS,r);
+ − 473
m.Complete(KErrNone,ETrue);
+ − 474
}
+ − 475
else
+ − 476
{
+ − 477
// Must be DoControl (Cancel is handled in the client thread).
+ − 478
TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
+ − 479
m.Complete(r,ETrue);
+ − 480
}
+ − 481
}
+ − 482
+ − 483
/**
+ − 484
Process a synchronous 'DoControl' request.
+ − 485
This function is called in the context of the DFC thread.
+ − 486
@param aFunction The request number.
+ − 487
@param a1 The first request argument.
+ − 488
@param a2 The second request argument.
+ − 489
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 490
*/
+ − 491
TInt DCameraScLdd::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+ − 492
{
+ − 493
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoControl(%d)",aFunction));
+ − 494
+ − 495
TInt r=KErrNotSupported;
+ − 496
switch (aFunction)
+ − 497
{
+ − 498
case RDevCameraSc::EControlCaps:
+ − 499
{
+ − 500
r = GetSensorCaps(a1);
+ − 501
break;
+ − 502
}
+ − 503
case RDevCameraSc::EControlSetCaptureMode:
+ − 504
{
+ − 505
// Change the capture mode.
+ − 506
r=SetCaptureMode((TInt)a1);
+ − 507
break;
+ − 508
}
+ − 509
case RDevCameraSc::EControlSetCamConfig:
+ − 510
{
+ − 511
// Set the new camera configuration.
+ − 512
NKern::ThreadEnterCS();
+ − 513
r=SetCamConfig((TInt)a1, (const TDesC8*)a2);
+ − 514
NKern::ThreadLeaveCS();
+ − 515
break;
+ − 516
}
+ − 517
case RDevCameraSc::EControlGetCamConfig:
+ − 518
{
+ − 519
// Write the config to the client.
+ − 520
TPtrC8 ptr((const TUint8*)&iCaptureModeConfig[(TInt)a1].iCamConfig,sizeof(iCaptureModeConfig[(TInt)a1].iCamConfig));
+ − 521
Kern::InfoCopy(*((TDes8*)a2),ptr);
+ − 522
r=KErrNone;
+ − 523
break;
+ − 524
}
+ − 525
case RDevCameraSc::EControlGetBufferConfig:
+ − 526
if (iCaptureModeConfig[(TInt)a1].iBufConfig)
+ − 527
{
+ − 528
// Write the buffer config to the client.
+ − 529
TPtrC8 ptr((const TUint8*)&(*iCaptureModeConfig[(TInt)a1].iBufConfig),iCaptureModeConfig[(TInt)a1].iBufConfigSize);
+ − 530
Kern::InfoCopy(*((TDes8*)a2),ptr);
+ − 531
r=KErrNone;
+ − 532
}
+ − 533
break;
+ − 534
case RDevCameraSc::EControlSetBufConfigChunkCreate:
+ − 535
// Need to be in critical section while deleting an exisiting config and creating a new one
+ − 536
NKern::ThreadEnterCS();
+ − 537
r=SetBufConfig((TInt)a1,(TInt)a2);
+ − 538
NKern::ThreadLeaveCS();
+ − 539
break;
+ − 540
case RDevCameraSc::EControlSetBufConfigChunkOpen:
+ − 541
SSetBufConfigChunkOpenInfo info;
+ − 542
r=Kern::ThreadRawRead(iOwningThread,a2,&info,sizeof(info));
+ − 543
if (r==KErrNone)
+ − 544
{
+ − 545
// Need to be in critical section while deleting an exisiting config and creating a new one
+ − 546
NKern::ThreadEnterCS();
+ − 547
r=SetBufConfig((TInt)a1,info.iBufferConfigBuf,info.iChunkHandle);
+ − 548
NKern::ThreadLeaveCS();
+ − 549
}
+ − 550
break;
+ − 551
case RDevCameraSc::EControlChunkClose:
+ − 552
r=ChunkClose((TInt)a1);
+ − 553
break;
+ − 554
case RDevCameraSc::EControlStart:
+ − 555
r=Start();
+ − 556
break;
+ − 557
case RDevCameraSc::EControlStop:
+ − 558
if (iState==ECapturing)
+ − 559
{
+ − 560
r=Pdd()->Stop();
+ − 561
DoCancel(1<<RDevCameraSc::ERequestNotifyNewImage);
+ − 562
if (r==KErrNone)
+ − 563
iState=EConfigured;
+ − 564
}
+ − 565
else
+ − 566
{
+ − 567
r=KErrGeneral;
+ − 568
}
+ − 569
break;
+ − 570
case RDevCameraSc::EControlReleaseBuffer:
+ − 571
r=ReleaseBuffer((TInt)a1);
+ − 572
break;
+ − 573
case RDevCameraSc::EControlNotifyNewImageSpecificCancel:
+ − 574
{
+ − 575
NKern::FMWait(&iMutex); // Acquire the buffer/request list mutex.
+ − 576
iRequestQueue.Cancel((TRequestStatus*)a1);
+ − 577
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 578
r=KErrNone;
+ − 579
break;
+ − 580
}
+ − 581
+ − 582
case RDevCameraSc::EControlBufferIdToOffset:
+ − 583
{
+ − 584
// a1 has pointer to buffer for search criteria
+ − 585
// a2 has pointer to offset for result
+ − 586
TDevCamBufferModeAndId info;
+ − 587
TPtr8 inDesc((TUint8*)(&info), sizeof(info));
+ − 588
+ − 589
r = Kern::ThreadDesRead(iOwningThread,a1,inDesc,0);
+ − 590
if (r == KErrNone)
+ − 591
{
+ − 592
TInt id = info.iId;
+ − 593
TDevCamCaptureMode captureMode = info.iCaptureMode;
+ − 594
+ − 595
r = KErrNotFound;
+ − 596
DBufferManager* mgr = iCaptureModeConfig[captureMode].iBufManager;
+ − 597
if (mgr)
+ − 598
{
+ − 599
if (mgr->iImageBuffer[id].iId == id)
+ − 600
{
+ − 601
kumemput32(a2, &mgr->iImageBuffer[id].iChunkOffset, sizeof(TInt));
+ − 602
r = KErrNone;
+ − 603
}
+ − 604
}
+ − 605
}
+ − 606
+ − 607
break;
+ − 608
}
+ − 609
case RDevCameraSc::EControlCapsSize:
+ − 610
{
+ − 611
r = Pdd()->CapsSize();
+ − 612
break;
+ − 613
}
+ − 614
case RDevCameraSc::EControlFrameSizeCaps:
+ − 615
{
+ − 616
r = GetFrameSizeCaps(a1, a2);
+ − 617
break;
+ − 618
}
+ − 619
+ − 620
case RDevCameraSc::EControlSetDynamicAttribute:
+ − 621
{
+ − 622
NKern::ThreadEnterCS();
+ − 623
r = SetDynamicAttribute((TInt)a1, (TUint)a2);
+ − 624
NKern::ThreadLeaveCS();
+ − 625
break;
+ − 626
}
+ − 627
+ − 628
case RDevCameraSc::EControlGetDynamicAttribute:
+ − 629
{
+ − 630
TInt attribute = (TInt)(a1);
+ − 631
TUint value = 0;
+ − 632
+ − 633
r = GetDynamicAttribute(attribute, value);
+ − 634
if (r == KErrNone)
+ − 635
{
+ − 636
kumemput32(a2, &value, sizeof(TUint));
+ − 637
}
+ − 638
+ − 639
break;
+ − 640
}
+ − 641
+ − 642
}
+ − 643
return(r);
+ − 644
}
+ − 645
+ − 646
/**
+ − 647
Process an asynchronous 'DoRequest' request.
+ − 648
This function is called in the context of the DFC thread.
+ − 649
@param aFunction The request number.
+ − 650
@param aStatus A pointer to the TRequestStatus.
+ − 651
@param a1 The first request argument.
+ − 652
@param a2 The second request argument.
+ − 653
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 654
*/
+ − 655
TInt DCameraScLdd::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* /*a1*/, TAny* /*a2*/)
+ − 656
{
+ − 657
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoRequest(%d)",aFunction));
+ − 658
+ − 659
TInt r=KErrNotSupported;
+ − 660
switch (aFunction)
+ − 661
{
+ − 662
case RDevCameraSc::ERequestNotifyNewImage:
+ − 663
r=NotifyNewImage(aStatus);
+ − 664
break;
+ − 665
}
+ − 666
+ − 667
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoRequest - %d",r));
+ − 668
return(r);
+ − 669
}
+ − 670
+ − 671
/**
+ − 672
Process the cancelling of asynchronous requests.
+ − 673
This function is called in the context of the DFC thread.
+ − 674
@param aMask A mask indicating which requests need to be cancelled.
+ − 675
@return The result of the cancel. Either KErrNone if successful, otherwise one of the other
+ − 676
system wide error codes.
+ − 677
*/
+ − 678
TInt DCameraScLdd::DoCancel(TUint aMask)
+ − 679
{
+ − 680
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoCancel(%08x)",aMask));
+ − 681
+ − 682
if (aMask&(1<<RDevCameraSc::ERequestNotifyNewImage))
+ − 683
{
+ − 684
NKern::FMWait(&iMutex); // Acquire the buffer/request list mutex.
+ − 685
iRequestQueue.CancelAll();
+ − 686
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 687
}
+ − 688
return(KErrNone);
+ − 689
}
+ − 690
+ − 691
/**
+ − 692
@pre The thread must be in a critical section.
+ − 693
*/
+ − 694
TInt DCameraScLdd::ReAllocBufferConfigInfo(TInt aNumBuffers)
+ − 695
{
+ − 696
for (TInt captureMode=0; captureMode < ECamCaptureModeMax; captureMode++)
+ − 697
{
+ − 698
if (iCaptureModeConfig[captureMode].iBufConfig)
+ − 699
{
+ − 700
Kern::Free(iCaptureModeConfig[captureMode].iBufConfig);
+ − 701
iCaptureModeConfig[captureMode].iBufConfig=NULL;
+ − 702
}
+ − 703
+ − 704
iCaptureModeConfig[captureMode].iBufConfigSize=aNumBuffers*(sizeof(SBufSpecList)); // Size of the three integers that hold the offset to the start of each buffer and the buffer id.
+ − 705
iCaptureModeConfig[captureMode].iBufConfigSize+=sizeof(TSharedChunkBufConfigBase);
+ − 706
iCaptureModeConfig[captureMode].iBufConfig=(TCameraSharedChunkBufConfig*)Kern::AllocZ(iCaptureModeConfig[captureMode].iBufConfigSize);
+ − 707
if (!iCaptureModeConfig[captureMode].iBufConfig)
+ − 708
return(KErrNoMemory);
+ − 709
}
+ − 710
return(KErrNone);
+ − 711
}
+ − 712
+ − 713
/**
+ − 714
Reallocate memory for the new buffer configuration.
+ − 715
@param aNumBuffers The number of buffers.
+ − 716
@pre The thread must be in a critical section.
+ − 717
*/
+ − 718
TInt DCameraScLdd::ReAllocBufferConfigInfo(TInt aCaptureMode, TInt aNumBuffers)
+ − 719
{
+ − 720
if (iCaptureModeConfig[aCaptureMode].iBufConfig)
+ − 721
{
+ − 722
Kern::Free(iCaptureModeConfig[aCaptureMode].iBufConfig);
+ − 723
iCaptureModeConfig[aCaptureMode].iBufConfig=NULL;
+ − 724
}
+ − 725
+ − 726
iCaptureModeConfig[aCaptureMode].iBufConfigSize=aNumBuffers*(sizeof(SBufSpecList)); // Size of the three integers that hold the offset to the start of each buffer and the buffer id.
+ − 727
iCaptureModeConfig[aCaptureMode].iBufConfigSize+=sizeof(TSharedChunkBufConfigBase);
+ − 728
iCaptureModeConfig[aCaptureMode].iBufConfig=(TCameraSharedChunkBufConfig*)Kern::AllocZ(iCaptureModeConfig[aCaptureMode].iBufConfigSize);
+ − 729
if (!iCaptureModeConfig[aCaptureMode].iBufConfig)
+ − 730
return(KErrNoMemory);
+ − 731
+ − 732
return(KErrNone);
+ − 733
}
+ − 734
+ − 735
/**
+ − 736
@return A handle to the shared chunk for the owning thread (a value >0), if successful;
+ − 737
otherwise one of the other system wide error codes, (a value <0).
+ − 738
@param aCamConfigBuf The supplied camera configuration.
+ − 739
@pre The thread must be in a critical section.
+ − 740
*/
+ − 741
TInt DCameraScLdd::SetCamConfig(TInt aCaptureMode, const TDesC8* aCamConfigBuf)
+ − 742
{
+ − 743
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetCamConfig()"));
+ − 744
+ − 745
// Set the configuration of the sensor
+ − 746
TInt r=DoSetConfig(aCaptureMode, aCamConfigBuf);
+ − 747
return(r);
+ − 748
}
+ − 749
+ − 750
/**
+ − 751
Allows changing of the dynamic settings.
+ − 752
Checks locally the validity of the arguments passed so as to increase performance by not
+ − 753
forcing a context switch.
+ − 754
+ − 755
If the setting has been accepted by the sensor the new value is cached by the LDD so further
+ − 756
querying does not involve another context switch.
+ − 757
+ − 758
@param aAttribute An enum identifying the dynamic attribute to change.
+ − 759
@param aValue The attributes value.
+ − 760
@return KErrNone if successful, KErrNotSupported if not supported, KErrArgument if aValue out of range.
+ − 761
Otherwise, one of the system wide error codes.
+ − 762
@pre The thread must be in a critical section.
+ − 763
*/
+ − 764
TInt DCameraScLdd::SetDynamicAttribute(TInt aAttribute, TUint aValue)
+ − 765
{
+ − 766
TUint* attrCachePtr = NULL;
+ − 767
TInt err = KErrNotSupported;
+ − 768
+ − 769
switch (aAttribute)
+ − 770
{
+ − 771
case ECamAttributeBrightness:
+ − 772
err = Pdd()->SetBrightness(aValue);
+ − 773
attrCachePtr = &iBrightnessValue;
+ − 774
break;
+ − 775
+ − 776
case ECamAttributeContrast:
+ − 777
err = Pdd()->SetContrast(aValue);
+ − 778
attrCachePtr = &iContrastValue;
+ − 779
break;
+ − 780
+ − 781
case ECamAttributeColorEffect:
+ − 782
err = Pdd()->SetColorEffect(aValue);
+ − 783
attrCachePtr = &iColorEffectValue;
+ − 784
break;
+ − 785
+ − 786
default:
+ − 787
return err;
+ − 788
}
+ − 789
+ − 790
if (err == KErrNone)
+ − 791
{
+ − 792
// Cache the set value.
+ − 793
__ASSERT_DEBUG(attrCachePtr, Kern::Fault(KCameraLddPanic, __LINE__));
+ − 794
*attrCachePtr = aValue;
+ − 795
}
+ − 796
+ − 797
return err;
+ − 798
}
+ − 799
+ − 800
+ − 801
/**
+ − 802
Allows querying of a dynamic setting.
+ − 803
The value is read from the cached LDD values.
+ − 804
+ − 805
@param aAttribute An enum identifying the dynamic attribute to change.
+ − 806
@param aValue A reference to a variable that will receive the attribute value.
+ − 807
@return KErrNone if successful, KErrNotFound if aAttribute is an unsupported
+ − 808
setting. The parameter aValue is not changed if this function fails.
+ − 809
*/
+ − 810
TInt DCameraScLdd::GetDynamicAttribute(TInt aAttribute, TUint& aValue)
+ − 811
{
+ − 812
switch (aAttribute)
+ − 813
{
+ − 814
case ECamAttributeBrightness:
+ − 815
aValue = iBrightnessValue;
+ − 816
break;
+ − 817
+ − 818
case ECamAttributeContrast:
+ − 819
aValue = iContrastValue;
+ − 820
break;
+ − 821
+ − 822
case ECamAttributeColorEffect:
+ − 823
aValue = iColorEffectValue;
+ − 824
break;
+ − 825
+ − 826
default:
+ − 827
return KErrNotFound;
+ − 828
}
+ − 829
+ − 830
return KErrNone;
+ − 831
}
+ − 832
+ − 833
+ − 834
/**
+ − 835
Updates the buffer configuration of the camera for the specified capture mode.
+ − 836
@return A handle to the shared chunk for the owning thread (a value >0), if successful;
+ − 837
otherwise one of the other system wide error codes, (a value <0).
+ − 838
*/
+ − 839
TInt DCameraScLdd::SetBufConfig(TInt aCaptureMode, TInt aNumBuffers)
+ − 840
{
+ − 841
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetBufConfig(CaptureMode=%d,NumBuffers=%d)",aCaptureMode,aNumBuffers));
+ − 842
+ − 843
// Free any memory and chunk already allocated
+ − 844
TInt r=ChunkClose(aCaptureMode);
+ − 845
if (r!=KErrNone)
+ − 846
return(r);
+ − 847
+ − 848
// Allocate a new shared chunk and create the specified number of buffers within it.
+ − 849
TInt buffersize=((iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth*iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight) * iCaptureModeConfig[aCaptureMode].iCamConfig.iPixelWidthInBytes);
+ − 850
__KTRACE_CAM(Kern::Printf(">>DCameraScLdd::SetBufConfig - iFrameSize:%d, iPixelWidthInBytes:%d => bufferSize:%d",(iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth*iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight),iCaptureModeConfig[aCaptureMode].iCamConfig.iPixelWidthInBytes,buffersize));
+ − 851
iCaptureModeConfig[aCaptureMode].iBufManager=new DBufferManager(this);
+ − 852
if (!iCaptureModeConfig[aCaptureMode].iBufManager)
+ − 853
return(KErrNoMemory);
+ − 854
r=iCaptureModeConfig[aCaptureMode].iBufManager->Create(aNumBuffers,buffersize);
+ − 855
if (r!=KErrNone)
+ − 856
return(r);
+ − 857
+ − 858
// Update the LDD's chunk/buffer geometry info.
+ − 859
r=ReAllocBufferConfigInfo(aCaptureMode, aNumBuffers);
+ − 860
if (r!=KErrNone)
+ − 861
return(r);
+ − 862
iCaptureModeConfig[aCaptureMode].iBufManager->GetBufConfig(*iCaptureModeConfig[aCaptureMode].iBufConfig);
+ − 863
+ − 864
// Create handle to the shared chunk for the owning thread.
+ − 865
r=Kern::MakeHandleAndOpen(iOwningThread,iCaptureModeConfig[aCaptureMode].iBufManager->iChunk);
+ − 866
if (r>0)
+ − 867
{
+ − 868
// And save the the chunk and handle for later. Normally the chunk handle will be closed when the chunk
+ − 869
// is closed, but if the chunk is re-allocated then it will need to be closed before re-allocation.
+ − 870
iCaptureModeConfig[aCaptureMode].iChunkHandle=r;
+ − 871
}
+ − 872
+ − 873
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::SetBufConfig - %d",r));
+ − 874
return(r);
+ − 875
}
+ − 876
+ − 877
/**
+ − 878
Updates the buffer configuration of the camera, which has been supplied by the user, for the specified capture mode.
+ − 879
@param aCaptureMode The capture mode for which the setting of the buffer configuration is made.
+ − 880
@param aBufferConfigBuf A buffer that holds the buffer configuration for the camera.
+ − 881
@param aChunkHandle A handle for the shared chunk supplied by the client.
+ − 882
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 883
@pre The thread must be in a critical section.
+ − 884
*/
+ − 885
TInt DCameraScLdd::SetBufConfig(TInt aCaptureMode,const TDesC8* aBufferConfigBuf,TInt aChunkHandle)
+ − 886
{
+ − 887
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetConfig(Handle-%d)",aChunkHandle));
+ − 888
+ − 889
// Read the buffer config structure from the client.
+ − 890
TInt numBuffers;
+ − 891
TPtr8 ptr((TUint8*)&numBuffers,sizeof(numBuffers));
+ − 892
TInt r=Kern::ThreadDesRead(iOwningThread,aBufferConfigBuf,ptr,0);
+ − 893
if (r!=KErrNone)
+ − 894
return(r);
+ − 895
// Calculate the minimum length of the descriptor.
+ − 896
TInt minDesLen=(numBuffers*sizeof(SBufSpecList))+sizeof(TSharedChunkBufConfigBase);
+ − 897
r=Kern::ThreadGetDesLength(iOwningThread,aBufferConfigBuf);
+ − 898
if (r<minDesLen)
+ − 899
return(KErrArgument);
+ − 900
r=ReAllocBufferConfigInfo(aCaptureMode, numBuffers);
+ − 901
if (r!=KErrNone)
+ − 902
return(r);
+ − 903
ptr.Set((TUint8*)iCaptureModeConfig[aCaptureMode].iBufConfig,0,iCaptureModeConfig[aCaptureMode].iBufConfigSize);
+ − 904
r=Kern::ThreadDesRead(iOwningThread,aBufferConfigBuf,ptr,0);
+ − 905
if (r!=KErrNone)
+ − 906
return(r);
+ − 907
+ − 908
// Free any memory and chunk already allocated
+ − 909
r=ChunkClose(aCaptureMode);
+ − 910
if (r!=KErrNone)
+ − 911
return(r);
+ − 912
+ − 913
// Open the shared chunk supplied and create buffer objects for the committed buffers within it.
+ − 914
iCaptureModeConfig[aCaptureMode].iBufManager=new DBufferManager(this);
+ − 915
if (!iCaptureModeConfig[aCaptureMode].iBufManager)
+ − 916
return(KErrNoMemory);
+ − 917
r=iCaptureModeConfig[aCaptureMode].iBufManager->Create(*iCaptureModeConfig[aCaptureMode].iBufConfig,aChunkHandle,iOwningThread);
+ − 918
if (r!=KErrNone)
+ − 919
return(r);
+ − 920
+ − 921
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::SetConfig - %d",KErrNone));
+ − 922
return(r);
+ − 923
}
+ − 924
+ − 925
/**
+ − 926
Frees the buffer manager associated with a chunk, and closes the chunk itself. The chunk being closed,
+ − 927
and its associated DBufferManager instance should have been allocated by the device driver. However,
+ − 928
this is not a requirement.
+ − 929
@param aCaptureMode The capture mode for which to free the buffer manager and chunk.
+ − 930
@return KErrNone if successful.
+ − 931
KErrInUse if an attempt has been made to free the memory and chunk while they are in use.
+ − 932
Otherwise one of the other system-wide error codes.
+ − 933
*/
+ − 934
TInt DCameraScLdd::ChunkClose(TInt aCaptureMode)
+ − 935
{
+ − 936
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ChunkClose(Capture Mode-%d)",aCaptureMode));
+ − 937
+ − 938
if(iCaptureMode == aCaptureMode)
+ − 939
{
+ − 940
if (iState==ECapturing)
+ − 941
return(KErrInUse);
+ − 942
}
+ − 943
+ − 944
// Delete any existing buffers
+ − 945
if (iCaptureModeConfig[aCaptureMode].iBufManager)
+ − 946
{
+ − 947
delete iCaptureModeConfig[aCaptureMode].iBufManager;
+ − 948
iCaptureModeConfig[aCaptureMode].iBufManager=NULL;
+ − 949
}
+ − 950
+ − 951
// If a handle to the shared chunk was created, close it, using the handle of the thread on which
+ − 952
// it was created, in case a different thread is now calling us
+ − 953
if (iCaptureModeConfig[aCaptureMode].iChunkHandle>0)
+ − 954
{
+ − 955
Kern::CloseHandle(iOwningThread,iCaptureModeConfig[aCaptureMode].iChunkHandle);
+ − 956
iCaptureModeConfig[aCaptureMode].iChunkHandle=0;
+ − 957
}
+ − 958
+ − 959
return(KErrNone);
+ − 960
}
+ − 961
+ − 962
/**
+ − 963
Set the current capture mode and submits the camera configuration to the PDD, passing it as a descriptor
+ − 964
to support future changes to the config structure.
+ − 965
+ − 966
@param aCaptureMode The capture mode that the camera switches to.
+ − 967
@return KErrNone if successful;
+ − 968
otherwise one of the other system-wide error codes.
+ − 969
*/
+ − 970
TInt DCameraScLdd::SetCaptureMode(TInt aCaptureMode)
+ − 971
{
+ − 972
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::SetCaptureMode(Mode-%d)",aCaptureMode));
+ − 973
+ − 974
TInt r=KErrNone;
+ − 975
if(aCaptureMode >= ECamCaptureModeMax || aCaptureMode < 0)
+ − 976
{
+ − 977
r=KErrNotFound;
+ − 978
return(r);
+ − 979
}
+ − 980
+ − 981
if (!iCaptureModeConfig[aCaptureMode].iBufManager)
+ − 982
{
+ − 983
r=KErrNotReady;
+ − 984
return(r);
+ − 985
}
+ − 986
+ − 987
iCaptureMode=(TDevCamCaptureMode)aCaptureMode; // The capture mode has already been checked for its validity.
+ − 988
+ − 989
__KTRACE_CAM(Kern::Printf("DCameraScLdd::SetCaptureMode: iFrameSize:%dx%d)",iCaptureModeConfig[iCaptureMode].iCamConfig.iFrameSize.iWidth, iCaptureModeConfig[iCaptureMode].iCamConfig.iFrameSize.iHeight));
+ − 990
+ − 991
// Call the PDD to change the hardware configuration according to the new capture mode.
+ − 992
// Pass it as a descriptor - to support future changes to the config structure.
+ − 993
TPtr8 ptr((TUint8*)&iCaptureModeConfig[iCaptureMode].iCamConfig,sizeof(iCaptureModeConfig[iCaptureMode].iCamConfig),sizeof(iCaptureModeConfig[iCaptureMode].iCamConfig));
+ − 994
r=Pdd()->SetConfig(ptr);
+ − 995
if (r!=KErrNone)
+ − 996
return(r);
+ − 997
return KErrNone;
+ − 998
}
+ − 999
+ − 1000
+ − 1001
/**
+ − 1002
Process a start image capture request from the client - in the capture mode supplied.
+ − 1003
If this is a free running mode then the PDD is called straight away to commence capturing frames. In one shot mode the driver postpones the capturing
+ − 1004
of frames until a NotifyNewImage() request is received.
+ − 1005
@return KErrNone if successful; whether capture mode was actually started or deferred until NotifyNewImage();
+ − 1006
KErrNotReady if SetConfig() has not been previously called;
+ − 1007
otherwise one of the other system-wide error codes.
+ − 1008
*/
+ − 1009
TInt DCameraScLdd::Start()
+ − 1010
{
+ − 1011
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::Start(Current Mode-%d)",iCaptureMode));
+ − 1012
+ − 1013
if (iState==ECapturing)
+ − 1014
return(KErrInUse);
+ − 1015
TInt r=KErrNone;
+ − 1016
+ − 1017
// Only continue if the mode being started has been configured
+ − 1018
if (iCaptureModeConfig[iCaptureMode].iBufManager)
+ − 1019
iState=EConfigured;
+ − 1020
+ − 1021
if (iState==EOpen)
+ − 1022
r=KErrNotReady;
+ − 1023
else if (iState==EConfigured)
+ − 1024
{
+ − 1025
iCaptureModeConfig[iCaptureMode].iBufManager->Reset();
+ − 1026
if (iCaptureMode!=ECamCaptureModeImage)
+ − 1027
r=DoStart();
+ − 1028
if (r==KErrNone)
+ − 1029
iState=ECapturing;
+ − 1030
}
+ − 1031
else
+ − 1032
r=KErrGeneral;
+ − 1033
return(r);
+ − 1034
}
+ − 1035
+ − 1036
/**
+ − 1037
Start the PDD capturing images.
+ − 1038
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 1039
*/
+ − 1040
TInt DCameraScLdd::DoStart()
+ − 1041
{
+ − 1042
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoStart()"));
+ − 1043
+ − 1044
DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
+ − 1045
TLinAddr linAddr=(bufManager->iChunkBase)+(bufManager->iCurrentBuffer->iChunkOffset);
+ − 1046
TPhysAddr physAddr=bufManager->iCurrentBuffer->iPhysicalAddress;
+ − 1047
TInt r=Pdd()->Start(iCaptureMode,linAddr,physAddr);
+ − 1048
+ − 1049
/*
+ − 1050
* James Cooper: Uncommenting this code will cause the ASSERT_DEBUG in SetImageCaptured() to fail
+ − 1051
* if (r==KErrNone && bufManager->iNextBuffer)
+ − 1052
{
+ − 1053
linAddr=(bufManager->iChunkBase)+(bufManager->iNextBuffer->iChunkOffset);
+ − 1054
physAddr=bufManager->iNextBuffer->iPhysicalAddress;
+ − 1055
r=Pdd()->CaptureNextImage(linAddr,physAddr);
+ − 1056
}
+ − 1057
*/
+ − 1058
return(r);
+ − 1059
}
+ − 1060
+ − 1061
/**
+ − 1062
Process a notify a new image request from the client.
+ − 1063
If there is an image already available then the request is completed straight away, otherwise it is added to the capture request queue.
+ − 1064
@param aStatus The request status to be signalled when the request is complete. If the request is successful then this is set
+ − 1065
to the offset within the shared chunk where the record data resides. Alternatively, if an error occurs,
+ − 1066
it will be set to one of the system wide error values.
+ − 1067
@return KErrNone if successful - whether the request was completed or simply queued;
+ − 1068
KErrNotReady if Start() hasn't been previousely called;
+ − 1069
KErrInUse: if the client needs to free up buffers before further requests can be accepted;
+ − 1070
KErrGeneral: if the client has more requests queued than there are buffers;
+ − 1071
otherwise one of the other system wide error codes.
+ − 1072
*/
+ − 1073
TInt DCameraScLdd::NotifyNewImage(TRequestStatus* aStatus)
+ − 1074
{
+ − 1075
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage(%x) - iState(%d)",aStatus,iState));
+ − 1076
DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
+ − 1077
TInt r;
+ − 1078
if (iState!=ECapturing || !bufManager)
+ − 1079
return(KErrNotReady);
+ − 1080
+ − 1081
NKern::FMWait(&iMutex); // Acquire the buffer/request list mutex.
+ − 1082
if (iCaptureMode!=ECamCaptureModeImage)
+ − 1083
{
+ − 1084
// We're operating in one of the free running modes, see if an image is already available.
+ − 1085
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage - Getting image for client"));
+ − 1086
TImageBuffer* buf=bufManager->GetImageForClient(EFalse);
+ − 1087
if (buf)
+ − 1088
{
+ − 1089
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage - There is an image available already"));
+ − 1090
// There is an image available already - complete the request.
+ − 1091
r=buf->iResult;
+ − 1092
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1093
if (r==KErrNone)
+ − 1094
{
+ − 1095
// Only complete if successful here. Errors will be completed on returning from this method.
+ − 1096
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::NotifyNewImage(iId:%d)",buf->iId));
+ − 1097
Kern::RequestComplete(iOwningThread,aStatus,(buf->iId));
+ − 1098
}
+ − 1099
return(r);
+ − 1100
}
+ − 1101
+ − 1102
// The buffer 'completed' list is empty. If the 'in-use' list contains all the buffers apart from the one being filled
+ − 1103
// then let the client know they need to free some buffers.
+ − 1104
if (bufManager->iFreeBufferQ.IsEmpty() && !bufManager->iNextBuffer)
+ − 1105
{
+ − 1106
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1107
return(KErrInUse);
+ − 1108
}
+ − 1109
}
+ − 1110
else
+ − 1111
{
+ − 1112
// We're operating in one shot image capture mode. Check if the client needs to free up some buffers
+ − 1113
// before we can accept the request.
+ − 1114
if (bufManager->iCompletedBufferQ.IsEmpty() && bufManager->iFreeBufferQ.IsEmpty() && !bufManager->iNextBuffer)
+ − 1115
{
+ − 1116
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1117
return(KErrInUse);
+ − 1118
}
+ − 1119
+ − 1120
// Enough buffers are available so we can start capturing data. First
+ − 1121
// check that there isn't already a capture request in progress.
+ − 1122
if (iRequestQueue.IsEmpty())
+ − 1123
{
+ − 1124
// No previous request in progress so start the PDD.
+ − 1125
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1126
r=DoStart();
+ − 1127
if (r!=KErrNone)
+ − 1128
return(r);
+ − 1129
NKern::FMWait(&iMutex); // Acquire the buffer/request list mutex again.
+ − 1130
}
+ − 1131
}
+ − 1132
+ − 1133
// Save the request in the pending queue and return. The request will be completed from the PDD and the DFC thread when
+ − 1134
// an image is available.
+ − 1135
r=iRequestQueue.Add(aStatus);
+ − 1136
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1137
return(r);
+ − 1138
}
+ − 1139
+ − 1140
/**
+ − 1141
Process a release buffer request from the client.
+ − 1142
@param aChunkOffset The chunk offset corresponding to the buffer to be freed.
+ − 1143
@return KErrNone if successful;
+ − 1144
KErrNotFound if no 'in use' buffer had the specified chunk offset;
+ − 1145
KErrNotReady if the driver hasn't been configured for the current capture mode.
+ − 1146
*/
+ − 1147
TInt DCameraScLdd::ReleaseBuffer(TInt aBufferId)
+ − 1148
{
+ − 1149
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ReleaseBuffer(%d)",aBufferId));
+ − 1150
if(!iCaptureModeConfig[iCaptureMode].iBufManager)
+ − 1151
return KErrNotReady;
+ − 1152
DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
+ − 1153
TInt chunkOffset = 0;
+ − 1154
+ − 1155
TInt r=KErrNone;
+ − 1156
/* The driver is left in an ECapturing state after capturing frames. However, it can be left in an
+ − 1157
EConfigured state as a result of Stop() being called. Stop() cancels all pending capture requests and
+ − 1158
leaves the driver in a state in which it can be restarted without needing reconfiguring. */
+ − 1159
if (iState!=EOpen && bufManager)
+ − 1160
{
+ − 1161
chunkOffset = bufManager->iImageBuffer[aBufferId].iChunkOffset;
+ − 1162
TImageBuffer* buf=NULL;
+ − 1163
NKern::FMWait(&iMutex); // Acquire the buffer/request list mutex.
+ − 1164
buf=bufManager->FindInUseImage(chunkOffset);
+ − 1165
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1166
if (buf)
+ − 1167
{
+ − 1168
// The buffer specified by the client has been found in the 'in-use' list.
+ − 1169
bufManager->Purge(buf);
+ − 1170
}
+ − 1171
else
+ − 1172
r=KErrNotFound;
+ − 1173
+ − 1174
if (r==KErrNone)
+ − 1175
{
+ − 1176
NKern::FMWait(&iMutex); // Acquire the buffer/request list mutex.
+ − 1177
// Release it from the 'in-use list into the 'free' list.
+ − 1178
r=bufManager->ReleaseImage(chunkOffset);
+ − 1179
if (r>0)
+ − 1180
{
+ − 1181
// The buffer needs to be queued straight away - so signal this to the PDD
+ − 1182
TLinAddr linAddr=(bufManager->iChunkBase)+(bufManager->iNextBuffer->iChunkOffset);
+ − 1183
TPhysAddr physAddr=bufManager->iNextBuffer->iPhysicalAddress;
+ − 1184
buf=bufManager->iNextBuffer;
+ − 1185
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1186
r=Pdd()->CaptureNextImage(linAddr,physAddr);
+ − 1187
if (r==KErrNotReady)
+ − 1188
r=KErrNone;
+ − 1189
}
+ − 1190
else
+ − 1191
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1192
}
+ − 1193
}
+ − 1194
else
+ − 1195
r=KErrNotReady;
+ − 1196
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::ReleaseBuffer() - r(%d)",r));
+ − 1197
return(r);
+ − 1198
}
+ − 1199
+ − 1200
/**
+ − 1201
Called from the PDD in the DFC thread each time it finishes capturing an image frame.
+ − 1202
This will complete a pending capture request and update buffer lists.
+ − 1203
@param aCaptureMode The capture mode of the image captured. @see TDevCamCaptureMode.
+ − 1204
@param aResult The result of the image capture request being completed.
+ − 1205
@param aLinAddr If this function returns KErrNone then on return, this holds the linear address of the start of the next buffer
+ − 1206
to use for image capture.
+ − 1207
@param aPhysAddr If this function returns KErrNone then on return, this holds the physical address that corresponds to the
+ − 1208
linear address: aLinAddr.
+ − 1209
@return KErrNone if capturing should continue - with holding information on the next buffer to use for image capture.
+ − 1210
KErrNotReady if capturing should continue - but with no further buffer available for image capture just yet.
+ − 1211
KErrAbort if image capturing should now be terminated.
+ − 1212
*/
+ − 1213
TInt DCameraScLdd::ImageCaptureCallback(TDevCamCaptureMode /*aCaptureMode*/,TInt aResult,TLinAddr* aLinAddr,TPhysAddr* aPhysAddr)
+ − 1214
{
+ − 1215
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ImageCaptureCallback"));
+ − 1216
+ − 1217
DBufferManager* bufManager=iCaptureModeConfig[iCaptureMode].iBufManager;
+ − 1218
// Update the buffer list and get the next buffer for capture.
+ − 1219
NKern::FMWait(&iMutex); // Acquire the buffer/request list mutex.
+ − 1220
TImageBuffer* nextBuffer=bufManager->SetImageCaptured(aResult); // Puts the captured image's buffer in the completed buffer queue.
+ − 1221
+ − 1222
// Check if there is a capture request pending.
+ − 1223
if (!iRequestQueue.IsEmpty())
+ − 1224
{
+ − 1225
// A capture request is pending.
+ − 1226
TBool removeLast=((iCaptureMode==ECamCaptureModeImage) ? (TBool) ETrue : (TBool) EFalse);
+ − 1227
TImageBuffer* buf=bufManager->GetImageForClient(removeLast); // Retrieved the captured image from the buffer in the completed buffer queue.
+ − 1228
if (buf)
+ − 1229
{
+ − 1230
// Update the request pending list and complete the request.
+ − 1231
TRequestStatus* rs=iRequestQueue.Remove();
+ − 1232
TInt reason=(buf->iResult==KErrNone) ? buf->iId : buf->iResult;
+ − 1233
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1234
buf->SyncMemoryAfterDmaRead();
+ − 1235
Kern::RequestComplete(iOwningThread,rs,reason); // Complete the request.
+ − 1236
}
+ − 1237
else
+ − 1238
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1239
}
+ − 1240
else
+ − 1241
NKern::FMSignal(&iMutex); // Release the buffer/request list mutex.
+ − 1242
+ − 1243
// Now work out what instruction to give to the PDD
+ − 1244
TInt r=KErrNone;
+ − 1245
if (iCaptureMode==ECamCaptureModeImage)
+ − 1246
{
+ − 1247
// Image capture mode. If we've just completed a one shot request, see if there is yet another one pending.
+ − 1248
if (!iRequestQueue.IsEmpty())
+ − 1249
{
+ − 1250
// Another request is pending so let the PDD carry on.
+ − 1251
// If an error occured we need to first stop and re-start image capture
+ − 1252
if (aResult!=KErrNone)
+ − 1253
{
+ − 1254
iRestartDfc.Enque(); // Queue a DFC to re-start the PDD later.
+ − 1255
r=KErrAbort;
+ − 1256
}
+ − 1257
}
+ − 1258
else
+ − 1259
{
+ − 1260
r=KErrAbort; // End of image gather mode so stop the PDD.
+ − 1261
}
+ − 1262
}
+ − 1263
else
+ − 1264
{
+ − 1265
// One of the free running modes. If an error occured we need to first stop and re-start image capture
+ − 1266
if (aResult!=KErrNone)
+ − 1267
{
+ − 1268
iRestartDfc.Enque(); // Queue a DFC to re-start the PDD later.
+ − 1269
r=KErrAbort;
+ − 1270
}
+ − 1271
}
+ − 1272
+ − 1273
// If capture should continue, check if there is a further buffer available to use for image capture.
+ − 1274
if (r==KErrNone)
+ − 1275
{
+ − 1276
if (nextBuffer)
+ − 1277
{
+ − 1278
*aLinAddr=(bufManager->iChunkBase)+(nextBuffer->iChunkOffset);
+ − 1279
*aPhysAddr=nextBuffer->iPhysicalAddress;
+ − 1280
}
+ − 1281
else
+ − 1282
r=KErrNotReady;
+ − 1283
}
+ − 1284
return(r);
+ − 1285
}
+ − 1286
+ − 1287
/**
+ − 1288
Stores the camera configuration passed in from the user after checking and validating it.
+ − 1289
@param aCaptureMode The capture mode for which the setting of the camera configuration is made.
+ − 1290
@param aCamConfigBuf A buffer that contains the camera configuration.
+ − 1291
@return KErrNone if successful
+ − 1292
KErrInUse if the camera is capturing an image
+ − 1293
KErrArgument if the camera configuration passed in is invalid
+ − 1294
otherwise a system wide error code.
+ − 1295
*/
+ − 1296
TInt DCameraScLdd::DoSetConfig(TInt aCaptureMode, const TDesC8* aCamConfigBuf)
+ − 1297
{
+ − 1298
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoSetConfig(CaptureMode=%d)",aCaptureMode));
+ − 1299
+ − 1300
if(iCaptureMode == aCaptureMode)
+ − 1301
{
+ − 1302
if (iState==ECapturing)
+ − 1303
return(KErrInUse);
+ − 1304
}
+ − 1305
+ − 1306
// Read the config structure from the client
+ − 1307
TCameraConfigV02 config;
+ − 1308
TPtr8 ptr((TUint8*)&config,sizeof(config));
+ − 1309
TInt r=Kern::ThreadDesRead(iOwningThread,aCamConfigBuf,ptr,0);
+ − 1310
if (r!=KErrNone)
+ − 1311
return(r);
+ − 1312
+ − 1313
// Check that it is compatible with this camera device
+ − 1314
r=ValidateConfig(aCaptureMode, config);
+ − 1315
if (r!=KErrNone)
+ − 1316
{
+ − 1317
if (r == KErrNotFound)
+ − 1318
r = KErrArgument;
+ − 1319
return(r);
+ − 1320
}
+ − 1321
+ − 1322
// We're about to replace any previous configuration - so set the
+ − 1323
// status back to un-configured. A new buffer configuration must be calculated as a result of that.
+ − 1324
//iState=EOpen;
+ − 1325
+ − 1326
// Save the new configuration.
+ − 1327
iCaptureModeConfig[aCaptureMode].iCamConfig=config;
+ − 1328
iCaptureModeConfig[aCaptureMode].iFrameHeight=iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iHeight;
+ − 1329
iCaptureModeConfig[aCaptureMode].iFrameWidth=iCaptureModeConfig[aCaptureMode].iCamConfig.iFrameSize.iWidth;
+ − 1330
+ − 1331
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoSetConfig - %d",KErrNone));
+ − 1332
return(r);
+ − 1333
}
+ − 1334
+ − 1335
/**
+ − 1336
Validates the configuration that is about to be used with the driver.
+ − 1337
@param aCaptureMode The capture mode that the configuration is for.
+ − 1338
@param aConfig The buffer that contains the camera configuration, as passed in from the user.
+ − 1339
@return KErrNotFound if the configuration is not supported by the camera sensor.
+ − 1340
KErrNotSupported if the driver does not support aCaptureMode
+ − 1341
KErrNone if successful.
+ − 1342
*/
+ − 1343
TInt DCameraScLdd::ValidateConfig(TInt aCaptureMode, TCameraConfigV02& aConfig)
+ − 1344
{
+ − 1345
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::ValidateConfig"));
+ − 1346
+ − 1347
TInt capsSize = Pdd()->CapsSize();
+ − 1348
NKern::ThreadEnterCS();
+ − 1349
TAny* capsBuf = Kern::Alloc(capsSize);
+ − 1350
if(!capsBuf)
+ − 1351
{
+ − 1352
NKern::ThreadLeaveCS();
+ − 1353
return KErrNoMemory;
+ − 1354
}
+ − 1355
+ − 1356
TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
+ − 1357
Pdd()->Caps(capsPtr);
+ − 1358
NKern::ThreadLeaveCS();
+ − 1359
+ − 1360
TCameraCapsV02* camCaps = (TCameraCapsV02*) capsPtr.Ptr();
+ − 1361
+ − 1362
TInt r;
+ − 1363
if(aCaptureMode==ECamCaptureModeImage && camCaps->iNumImagePixelFormats)
+ − 1364
{
+ − 1365
r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
+ − 1366
}
+ − 1367
else if(aCaptureMode==ECamCaptureModeVideo && camCaps->iNumVideoPixelFormats)
+ − 1368
{
+ − 1369
r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
+ − 1370
}
+ − 1371
else if(aCaptureMode==ECamCaptureModeViewFinder && camCaps->iNumViewFinderPixelFormats)
+ − 1372
{
+ − 1373
r=DoValidateConfig(camCaps, aCaptureMode, aConfig);
+ − 1374
}
+ − 1375
else
+ − 1376
r=KErrNotSupported;
+ − 1377
+ − 1378
if(r==KErrNone)
+ − 1379
{
+ − 1380
// Calculate the pixel width (in bytes) for the format specified
+ − 1381
aConfig.iPixelWidthInBytes=aConfig.iPixelFormat.iPixelWidthInBytes;
+ − 1382
}
+ − 1383
+ − 1384
NKern::ThreadEnterCS();
+ − 1385
Kern::Free(capsBuf);
+ − 1386
NKern::ThreadLeaveCS();
+ − 1387
+ − 1388
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::ValidateConfig - %d",r));
+ − 1389
return(r);
+ − 1390
}
+ − 1391
+ − 1392
/**
+ − 1393
Validates the configuration that is about to be used with the driver by checking it against what the camera sensor supports.
+ − 1394
@param aCamCaps The buffer that contains the capabilities of the camera driver.
+ − 1395
@param aCaptureMode The capture mode that the configuration is for.
+ − 1396
@param aConfig The buffer that contains the camera configuration, as passed in from the user.
+ − 1397
@return KErrNotFound if the configuration is not supported by the camera sensor
+ − 1398
KErrNone if successful
+ − 1399
or one of the system wide error values.
+ − 1400
*/
+ − 1401
TInt DCameraScLdd::DoValidateConfig(TCameraCapsV02* aCamCaps, TInt& aCaptureMode, TCameraConfigV02& aConfig)
+ − 1402
{
+ − 1403
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::DoValidateConfig"));
+ − 1404
TAny* frameSizeCapsBuf;
+ − 1405
TInt frameSizeCapsSize;
+ − 1406
SFrameSizeCapsInfo info;
+ − 1407
SDevCamFrameSize* frameSize;
+ − 1408
TUint i;
+ − 1409
TUint l;
+ − 1410
SDevCamPixelFormat* pixelFormat;
+ − 1411
TUint start;
+ − 1412
TUint end;
+ − 1413
TInt r;
+ − 1414
pixelFormat = (SDevCamPixelFormat*) (aCamCaps + 1);
+ − 1415
if(aCaptureMode==ECamCaptureModeImage)
+ − 1416
{
+ − 1417
start=0;
+ − 1418
end=aCamCaps->iNumImagePixelFormats;
+ − 1419
}
+ − 1420
else if(aCaptureMode==ECamCaptureModeVideo)
+ − 1421
{
+ − 1422
start=aCamCaps->iNumImagePixelFormats;
+ − 1423
end=aCamCaps->iNumImagePixelFormats + aCamCaps->iNumVideoPixelFormats;
+ − 1424
pixelFormat += aCamCaps->iNumImagePixelFormats;
+ − 1425
}
+ − 1426
else if(aCaptureMode==ECamCaptureModeViewFinder)
+ − 1427
{
+ − 1428
start=aCamCaps->iNumImagePixelFormats+aCamCaps->iNumVideoPixelFormats;
+ − 1429
end=aCamCaps->iNumImagePixelFormats + aCamCaps->iNumVideoPixelFormats + aCamCaps->iNumViewFinderPixelFormats;
+ − 1430
pixelFormat += aCamCaps->iNumImagePixelFormats;
+ − 1431
pixelFormat += aCamCaps->iNumVideoPixelFormats;
+ − 1432
}
+ − 1433
else
+ − 1434
return KErrNotSupported;
+ − 1435
+ − 1436
for (i=start; i<end; i++)
+ − 1437
{
+ − 1438
if(aConfig.iPixelFormat.iPixelFormat==pixelFormat->iPixelFormat)
+ − 1439
{
+ − 1440
info.iUidPixelFormat = pixelFormat->iPixelFormat;
+ − 1441
info.iCaptureMode = (TDevCamCaptureMode) aCaptureMode;
+ − 1442
frameSizeCapsSize = pixelFormat->iNumFrameSizes*sizeof(SDevCamFrameSize);
+ − 1443
NKern::ThreadEnterCS();
+ − 1444
frameSizeCapsBuf = Kern::Alloc(frameSizeCapsSize);
+ − 1445
NKern::ThreadLeaveCS();
+ − 1446
if (!frameSizeCapsBuf)
+ − 1447
{
+ − 1448
return KErrNoMemory;
+ − 1449
}
+ − 1450
TPtr8 frameSizeCapsPtr( (TUint8*)frameSizeCapsBuf, frameSizeCapsSize, frameSizeCapsSize );
+ − 1451
if ((r = Pdd()->FrameSizeCaps(info.iCaptureMode, info.iUidPixelFormat, frameSizeCapsPtr)) == KErrNone)
+ − 1452
{
+ − 1453
frameSize = (SDevCamFrameSize*) frameSizeCapsPtr.Ptr();
+ − 1454
for(l=0; l<pixelFormat->iNumFrameSizes; l++ )
+ − 1455
{
+ − 1456
if (aConfig.iFrameSize.iWidth == frameSize->iWidth &&
+ − 1457
aConfig.iFrameSize.iHeight == frameSize->iHeight &&
+ − 1458
aConfig.iFrameRate >= frameSize->iMinFrameRate &&
+ − 1459
aConfig.iFrameRate <= frameSize->iMaxFrameRate)
+ − 1460
{
+ − 1461
NKern::ThreadEnterCS();
+ − 1462
Kern::Free(frameSizeCapsBuf);
+ − 1463
NKern::ThreadLeaveCS();
+ − 1464
__KTRACE_CAM(Kern::Printf("<DCameraScLdd::DoValidateConfig"));
+ − 1465
return KErrNone;
+ − 1466
}
+ − 1467
frameSize++;
+ − 1468
}
+ − 1469
NKern::ThreadEnterCS();
+ − 1470
Kern::Free(frameSizeCapsBuf);
+ − 1471
NKern::ThreadLeaveCS();
+ − 1472
return KErrNotFound;
+ − 1473
}
+ − 1474
else
+ − 1475
{
+ − 1476
NKern::ThreadEnterCS();
+ − 1477
Kern::Free(frameSizeCapsBuf);
+ − 1478
NKern::ThreadLeaveCS();
+ − 1479
return r;
+ − 1480
}
+ − 1481
}
+ − 1482
pixelFormat++;
+ − 1483
}
+ − 1484
return KErrNotFound;
+ − 1485
}
+ − 1486
+ − 1487
/**
+ − 1488
The DFC used to re-start the PDD following a data capture error.
+ − 1489
@param aChannel A pointer to the camera driver logical channel object.
+ − 1490
*/
+ − 1491
void DCameraScLdd::RestartDfc(TAny* aChannel)
+ − 1492
{
+ − 1493
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::RestartDfc"));
+ − 1494
+ − 1495
DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
+ − 1496
+ − 1497
if (!drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer)
+ − 1498
drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer=drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->NextAvailableForCapture();
+ − 1499
__ASSERT_ALWAYS(drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iCurrentBuffer,Kern::Fault(KCameraLddPanic,__LINE__));
+ − 1500
+ − 1501
if (!drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iNextBuffer)
+ − 1502
drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->iNextBuffer=drv.iCaptureModeConfig[drv.iCaptureMode].iBufManager->NextAvailableForCapture();
+ − 1503
+ − 1504
drv.DoStart();
+ − 1505
}
+ − 1506
+ − 1507
/**
+ − 1508
The DFC used to handle power down requests from the power manager before a transition into system
+ − 1509
shutdown/standby.
+ − 1510
@param aChannel A pointer to the camera driver logical channel object.
+ − 1511
*/
+ − 1512
void DCameraScLdd::PowerDownDfc(TAny* aChannel)
+ − 1513
{
+ − 1514
DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
+ − 1515
drv.Shutdown();
+ − 1516
drv.iPowerHandler->PowerDownDone();
+ − 1517
}
+ − 1518
+ − 1519
/**
+ − 1520
The DFC used to handle power up requests from the power manager following a transition out of system standby.
+ − 1521
@param aChannel A pointer to the camera driver logical channel object.
+ − 1522
*/
+ − 1523
void DCameraScLdd::PowerUpDfc(TAny* aChannel)
+ − 1524
{
+ − 1525
DCameraScLdd& drv=*(DCameraScLdd*)aChannel;
+ − 1526
drv.iPowerHandler->PowerUpDone();
+ − 1527
}
+ − 1528
+ − 1529
void DCameraScLdd::PanicClientThread(TInt aReason)
+ − 1530
{
+ − 1531
Kern::ThreadKill(iOwningThread, EExitPanic, aReason, KDevCameraScName);
+ − 1532
}
+ − 1533
+ − 1534
/**
+ − 1535
Retrieves the capabilities of the camera sensor.
+ − 1536
@param aBuffer A pointer to a descriptor passed in by the user.
+ − 1537
*/
+ − 1538
TInt DCameraScLdd::GetSensorCaps(TAny* aBuffer)
+ − 1539
{
+ − 1540
// Return the capabilities for this device. Read this from the PDD and
+ − 1541
// then write it to the client
+ − 1542
TInt capsSize = Pdd()->CapsSize();
+ − 1543
TInt bufferSize;
+ − 1544
TInt maxBufferSize;
+ − 1545
Kern::KUDesInfo(*((TDes8*)aBuffer), bufferSize, maxBufferSize);
+ − 1546
if(capsSize>maxBufferSize)
+ − 1547
{
+ − 1548
return KErrArgument;
+ − 1549
}
+ − 1550
NKern::ThreadEnterCS();
+ − 1551
TAny* capsBuf = Kern::Alloc(capsSize);
+ − 1552
if(!capsBuf)
+ − 1553
{
+ − 1554
NKern::ThreadLeaveCS();
+ − 1555
return KErrNoMemory;
+ − 1556
}
+ − 1557
+ − 1558
TPtr8 capsPtr( (TUint8*)capsBuf, capsSize, capsSize );
+ − 1559
Pdd()->Caps(capsPtr);
+ − 1560
NKern::ThreadLeaveCS();
+ − 1561
Kern::InfoCopy(*((TDes8*)aBuffer), capsPtr.Ptr(), capsSize);
+ − 1562
NKern::ThreadEnterCS();
+ − 1563
Kern::Free((TAny*)capsBuf);
+ − 1564
NKern::ThreadLeaveCS();
+ − 1565
return KErrNone;
+ − 1566
}
+ − 1567
+ − 1568
/**
+ − 1569
Retrieves the frame sizes supported for a given pixel format.
+ − 1570
@param aBuffer A pointer to descriptor passed in by the user.
+ − 1571
@param aFrameSizeCapsInfo A structure that holds information regarding the requested capabilities.
+ − 1572
*/
+ − 1573
TInt DCameraScLdd::GetFrameSizeCaps(TAny* aBuffer, TAny* aFrameSizeCapsInfo)
+ − 1574
{
+ − 1575
__KTRACE_CAM(Kern::Printf(">DCameraScLdd::GetFrameSizeCaps()"));
+ − 1576
TInt frameSizeCapsMaxSize;
+ − 1577
TInt frameSizeCapsSize;
+ − 1578
Kern::KUDesInfo(*((TDes8*)aBuffer),frameSizeCapsSize,frameSizeCapsMaxSize);
+ − 1579
SFrameSizeCapsInfo info;
+ − 1580
kumemget((TAny*)&info,aFrameSizeCapsInfo,sizeof(info));
+ − 1581
NKern::ThreadEnterCS();
+ − 1582
// Allocate memory on the heap for the frame size structure.
+ − 1583
TAny* frameSizeCapsBuf = Kern::Alloc(frameSizeCapsMaxSize);
+ − 1584
if (!frameSizeCapsBuf)
+ − 1585
{
+ − 1586
NKern::ThreadLeaveCS();
+ − 1587
return KErrNoMemory;
+ − 1588
}
+ − 1589
TPtr8 frameSizeCapsPtr( (TUint8*)frameSizeCapsBuf, frameSizeCapsMaxSize, frameSizeCapsMaxSize );
+ − 1590
// Request the frame sizes from the Pdd.
+ − 1591
TInt r=Pdd()->FrameSizeCaps(info.iCaptureMode, info.iUidPixelFormat, frameSizeCapsPtr);
+ − 1592
NKern::ThreadLeaveCS();
+ − 1593
if (r!=KErrNone)
+ − 1594
{
+ − 1595
NKern::ThreadEnterCS();
+ − 1596
Kern::Free((TAny*)frameSizeCapsBuf);
+ − 1597
NKern::ThreadLeaveCS();
+ − 1598
return r;
+ − 1599
}
+ − 1600
Kern::InfoCopy(*((TDes8*)aBuffer),frameSizeCapsPtr.Ptr(), frameSizeCapsMaxSize);
+ − 1601
NKern::ThreadEnterCS();
+ − 1602
Kern::Free((TAny*)frameSizeCapsBuf);
+ − 1603
NKern::ThreadLeaveCS();
+ − 1604
return KErrNone;
+ − 1605
}
+ − 1606
+ − 1607
+ − 1608
/**
+ − 1609
Constructor for the buffer manager.
+ − 1610
*/
+ − 1611
DBufferManager::DBufferManager(DCameraScLdd* aLdd)
+ − 1612
: iLdd(aLdd)
+ − 1613
{
+ − 1614
// iChunk=NULL;
+ − 1615
// iNumBuffers=0;
+ − 1616
// iImageBuffer=NULL;
+ − 1617
}
+ − 1618
+ − 1619
/**
+ − 1620
Destructor for the buffer manager.
+ − 1621
@pre The thread must be in a critical section.
+ − 1622
*/
+ − 1623
DBufferManager::~DBufferManager()
+ − 1624
{
+ − 1625
if (iChunk)
+ − 1626
Kern::ChunkClose(iChunk);
+ − 1627
delete[] iImageBuffer;
+ − 1628
}
+ − 1629
+ − 1630
/**
+ − 1631
Second stage constructor for the buffer manager. This version creates a shared chunk and a buffer object for each
+ − 1632
buffer specified within this. Then it commits memory within the chunk for each of these buffers. This also involves the
+ − 1633
creation of a set of buffer lists to manage the buffers.
+ − 1634
@param aNumBuffers The number of buffers required in the shared chunk.
+ − 1635
@param aBufferSize The size of each buffer required in the shared chunk.
+ − 1636
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 1637
@pre The thread must be in a critical section.
+ − 1638
*/
+ − 1639
TInt DBufferManager::Create(TInt aNumBuffers,TInt aBufferSize)
+ − 1640
{
+ − 1641
__KTRACE_CAM(Kern::Printf(">DBufferManager::Create(Bufs-%d,Sz-%d)",aNumBuffers,aBufferSize));
+ − 1642
+ − 1643
TInt r=CreateBufferLists(aNumBuffers);
+ − 1644
if (r!=KErrNone)
+ − 1645
return(r);
+ − 1646
+ − 1647
// Calculate the size of the chunk required for the buffer configuration specified.
+ − 1648
aBufferSize=Kern::RoundToPageSize(aBufferSize);
+ − 1649
TInt pageSize=Kern::RoundToPageSize(1);
+ − 1650
// Leave space for guard pages around each buffer. There is a guard page in between each buffer but
+ − 1651
// NO guard page before the first buffer or after the last buffer
+ − 1652
TUint64 chunkSize=TUint64(aBufferSize+pageSize)*aNumBuffers-pageSize;
+ − 1653
if (chunkSize>(TUint64)KMaxTInt)
+ − 1654
return(KErrNoMemory); // Need more than 2GB of memory!
+ − 1655
+ − 1656
// Create the shared chunk. The PDD supplies most of the chunk create info - but not the maximum size.
+ − 1657
TChunkCreateInfo info;
+ − 1658
info.iMaxSize=(TInt)chunkSize;
+ − 1659
iLdd->Pdd()->GetChunkCreateInfo(info); // Call down to the PDD for the rest.
+ − 1660
+ − 1661
r = Kern::ChunkCreate(info,iChunk,iChunkBase,iChunkMapAttr);
+ − 1662
if (r!=KErrNone)
+ − 1663
return(r);
+ − 1664
+ − 1665
// Commit memory in the chunk for each buffer.
+ − 1666
TInt offset=0;
+ − 1667
TBool isContiguous;
+ − 1668
for (TInt i=0; i<aNumBuffers ; i++)
+ − 1669
{
+ − 1670
r=CommitMemoryForBuffer(offset,aBufferSize,isContiguous);
+ − 1671
if (r!=KErrNone)
+ − 1672
return(r);
+ − 1673
r=iImageBuffer[i].Create(iChunk,offset,aBufferSize,i,isContiguous);
+ − 1674
iImageBuffer[i].iId=i;
+ − 1675
if (r!=KErrNone)
+ − 1676
return(r);
+ − 1677
offset += (aBufferSize+pageSize);
+ − 1678
}
+ − 1679
+ − 1680
return(KErrNone);
+ − 1681
}
+ − 1682
+ − 1683
/**
+ − 1684
Second stage constructor for the buffer manager. This version opens an existing shared chunk using a client supplied
+ − 1685
handle. It then creates a buffer object for each buffer that exists within the chunk as well as creating a set of buffer
+ − 1686
lists to manage the buffers.
+ − 1687
@param aBufConfig The shared chunk buffer configuration object - specifying the geometry of the buffer configuration
+ − 1688
within the shared chunk supplied.
+ − 1689
@param aChunkHandle A handle for the shared chunk supplied by the client.
+ − 1690
@param anOwningThread The thread in which the given handle is valid.
+ − 1691
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 1692
@pre The thread must be in a critical section.
+ − 1693
*/
+ − 1694
TInt DBufferManager::Create(TCameraSharedChunkBufConfig& aBufConfig,TInt aChunkHandle,DThread* anOwningThread)
+ − 1695
{
+ − 1696
__KTRACE_CAM(Kern::Printf(">DBufferManager::Create(Handle-%d)",aChunkHandle));
+ − 1697
+ − 1698
// Validate the buffer configuration information
+ − 1699
if (!aBufConfig.iFlags&KScFlagBufOffsetListInUse)
+ − 1700
return(KErrArgument);
+ − 1701
+ − 1702
TInt numBuffers=aBufConfig.iNumBuffers;
+ − 1703
TInt r=CreateBufferLists(numBuffers);
+ − 1704
if (r!=KErrNone)
+ − 1705
return(r);
+ − 1706
+ − 1707
DChunk* chunk;
+ − 1708
chunk=Kern::OpenSharedChunk(anOwningThread,aChunkHandle,ETrue);
+ − 1709
if (!chunk)
+ − 1710
return(KErrBadHandle);
+ − 1711
iChunk=chunk;
+ − 1712
+ − 1713
// Read the physical address for the 1st buffer in order to determine the kernel address and the map attributes.
+ − 1714
TInt bufferSizeInBytes=aBufConfig.iBufferSizeInBytes;
+ − 1715
+ − 1716
SBufSpecList* bufferSpec=&aBufConfig.iSpec;
+ − 1717
+ − 1718
TInt offset=bufferSpec[0].iBufferOffset;
+ − 1719
+ − 1720
TPhysAddr physAddr;
+ − 1721
r=Kern::ChunkPhysicalAddress(iChunk,offset,bufferSizeInBytes,iChunkBase,iChunkMapAttr,physAddr,NULL);
+ − 1722
if (r!=KErrNone)
+ − 1723
return(r);
+ − 1724
+ − 1725
// Store the supplied buffer info. into each buffer object.
+ − 1726
+ − 1727
for (TInt i=0; i<numBuffers; i++)
+ − 1728
{
+ − 1729
offset=bufferSpec[i].iBufferOffset;
+ − 1730
// Assume it isn't contiguous here - Create() will detect and do the right thing if it is contiguous.
+ − 1731
r=iImageBuffer[i].Create(iChunk,offset,bufferSizeInBytes,i,EFalse);
+ − 1732
iImageBuffer[i].iId=i;
+ − 1733
if (r!=KErrNone)
+ − 1734
return(r);
+ − 1735
}
+ − 1736
__KTRACE_CAM(Kern::Printf("<DBufferManager::Create - %d",KErrNone));
+ − 1737
return(KErrNone);
+ − 1738
}
+ − 1739
+ − 1740
/**
+ − 1741
Copies the contents of the Buffer Manager's configuration into aBufConfig
+ − 1742
@param aBufConfig The buffer that the data is copied into.
+ − 1743
*/
+ − 1744
void DBufferManager::GetBufConfig(TCameraSharedChunkBufConfig& aBufConfig)
+ − 1745
{
+ − 1746
__KTRACE_CAM(Kern::Printf(">DBufferManager::GetBufConfig"));
+ − 1747
TInt numBuffers=iNumBuffers;
+ − 1748
if (numBuffers<=0)
+ − 1749
return;
+ − 1750
+ − 1751
SBufSpecList* bufferSpec=&aBufConfig.iSpec;
+ − 1752
+ − 1753
while (numBuffers--)
+ − 1754
{
+ − 1755
bufferSpec[numBuffers].iBufferOffset=iImageBuffer[numBuffers].iChunkOffset;
+ − 1756
bufferSpec[numBuffers].iBufferId=iImageBuffer[numBuffers].iId;
+ − 1757
}
+ − 1758
+ − 1759
aBufConfig.iNumBuffers=iNumBuffers;
+ − 1760
aBufConfig.iBufferSizeInBytes=iImageBuffer[0].iSize; // They're all the same size - so read from the 1st one.
+ − 1761
aBufConfig.iFlags|=KScFlagBufOffsetListInUse;
+ − 1762
return;
+ − 1763
}
+ − 1764
+ − 1765
/**
+ − 1766
Allocate an array of buffer objects, - one for each buffer contained within the shared chunk.
+ − 1767
@param aNumBuffers The number of buffer objects required.
+ − 1768
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 1769
@pre The thread must be in a critical section.
+ − 1770
*/
+ − 1771
TInt DBufferManager::CreateBufferLists(TInt aNumBuffers)
+ − 1772
{
+ − 1773
__KTRACE_CAM(Kern::Printf(">DBufferManager::CreateBufferLists(Bufs-%d)",aNumBuffers));
+ − 1774
+ − 1775
// Construct the array of buffers.
+ − 1776
iNumBuffers=aNumBuffers;
+ − 1777
iImageBuffer=new TImageBuffer[aNumBuffers];
+ − 1778
if (!iImageBuffer)
+ − 1779
return(KErrNoMemory);
+ − 1780
return(KErrNone);
+ − 1781
}
+ − 1782
+ − 1783
TInt DBufferManager::CommitMemoryForBuffer(TInt aChunkOffset,TInt aSize,TBool& aIsContiguous)
+ − 1784
{
+ − 1785
__KTRACE_CAM(Kern::Printf(">DBufferManager::CommitMemoryForBuffer(Offset-%x,Sz-%d)",aChunkOffset,aSize));
+ − 1786
+ − 1787
// Try for physically contiguous memory first.
+ − 1788
TPhysAddr physicalAddress;
+ − 1789
TInt r=Kern::ChunkCommitContiguous(iChunk,aChunkOffset,aSize,physicalAddress);
+ − 1790
if (r==KErrNone)
+ − 1791
{
+ − 1792
aIsContiguous=ETrue;
+ − 1793
return(r);
+ − 1794
}
+ − 1795
+ − 1796
// Commit memory that isn't contiguous instead.
+ − 1797
aIsContiguous=EFalse;
+ − 1798
r=Kern::ChunkCommit(iChunk,aChunkOffset,aSize);
+ − 1799
return(r);
+ − 1800
}
+ − 1801
+ − 1802
/**
+ − 1803
Reset all image buffer lists to reflect the state at the start of the image capture process.
+ − 1804
@pre The buffer/request queue mutex must be held.
+ − 1805
*/
+ − 1806
void DBufferManager::Reset()
+ − 1807
{
+ − 1808
__KTRACE_CAM(Kern::Printf(">DBufferManager::Reset"));
+ − 1809
+ − 1810
TImageBuffer* pBuf;
+ − 1811
+ − 1812
// Before reseting buffer lists, purge the cache for all cached buffers currently in use by client.
+ − 1813
pBuf=(TImageBuffer*)iInUseBufferQ.First();
+ − 1814
SDblQueLink* anchor=&iInUseBufferQ.iA;
+ − 1815
while (pBuf!=anchor)
+ − 1816
{
+ − 1817
Purge(pBuf);
+ − 1818
pBuf=(TImageBuffer*)pBuf->iNext;
+ − 1819
}
+ − 1820
+ − 1821
// Start by reseting all the lists.
+ − 1822
iFreeBufferQ.iA.iNext=iFreeBufferQ.iA.iPrev=&iFreeBufferQ.iA;
+ − 1823
iCompletedBufferQ.iA.iNext=iCompletedBufferQ.iA.iPrev=&iCompletedBufferQ.iA;
+ − 1824
iInUseBufferQ.iA.iNext=iInUseBufferQ.iA.iPrev=&iInUseBufferQ.iA;
+ − 1825
+ − 1826
// Set the pointers to the current and the next record buffers.
+ − 1827
pBuf=iImageBuffer; // This is the first buffer
+ − 1828
iCurrentBuffer=pBuf++;
+ − 1829
iNextBuffer = pBuf++;
+ − 1830
+ − 1831
// Add all other buffers to the free list.
+ − 1832
TImageBuffer* bufferLimit=iImageBuffer+iNumBuffers;
+ − 1833
while(pBuf<bufferLimit)
+ − 1834
iFreeBufferQ.Add(pBuf++);
+ − 1835
}
+ − 1836
+ − 1837
/**
+ − 1838
Purge the cache for a cached image buffer.
+ − 1839
@param aBuffer The buffer to be purged.
+ − 1840
*/
+ − 1841
void DBufferManager::Purge(TImageBuffer* aBuffer)
+ − 1842
{
+ − 1843
aBuffer->SyncMemoryBeforeDmaRead();
+ − 1844
}
+ − 1845
+ − 1846
/**
+ − 1847
Update buffer lists after an image has been captured.
+ − 1848
@param aResult The result of the image capture operation that has just completed.
+ − 1849
@return A pointer to the next image buffer for capture - or NULL if none are available.
+ − 1850
@pre The buffer/request queue mutex must be held.
+ − 1851
*/
+ − 1852
TImageBuffer* DBufferManager::SetImageCaptured(TInt aResult)
+ − 1853
{
+ − 1854
// Take a copy of the buffer with the image just captured.
+ − 1855
__ASSERT_DEBUG(iCurrentBuffer,Kern::Fault(KCameraLddPanic,__LINE__));
+ − 1856
TImageBuffer* cur=iCurrentBuffer;
+ − 1857
+ − 1858
// Make the queued buffer the current one.
+ − 1859
iCurrentBuffer=iNextBuffer;
+ − 1860
+ − 1861
// Now we need to identify the next image buffer to queue.
+ − 1862
iNextBuffer=NextAvailableForCapture();
+ − 1863
+ − 1864
// Now add the buffer with the image just captured to the 'completed' list.
+ − 1865
if (cur)
+ − 1866
{
+ − 1867
cur->iResult=aResult; // Store the result of the capture operation in the image buffer object.
+ − 1868
iCompletedBufferQ.Add(cur);
+ − 1869
}
+ − 1870
+ − 1871
__KTRACE_CAM(Kern::Printf("<DBufferManager::SetImageCaptured(buf=%08x)-%d",cur->iChunkOffset,aResult));
+ − 1872
return(iNextBuffer);
+ − 1873
}
+ − 1874
+ − 1875
/**
+ − 1876
Remove from the buffer lists the next buffer that is available to queue for transfer.
+ − 1877
@return A pointer to the next image buffer for capture - or NULL if none are available.
+ − 1878
@pre The buffer/request queue mutex must be held.
+ − 1879
*/
+ − 1880
TImageBuffer* DBufferManager::NextAvailableForCapture()
+ − 1881
{
+ − 1882
// We need to identify the next image buffer to queue. Try to get one from the 'free' list.
+ − 1883
TImageBuffer* buffer=(TImageBuffer*)iFreeBufferQ.GetFirst();
+ − 1884
#ifdef DISCARD_COMPLETED_TO_AVOID_OVERFLOW
+ − 1885
// If there are none left on the 'free' list then take one from the completed list.
+ − 1886
if (!buffer)
+ − 1887
buffer=(TImageBuffer*)iCompletedBufferQ.GetFirst();
+ − 1888
#endif
+ − 1889
return(buffer);
+ − 1890
}
+ − 1891
+ − 1892
/**
+ − 1893
Get the next image from the 'completed' capture list. If there is no error associated with the buffer,
+ − 1894
make it 'in use' by the client. Otherwise, return the buffer to the free list.
+ − 1895
@param aRemoveLast If true, the buffer is removed from the tail of the completed capture list, otherwise
+ − 1896
it is removed from the head of this list.
+ − 1897
@return A pointer to the next completed image buffer - or NULL if there is no buffer available.
+ − 1898
@pre The buffer/request queue mutex must be held.
+ − 1899
*/
+ − 1900
TImageBuffer* DBufferManager::GetImageForClient(TBool aRemoveLast)
+ − 1901
{
+ − 1902
__KTRACE_CAM(Kern::Printf("<DBufferManager::GetImageForClient"));
+ − 1903
TImageBuffer* buffer=NULL;
+ − 1904
if (!iCompletedBufferQ.IsEmpty())
+ − 1905
{
+ − 1906
buffer = (aRemoveLast) ? (TImageBuffer*)iCompletedBufferQ.Last() : (TImageBuffer*)iCompletedBufferQ.First();
+ − 1907
buffer->Deque();
+ − 1908
+ − 1909
if (buffer->iResult==KErrNone)
+ − 1910
iInUseBufferQ.Add(buffer);
+ − 1911
else
+ − 1912
iFreeBufferQ.Add(buffer);
+ − 1913
}
+ − 1914
return(buffer);
+ − 1915
}
+ − 1916
+ − 1917
/**
+ − 1918
Release (move to free list) the 'in use' image specified by the given chunk offset.
+ − 1919
@param aChunkOffset The chunk offset corresponding to the buffer to be freed.
+ − 1920
@return The freed image buffer, or NULL if no 'in use' buffer had the specified chunk offset.
+ − 1921
@return KErrNone if buffer moved to the free list;
+ − 1922
1 if the buffer needs to be queued straight away
+ − 1923
KErrArgument if no 'in use' buffer had the specified chunk offset;
+ − 1924
@pre The buffer/request queue mutex must be held.
+ − 1925
*/
+ − 1926
TInt DBufferManager::ReleaseImage(TInt aChunkOffset)
+ − 1927
{
+ − 1928
__KTRACE_CAM(Kern::Printf(">DBufferManager::ReleaseImage(chunkOffset=%08x)",aChunkOffset));
+ − 1929
TInt r=KErrArgument;
+ − 1930
+ − 1931
// Scan 'in use' list for the image buffer
+ − 1932
TImageBuffer* pBuf;
+ − 1933
pBuf=(TImageBuffer*)iInUseBufferQ.First();
+ − 1934
SDblQueLink* anchor=&iInUseBufferQ.iA;
+ − 1935
while (pBuf!=anchor && pBuf->iChunkOffset!=aChunkOffset)
+ − 1936
pBuf=(TImageBuffer*)pBuf->iNext;
+ − 1937
+ − 1938
if (pBuf!=anchor)
+ − 1939
{
+ − 1940
// Buffer found in 'in-use' list.
+ − 1941
if (!iNextBuffer)
+ − 1942
{
+ − 1943
// We need to signal the pdd to queue this buffer straight away.
+ − 1944
iNextBuffer=(TImageBuffer*)pBuf->Deque();
+ − 1945
r=1;
+ − 1946
}
+ − 1947
else
+ − 1948
{
+ − 1949
// Move buffer to the free list.
+ − 1950
iFreeBufferQ.Add(pBuf->Deque());
+ − 1951
r=KErrNone;
+ − 1952
}
+ − 1953
}
+ − 1954
+ − 1955
__KTRACE_CAM(Kern::Printf("<DBufferManager::ReleaseImage(buf=%08x)",((pBuf!=anchor) ? pBuf->iChunkOffset : -1)));
+ − 1956
return(r);
+ − 1957
}
+ − 1958
+ − 1959
/**
+ − 1960
Find the 'in use' image specified by the given chunk offset
+ − 1961
@param aChunkOffset The chunk offset corresponding to the buffer to be freed
+ − 1962
@return The image buffer, or NULL if no 'in use' buffer had the specified chunk offset
+ − 1963
@pre The buffer/request queue mutex must be held.
+ − 1964
*/
+ − 1965
TImageBuffer* DBufferManager::FindInUseImage(TInt aChunkOffset)
+ − 1966
{
+ − 1967
// Scan 'in use' list for the image buffer
+ − 1968
TImageBuffer* pBuf;
+ − 1969
pBuf=(TImageBuffer*)iInUseBufferQ.First();
+ − 1970
SDblQueLink* anchor=&iInUseBufferQ.iA;
+ − 1971
while (pBuf!=anchor && pBuf->iChunkOffset!=aChunkOffset)
+ − 1972
pBuf=(TImageBuffer*)pBuf->iNext;
+ − 1973
+ − 1974
return((pBuf!=anchor)?pBuf:NULL);
+ − 1975
}
+ − 1976
+ − 1977
/**
+ − 1978
Constructor for the image buffer class.
+ − 1979
Clears all member data
+ − 1980
*/
+ − 1981
TImageBuffer::TImageBuffer()
+ − 1982
{
+ − 1983
memclr(this,sizeof(*this));
+ − 1984
}
+ − 1985
+ − 1986
/**
+ − 1987
Destructor for the image buffer class.
+ − 1988
*/
+ − 1989
TImageBuffer::~TImageBuffer()
+ − 1990
{
+ − 1991
delete[] iPhysicalPages;
+ − 1992
}
+ − 1993
+ − 1994
/**
+ − 1995
Second stage constructor for the image buffer class - get information on the memory
+ − 1996
allocated to this buffer.
+ − 1997
@param aChunk The chunk into which the memory is to be commited
+ − 1998
@param aOffset The offset within aChunk for the start of the comitted memory.
+ − 1999
Must be a multiple of the MMU page size.
+ − 2000
@param aSize The number of bytes of memory commited.
+ − 2001
Must be a multiple of the MMU page size.
+ − 2002
@return KErrNone if successful, otherwise one of the other system wide error codes.
+ − 2003
@pre The thread must be in a critical section.
+ − 2004
*/
+ − 2005
TInt TImageBuffer::Create(DChunk* aChunk,TInt aOffset,TInt aSize, TInt aId, TBool aIsContiguous)
+ − 2006
{
+ − 2007
__KTRACE_CAM(Kern::Printf(">TImageBuffer::Create(Off-%x,Sz-%d,Contig-%d)",aOffset,aSize,aIsContiguous));
+ − 2008
+ − 2009
// Save info. on the chunk the buffer is in, and the offset and size of the buffer.
+ − 2010
iChunk=aChunk;
+ − 2011
iChunkOffset=aOffset;
+ − 2012
iId=aId;
+ − 2013
iSize=aSize;
+ − 2014
+ − 2015
TInt r=KErrNone;
+ − 2016
iPhysicalPages=NULL;
+ − 2017
if (!aIsContiguous)
+ − 2018
{
+ − 2019
// Allocate an array for a list of the physical pages.
+ − 2020
iPhysicalPages = new TPhysAddr[aSize/Kern::RoundToPageSize(1)+2];
+ − 2021
if (!iPhysicalPages)
+ − 2022
r=KErrNoMemory;
+ − 2023
}
+ − 2024
+ − 2025
if (r==KErrNone)
+ − 2026
{
+ − 2027
// Get the physical addresses of the pages in the buffer.
+ − 2028
TUint32 mapAttr;
+ − 2029
r=Kern::ChunkPhysicalAddress(aChunk,aOffset,aSize,iLinearAddress,mapAttr,iPhysicalAddress,iPhysicalPages);
+ − 2030
// r = 0 or 1 on success. (1 meaning the physical pages are not contiguous).
+ − 2031
if (r==1)
+ − 2032
{
+ − 2033
// The physical pages are not contiguous.
+ − 2034
iPhysicalAddress=KPhysAddrInvalid; // Mark the physical address as invalid.
+ − 2035
r=(aIsContiguous) ? KErrGeneral : KErrNone;
+ − 2036
}
+ − 2037
if (r==0)
+ − 2038
{
+ − 2039
delete[] iPhysicalPages; // We shouldn't retain this info. if the physical pages are contiguous.
+ − 2040
iPhysicalPages=NULL;
+ − 2041
}
+ − 2042
}
+ − 2043
__KTRACE_CAM(Kern::Printf("<TImageBuffer::Create - %d",r));
+ − 2044
return(r);
+ − 2045
}
+ − 2046
+ − 2047
/**
+ − 2048
Prepares a cacheable buffer for use by the DMA engine, before an image capture.
+ − 2049
*/
+ − 2050
void TImageBuffer::SyncMemoryBeforeDmaRead()
+ − 2051
{
+ − 2052
#ifndef __WINS__
+ − 2053
if (iChunk->iMapAttr&EMapAttrCachedMax)
+ − 2054
{
+ − 2055
Cache::SyncMemoryBeforeDmaRead(iLinearAddress,iSize);
+ − 2056
}
+ − 2057
#endif
+ − 2058
}
+ − 2059
+ − 2060
/**
+ − 2061
Prepare a cacheable buffer for use by the CPU, after an image capture using DMA.
+ − 2062
*/
+ − 2063
void TImageBuffer::SyncMemoryAfterDmaRead()
+ − 2064
{
+ − 2065
#ifndef __WINS__
+ − 2066
if (iChunk->iMapAttr&EMapAttrCachedMax)
+ − 2067
{
+ − 2068
Cache::SyncMemoryAfterDmaRead(iLinearAddress,iSize);
+ − 2069
}
+ − 2070
#endif
+ − 2071
}
+ − 2072
+ − 2073
/**
+ − 2074
Constructor for the capture request queue.
+ − 2075
*/
+ − 2076
TCameraScRequestQueue::TCameraScRequestQueue(NFastMutex* aMutexPtr)
+ − 2077
: iMutexPtr(aMutexPtr)
+ − 2078
{
+ − 2079
iOwningThread=NULL;
+ − 2080
memclr(&iRequest[0],sizeof(TCameraScRequest*)*KMaxCamScRequestsPending);
+ − 2081
}
+ − 2082
+ − 2083
/**
+ − 2084
Destructor for the capture request queue.
+ − 2085
*/
+ − 2086
TCameraScRequestQueue::~TCameraScRequestQueue()
+ − 2087
{
+ − 2088
for (TInt i=0 ; i<KMaxCamScRequestsPending ; i++)
+ − 2089
delete iRequest[i];
+ − 2090
}
+ − 2091
+ − 2092
/**
+ − 2093
Second stage constructor for the capture request queue.
+ − 2094
@param anOwningThread A pointer to the owning client thread.
+ − 2095
@return KErrNone if successful;
+ − 2096
KErrNoMemory if unable to allocate memory for the capture request queue.
+ − 2097
@pre The thread must be in a critical section.
+ − 2098
*/
+ − 2099
TInt TCameraScRequestQueue::Create(DThread* anOwningThread)
+ − 2100
{
+ − 2101
iOwningThread=anOwningThread;
+ − 2102
+ − 2103
// Create the set of available request objects and add them to the unused request queue.
+ − 2104
for (TInt i=0 ; i<KMaxCamScRequestsPending ; i++)
+ − 2105
{
+ − 2106
iRequest[i]=new TCameraScRequest;
+ − 2107
if (!iRequest[i])
+ − 2108
return(KErrNoMemory);
+ − 2109
iUnusedRequestQ.Add(iRequest[i]);
+ − 2110
}
+ − 2111
+ − 2112
return(KErrNone);
+ − 2113
}
+ − 2114
+ − 2115
/**
+ − 2116
Store a request status pointer onto the tail of the capture request queue.
+ − 2117
@param aStatus The request status pointer to be stored.
+ − 2118
@return KErrNone if successful;
+ − 2119
KErrGeneral if the limit on the number of pending capture request (KMaxCamScRequestsPending) would be exceeded.
+ − 2120
@pre The buffer/request queue mutex must be held.
+ − 2121
*/
+ − 2122
TInt TCameraScRequestQueue::Add(TRequestStatus* aStatus)
+ − 2123
{
+ − 2124
TCameraScRequest* req=(TCameraScRequest*)iUnusedRequestQ.GetFirst();
+ − 2125
if (!req)
+ − 2126
return(KErrGeneral); // Must have exceeded KMaxCamScRequestsPending
+ − 2127
+ − 2128
req->iStatus=aStatus;
+ − 2129
iPendRequestQ.Add(req);
+ − 2130
return(KErrNone);
+ − 2131
}
+ − 2132
+ − 2133
/**
+ − 2134
Retrieve the next request status pointer from the head of the capture request queue.
+ − 2135
@return The request status pointer removed or NULL if the list is empty.
+ − 2136
@pre The buffer/request queue mutex must be held.
+ − 2137
*/
+ − 2138
TRequestStatus* TCameraScRequestQueue::Remove()
+ − 2139
{
+ − 2140
TRequestStatus* status=NULL;
+ − 2141
TCameraScRequest* req=(TCameraScRequest*)iPendRequestQ.GetFirst();
+ − 2142
if (req)
+ − 2143
{
+ − 2144
status=req->iStatus;
+ − 2145
iUnusedRequestQ.Add(req);
+ − 2146
}
+ − 2147
return(status);
+ − 2148
}
+ − 2149
+ − 2150
/**
+ − 2151
Remove a specifc request status pointer from the the capture request queue, completing it with a 'KErrCancel' completion reason.
+ − 2152
@param aStatus The request status pointer to be completed.
+ − 2153
@pre The buffer/request queue mutex must be held.
+ − 2154
*/
+ − 2155
void TCameraScRequestQueue::Cancel(TRequestStatus* aStatus)
+ − 2156
{
+ − 2157
// Find the entry concerned
+ − 2158
TCameraScRequest* req=(TCameraScRequest*)iPendRequestQ.First();
+ − 2159
SDblQueLink* anchor=&iPendRequestQ.iA;
+ − 2160
while (req!=anchor && req->iStatus!=aStatus)
+ − 2161
req=(TCameraScRequest*)req->iNext;
+ − 2162
if (req==anchor)
+ − 2163
return;
+ − 2164
+ − 2165
// Remove and cancel it.
+ − 2166
req->Deque();
+ − 2167
iUnusedRequestQ.Add(req);
+ − 2168
NKern::FMSignal(iMutexPtr); // Release the request list mutex while we complete the request. This is safe.
+ − 2169
Kern::RequestComplete(iOwningThread,req->iStatus,KErrCancel);
+ − 2170
NKern::FMWait(iMutexPtr); // Re-acquire the request list mutex.
+ − 2171
}
+ − 2172
+ − 2173
/**
+ − 2174
Remove each request status pointer from the the capture request queue, completing each with a 'KErrCancel' completion reason.
+ − 2175
@pre The buffer/request queue mutex must be held.
+ − 2176
*/
+ − 2177
void TCameraScRequestQueue::CancelAll()
+ − 2178
{
+ − 2179
+ − 2180
TRequestStatus* status;
+ − 2181
while ((status=Remove())!=NULL)
+ − 2182
{
+ − 2183
NKern::FMSignal(iMutexPtr); // Release the request list mutex while we complete the request. This is safe.
+ − 2184
Kern::RequestComplete(iOwningThread,status,KErrCancel);
+ − 2185
NKern::FMWait(iMutexPtr); // Re-acquire the request list mutex.
+ − 2186
}
+ − 2187
}
+ − 2188
+ − 2189
/**
+ − 2190
Constructor for the camera driver power handler class.
+ − 2191
@param aChannel A pointer to the camera driver logical channel which owns this power handler.
+ − 2192
*/
+ − 2193
DCameraScPowerHandler::DCameraScPowerHandler(DCameraScLdd* aChannel)
+ − 2194
: DPowerHandler(KDevCameraScName),
+ − 2195
iChannel(aChannel)
+ − 2196
{
+ − 2197
}
+ − 2198
+ − 2199
/**
+ − 2200
A request from the power manager for the power down of the camera device.
+ − 2201
This is called during a transition of the phone into standby or power off.
+ − 2202
@param aState The target power state; can be EPwStandby or EPwOff only.
+ − 2203
*/
+ − 2204
void DCameraScPowerHandler::PowerDown(TPowerState aPowerState)
+ − 2205
{
+ − 2206
(void)aPowerState;
+ − 2207
__KTRACE_CAM(Kern::Printf(">DCameraScPowerHandler::PowerDown(State-%d)",aPowerState));
+ − 2208
+ − 2209
// Power-down involves hardware access so queue a DFC to perform this from the driver thread.
+ − 2210
iChannel->iPowerDownDfc.Enque();
+ − 2211
}
+ − 2212
+ − 2213
/**
+ − 2214
A request from the power manager for the power up of the camera device.
+ − 2215
This is called during a transition of the phone out of standby.
+ − 2216
*/
+ − 2217
void DCameraScPowerHandler::PowerUp()
+ − 2218
{
+ − 2219
__KTRACE_CAM(Kern::Printf(">DCameraScPowerHandler::PowerUp"));
+ − 2220
+ − 2221
// Power-up involves hardware access so queue a DFC to perform this from the driver thread.
+ − 2222
iChannel->iPowerUpDfc.Enque();
+ − 2223
}