--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usbclasses/pictbridgeengine/src/dpstransaction.cpp Thu Dec 17 09:14:30 2009 +0200
@@ -0,0 +1,455 @@
+/*
+* Copyright (c) 2006, 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: This class creates and parses dps operations.
+*
+*/
+
+
+#include <e32base.h>
+#include <e32debug.h>
+#include <pathinfo.h>
+#include <s32file.h>
+#include "dpstransaction.h"
+#include "dpsscriptsender.h"
+#include "dpsdefs.h"
+#include "dpsxmlparser.h"
+#include "dpsxmlgenerator.h"
+#include "dpsconst.h"
+#include "dpsfile.h"
+#include "dpsstatemachine.h"
+#include "dpsscriptreceiver.h"
+#include "pictbridge.h"
+#include <xml/parser.h>
+#include "dpsparam.h"
+#include "dpsoperation.h"
+#include "dpsxmlstring.h"
+
+#ifdef _DEBUG
+# define IF_DEBUG(t) {RDebug::t;}
+#else
+# define IF_DEBUG(t)
+#endif
+
+const TInt KPathLength = 3;
+const TInt KPercentagePosition = 3;
+const TInt KPercentage = 100;
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CDpsTransaction* CDpsTransaction::NewL(CDpsStateMachine* aOperator)
+ {
+ IF_DEBUG(Print(_L("CDpsTransaction::NewL")));
+ CDpsTransaction* self = new(ELeave) CDpsTransaction(aOperator);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CDpsTransaction::CDpsTransaction(CDpsStateMachine* aOperator) :
+ iOperator(aOperator), iReply(EFalse)
+ {
+ IF_DEBUG(Print(_L("CDpsTransaction::Ctor")));
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::ConstructL()
+ {
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::ConstructL")));
+ iFile = CDpsFile::NewL();
+ iXmlGen = CDpsXmlGenerator::NewL(iOperator->DpsEngine());
+ iXmlPar = CDpsXmlParser::NewL(iOperator->DpsEngine());
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::ConstructL")));
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+CDpsTransaction::~CDpsTransaction()
+ {
+ IF_DEBUG(Print(_L(">>>~CDpsTransaction")));
+ delete iXmlPar;
+ iXmlPar = NULL;
+
+ delete iXmlGen;
+ iXmlGen = NULL;
+
+ delete iFile;
+ iFile = NULL;
+
+ IF_DEBUG(Print(_L("<<<~CDpsTransaction")));
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::CreateRequestL(TMDpsOperation* aOperation)
+ {
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::CreateRequest ")));
+ IF_DEBUG(Print(_L(" the request is %d"), aOperation->iOperation));
+ TDpsArgArray args;
+ TDpsEleArray elements;
+ TDpsAttribute attrib = 0;
+ CleanupClosePushL(args);
+ CleanupClosePushL(elements);
+ RFileWriteStream writer;
+ writer.PushL();
+ TFileName defaultPath = iOperator->DpsEngine()->DpsFolder();
+ defaultPath.Append(KDpsDeviceRequestFileName);
+ User::LeaveIfError(writer.Replace(iFile->FileSession(), defaultPath,
+ EFileWrite));
+ IF_DEBUG(Print(_L("*** file created ")));
+ User::LeaveIfError(aOperation->FillReqArgs(args, elements, attrib, this));
+ aOperation->CreateReqScriptL(args, elements, attrib, writer, this);
+ writer.CommitL();
+ writer.Pop();
+ writer.Release();
+ User::LeaveIfError(iOperator->ScriptSender()->SendScript(EFalse));
+ CleanupStack::PopAndDestroy(&elements);
+ CleanupStack::PopAndDestroy(&args);
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::CreateRequest ")));
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::Filter(TDes8& aScript)
+ {
+ TInt size = aScript.Size();
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::Filter size %d"), size));
+
+ for (TInt i = 0; i < size; )
+ {
+ // removes any unprintalbe char between two XML attributes, e.g.
+ // between > and <
+ if (aScript[i] >= KSOH && aScript[i] <= KSpace && aScript[i -1] == '>')
+ {
+ aScript.Delete(i, 1);
+ size--;
+ }
+ else
+ {
+ i++;
+ }
+ }
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::Filter size %d"), size));
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::ParseScriptL(TBool aReply)
+ {
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::ParseScript")));
+ iReply = aReply;
+ TInt size;
+ iFile->FileSizeL(iOperator->ScriptReceiver()->FileNameAndPath(), size);
+ HBufC8* script = HBufC8::NewLC(size);
+ TPtr8 ptr_script = script->Des();
+ iFile->GetContentL(iOperator->ScriptReceiver()->FileNameAndPath(),
+ ptr_script);
+ Filter(ptr_script);
+ iXmlPar->Reset();
+ CParser* parser = CParser::NewLC(KDpsXmlMimeType, *iXmlPar);
+ Xml::ParseL(*parser, ptr_script);
+ TDpsArgArray args; iXmlPar->GetParameters(args);
+
+#ifdef _DEBUG
+ //print what we get now
+ TBuf<KMaxArgLen> print;
+ for (TInt i = 0; i < args.Count(); i++)
+ {
+ print.Copy(args[i].iContent);
+ IF_DEBUG(Print(_L("element %d content %S"),
+ args[i].iElement, &print));
+ }
+#endif
+
+ if (aReply)
+ {
+ TMDpsOperation* op = iOperator->MOperation();
+ User::LeaveIfError(op->FillRepArgs(args, this));
+ iXmlPar->SetOperationResult(op->iResult);
+ }
+ else
+ {
+ TDpsResult result;
+ result.iMajorCode = EDpsResultOk;
+ result.iMinorCode = EDpsResultNone;
+ if (iXmlPar->IsEvent())
+ {
+ TDpsEvent event = iXmlPar->Event();
+ iOperator->SetEvent(event);
+ if (event == EDpsEvtNotifyJobStatus)
+ {
+ User::LeaveIfError(iOperator->DpsEngine()->Event()->
+ iJobEvent.FillRepArgs(args, this));
+ }
+ else
+ {
+ User::LeaveIfError(iOperator->DpsEngine()->Event()->
+ iPrinterEvent.FillRepArgs(args, this));
+ }
+ CreateEventReplyL(event, result);
+ }
+ else
+ {
+ // the request from the host is only this one:
+ // GetFileID and used by DPOF printing
+ TDpsOperation ope = iXmlPar->Operation();
+ iOperator->SetOperation(ope);
+ if (iOperator->Operation() != EDpsOpGetFileID)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ CreateRequestReplyL(args, result);
+ }
+ }
+ CleanupStack::PopAndDestroy(parser);
+ CleanupStack::PopAndDestroy(script);
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::ParseScript")));
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::HandleHostRequestError(TInt aErr)
+ {
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::HandleHostRequestError %d"), aErr));
+ TDpsResult result;
+ // here we need to map the aErr to Dps standard error
+ switch (aErr)
+ {
+ case KErrNotSupported:
+ result.iMajorCode = EDpsResultNotRecognized;
+ result.iMinorCode = EDpsResultNone;
+ break;
+
+ case KErrArgument:
+ result.iMajorCode = EDpsResultNotSupported;
+ result.iMinorCode = EDpsResultillegalParam;
+ break;
+
+ default:
+ IF_DEBUG(Print(_L("unknown err")));
+ return;
+ }
+ TRAP_IGNORE(CreateEventReplyL(iXmlPar->Event(), result));
+
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::HandleHostRequestError")));
+ return;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TInt CDpsTransaction::ConvertVersion(TLex8& aParser, TDpsVersion& aVersion)
+ {
+ aParser.Mark();
+ while (!aParser.Eos())
+ {
+ TChar c = aParser.Peek();
+ if (!c.IsDigit())
+ {
+ break;
+ }
+ aParser.Inc();
+ }
+ TPtrC8 token = aParser.MarkedToken();
+ TLex8 converter(token);
+ TInt error = converter.Val(aVersion.iMajor);
+
+ if (error != KErrNone)
+ {
+ IF_DEBUG(Print(_L("\t convert error 1")));
+ return error;
+ }
+ IF_DEBUG(Print(_L("verion major %d"), aVersion.iMajor));
+ aParser.Inc();
+ TPtrC8 tokenDe = aParser.Remainder();
+ converter.Assign(tokenDe);
+ error = converter.Val(aVersion.iMinor);
+ if (error != KErrNone)
+ {
+ IF_DEBUG(Print(_L("\t convert error 2")));
+ return error;
+ }
+ IF_DEBUG(Print(_L("verion minor %d"), aVersion.iMinor));
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TInt CDpsTransaction::ParsePercentage(const TDes8& aPer)
+ {
+ TLex8 parser(aPer);
+ parser.Mark();
+ parser.Inc(KPercentagePosition);
+ TPtrC8 digital = parser.MarkedToken();
+ TLex8 converter(digital);
+ TInt num1;
+ TInt error = converter.Val(num1);
+ if (error != KErrNone)
+ {
+ return error;
+ }
+
+ parser.Inc(1);
+ parser.Mark();
+ parser.Inc(KPercentagePosition);
+ digital.Set(parser.MarkedToken());
+ converter.Assign(digital);
+ TInt num2;
+ error = converter.Val(num2);
+ if (error != KErrNone)
+ {
+ return error;
+ }
+
+ TReal per = (TReal)num1 / (TReal)num2 * KPercentage;
+ return (TInt)per;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::CreateEventReplyL(TDpsEvent aEvent,
+ const TDpsResult& aResult)
+
+ {
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::CreateReply")));
+ IF_DEBUG(Print(_L
+ (" the operation reply is %d"), iOperator->Operation()));
+ IF_DEBUG(Print(_L("\t the event reply is %d"), iOperator->Event()));
+ RFileWriteStream writer;
+ writer.PushL();
+ TFileName defaultPath = iOperator->DpsEngine()->DpsFolder();
+ defaultPath.Append(KDpsDeviceResponseFileName);
+ User::LeaveIfError(writer.Replace(iFile->FileSession(), defaultPath,
+ EFileWrite));
+ IF_DEBUG(Print(_L("*** file created ")));
+ iXmlGen->CreateResultScriptL(aEvent, writer, aResult);
+ writer.CommitL();
+ writer.Pop();
+ writer.Release();
+ User::LeaveIfError(iOperator->ScriptSender()->SendScript(ETrue));
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::CreateReply")));
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::CreateRequestReplyL(const TDpsArgArray& aArgs,
+ const TDpsResult& aResult)
+ {
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::CreateRequestReply")));
+ TInt count = aArgs.Count();
+ TInt basePathId;
+ TBuf8<KMaxArgLen> filePath;
+ TLex8 converter;
+
+ for (TInt i = 0; i < count; i++)
+ {
+ switch (aArgs[i].iElement)
+ {
+ case EDpsArgBasePathID:
+ converter.Assign(aArgs[i].iContent);
+ User::LeaveIfError(converter.Val(basePathId));
+ break;
+
+ case EDpsArgFilePath:
+ filePath.Copy(aArgs[i].iContent);
+ break;
+
+ default:
+ __IF_DEBUG(Print(_L("***wrong args")));
+ User::Leave(KErrArgument);
+ break;
+ }
+ TUint32 fileId;
+
+ SubstitutePath(filePath);
+ TBuf<KMaxArgLen> file;
+ file.Copy(filePath);
+ User::LeaveIfError(iOperator->DpsEngine()->
+ Ptp().GetObjectHandleByName(file, fileId));
+ TDpsArg arg;
+ arg.iElement = EDpsArgFileID;
+ arg.iContent.AppendNumFixedWidth(fileId, EHex, KFullWordWidth);
+ RFileWriteStream writer;
+ writer.PushL();
+ TFileName defaultPath = iOperator->DpsEngine()->DpsFolder();
+ defaultPath.Append(KDpsDeviceResponseFileName);
+ User::LeaveIfError(writer.Replace(iFile->FileSession(), defaultPath,
+ EFileWrite));
+ IF_DEBUG(Print(_L("*** file created ")));
+ iXmlGen->CreateReplyScriptL(EDpsOpGetFileID, writer, aResult, arg);
+ User::LeaveIfError(iOperator->ScriptSender()->SendScript(ETrue));
+ writer.CommitL();
+ writer.Pop();
+ writer.Release();
+ }
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::CreateRequestReply")));
+ }
+
+// ---------------------------------------------------------------------------
+// The aPath is not the full file path, at least the
+// driver letter is not included. The structure of the DPOF filePath is
+// ../path/childpath/imagePrinted.jpg and GetObjectHandleByName
+// requires the full path file as e:\images\image1.jpg
+// the basePathId is not useful because it is always the fileId
+// of AUTPRINT.MRK. But since DPOF is always used for the removable
+// media, we assume that images are only stored in removable media.
+// If the assumption is true (must be true), we need here first to
+// get the removable drive (hopefully only one). Then substitute
+// the / by the \ in the filePath. Finally, insert the removable drive
+// letter and : at the beginning of the filePath. The new full path
+// file can be used by GetObjectHandleByName
+// ---------------------------------------------------------------------------
+//
+void CDpsTransaction::SubstitutePath(TDes8& aPath)
+ {
+ IF_DEBUG(Print(_L(">>>CDpsTransaction::SubstitutePath %S"), &aPath));
+ TInt size = aPath.Size();
+ for (TInt i = 0; i < size; i++)
+ {
+ if (aPath[i] == KSlash)
+ {
+ aPath[i] = KBackSlash;
+ }
+ }
+ TBuf<KPathLength> driveEWide = PathInfo::MemoryCardRootPath();
+ TBuf8<KPathLength> driveENarrow;
+ driveENarrow.Copy(driveEWide);
+ aPath.Replace(0, KPathLength - 1, driveENarrow);
+ IF_DEBUG(Print(_L("<<<CDpsTransaction::SubstitutePath %S"), &aPath));
+ }