Update contrib.
1 // Copyright (c) 2000-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test/device/t_usbco2.cpp
15 // USB Test Program T_USB, functional part.
16 // Device-side part, to work against USBRFLCT running on the host.
24 #include "t_usb.h" // CActiveConsole, CActiveRW
25 #include "t_usblib.h" // Helpers
28 _LIT(KUsbLddFilename, "eusbc"); // .ldd assumed - it's a filename
29 _LIT(KOtgdiLddFilename, "otgdi");
30 _LIT(KUsbDeviceName, "Usbc");
31 _LIT(KFileName, "\\T_USBFILE.BIN");
32 _LIT(KActivePanic, "T_USB");
34 static const TUint32 KTusbVersion = 20070524; // just an edit date really
35 static const TUint8 KUsbrflctVersionMajor = 1; // the version we're compatible with
36 static const TUint8 KUsbrflctVersionMinor = 5;
37 static const TUint8 KUsbrflctVersionMicro = 0;
39 static const TInt KMaxFileSize = 100 * 1024 * 1024; // 100MB (requires at least 128MB card)
40 static const TInt KInitialBufSz = 0;
41 static const TInt stridx1 = 0xCC;
42 static const TInt stridx2 = 0xEE;
45 // --- class CActiveConsole ---------------------------------------------------------
48 CActiveConsole::CActiveConsole(CConsoleBase* aConsole, TBool aVerboseOutput)
49 : CActive(EPriorityNormal),
52 iBufferSizeChosen(EFalse),
53 iBandwidthPriorityChosen(EFalse),
55 iDoubleBufferingChosen(EFalse),
56 iSoftwareConnect(EFalse),
59 iVerbose(aVerboseOutput)
63 CActiveConsole* CActiveConsole::NewLC(CConsoleBase* aConsole, TBool aVerboseOutput)
65 CActiveConsole* self = new (ELeave) CActiveConsole(aConsole, aVerboseOutput);
66 CleanupStack::PushL(self);
72 CActiveConsole* CActiveConsole::NewL(CConsoleBase* aConsole, TBool aVerboseOutput)
74 CActiveConsole* self = NewLC(aConsole, aVerboseOutput);
80 void CActiveConsole::ConstructL()
82 CActiveScheduler::Add(this);
84 // Load logical driver (LDD)
85 // (There's no physical driver (PDD) with USB: it's a kernel extension DLL which
86 // was already loaded at boot time.)
87 TInt r = User::LoadLogicalDevice(KUsbLddFilename);
88 if (r != KErrNone && r != KErrAlreadyExists)
90 TUSB_PRINT1("Error %d on loading USB LDD", r);
94 TUSB_PRINT("Successfully loaded USB LDD");
100 TUSB_PRINT1("Error %d on opening USB port", r);
104 TUSB_PRINT("Successfully opened USB port");
106 // Create Reader/Writer active object
107 iRW = CActiveRW::NewL(iConsole, &iPort, iVerbose);
110 TUSB_PRINT("Failed to create reader/writer");
114 TUSB_PRINT("Created reader/writer");
116 // Check for OTG support
117 TBuf8<KUsbDescSize_Otg> otg_desc;
118 r = iPort.GetOtgDescriptor(otg_desc);
119 if (!(r == KErrNotSupported || r == KErrNone))
121 TUSB_PRINT1("Error %d while fetching OTG descriptor", r);
125 iOtg = (r != KErrNotSupported) ? ETrue : EFalse;
127 // On an OTG device we have to start the OTG driver, otherwise the Client
128 // stack will remain disabled forever.
131 TUSB_PRINT("Running on OTG device: loading OTG driver");
132 r = User::LoadLogicalDevice(KOtgdiLddFilename);
135 TUSB_PRINT1("Error %d on loading OTG LDD", r);
142 TUSB_PRINT1("Error %d on opening OTG port", r);
146 r = iOtgPort.StartStacks();
149 TUSB_PRINT1("Error %d on starting USB stack", r);
157 TInt CActiveConsole::SetupInterface()
159 // Query the USB device/Setup the USB interface
160 TInt r = QueryUsbClientL();
163 TUSB_PRINT1("Interface setup failed", r);
166 TUSB_PRINT("Interface successfully set up");
168 // Change some descriptors to contain suitable values
169 r = SetupDescriptors();
172 TUSB_PRINT1("Descriptor setup failed", r);
176 // Create device state active object
177 iDeviceStateNotifier = CActiveDeviceStateNotifier::NewL(iConsole, &iPort, iVerbose);
178 if (!iDeviceStateNotifier)
180 TUSB_PRINT("Failed to create device state notifier");
183 iDeviceStateNotifier->Activate();
185 // Create endpoint stall status active object
186 iStallNotifier = CActiveStallNotifier::NewL(iConsole, &iPort, iVerbose);
189 TUSB_PRINT("Failed to create stall notifier");
192 iStallNotifier->Activate();
198 CActiveConsole::~CActiveConsole()
200 TUSB_VERBOSE_PRINT("CActiveConsole::~CActiveConsole()");
201 Cancel(); // base class cancel -> calls our DoCancel
202 delete iRW; // destroy the reader/writer
203 delete iDeviceStateNotifier;
204 delete iStallNotifier;
205 TInt r = iPort.RemoveStringDescriptor(stridx1);
208 TUSB_PRINT1("Error %d on string removal", r);
210 r = iPort.RemoveStringDescriptor(stridx2);
213 TUSB_PRINT1("Error %d on string removal", r);
217 TUSB_PRINT("Running on OTG device: unloading OTG driver");
218 iOtgPort.StopStacks();
220 r = User::FreeLogicalDevice(RUsbOtgDriver::Name());
223 TUSB_PRINT1("Error %d on freeing OTG LDD", r);
226 iPort.Close(); // close USB channel
227 r = User::FreeLogicalDevice(KUsbDeviceName);
230 TUSB_PRINT1("Error %d during unloading USB LDD", r);
234 TUSB_PRINT("Successfully unloaded USB LDD");
238 void CActiveConsole::DoCancel()
240 TUSB_VERBOSE_PRINT("CActiveConsole::DoCancel()");
241 iConsole->ReadCancel();
245 void CActiveConsole::RunL()
247 TUSB_VERBOSE_PRINT("CActiveConsole::RunL()");
248 ProcessKeyPressL(static_cast<TChar>(iConsole->KeyCode()));
252 void CActiveConsole::RequestCharacter()
254 // A request is issued to the CConsoleBase to accept a character from the keyboard.
255 __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
256 if (!iBufferSizeChosen)
258 iConsole->Printf(_L("\n"));
259 iConsole->Printf(_L("++++ Choose max. Transfer Size ++++\n"));
260 iConsole->Printf(_L(" '0' - Set up USB device for USBCV\n"));
261 iConsole->Printf(_L(" '1' - 32 bytes\n"));
262 iConsole->Printf(_L(" '2' - 1024 bytes\n"));
263 iConsole->Printf(_L(" '3' - 64 kbytes\n"));
264 iConsole->Printf(_L(" '4' - 1 Mbyte\n"));
266 else if (!iBandwidthPriorityChosen)
268 iConsole->Printf(_L("\n"));
269 iConsole->Printf(_L("++++ Choose Bandwidth Priority ++++\n"));
270 iConsole->Printf(_L(" '1' - Economical buffering - default\n"));
271 iConsole->Printf(_L(" '2' - More memory than default buffering - Plus1\n"));
272 iConsole->Printf(_L(" '3' - More memory than Plus1 buffering - Plus2\n"));
273 iConsole->Printf(_L(" '4' - Maximum buffering\n"));
275 else if (!iDMAChosen)
277 iConsole->Printf(_L("\n"));
278 iConsole->Printf(_L("++++ Choose Endpoint I/O Transfer Mode ++++\n"));
279 iConsole->Printf(_L(" '1' - Interrupt Mode\n"));
280 iConsole->Printf(_L(" '2' - DMA Mode (recommended)\n"));
282 else if (!iDoubleBufferingChosen)
284 iConsole->Printf(_L("\n"));
285 iConsole->Printf(_L("++++ Choose Endpoint FIFO Mode ++++\n"));
286 iConsole->Printf(_L(" '1' - Normal Buffering Mode\n"));
287 iConsole->Printf(_L(" '2' - Double Buffering Mode (recommended)\n"));
291 iConsole->Printf(_L("\n"));
292 iConsole->Printf(_L("++++ Select Program Option ++++\n"));
293 iConsole->Printf(_L(" 'L'oop test\n"));
294 iConsole->Printf(_L(" Loop test with data 'C'ompare\n"));
295 iConsole->Printf(_L(" 'R'eceive-only test (we receive, host transmits)\n"));
296 iConsole->Printf(_L(" 'T'ransmit-only test\n"));
297 iConsole->Printf(_L(" Receive and 'P'ut (write) to File\n"));
298 iConsole->Printf(_L(" Transmit and 'G'et (read) from File\n"));
299 iConsole->Printf(_L(" Signal Remote-'W'akeup to the host\n"));
300 iConsole->Printf(_L(" 'S'top current transfer\n"));
301 #ifdef WITH_DUMP_OPTION
302 iConsole->Printf(_L(" 'D'ump USB regs to debugout\n"));
304 iConsole->Printf(_L(" Re'E'numerate device\n"));
305 iConsole->Printf(_L(" 'Q'uit this app\n"));
307 iConsole->Read(iStatus);
312 void CActiveConsole::ProcessKeyPressL(TChar aChar)
314 if (aChar == EKeyEscape)
316 RDebug::Print(_L("CActiveConsole: ESC key pressed -> stopping active scheduler..."));
317 CActiveScheduler::Stop();
320 if (!iBufferSizeChosen)
322 // Set maximum buffer size from keypress
326 // This is for creating a USB device that just enumerates,
327 // to be used for compliance testing with USBCV.
328 iRW->SetMaxBufSize(0);
331 iRW->SetMaxBufSize(32);
334 iRW->SetMaxBufSize(1024);
337 iRW->SetMaxBufSize(64 * 1024);
340 iRW->SetMaxBufSize(KMaxBufSize);
343 TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
346 TUSB_PRINT1("Maximum buffer size set to %d bytes", iRW->MaxBufSize());
347 iBufferSizeChosen = ETrue;
349 else if (!iBandwidthPriorityChosen)
351 // Set bandwidth priority from keypress
355 iBandwidthPriority = EUsbcBandwidthOUTDefault | EUsbcBandwidthINDefault;
356 TUSB_PRINT("Bandwith priority set to default");
359 iBandwidthPriority = EUsbcBandwidthOUTPlus1 | EUsbcBandwidthINPlus1;
360 TUSB_PRINT("Bandwith priority set to Plus1");
363 iBandwidthPriority = EUsbcBandwidthOUTPlus2 | EUsbcBandwidthINPlus2;
364 TUSB_PRINT("Bandwith priority set to Plus2");
367 iBandwidthPriority = EUsbcBandwidthINMaximum | EUsbcBandwidthOUTMaximum;
368 TUSB_PRINT("Bandwith priority set to maximum");
371 TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
374 TUSB_PRINT1("(Set to 0x%08X)", iBandwidthPriority);
375 iBandwidthPriorityChosen = ETrue;
377 TUSB_PRINT("Configuring interface...");
378 TInt r = SetupInterface();
381 TUSB_PRINT1("Error: %d. Stopping active scheduler...", r);
382 CActiveScheduler::Stop();
386 else if (!iDMAChosen)
388 // Set DMA mode from keypress
392 TUSB_PRINT("- Trying to deallocate endpoint DMA:\n");
393 DeAllocateEndpointDMA(EEndpoint1);
394 DeAllocateEndpointDMA(EEndpoint2);
397 TUSB_PRINT("- Trying to allocate endpoint DMA:\n");
398 AllocateEndpointDMA(EEndpoint1);
399 AllocateEndpointDMA(EEndpoint2);
402 TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
407 else if (!iDoubleBufferingChosen)
409 // Set Double Buffering from keypress
413 TUSB_PRINT("- Trying to deallocate Double Buffering:\n");
414 DeAllocateDoubleBuffering(EEndpoint1);
415 DeAllocateDoubleBuffering(EEndpoint2);
418 TUSB_PRINT("- Trying to allocate Double Buffering:\n");
419 AllocateDoubleBuffering(EEndpoint1);
420 AllocateDoubleBuffering(EEndpoint2);
423 TUSB_PRINT1("Not a valid input character: %c", aChar.operator TUint());
426 iDoubleBufferingChosen = ETrue;
428 // Everything chosen, so let's re-enumerate...
429 TUSB_PRINT("Enumeration...");
430 TInt r = ReEnumerate();
433 TUSB_PRINT1("Error: %d. Stopping active scheduler...", r);
434 CActiveScheduler::Stop();
437 TUSB_PRINT("Device successfully re-enumerated\n");
439 // Make sure program versions match if testing against USBRFLCT
440 if (iRW->MaxBufSize() != 0)
442 r = iRW->ExchangeVersions();
445 TUSB_PRINT1("Error: %d. Stopping active scheduler...", r);
446 CActiveScheduler::Stop();
453 // Execute one of the 'proper' program functions
456 case 'l': // start loop test
458 TUSB_PRINT("-> Loop test selected\n");
459 iRW->SetTransferMode(ELoop);
462 case 'c': // start loop/compare test
464 TUSB_PRINT("-> Loop test with compare selected\n");
465 iRW->SetTransferMode(ELoopComp);
468 case 'r': // start receive-only test
470 TUSB_PRINT("-> Receive-only test selected\n");
471 iRW->SetTransferMode(EReceiveOnly);
474 case 't': // start transmit-only test
476 TUSB_PRINT("-> Transmit-only test selected\n");
477 iRW->SetTransferMode(ETransmitOnly);
480 case 'g': // start transmit & get-from-file test
482 TUSB_PRINT("-> Transmit from file test selected\n");
483 iRW->SetTransferMode(ETransmitOnly);
484 iRW->ReadFromDisk(ETrue);
487 case 'p': // start receive & put-to-file test
489 TUSB_PRINT("-> Receive to file test selected\n");
490 iRW->SetTransferMode(EReceiveOnly);
491 iRW->WriteToDisk(ETrue);
494 case 'w': // remote-wakeup
496 TUSB_PRINT("-> Signal Remote-wakeup selected\n");
497 iPort.SignalRemoteWakeup();
499 case 's': // stop either
501 TUSB_PRINT("-> Stop transfer selected\n");
504 #ifdef WITH_DUMP_OPTION
505 case 'd': // dump controller registers
507 TUSB_PRINT("-> Dump option selected\n");
508 iPort.DumpRegisters();
512 case 'e': // ReEnumerate()
514 TUSB_PRINT("-> Re-enumerate device selected\n");
519 TUSB_PRINT("-> Quit program selected\n");
520 TUSB_VERBOSE_PRINT("CActiveConsole: stopping active scheduler...");
521 CActiveScheduler::Stop();
524 TUSB_PRINT1("-> Not a valid input character: %c", aChar.operator TUint());
534 #ifdef WITH_DUMP_OPTION
535 void CActiveConsole::QueryRxBuffer()
537 // Let's look whether there's data in the rx buffer
539 TInt r = iPort.QueryReceiveBuffer(EEndpoint2, bytes);
542 RDebug::Print(_L(" Error %d on querying read buffer\n"), r);
546 RDebug::Print(_L(" %d bytes in RX buffer\n"), bytes);
552 TInt CActiveConsole::QueryUsbClientL()
554 // Not really just querying... but rather setting up the whole interface.
555 // It's in fact a bit lengthy, but all these steps are required, once,
556 // and in that order.
558 // Get device/endpoint capabilities
560 // A TPckg, or TPckBuf was not used in the following, because
562 // TPckgBuf<TUsbcEndpointData[KUsbcMaxEndpoints]> databuf;
564 // doesn't work. Also,
566 // TUsbcEndpointData data[KUsbcMaxEndpoints];
567 // TPckgBuf<TUsbcEndpointData[KUsbcMaxEndpoints]> databuf(data);
569 // doesn't work. Also,
571 // TUsbcEndpointData data[KUsbcMaxEndpoints];
572 // TPckgBuf<TUsbcEndpointData[]> databuf(data);
575 // So we seem to have to stick to the ugly cast below.
577 // TUsbcEndpointData data[KUsbcMaxEndpoints];
578 // TPtr8 databuf(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
582 TUsbDeviceCaps d_caps;
583 TInt r = iPort.DeviceCaps(d_caps);
586 TUSB_PRINT1("Error %d on querying device capabilities", r);
589 const TInt n = d_caps().iTotalEndpoints;
591 TUSB_PRINT("### USB device capabilities:");
592 TUSB_PRINT1("Number of endpoints: %d", n);
593 TUSB_PRINT1("Supports Software-Connect: %s",
594 d_caps().iConnect ? _S("yes") : _S("no"));
595 TUSB_PRINT1("Device is Self-Powered: %s",
596 d_caps().iSelfPowered ? _S("yes") : _S("no"));
597 TUSB_PRINT1("Supports Remote-Wakeup: %s",
598 d_caps().iRemoteWakeup ? _S("yes") : _S("no"));
599 TUSB_PRINT1("Supports High-speed: %s",
600 d_caps().iHighSpeed ? _S("yes") : _S("no"));
601 TUSB_PRINT1("Supports OTG: %s",
602 iOtg ? _S("yes") : _S("no"));
603 TUSB_PRINT1("Supports unpowered cable detection: %s",
604 (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ?
605 _S("yes") : _S("no"));
606 TUSB_PRINT1("Supports endpoint resource alloc scheme V2: %s\n",
607 (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) ?
608 _S("yes") : _S("no"));
611 iSoftwareConnect = d_caps().iConnect; // we need to remember this
615 TUSB_PRINT1("Error: only %d endpoints available on device", n);
620 TUsbcEndpointData data[KUsbcMaxEndpoints];
621 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
622 r = iPort.EndpointCaps(dataptr);
625 TUSB_PRINT1("Error %d on querying endpoint capabilities", r);
628 TUSB_PRINT("### USB device endpoint capabilities:");
629 for (TInt i = 0; i < n; i++)
631 const TUsbcEndpointCaps* caps = &data[i].iCaps;
632 TUSB_PRINT2("Endpoint: SizeMask = 0x%08x TypeDirMask = 0x%08x",
633 caps->iSizes, caps->iTypesAndDir);
637 // Set up the active interface
638 TUsbcInterfaceInfoBuf ifc;
640 TBool foundBulkIN = EFalse;
641 TBool foundBulkOUT = EFalse;
642 for (TInt i = 0; i < n; i++)
644 const TUsbcEndpointCaps* const caps = &data[i].iCaps;
645 const TInt mps = caps->MaxPacketSize();
647 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) ==
648 (KUsbEpTypeBulk | KUsbEpDirIn))
650 if (!(mps == 64 || mps == 512))
652 TUSB_PRINT1("Funny Bulk IN MaxPacketSize: %d - T_USB will probably fail...", mps);
654 // EEndpoint1 is going to be our Tx (IN) endpoint
655 ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
656 ifc().iEndpointData[0].iDir = KUsbEpDirIn;
657 ifc().iEndpointData[0].iSize = mps;
662 else if (!foundBulkOUT &&
663 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) ==
664 (KUsbEpTypeBulk | KUsbEpDirOut))
666 if (!(mps == 64 || mps == 512))
668 TUSB_PRINT1("Funny Bulk OUT MaxPacketSize: %d - T_USB will probably fail...", mps);
670 // EEndpoint2 is going to be our Rx (OUT) endpoint
671 ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
672 ifc().iEndpointData[1].iDir = KUsbEpDirOut;
673 ifc().iEndpointData[1].iSize = mps;
674 foundBulkOUT = ETrue;
681 TUSB_PRINT1("No suitable endpoints found", r);
685 _LIT16(ifcname, "T_USB Test Interface (Default Setting 0)");
686 ifc().iString = const_cast<TDesC16*>(&ifcname);
687 ifc().iTotalEndpointsUsed = 2;
688 ifc().iClass.iClassNum = 0xff; // vendor-specific
689 ifc().iClass.iSubClassNum = 0xff; // vendor-specific
690 ifc().iClass.iProtocolNum = 0xff; // vendor-specific
691 r = iPort.SetInterface(0, ifc, iBandwidthPriority);
694 TUSB_PRINT1("Error %d on setting active interface", r);
697 // Find ep's for an alternate ifc setting.
698 // We're not really going to use it, but it gives USBCV et al. more stuff to play with.
699 if (!SupportsAlternateInterfaces())
701 TUSB_PRINT("Alternate Interfaces not supported - skipping alternate setting setup\n");
705 TBool foundIsoIN = EFalse;
706 TBool foundIsoOUT = EFalse;
708 // NB! We cannot assume that any specific device has any given set of
709 // capabilities, so whilst we try and set an assortment of endpoint types
710 // we may not get what we want.
712 // Also, note that the endpoint[] array in the interface descriptor
713 // must be filled from ep[0]...ep[n-1].
715 for (TInt i = 0; i < n; i++)
717 const TUsbcEndpointCaps* const caps = &data[i].iCaps;
718 const TInt mps = caps->MaxPacketSize();
720 (caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirIn)) ==
721 (KUsbEpTypeIsochronous | KUsbEpDirIn))
723 // This is going to be our Iso TX (IN) endpoint
724 ifc().iEndpointData[ep_found].iType = KUsbEpTypeIsochronous;
725 ifc().iEndpointData[ep_found].iDir = KUsbEpDirIn;
726 ifc().iEndpointData[ep_found].iSize = mps;
727 ifc().iEndpointData[ep_found].iInterval = 0x01; // 2^(bInterval-1)ms, bInterval must be [1..16]
728 ifc().iEndpointData[ep_found].iInterval_Hs = 0x01; // same as for FS
729 ifc().iEndpointData[ep_found].iExtra = 2; // 2 extra bytes for Audio Class EP descriptor
734 else if (!foundIsoOUT &&
735 (caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirOut)) ==
736 (KUsbEpTypeIsochronous | KUsbEpDirOut))
738 // This is going to be our Iso RX (OUT) endpoint
739 ifc().iEndpointData[ep_found].iType = KUsbEpTypeIsochronous;
740 ifc().iEndpointData[ep_found].iDir = KUsbEpDirOut;
741 ifc().iEndpointData[ep_found].iSize = mps;
742 ifc().iEndpointData[ep_found].iInterval = 0x01; // 2^(bInterval-1)ms, bInterval must be [1..16]
743 ifc().iEndpointData[ep_found].iExtra = 2; // 2 extra bytes for Audio Class EP descriptor
749 // Let's try to add Bulk endpoints up to the max # of 2.
752 for (TInt i = 0; i < n; i++)
754 const TUsbcEndpointCaps* const caps = &data[i].iCaps;
755 const TUint mps = caps->MaxPacketSize();
756 if (caps->iTypesAndDir & KUsbEpTypeBulk)
758 const TUint dir = (caps->iTypesAndDir & KUsbEpDirIn) ? KUsbEpDirIn : KUsbEpDirOut;
759 ifc().iEndpointData[ep_found].iType = KUsbEpTypeBulk;
760 ifc().iEndpointData[ep_found].iDir = dir;
761 ifc().iEndpointData[ep_found].iSize = mps;
769 TUSB_PRINT("Not enough suitable endpoints found for alt ifc");
770 // not a disaster though
774 _LIT16(ifcname1, "T_USB Test Interface (Alternate Setting 1)");
775 ifc().iString = const_cast<TDesC16*>(&ifcname1);
776 ifc().iTotalEndpointsUsed = ep_found;
777 ifc().iClass.iClassNum = KUsbAudioInterfaceClassCode;
778 ifc().iClass.iSubClassNum = KUsbAudioInterfaceSubclassCode_Audiostreaming;
779 ifc().iClass.iProtocolNum = KUsbAudioInterfaceProtocolCode_Pr_Protocol_Undefined;
780 // Tell the driver that this setting is not interested in Ep0 requests:
781 ifc().iFeatureWord |= KUsbcInterfaceInfo_NoEp0RequestsPlease;
782 r = iPort.SetInterface(1, ifc);
785 TUSB_PRINT1("Error %d on setting alternate interface", r);
792 void CActiveConsole::AllocateEndpointDMA(TEndpointNumber aEndpoint)
794 TInt r = iPort.AllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDMA);
796 RDebug::Print(_L("DMA allocation on endpoint %d: KErrNone"), aEndpoint);
797 else if (r == KErrInUse)
798 RDebug::Print(_L("DMA allocation on endpoint %d: KErrInUse"), aEndpoint);
799 else if (r == KErrNotSupported)
800 RDebug::Print(_L("DMA allocation on endpoint %d: KErrNotSupported"), aEndpoint);
802 RDebug::Print(_L("DMA allocation on endpoint %d: unexpected return value %d"),
804 TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA);
805 TUSB_PRINT2("DMA on endpoint %d %s\n",
806 aEndpoint, res ? _S("allocated") : _S("not allocated"));
808 if ((r == KErrNone) && !res)
809 RDebug::Print(_L("(Allocation success but negative query result: contradiction!)\n"));
810 else if ((r != KErrNone) && res)
811 RDebug::Print(_L("(Allocation failure but positive query result: contradiction!)\n"));
815 void CActiveConsole::DeAllocateEndpointDMA(TEndpointNumber aEndpoint)
817 TInt r = iPort.DeAllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDMA);
819 RDebug::Print(_L("DMA deallocation on endpoint %d: KErrNone"), aEndpoint);
820 else if (r == KErrNotSupported)
821 RDebug::Print(_L("DMA deallocation on endpoint %d: KErrNotSupported"), aEndpoint);
823 RDebug::Print(_L("DMA deallocation on endpoint %d: unexpected return value %d"),
825 TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDMA);
826 TUSB_PRINT2("DMA on endpoint %d %s\n",
827 aEndpoint, res ? _S("allocated") : _S("not allocated"));
831 void CActiveConsole::AllocateDoubleBuffering(TEndpointNumber aEndpoint)
833 TInt r = iPort.AllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
835 RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrNone"), aEndpoint);
836 else if (r == KErrInUse)
837 RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrInUse"), aEndpoint);
838 else if (r == KErrNotSupported)
839 RDebug::Print(_L("Double Buffering allocation on endpoint %d: KErrNotSupported"), aEndpoint);
841 RDebug::Print(_L("Double Buffering allocation on endpoint %d: unexpected return value %d"),
843 TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
844 TUSB_PRINT2("Double Buffering on endpoint %d %s\n",
845 aEndpoint, res ? _S("allocated") : _S("not allocated"));
847 if ((r == KErrNone) && !res)
848 RDebug::Print(_L("(Allocation success but negative query result: contradiction!)\n"));
849 else if ((r != KErrNone) && res)
850 RDebug::Print(_L("(Allocation failure but positive query result: contradiction!)\n"));
854 void CActiveConsole::DeAllocateDoubleBuffering(TEndpointNumber aEndpoint)
856 TInt r = iPort.DeAllocateEndpointResource(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
858 RDebug::Print(_L("Double Buffering deallocation on endpoint %d: KErrNone"), aEndpoint);
859 else if (r == KErrNotSupported)
860 RDebug::Print(_L("Double Buffering deallocation on endpoint %d: KErrNotSupported"), aEndpoint);
862 RDebug::Print(_L("Double Buffering deallocation on endpoint %d: unexpected return value %d"),
864 TBool res = iPort.QueryEndpointResourceUse(aEndpoint, EUsbcEndpointResourceDoubleBuffering);
865 TUSB_PRINT2("Double Buffering on endpoint %d %s\n",
866 aEndpoint, res ? _S("allocated") : _S("not allocated"));
870 TInt CActiveConsole::ReEnumerate()
872 TRequestStatus enum_status;
873 iPort.ReEnumerate(enum_status);
874 if (!iSoftwareConnect)
876 iConsole->Printf(_L("This device does not support software\n"));
877 iConsole->Printf(_L("disconnect/reconnect\n"));
878 iConsole->Printf(_L("Please physically unplug and replug\n"));
879 iConsole->Printf(_L("the USB cable NOW... "));
881 iConsole->Printf(_L("\n>>> START THE USBRFLCT PROGRAM ON THE HOST SIDE NOW <<<\n"));
882 User::WaitForRequest(enum_status);
883 if (enum_status != KErrNone)
885 TUSB_PRINT1("Error: Re-enumeration status = %d", enum_status.Int());
888 TUsbcDeviceState device_state = EUsbcDeviceStateUndefined;
889 TInt r = iPort.DeviceStatus(device_state);
892 TUSB_PRINT1("Error %d on querying device state", r);
896 TUSB_PRINT1("Current device state: %s",
897 (device_state == EUsbcDeviceStateUndefined) ? _S("Undefined") :
898 ((device_state == EUsbcDeviceStateAttached) ? _S("Attached") :
899 ((device_state == EUsbcDeviceStatePowered) ? _S("Powered") :
900 ((device_state == EUsbcDeviceStateDefault) ? _S("Default") :
901 ((device_state == EUsbcDeviceStateAddress) ? _S("Address") :
902 ((device_state == EUsbcDeviceStateConfigured) ? _S("Configured") :
903 ((device_state == EUsbcDeviceStateSuspended) ? _S("Suspended") :
904 _S("Unknown"))))))));
907 // Check the speed of the established physical USB connection
908 iHighSpeed = iPort.CurrentlyUsingHighSpeed();
911 TUSB_PRINT("---> USB High-speed Testing\n");
912 // It can only be 512 bytes when using high-speed.
913 iRW->SetMaxPacketSize(512); // iRW already exists at this point
917 TUSB_PRINT("---> USB Full-speed Testing\n");
918 // We only support 64 bytes when using full-speed.
919 iRW->SetMaxPacketSize(64); // iRW already exists at this point
933 TUSB_PRINT1("Failure occurred! - on line %d", __LINE__); \
934 return KErrGeneral; \
939 TInt CActiveConsole::SetupDescriptors()
941 // === Device Descriptor
943 TInt deviceDescriptorSize = 0;
944 iPort.GetDeviceDescriptorSize(deviceDescriptorSize);
945 test(static_cast<TUint>(deviceDescriptorSize) == KUsbDescSize_Device);
947 TBuf8<KUsbDescSize_Device> deviceDescriptor;
948 TInt r = iPort.GetDeviceDescriptor(deviceDescriptor);
951 const TInt KUsbSpecOffset = 2;
952 const TInt KUsbVendorIdOffset = 8;
953 const TInt KUsbProductIdOffset = 10;
954 const TInt KUsbDevReleaseOffset = 12;
955 // Change the USB spec number to 2.00
956 deviceDescriptor[KUsbSpecOffset] = 0x00;
957 deviceDescriptor[KUsbSpecOffset+1] = 0x02;
958 // Change the device vendor ID (VID) to 0x0E22 (Symbian)
959 deviceDescriptor[KUsbVendorIdOffset] = 0x22; // little endian!
960 deviceDescriptor[KUsbVendorIdOffset+1] = 0x0E;
961 // Change the device product ID (PID) to 0x1111
962 deviceDescriptor[KUsbProductIdOffset] = 0x11;
963 deviceDescriptor[KUsbProductIdOffset+1] = 0x11;
964 // Change the device release number to 3.05
965 deviceDescriptor[KUsbDevReleaseOffset] = 0x05;
966 deviceDescriptor[KUsbDevReleaseOffset+1] = 0x03;
967 r = iPort.SetDeviceDescriptor(deviceDescriptor);
970 const TUint16 Vid = (((TUint16)deviceDescriptor[KUsbVendorIdOffset + 1] << 8) & 0xff00) |
971 deviceDescriptor[KUsbVendorIdOffset];
972 const TUint16 Pid = (((TUint16)deviceDescriptor[KUsbProductIdOffset + 1] << 8) & 0xff00) |
973 deviceDescriptor[KUsbProductIdOffset];
975 TUSB_PRINT6("\nVID = 0x%04X / PID = 0x%04X / DevRel = %d%d.%d%d\n", Vid, Pid,
976 ((deviceDescriptor[KUsbDevReleaseOffset + 1] >> 4) & 0x0f),
977 (deviceDescriptor[KUsbDevReleaseOffset + 1] & 0x0f),
978 ((deviceDescriptor[KUsbDevReleaseOffset] >> 4) & 0x0f),
979 (deviceDescriptor[KUsbDevReleaseOffset] & 0x0f));
981 // === Configuration Descriptor
983 TInt configDescriptorSize = 0;
984 iPort.GetConfigurationDescriptorSize(configDescriptorSize);
985 test(static_cast<TUint>(configDescriptorSize) == KUsbDescSize_Config);
987 TBuf8<KUsbDescSize_Config> configDescriptor;
988 r = iPort.GetConfigurationDescriptor(configDescriptor);
991 // Change the reported max power to 100mA (= 2 * 0x32),
992 // which is the highest value allowed for a bus-powered device.
993 const TInt KUsbMaxPowerOffset = 8;
994 configDescriptor[KUsbMaxPowerOffset] = 0x32;
995 r = iPort.SetConfigurationDescriptor(configDescriptor);
998 // === String Descriptors
1000 // Set up two arbitrary string descriptors, which can be queried
1001 // manually from the host side for testing purposes (for instance
1002 // using 'usbcheck').
1004 _LIT16(string_one, "Arbitrary String Descriptor Test String 1");
1005 TBuf16<KUsbStringDescStringMaxSize / 2> wr_str(string_one);
1006 r = iPort.SetStringDescriptor(stridx1, wr_str);
1007 test(r == KErrNone);
1009 _LIT16(string_two, "Another Arbitrary String Descriptor Test String");
1010 wr_str.FillZ(wr_str.MaxLength());
1011 wr_str = string_two;
1012 r = iPort.SetStringDescriptor(stridx2, wr_str);
1013 test(r == KErrNone);
1020 // --- class CActiveRW ---------------------------------------------------------
1023 CActiveRW::CActiveRW(CConsoleBase* aConsole, RDevUsbcClient* aPort, TBool aVerboseOutput)
1024 : CActive(EPriorityNormal),
1027 iBufSz(KInitialBufSz),
1028 iMaxBufSz(KInitialBufSz),
1030 iCurrentXfer(ENone),
1034 iVerbose(aVerboseOutput)
1036 TUSB_VERBOSE_PRINT("CActiveRW::CActiveRW()");
1040 CActiveRW* CActiveRW::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort, TBool aVerboseOutput)
1042 CActiveRW* self = new (ELeave) CActiveRW(aConsole, aPort, aVerboseOutput);
1043 CleanupStack::PushL(self);
1045 CActiveScheduler::Add(self);
1046 CleanupStack::Pop(); // self
1051 void CActiveRW::ConstructL()
1053 TUSB_VERBOSE_PRINT("CActiveRW::ConstructL()");
1055 User::LeaveIfError(iFs.Connect());
1057 // Prepare Preamble buffer
1058 iPreambleBuf.SetMax();
1059 iPreambleBuf.FillZ();
1061 // Prepare IN data buffer
1063 for (TInt i = 0; i < iWriteBuf.MaxSize(); i++)
1068 // Prepare OUT data buffer
1071 // Create read timeout timer active object (but don't activate it yet)
1072 iTimeoutTimer = CActiveTimer::NewL(iConsole, iPort, iVerbose);
1075 TUSB_PRINT("Failed to create timeout timer");
1080 CActiveRW::~CActiveRW()
1082 TUSB_VERBOSE_PRINT("CActiveRW::~CActiveRW()");
1083 Cancel(); // base class
1084 delete iTimeoutTimer;
1090 void CActiveRW::SetMaxBufSize(TInt aBufSz)
1092 if (aBufSz > KMaxBufSize)
1094 TUSB_PRINT2("SetMaxBufSize(): too large: %d! (using %d)", aBufSz, KMaxBufSize);
1095 aBufSz = KMaxBufSize;
1101 void CActiveRW::SetMaxPacketSize(TInt aPktSz)
1107 TInt CActiveRW::MaxBufSize() const
1113 void CActiveRW::SetTransferMode(TXferMode aMode)
1116 if (aMode == EReceiveOnly || aMode == ETransmitOnly)
1118 // For streaming transfers we do this only once.
1124 void CActiveRW::RunL()
1126 TUSB_VERBOSE_PRINT("CActiveRW::RunL()");
1127 if (iStatus != KErrNone)
1129 TUSB_PRINT1("Error %d in RunL", iStatus.Int());
1133 TUSB_PRINT("Stopped");
1137 switch (iCurrentXfer)
1140 if (iXferMode != EReceiveOnly)
1141 SendData(); // next we write data
1143 ReadData(); // or we read data
1146 if (iXferMode == ETransmitOnly)
1147 SendData(); // next we send data
1149 ReadData(); // or we read data
1152 if (iXferMode == EReceiveOnly)
1154 const TUint32 num = *reinterpret_cast<const TUint32*>(iReadBuf.Ptr());
1155 if (num != ++iPktNum)
1157 TUSB_PRINT2("*** rcv'd wrong pkt number: 0x%x (expected: 0x%x)", num, iPktNum);
1158 // Update the packet number with the received number, so that
1159 // if a single packet is duplicated or lost then a single error occurs
1162 if (iDiskAccessEnabled)
1164 // Write out to disk previous completed Read
1165 TUSB_VERBOSE_PRINT2("iMaxBufSz = %d (iReadBuf.Size(): %d)",
1166 iMaxBufSz, iReadBuf.Size());
1167 WriteBufferToDisk(iReadBuf, iMaxBufSz);
1169 ReadData(); // next we read data
1172 if (iXferMode == ELoopComp)
1174 if (!CompareBuffers(iBufSz))
1176 TUSB_PRINT1("Error while comparing tx & rx buffers for packet 0x%x", iPktNum);
1179 else if (iBufSz > 3)
1181 const TUint32 num = *reinterpret_cast<const TUint32*>(iReadBuf.Ptr());
1184 TUSB_PRINT2("*** rcv'd wrong pkt number: 0x%x (expected: 0x%x)", num, iPktNum);
1187 if (iBufSz == iMaxBufSz)
1189 iBufSz = KInitialBufSz;
1195 SendPreamble(); // next we send the length
1198 TUSB_PRINT("Oops. (Shouldn't end up here...)");
1205 TInt CActiveRW::SendVersion()
1207 TUSB_VERBOSE_PRINT("CActiveRW::SendVersion()");
1208 if (iXferMode != ::ENone)
1210 TUSB_PRINT1("Error : wrong state: %d", iXferMode);
1213 // Here we send our version packet to the host.
1214 // (We can use the preamble buffer because we only need it
1215 // once and that's also before the preamble uses.)
1216 TUSB_PRINT1("Sending T_USB version: %d\n", KTusbVersion);
1217 iPreambleBuf.FillZ();
1218 *reinterpret_cast<TUint32*>(&iPreambleBuf[0]) = SWAP_BYTES_32(KTusbVersion);
1219 // A 'magic' string so that USBRFLCT doesn't interpret the first 4 bytes
1220 // of a data preamble packet of an old T_USB as the version number.
1221 iPreambleBuf[4] = 'V';
1222 iPreambleBuf[5] = 'e';
1223 iPreambleBuf[6] = 'r';
1224 iPreambleBuf[7] = 's';
1225 TRequestStatus send_status;
1226 iPort->Write(send_status, EEndpoint1, iPreambleBuf, KPreambleLength);
1227 TUSB_VERBOSE_PRINT("Waiting for write request to complete...");
1228 User::WaitForRequest(send_status);
1229 TUSB_VERBOSE_PRINT("...done.\n");
1230 return send_status.Int();
1234 TInt CActiveRW::ReceiveVersion()
1236 TUSB_VERBOSE_PRINT("CActiveRW::ReceiveVersion()");
1237 if (iXferMode != ::ENone)
1239 TUSB_PRINT1("Error : wrong state: %d", iXferMode);
1242 // Here we try to receive a version packet from the host.
1243 // (We can use the preamble buffer because we only need it
1244 // once and that's also before the preamble uses.)
1245 TUSB_PRINT("Getting host program versions...");
1246 iPreambleBuf.FillZ();
1247 TRequestStatus receive_status;
1248 iPort->Read(receive_status, EEndpoint2, iPreambleBuf, KPreambleLength);
1249 TUSB_VERBOSE_PRINT("Waiting for read request to complete...");
1250 iTimeoutTimer->Activate(5000000); // Host gets 5s
1251 User::WaitForRequest(receive_status, iTimeoutTimer->iStatus);
1252 if (receive_status == KRequestPending)
1254 // Read() still pending...
1255 TUSB_PRINT("Cancelling USB Read(): no response from host.\n");
1256 iPort->ReadCancel(EEndpoint2);
1257 TUSB_PRINT("THIS COULD BE DUE TO AN OLD VERSION OF USBRFLCT ON THE PC:");
1258 TUSB_PRINT3("PLEASE CHECK THE VERSION THERE - WE NEED AT LEAST V%d.%d.%d!\n",
1259 KUsbrflctVersionMajor, KUsbrflctVersionMinor, KUsbrflctVersionMicro);
1260 TUSB_PRINT("When updating an existing USBRFLCT installation <= v1.3.1,\n" \
1261 L"the following three things will need to be done:\n");
1262 TUSB_PRINT("1. Connect the device to the PC & start T_USB (just as now),\n" \
1263 L"then find the USB device in the Windows Device Manager\n" \
1264 L"('Control Panel'->'System'->'Hardware'->'Device Manager').\n" \
1265 L"Right click on the device name and choose 'Uninstall...'.\n");
1266 TUSB_PRINT("2. In c:\\winnt\\inf\\, find (by searching for \"Symbian\") and\n" \
1267 L"delete the *.INF file that was used to install the existing\n" \
1268 L"version of USBRFLCT.SYS. Make sure to also delete the\n" \
1269 L"precompiled version of that file (<samename>.PNF).\n");
1270 TUSB_PRINT("3. In c:\\winnt\\system32\\drivers\\, delete the file USBRFLCT.SYS.\n");
1271 TUSB_PRINT("Then unplug & reconnect the USB device and, when prompted, install\n" \
1272 L"the new USBRFLCT.SYS driver using the .INF file from this distribution.\n" \
1273 L"(All files can be found under e32test\\win32\\usbrflct_distribution\\.)\n");
1274 TUSB_PRINT("Use the new USBRFLCT.EXE from this distribution.\n");
1278 TUSB_VERBOSE_PRINT("...done.");
1279 // Timeout not needed any longer
1280 TUSB_VERBOSE_PRINT("Cancelling timeout timer: USB Read() completed.\n");
1281 iTimeoutTimer->Cancel();
1283 return receive_status.Int();
1287 TInt CActiveRW::ExchangeVersions()
1289 TUSB_VERBOSE_PRINT("CActiveRW::ExchangeVersions()");
1290 // First check the version of USBRFLCT that's running on the host
1291 TInt r = ReceiveVersion();
1296 TUint8 usbrflct_ver_major = iPreambleBuf[0];
1297 TUint8 usbrflct_ver_minor = iPreambleBuf[1];
1298 TUint8 usbrflct_ver_micro = iPreambleBuf[2];
1299 TUint8 usbio_ver_major = iPreambleBuf[3];
1300 TUint8 usbio_ver_minor = iPreambleBuf[4];
1301 TUSB_PRINT5("Host-side: USBRFLCT v%d.%d.%d USBIO v%d.%d\n",
1302 usbrflct_ver_major, usbrflct_ver_minor, usbrflct_ver_micro,
1303 usbio_ver_major, usbio_ver_minor);
1304 if (usbrflct_ver_major < KUsbrflctVersionMajor)
1306 TUSB_PRINT1("USBRFLCT version not sufficient (need at least v%d.x.x)\n",
1307 KUsbrflctVersionMajor);
1310 // Just using '<' instead of the seemingly absurd '<= && !==' doesn't work without
1311 // GCC compiler warning because Kxxx can also be zero (in which case there's no '<').
1312 else if ((usbrflct_ver_minor <= KUsbrflctVersionMinor) &&
1313 !(usbrflct_ver_minor == KUsbrflctVersionMinor))
1315 TUSB_PRINT2("USBRFLCT version not sufficient (need at least v%d.%d.x)\n",
1316 KUsbrflctVersionMajor, KUsbrflctVersionMinor);
1319 // Just using '<' instead of the seemingly absurd '<= && !==' doesn't work without
1320 // GCC compiler warning because Kxxx can also be zero (in which case there's no '<').
1321 else if ((usbrflct_ver_micro <= KUsbrflctVersionMicro) &&
1322 !(usbrflct_ver_micro == KUsbrflctVersionMicro))
1324 TUSB_PRINT3("USBRFLCT version not sufficient (need at least v%d.%d.%d)\n",
1325 KUsbrflctVersionMajor, KUsbrflctVersionMinor, KUsbrflctVersionMicro);
1328 // Now we send T_USB's version to the host
1338 void CActiveRW::SendPreamble()
1340 TUSB_VERBOSE_PRINT("CActiveRW::SendPreamble()");
1341 __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
1342 TUSB_VERBOSE_PRINT1("Sending data length: %d bytes", iBufSz);
1343 *reinterpret_cast<TUint32*>(&iPreambleBuf[0]) = SWAP_BYTES_32(iBufSz);
1344 iPort->Write(iStatus, EEndpoint1, iPreambleBuf, KPreambleLength);
1345 iCurrentXfer = EPreamble;
1350 void CActiveRW::SendData()
1352 TUSB_VERBOSE_PRINT("CActiveRW::SendData()");
1353 __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
1354 if (iDiskAccessEnabled)
1356 ReadBufferFromDisk(iWriteBuf, iBufSz);
1361 *reinterpret_cast<TUint32*>(const_cast<TUint8*>(iWriteBuf.Ptr())) = iPktNum;
1363 if (iXferMode == ELoopComp)
1365 for (TInt i = 4; i < iBufSz; i++)
1367 iWriteBuf[i] = static_cast<TUint8>(iPktNum & 0x000000ff);
1370 TUSB_VERBOSE_PRINT1("Sending data: %d bytes", iBufSz);
1371 iPort->Write(iStatus, EEndpoint1, iWriteBuf, iBufSz);
1372 iCurrentXfer = EWriteXfer;
1377 TInt CActiveRW::SelectDrive()
1379 TDriveList driveList;
1380 TInt r = iFs.DriveList(driveList);
1383 TUSB_PRINT1("RFs::DriveList() returned %d", r);
1386 TUSB_PRINT("Available drives:");
1387 for (TInt n = 0; n < KMaxDrives; n++)
1389 if (driveList[n] != 0)
1391 TVolumeInfo volumeInfo;
1392 r = iFs.Volume(volumeInfo, n);
1395 TPtr name(volumeInfo.iName.Des());
1396 TUSB_PRINT2("Drive %c: %- 16S", 'A' + n, &name);
1397 if (volumeInfo.iDrive.iMediaAtt & KMediaAttWriteProtected)
1398 TUSB_PRINT(" (read-only)");
1403 iConsole->Printf(_L("Please select a drive letter (or 'Q' to quit)..."));
1406 TVolumeInfo volumeInfo;
1409 driveLetter = (TUint)iConsole->Getch();
1410 driveLetter.UpperCase();
1411 if (driveLetter == 'Q')
1415 driveNumber = (TUint)driveLetter - 'A';
1416 r = iFs.Volume(volumeInfo, driveNumber);
1418 while ((driveNumber < 0) ||
1419 (driveNumber >= KMaxDrives) ||
1421 (driveList[driveNumber] == 0) ||
1422 (volumeInfo.iDrive.iMediaAtt & KMediaAttWriteProtected));
1424 iFileName.Format(_L("%c:"), driveLetter.operator TUint());
1425 iFileName.Append(KFileName);
1426 TUSB_PRINT1("\nFilename = %S", &iFileName);
1427 TUSB_PRINT1("File size: %d", KMaxFileSize);
1432 TInt CActiveRW::WriteToDisk(TBool aEnable)
1434 iDiskAccessEnabled = aEnable;
1437 if (iDiskAccessEnabled)
1442 iDiskAccessEnabled = EFalse;
1445 // open the record file
1446 r = iFile.Replace(iFs, iFileName, EFileWrite);
1453 TInt CActiveRW::ReadFromDisk(TBool aEnable)
1455 iDiskAccessEnabled = aEnable;
1458 if (iDiskAccessEnabled)
1463 iDiskAccessEnabled = EFalse;
1466 // First create the file & fill it
1467 r = iFile.Replace(iFs, iFileName, EFileWrite);
1470 TUSB_PRINT1("RFile::Replace() returned %d", r);
1471 iDiskAccessEnabled = EFalse;
1474 const TInt KBufferSize = 4 * 1024;
1475 TBuf8<KBufferSize> buffer;
1476 buffer.SetLength(KBufferSize);
1477 for (TInt n = 0; n < KBufferSize; n++)
1479 buffer[n] = static_cast<TUint8>(n & 0x000000ff);
1481 TUSB_PRINT("Writing data to file (this may take some minutes...)");
1482 for (TInt n = 0; n < KMaxFileSize; n += KBufferSize)
1484 r = iFile.Write(buffer, KBufferSize);
1487 TUSB_PRINT1("RFile::Write() returned %d (disk full?)", r);
1489 iDiskAccessEnabled = EFalse;
1493 TUSB_PRINT("Done.");
1495 // Now open the file for reading
1496 r = iFile.Open(iFs, iFileName, EFileRead);
1499 TUSB_PRINT1("RFile::Open() returned %d", r);
1500 iDiskAccessEnabled = EFalse;
1509 void CActiveRW::WriteBufferToDisk(TDes8& aBuffer, TInt aLen)
1511 TUSB_VERBOSE_PRINT1("CActiveRW::WriteBufferToDisk(), len = %d", aLen);
1512 TInt r = iFile.Write(aBuffer, aLen);
1515 TUSB_PRINT2("Error writing to %S (%d)", &iFileName, r);
1516 iDiskAccessEnabled = EFalse;
1519 iFileOffset += aLen;
1520 if (iFileOffset >= KMaxFileSize)
1523 iFile.Seek(ESeekStart, iFileOffset);
1528 void CActiveRW::ReadBufferFromDisk(TDes8& aBuffer, TInt aLen)
1530 if (iFileOffset + aLen >= KMaxFileSize)
1533 iFile.Seek(ESeekStart, iFileOffset);
1535 const TInt r = iFile.Read(aBuffer, aLen);
1538 TUSB_PRINT2("Error reading from %S (%d)", &iFileName, r);
1539 iDiskAccessEnabled = EFalse;
1542 TInt readLen = aBuffer.Length();
1543 TUSB_VERBOSE_PRINT1("CActiveRW::ReadBufferFromDisk(), len = %d\n", readLen);
1546 TUSB_PRINT3("Only %d bytes of %d read from file %S)",
1547 readLen, aLen, &iFileName);
1548 iDiskAccessEnabled = EFalse;
1551 iFileOffset += aLen;
1555 void CActiveRW::ReadData()
1557 TUSB_VERBOSE_PRINT("CActiveRW::ReadData()");
1558 __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
1559 TUSB_VERBOSE_PRINT1("Reading data: %d bytes", iBufSz);
1560 if (iXferMode == EReceiveOnly)
1562 TUSB_VERBOSE_PRINT(" (rx only)");
1563 iPort->Read(iStatus, EEndpoint2, iReadBuf, iBufSz);
1565 else if (iBufSz == iMaxPktSz)
1567 // we also want to test the packet version of Read()
1568 TUSB_VERBOSE_PRINT(" (a single packet)");
1569 iPort->ReadPacket(iStatus, EEndpoint2, iReadBuf, iBufSz);
1571 else if (iBufSz == iReadBuf.MaxSize())
1573 // or we could perhaps test the three-parameter version
1574 TUSB_VERBOSE_PRINT(" (w/o length)");
1575 iPort->Read(iStatus, EEndpoint2, iReadBuf);
1579 // otherwise, we use the universal default version
1580 TUSB_VERBOSE_PRINT(" (normal)");
1581 iPort->Read(iStatus, EEndpoint2, iReadBuf, iBufSz);
1583 iCurrentXfer = EReadXfer;
1588 void CActiveRW::Stop()
1592 TUSB_PRINT("CActiveRW::Stop(): Not active");
1595 TUSB_PRINT("Cancelling outstanding transfer requests\n");
1596 iBufSz = KInitialBufSz;
1599 iCurrentXfer = ENone;
1604 void CActiveRW::DoCancel()
1606 TUSB_VERBOSE_PRINT("CActiveRW::DoCancel()");
1607 // Canceling the transfer requests can be done explicitly
1608 // for every transfer...
1609 iPort->WriteCancel(EEndpoint1);
1610 iPort->ReadCancel(EEndpoint2);
1612 iPort->EndpointTransferCancel(~0);
1616 TBool CActiveRW::CompareBuffers(TInt aLen)
1618 TUSB_VERBOSE_PRINT1("CActiveRW::CompareBuffers(%d)", aLen);
1619 for (TInt i = 0; i < aLen; i++)
1621 if (iReadBuf[i] != iWriteBuf[i])
1623 TUSB_VERBOSE_PRINT1("Error: for i = %d:", i);
1624 TUSB_VERBOSE_PRINT2("iReadBuf: %d != iWriteBuf: %d",
1625 iReadBuf[i], iWriteBuf[i]);
1634 // --- class CActiveStallNotifier ---------------------------------------------------------
1637 CActiveStallNotifier::CActiveStallNotifier(CConsoleBase* aConsole, RDevUsbcClient* aPort,
1638 TBool aVerboseOutput)
1639 : CActive(EPriorityNormal),
1643 iVerbose(aVerboseOutput)
1645 CActiveScheduler::Add(this);
1648 CActiveStallNotifier* CActiveStallNotifier::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort,
1649 TBool aVerboseOutput)
1651 CActiveStallNotifier* self = new (ELeave) CActiveStallNotifier(aConsole, aPort, aVerboseOutput);
1652 CleanupStack::PushL(self);
1654 CleanupStack::Pop(); // self
1659 void CActiveStallNotifier::ConstructL()
1663 CActiveStallNotifier::~CActiveStallNotifier()
1665 TUSB_VERBOSE_PRINT("CActiveStallNotifier::~CActiveStallNotifier()");
1666 Cancel(); // base class
1670 void CActiveStallNotifier::DoCancel()
1672 TUSB_VERBOSE_PRINT("CActiveStallNotifier::DoCancel()");
1673 iPort->EndpointStatusNotifyCancel();
1677 void CActiveStallNotifier::RunL()
1679 // This just displays the bitmap, showing which endpoints (if any) are now stalled.
1680 // In a real world program, the user could take here appropriate action (cancel a
1681 // transfer request or whatever).
1682 TUSB_VERBOSE_PRINT1("StallNotifier: Endpointstate 0x%x\n", iEndpointState);
1687 void CActiveStallNotifier::Activate()
1689 __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
1690 iPort->EndpointStatusNotify(iStatus, iEndpointState);
1696 // --- class CActiveDeviceStateNotifier ---------------------------------------------------------
1699 CActiveDeviceStateNotifier::CActiveDeviceStateNotifier(CConsoleBase* aConsole, RDevUsbcClient* aPort,
1700 TBool aVerboseOutput)
1701 : CActive(EPriorityNormal),
1705 iVerbose(aVerboseOutput)
1707 CActiveScheduler::Add(this);
1710 CActiveDeviceStateNotifier* CActiveDeviceStateNotifier::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort,
1711 TBool aVerboseOutput)
1713 CActiveDeviceStateNotifier* self = new (ELeave) CActiveDeviceStateNotifier(aConsole, aPort, aVerboseOutput);
1714 CleanupStack::PushL(self);
1716 CleanupStack::Pop(); // self
1721 void CActiveDeviceStateNotifier::ConstructL()
1725 CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier()
1727 TUSB_VERBOSE_PRINT("CActiveDeviceStateNotifier::~CActiveDeviceStateNotifier()");
1728 Cancel(); // base class
1732 void CActiveDeviceStateNotifier::DoCancel()
1734 TUSB_VERBOSE_PRINT("CActiveDeviceStateNotifier::DoCancel()");
1735 iPort->AlternateDeviceStatusNotifyCancel();
1739 void CActiveDeviceStateNotifier::RunL()
1741 // This displays the device state.
1742 // In a real world program, the user could take here appropriate action (cancel a
1743 // transfer request or whatever).
1744 if (!(iDeviceState & KUsbAlternateSetting) && iVerbose)
1746 switch (iDeviceState)
1748 case EUsbcDeviceStateUndefined:
1749 TUSB_PRINT("Device State notifier: Undefined");
1751 case EUsbcDeviceStateAttached:
1752 TUSB_PRINT("Device State notifier: Attached");
1754 case EUsbcDeviceStatePowered:
1755 TUSB_PRINT("Device State notifier: Powered");
1757 case EUsbcDeviceStateDefault:
1758 TUSB_PRINT("Device State notifier: Default");
1760 case EUsbcDeviceStateAddress:
1761 TUSB_PRINT("Device State notifier: Address");
1763 case EUsbcDeviceStateConfigured:
1764 TUSB_PRINT("Device State notifier: Configured");
1766 case EUsbcDeviceStateSuspended:
1767 TUSB_PRINT("Device State notifier: Suspended");
1770 TUSB_PRINT("Device State notifier: ***BAD***");
1773 else if (iDeviceState & KUsbAlternateSetting)
1775 TUSB_PRINT1("Device State notifier: Alternate interface setting has changed: now %d",
1776 iDeviceState & ~KUsbAlternateSetting);
1782 void CActiveDeviceStateNotifier::Activate()
1784 __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
1785 iPort->AlternateDeviceStatusNotify(iStatus, iDeviceState);
1791 // --- class CActiveTimer ---------------------------------------------------------
1794 CActiveTimer::CActiveTimer(CConsoleBase* aConsole, RDevUsbcClient* aPort,
1795 TBool aVerboseOutput)
1796 : CActive(EPriorityNormal),
1799 iVerbose(aVerboseOutput)
1801 CActiveScheduler::Add(this);
1805 CActiveTimer* CActiveTimer::NewL(CConsoleBase* aConsole, RDevUsbcClient* aPort,
1806 TBool aVerboseOutput)
1808 CActiveTimer* self = new (ELeave) CActiveTimer(aConsole, aPort, aVerboseOutput);
1809 CleanupStack::PushL(self);
1811 CleanupStack::Pop(); // self
1816 void CActiveTimer::ConstructL()
1818 User::LeaveIfError(iTimer.CreateLocal());
1822 CActiveTimer::~CActiveTimer()
1824 TUSB_VERBOSE_PRINT("CActiveTimer::~CActiveTimer()");
1825 Cancel(); // base class
1830 void CActiveTimer::DoCancel()
1832 TUSB_VERBOSE_PRINT("CActiveTimer::DoCancel()");
1837 void CActiveTimer::RunL()
1839 TUSB_VERBOSE_PRINT("CActiveTimer::RunL()");
1840 // Nothing to do here, as we call ReadCancel() after a manual WaitForRequest()
1841 // (in CActiveRW::ReceiveVersion()).
1845 void CActiveTimer::Activate(TTimeIntervalMicroSeconds32 aDelay)
1847 __ASSERT_ALWAYS(!IsActive(), User::Panic(KActivePanic, 666));
1848 iTimer.After(iStatus, aDelay);