Update contrib.
1 // Copyright (c) 2003-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_usbapi.cpp
16 // USB API Test Program (a standalone USB test program).
19 // - Query whether the platform is operating HS (or it is connected to a HS host) or not,
20 // and executes the appropiate tests in each case (see RunTests() for the actual code,
21 // state machine enclosed for clarity):
22 // - Load and open an EUSBC device driver (logical device)
23 // - Setup the USB interface: query device capabilities, setup interface.
24 // - Test allocating DMA and double buffering resources with
25 // AllocateEndpointResource results in their use being correctly reported by
26 // QueryEndpointResourceUse
27 // - Test descriptor manipulation: validate the device, configuration,
28 // interface, alternate interface, endpoint and string descriptor
30 // HS: device_qualifier and other_speed_configuation descriptors.
31 // - Check and validate the EndpointZeroMaxPacketSizes.
32 // - Quick test that calling the following APIs doesn't generate errors: device
33 // control, AlternateDeviceStatusNotify, EndpointStatusNotify
34 // - Test HaltEndpoint and ClearHaltEndpoint correctly result in endpoint
35 // status being reported as stalled/not stalled.
36 // - Test OTG extensions: OTG descriptor manipulations; set/get OTG feature
37 // - Close and free the logical device.
38 // Platforms/Drives/Compatibility:
40 // Assumptions/Requirement/Pre-requisites:
41 // Failures and causes:
42 // Base Port information:
56 // --- Local Top Level Variables
58 static RTest test(_L("T_USBAPI"));
59 static RDevUsbcClient gPort;
60 static RUsbOtgDriver gOTG;
61 static TBool gSupportsOtg;
62 static TBool gSupportsHighSpeed;
63 static TBool gUsingHighSpeed;
65 static TChar gKeychar = 'a';
67 // Store the actual endpoint number(s) of our alternate interface
68 static TInt INT_IN_ep = -1;
70 _LIT(KUsbLddFilename, "eusbc");
71 _LIT(KOtgdiLddFilename, "otgdi");
72 _LIT(KUsbDeviceName, "Usbc");
75 // --- Local Constants
77 static const TInt KUsbDesc_SizeOffset = 0;
78 static const TInt KUsbDesc_TypeOffset = 1;
80 static const TInt KDevDesc_SpecOffset = 2;
81 static const TInt KDevDesc_DevClassOffset = 4;
82 static const TInt KDevDesc_DevSubClassOffset = 5;
83 static const TInt KDevDesc_DevProtocolOffset = 6;
84 static const TInt KDevDesc_Ep0SizeOffset = 7;
85 static const TInt KDevDesc_VendorIdOffset = 8;
86 static const TInt KDevDesc_ProductIdOffset = 10;
87 static const TInt KDevDesc_DevReleaseOffset = 12;
89 static const TInt KConfDesc_AttribOffset = 7;
90 static const TInt KConfDesc_MaxPowerOffset = 8;
92 static const TInt KIfcDesc_SettingOffset = 2;
93 static const TInt KIfcDesc_ProtocolOffset = 7;
95 static const TInt KEpDesc_PacketSizeOffset = 4;
96 static const TInt KEpDesc_IntervalOffset = 6;
97 static const TInt KEpDesc_SynchAddressOffset = 8;
103 static TEndpointState QueryEndpointState(TEndpointNumber aEndpoint)
105 TEndpointState ep_state = EEndpointStateUnknown;
106 TInt r = gPort.EndpointStatus(aEndpoint, ep_state);
108 test.Printf(_L("Endpoint %d state: %s\n"), aEndpoint,
109 (ep_state == EEndpointStateNotStalled) ? _S("Not stalled") :
110 ((ep_state == EEndpointStateStalled) ? _S("Stalled") :
116 // --- Class CActiveKeypressNotifier
118 class CActiveKeypressNotifier : public CActive
121 static CActiveKeypressNotifier* NewL(CConsoleBase* aConsole);
122 ~CActiveKeypressNotifier();
123 void RequestCharacter();
124 void ProcessKeyPressL(TChar aChar);
126 virtual void DoCancel();
128 CActiveKeypressNotifier(CConsoleBase* aConsole);
129 void ConstructL() {};
131 CConsoleBase* iConsole;
135 CActiveKeypressNotifier* CActiveKeypressNotifier::NewL(CConsoleBase* aConsole)
137 CActiveKeypressNotifier* self = new (ELeave) CActiveKeypressNotifier(aConsole);
138 CleanupStack::PushL(self);
140 CActiveScheduler::Add(self);
146 CActiveKeypressNotifier::CActiveKeypressNotifier(CConsoleBase* aConsole)
147 : CActive(EPriorityNormal), iConsole(aConsole)
151 CActiveKeypressNotifier::~CActiveKeypressNotifier()
153 Cancel(); // base class cancel -> calls our DoCancel
157 void CActiveKeypressNotifier::RunL()
159 gKeychar = (static_cast<TChar>(iConsole->KeyCode()));
164 void CActiveKeypressNotifier::DoCancel()
166 iConsole->ReadCancel();
170 void CActiveKeypressNotifier::RequestCharacter()
172 // A request is issued to the CConsoleBase to accept a character from the keyboard.
177 iConsole->Read(iStatus);
182 // --- Actual Test Functions
184 // 2nd Thread helper function
185 static TInt TestThreadFunction(TAny* aPtr)
187 RThread* other = static_cast<RThread*>(aPtr);
188 RDevUsbcClient port = gPort;
189 // Now try to duplicate the USB channel handle
190 TInt r = port.Duplicate(*other);
192 User::After(1000000);
197 static void OpenChannel()
199 test.Start(_L("Open Channel"));
201 test.Next(_L("Load USB LDD"));
202 TInt r = User::LoadLogicalDevice(KUsbLddFilename);
203 test(r == KErrNone || r == KErrAlreadyExists);
205 RDevUsbcClient port1;
206 test.Next(_L("Open local USB channel 1"));
210 test.Next(_L("Open global USB channel"));
214 RDevUsbcClient port2;
215 test.Next(_L("Open local USB channel 2"));
219 test.Next(_L("Close USB channel 1"));
222 RDevUsbcClient port3;
223 test.Next(_L("Open local USB channel 3"));
227 test.Next(_L("Close USB channel 2"));
230 test.Next(_L("Close USB channel 3"));
233 // Check for OTG support
234 TBuf8<KUsbDescSize_Otg> otg_desc;
235 r = gPort.GetOtgDescriptor(otg_desc);
236 test(r == KErrNotSupported || r == KErrNone);
237 gSupportsOtg = (r != KErrNotSupported) ? ETrue : EFalse;
239 // On an OTG device we have to start the OTG driver, otherwise the Client
240 // stack will remain disabled forever.
243 test.Printf(_L("Running on OTG device: loading OTG driver\n"));
244 test.Next(_L("Load OTG LDD"));
245 r = User::LoadLogicalDevice(KOtgdiLddFilename);
246 test((r == KErrNone) || (r == KErrAlreadyExists));
248 test.Next(_L("Open OTG channel"));
252 test.Next(_L("Start OTG stack"));
253 r = gOTG.StartStacks();
257 // Try duplicating channel handle in a second thread
258 // (which should not work because we don't support it)
260 test.Next(_L("Create 2nd Thread"));
262 TThreadId me_id = me.Id();
263 // We need to open the RThread object, otherwise we'll only get the
264 // 'special' handle 0xFFFF8001.
265 test(me.Open(me_id) == KErrNone);
267 TBuf<17> name = _L("tusbapitestthread");
268 test(test_thread.Create(name, TestThreadFunction, 0x1000, NULL, &me) == KErrNone);
269 test.Next(_L("Logon to 2nd Thread"));
271 test_thread.Logon(stat);
272 test(stat == KRequestPending);
273 test_thread.Resume();
274 test.Next(_L("Wait for 2nd Thread to exit"));
275 User::WaitForRequest(stat);
276 // Check correct return value of RDevUsbcClient::Duplicate()
277 test(stat == KErrAccessDenied);
278 test.Next(_L("Close 2nd Thread"));
285 static void TestResourceAllocation()
287 test.Start(_L("Test Endpoint Resource Allocation"));
289 test.Next(_L("Request DMA resource"));
290 const TInt dma = gPort.AllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDMA);
291 TBool res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDMA);
292 test.Printf(_L("DMA on endpoint 1 %s\n"),
293 res ? _S("now allocated") : _S("not allocated"));
295 // Only if DMA resource was successfully allocated should we expect truth here:
300 test.Next(_L("Request Double Buffering resource"));
301 const TInt db = gPort.AllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
302 res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
303 test.Printf(_L("Double Buffering on endpoint 1 %s\n"),
304 res ? _S("now allocated") : _S("not allocated"));
306 // Only if DB resource was successfully allocated should we expect truth here:
311 test.Next(_L("Deallocate Double Buffering resource"));
312 TInt r = gPort.DeAllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
313 // Whether DB is dynamic or permanent - deallocation (if supported) should always return success:
318 res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDoubleBuffering);
319 test.Printf(_L("Double Buffering on endpoint 1 %s\n"),
320 res ? _S("still allocated") : _S("not (longer) allocated"));
322 test.Next(_L("Deallocate DMA resource"));
323 r = gPort.DeAllocateEndpointResource(EEndpoint1, EUsbcEndpointResourceDMA);
324 // Whether DMA is dynamic or permanent - deallocation (if supported) should always return success:
329 res = gPort.QueryEndpointResourceUse(EEndpoint1, EUsbcEndpointResourceDMA);
330 test.Printf(_L("DMA on endpoint 1 %s\n"),
331 res ? _S("still allocated") : _S("not (longer) allocated"));
337 static void SetupInterface()
339 test.Start(_L("Query USB device caps and set up interface"));
342 test.Next(_L("Query USB device caps"));
343 TUsbDeviceCaps d_caps;
344 TInt r = gPort.DeviceCaps(d_caps);
346 TInt n = d_caps().iTotalEndpoints;
348 // Global variable - we'll need this value later
349 gSupportsHighSpeed = d_caps().iHighSpeed;
351 test.Printf(_L("### USB device capabilities:\n"));
352 test.Printf(_L("Number of endpoints: %d\n"), n);
353 test.Printf(_L("Supports Software-Connect: %s\n"),
354 d_caps().iConnect ? _S("yes") : _S("no"));
355 test.Printf(_L("Device is Self-Powered: %s\n"),
356 d_caps().iSelfPowered ? _S("yes") : _S("no"));
357 test.Printf(_L("Supports Remote-Wakeup: %s\n"),
358 d_caps().iRemoteWakeup ? _S("yes") : _S("no"));
359 test.Printf(_L("Supports High-speed: %s\n"),
360 gSupportsHighSpeed ? _S("yes") : _S("no"));
361 test.Printf(_L("Supports OTG: %s\n"),
362 gSupportsOtg ? _S("yes") : _S("no"));
363 test.Printf(_L("Supports unpowered cable detection: %s\n"),
364 (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_CableDetectWithoutPower) ?
365 _S("yes") : _S("no"));
366 test.Printf(_L("Supports endpoint resource alloc scheme V2: %s\n"),
367 (d_caps().iFeatureWord1 & KUsbDevCapsFeatureWord1_EndpointResourceAllocV2) ?
368 _S("yes") : _S("no"));
371 test.Printf(_L("(Device has sufficient endpoints.)\n"));
374 test.Next(_L("Query USB endpoint caps"));
375 TUsbcEndpointData data[KUsbcMaxEndpoints];
376 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
377 r = gPort.EndpointCaps(dataptr);
380 test.Printf(_L("### USB device endpoint capabilities:\n"));
381 for (TInt i = 0; i < n; i++)
383 const TUsbcEndpointCaps* caps = &data[i].iCaps;
384 test.Printf(_L("Endpoint: SizeMask = 0x%08x TypeDirMask = 0x%08x\n"),
385 caps->iSizes, caps->iTypesAndDir);
386 if (caps->iHighBandwidth)
388 test.Printf(_L(" (high-speed, high bandwidth endpoint)\n"));
389 // Must be HS Int or Iso ep
390 test(gSupportsHighSpeed);
391 test(caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpTypeInterrupt));
395 test.Next(_L("Looking for suitable endpoints"));
396 // Set the active interface
397 TUsbcInterfaceInfoBuf ifc;
399 TBool foundBulkIN = EFalse;
400 TBool foundBulkOUT = EFalse;
401 for (TInt i = 0; i < n; i++)
403 const TUsbcEndpointCaps* caps = &data[i].iCaps;
404 const TInt mps = caps->MaxPacketSize();
406 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirIn)) ==
407 (KUsbEpTypeBulk | KUsbEpDirIn))
409 // EEndpoint1 is going to be our TX (IN, write) endpoint
410 ifc().iEndpointData[0].iType = KUsbEpTypeBulk;
411 ifc().iEndpointData[0].iDir = KUsbEpDirIn;
412 ifc().iEndpointData[0].iSize = mps;
417 else if (!foundBulkOUT &&
418 (caps->iTypesAndDir & (KUsbEpTypeBulk | KUsbEpDirOut)) ==
419 (KUsbEpTypeBulk | KUsbEpDirOut))
421 // EEndpoint2 is going to be our RX (OUT, read) endpoint
422 ifc().iEndpointData[1].iType = KUsbEpTypeBulk;
423 ifc().iEndpointData[1].iDir = KUsbEpDirOut;
424 ifc().iEndpointData[1].iSize = mps;
425 foundBulkOUT = ETrue;
432 test.Next(_L("Setting up main interface"));
433 _LIT16(string, "T_USBAPI Test Interface (Setting 0)");
434 ifc().iString = const_cast<TDesC16*>(&string);
435 ifc().iTotalEndpointsUsed = 2;
436 ifc().iClass.iClassNum = 0xff;
437 ifc().iClass.iSubClassNum = 0xff;
438 ifc().iClass.iProtocolNum = 0xff;
439 // Set up the interface.
440 r = gPort.SetInterface(0, ifc);
444 r = gPort.GetAlternateSetting(ifc_no);
445 test(r == KErrUsbDeviceNotConfigured);
447 // Some UDCs won't allow endpoint resource manipulation once the hardware has been
448 // configured and turned on. So we do it here & now:
449 TestResourceAllocation();
451 // On the other hand, since some UDCs won't let us test many features which require
452 // register access until the USB hardware is powered up (and because it might start
453 // out unpowered), we should turn it on here explicitly.
454 // (It will be turned off automatically by the PIL after all tests have been run,
455 // when the interface gets deleted.)
456 test.Next(_L("Powering up UDC (1)"));
457 r = gPort.PowerUpUdc();
464 test((r == KErrNone) || (r == KErrNotReady));
466 if (gSupportsOtg && (r == KErrNotReady))
468 test.Printf(_L("OTG device but not connected to Host, stopping subtest here.\n"));
472 // The board might be attached to a PC with HS controller, thus enabling us
473 // to test some HS-specific features. For that to work we have to connect
474 // the board to the PC. The "Found new device" box that may pop up on the PC
475 // in response to this can be ignored (i.e. just closed).
476 test.Next(_L("Connecting to Host (1)"));
477 r = gPort.DeviceConnectToHost();
479 // Suspend thread to let things get stable on the bus.
480 test.Printf(_L("Waiting a short moment..."));
481 User::After(2000000);
482 test.Printf(_L(" done.\n"));
484 // Check the speed of the physical connection (if any).
485 gUsingHighSpeed = gPort.CurrentlyUsingHighSpeed();
488 test(gSupportsHighSpeed); // sane?
489 test.Printf(_L("---> USB High-speed Testing\n"));
493 test.Printf(_L("---> USB Full-speed Testing\n"));
496 // By pulling down the interface/connection and bringing them up again we
497 // simulate a starting/stopping of the USB service by a control app.
499 test.Next(_L("Disconnecting from Host"));
500 r = gPort.DeviceDisconnectFromHost();
503 test.Next(_L("Releasing interface"));
504 r = gPort.ReleaseInterface(0);
507 test.Next(_L("Setting interface"));
508 r = gPort.SetInterface(0, ifc);
511 // Suspend thread before connecting again.
512 test.Printf(_L("Waiting a short moment..."));
513 User::After(1000000);
514 test.Printf(_L(" done.\n"));
516 test.Next(_L("Powering up UDC (2)"));
517 r = gPort.PowerUpUdc();
524 test((r == KErrNone) || (r == KErrNotReady));
526 if (gSupportsOtg && (r == KErrNotReady))
528 test.Printf(_L("OTG device but not connected to Host, stopping subtest here.\n"));
533 test.Next(_L("Connecting to Host (2)"));
534 r = gPort.DeviceConnectToHost();
536 // Suspend thread to let things get stable on the bus.
537 User::After(2000000);
543 static void TestDeviceDescriptor()
545 test.Start(_L("Device Descriptor Manipulation"));
547 test.Next(_L("GetDeviceDescriptorSize()"));
549 gPort.GetDeviceDescriptorSize(desc_size);
550 test(static_cast<TUint>(desc_size) == KUsbDescSize_Device);
552 test.Next(_L("GetDeviceDescriptor()"));
553 TBuf8<KUsbDescSize_Device> descriptor;
554 TInt r = gPort.GetDeviceDescriptor(descriptor);
557 test.Next(_L("SetDeviceDescriptor()"));
558 // Change the USB spec number to 2.30
559 descriptor[KDevDesc_SpecOffset] = 0x30;
560 descriptor[KDevDesc_SpecOffset+1] = 0x02;
561 // Change the device vendor ID (VID) to 0x1234
562 descriptor[KDevDesc_VendorIdOffset] = 0x34; // little endian
563 descriptor[KDevDesc_VendorIdOffset+1] = 0x12;
564 // Change the device product ID (PID) to 0x1111
565 descriptor[KDevDesc_ProductIdOffset] = 0x11;
566 descriptor[KDevDesc_ProductIdOffset+1] = 0x11;
567 // Change the device release number to 3.05
568 descriptor[KDevDesc_DevReleaseOffset] = 0x05;
569 descriptor[KDevDesc_DevReleaseOffset+1] = 0x03;
570 r = gPort.SetDeviceDescriptor(descriptor);
573 test.Next(_L("GetDeviceDescriptor()"));
574 TBuf8<KUsbDescSize_Device> descriptor2;
575 r = gPort.GetDeviceDescriptor(descriptor2);
578 test.Next(_L("Compare device descriptor with value set"));
579 r = descriptor2.Compare(descriptor);
584 // HS only allows one possible packet size.
585 test(descriptor[KDevDesc_Ep0SizeOffset] == 64);
592 static void TestDeviceQualifierDescriptor()
594 test.Start(_L("Device_Qualifier Descriptor Manipulation"));
596 if (!gSupportsHighSpeed)
598 test.Printf(_L("*** Not supported - skipping Device_Qualifier descriptor tests\n"));
603 test.Next(_L("GetDeviceQualifierDescriptor()"));
604 TBuf8<KUsbDescSize_DeviceQualifier> descriptor;
605 TInt r = gPort.GetDeviceQualifierDescriptor(descriptor);
608 test.Next(_L("SetDeviceQualifierDescriptor()"));
609 // Change the USB spec number to 3.00
610 descriptor[KDevDesc_SpecOffset] = 0x00;
611 descriptor[KDevDesc_SpecOffset+1] = 0x03;
612 // Change the device class, subclass and protocol codes
613 descriptor[KDevDesc_DevClassOffset] = 0xA1;
614 descriptor[KDevDesc_DevSubClassOffset] = 0xB2;
615 descriptor[KDevDesc_DevProtocolOffset] = 0xC3;
616 r = gPort.SetDeviceQualifierDescriptor(descriptor);
619 test.Next(_L("GetDeviceQualifierDescriptor()"));
620 TBuf8<KUsbDescSize_DeviceQualifier> descriptor2;
621 r = gPort.GetDeviceQualifierDescriptor(descriptor2);
624 test.Next(_L("Compare Device_Qualifier desc with value set"));
625 r = descriptor2.Compare(descriptor);
628 if (!gUsingHighSpeed)
630 // HS only allows one possible packet size.
631 test(descriptor[KDevDesc_Ep0SizeOffset] == 64);
638 static void TestConfigurationDescriptor()
640 test.Start(_L("Configuration Descriptor Manipulation"));
642 test.Next(_L("GetConfigurationDescriptorSize()"));
644 gPort.GetConfigurationDescriptorSize(desc_size);
645 test(static_cast<TUint>(desc_size) == KUsbDescSize_Config);
647 test.Next(_L("GetConfigurationDescriptor()"));
648 TBuf8<KUsbDescSize_Config> descriptor;
649 TInt r = gPort.GetConfigurationDescriptor(descriptor);
652 test.Next(_L("SetConfigurationDescriptor()"));
653 // Invert Remote-Wakup support
654 descriptor[KConfDesc_AttribOffset] = (descriptor[KConfDesc_AttribOffset] ^ KUsbDevAttr_RemoteWakeup);
655 // Change the reported max power to 200mA (2 * 0x64)
656 descriptor[KConfDesc_MaxPowerOffset] = 0x64;
657 r = gPort.SetConfigurationDescriptor(descriptor);
660 test.Next(_L("GetConfigurationDescriptor()"));
661 TBuf8<KUsbDescSize_Config> descriptor2;
662 r = gPort.GetConfigurationDescriptor(descriptor2);
665 test.Next(_L("Compare configuration desc with value set"));
666 r = descriptor2.Compare(descriptor);
673 static void TestOtherSpeedConfigurationDescriptor()
675 test.Start(_L("Other_Speed_Configuration Desc Manipulation"));
677 if (!gSupportsHighSpeed)
679 test.Printf(_L("*** Not supported - skipping Other_Speed_Configuration desc tests\n"));
684 test.Next(_L("GetOtherSpeedConfigurationDescriptor()"));
685 TBuf8<KUsbDescSize_OtherSpeedConfig> descriptor;
686 TInt r = gPort.GetOtherSpeedConfigurationDescriptor(descriptor);
689 test.Next(_L("SetOtherSpeedConfigurationDescriptor()"));
690 // Invert Remote-Wakup support
691 descriptor[KConfDesc_AttribOffset] = (descriptor[KConfDesc_AttribOffset] ^ KUsbDevAttr_RemoteWakeup);
692 // Change the reported max power to 330mA (2 * 0xA5)
693 descriptor[KConfDesc_MaxPowerOffset] = 0xA5;
694 r = gPort.SetOtherSpeedConfigurationDescriptor(descriptor);
697 test.Next(_L("GetOtherSpeedConfigurationDescriptor()"));
698 TBuf8<KUsbDescSize_OtherSpeedConfig> descriptor2;
699 r = gPort.GetOtherSpeedConfigurationDescriptor(descriptor2);
702 test.Next(_L("Compare O_S_Config desc with value set"));
703 r = descriptor2.Compare(descriptor);
710 static void TestInterfaceDescriptor()
712 test.Start(_L("Interface Descriptor Manipulation"));
714 // First the standard Interface descriptor
716 test.Next(_L("GetInterfaceDescriptorSize()"));
718 TInt r = gPort.GetInterfaceDescriptorSize(0, desc_size);
720 test(static_cast<TUint>(desc_size) == KUsbDescSize_Interface);
722 test.Next(_L("GetInterfaceDescriptor()"));
723 TBuf8<KUsbDescSize_Interface> descriptor;
724 r = gPort.GetInterfaceDescriptor(0, descriptor);
727 test.Next(_L("SetInterfaceDescriptor()"));
728 // Change the interface protocol to 0x78(+)
730 if (descriptor[KIfcDesc_ProtocolOffset] == prot)
732 descriptor[KIfcDesc_ProtocolOffset] = prot;
733 r = gPort.SetInterfaceDescriptor(0, descriptor);
736 test.Next(_L("GetInterfaceDescriptor()"));
737 TBuf8<KUsbDescSize_Interface> descriptor2;
738 r = gPort.GetInterfaceDescriptor(0, descriptor2);
741 test.Next(_L("Compare interface descriptor with value set"));
742 r = descriptor2.Compare(descriptor);
749 static void TestClassSpecificDescriptors()
751 test.Start(_L("Class-specific Descriptor Manipulation"));
753 // First a class-specific Interface descriptor
755 test.Next(_L("SetCSInterfaceDescriptorBlock()"));
756 // choose arbitrary new descriptor size
757 const TInt KUsbDescSize_CS_Interface = KUsbDescSize_Interface + 10;
758 TBuf8<KUsbDescSize_CS_Interface> cs_ifc_descriptor;
759 cs_ifc_descriptor.FillZ(cs_ifc_descriptor.MaxLength());
760 cs_ifc_descriptor[KUsbDesc_SizeOffset] = KUsbDescSize_CS_Interface;
761 cs_ifc_descriptor[KUsbDesc_TypeOffset] = KUsbDescType_CS_Interface;
762 TInt r = gPort.SetCSInterfaceDescriptorBlock(0, cs_ifc_descriptor);
765 test.Next(_L("GetCSInterfaceDescriptorBlockSize()"));
767 r = gPort.GetCSInterfaceDescriptorBlockSize(0, desc_size);
769 test(desc_size == KUsbDescSize_CS_Interface);
771 test.Next(_L("GetCSInterfaceDescriptorBlock()"));
772 TBuf8<KUsbDescSize_CS_Interface> descriptor;
773 r = gPort.GetCSInterfaceDescriptorBlock(0, descriptor);
776 test.Next(_L("Compare CS ifc descriptor with value set"));
777 r = descriptor.Compare(cs_ifc_descriptor);
780 // Next a class-specific Endpoint descriptor
782 test.Next(_L("SetCSEndpointDescriptorBlock()"));
783 // choose arbitrary new descriptor size
784 const TInt KUsbDescSize_CS_Endpoint = KUsbDescSize_Endpoint + 5;
785 TBuf8<KUsbDescSize_CS_Endpoint> cs_ep_descriptor;
786 cs_ep_descriptor.FillZ(cs_ep_descriptor.MaxLength());
787 cs_ep_descriptor[KUsbDesc_SizeOffset] = KUsbDescSize_CS_Endpoint;
788 cs_ep_descriptor[KUsbDesc_TypeOffset] = KUsbDescType_CS_Endpoint;
789 r = gPort.SetCSEndpointDescriptorBlock(0, 2, cs_ep_descriptor);
792 test.Next(_L("GetCSEndpointDescriptorBlockSize()"));
793 r = gPort.GetCSEndpointDescriptorBlockSize(0, 2, desc_size);
795 test(desc_size == KUsbDescSize_CS_Endpoint);
797 test.Next(_L("GetCSEndpointDescriptorBlock()"));
798 TBuf8<KUsbDescSize_CS_Endpoint> descriptor2;
799 r = gPort.GetCSEndpointDescriptorBlock(0, 2, descriptor2);
802 test.Next(_L("Compare CS ep descriptor with value set"));
803 r = descriptor2.Compare(cs_ep_descriptor);
810 static void TestAlternateInterfaceManipulation()
812 test.Start(_L("Alternate Interface Setting Manipulation"));
814 if (!SupportsAlternateInterfaces())
816 test.Printf(_L("*** Not supported - skipping alternate interface settings tests\n"));
821 // Fetch endpoint data (again)
822 test.Next(_L("Get endpoint capabilities"));
823 TUsbDeviceCaps d_caps;
824 TInt r = gPort.DeviceCaps(d_caps);
826 const TInt n = d_caps().iTotalEndpoints;
827 TUsbcEndpointData data[KUsbcMaxEndpoints];
828 TPtr8 dataptr(reinterpret_cast<TUint8*>(data), sizeof(data), sizeof(data));
829 r = gPort.EndpointCaps(dataptr);
832 // Find ep's for alternate ifc setting
833 test.Next(_L("Find suitable endpoints"));
835 TBool foundIsoIN = EFalse;
836 TBool foundIsoOUT = EFalse;
837 TBool foundIntIN = EFalse;
838 TUsbcInterfaceInfoBuf ifc;
840 // NB! We cannot assume that any specific device has any given set of
841 // capabilities, so whilst we try and set an assortment of endpoint types
842 // we may not get what we want.
844 // Also, note that the endpoint[] array in the interface descriptor
845 // must be filled from ep[0]...ep[n-1].
847 for (TInt i = 0; i < n; i++)
849 const TUsbcEndpointCaps* const caps = &data[i].iCaps;
850 const TInt mps = caps->MaxPacketSize();
852 (caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirIn)) ==
853 (KUsbEpTypeIsochronous | KUsbEpDirIn))
855 // This is going to be our Iso TX (IN) endpoint
856 ifc().iEndpointData[ep_found].iType = KUsbEpTypeIsochronous;
857 ifc().iEndpointData[ep_found].iDir = KUsbEpDirIn;
858 ifc().iEndpointData[ep_found].iSize = mps;
859 ifc().iEndpointData[ep_found].iInterval = 0x01; // 2^(bInterval-1)ms, bInterval must be [1..16]
860 ifc().iEndpointData[ep_found].iInterval_Hs = 0x01; // same as for FS
861 test.Printf(_L("ISO IN size = %4d (ep %d)\n"), mps, ep_found + 1);
866 else if (!foundIsoOUT &&
867 (caps->iTypesAndDir & (KUsbEpTypeIsochronous | KUsbEpDirOut)) ==
868 (KUsbEpTypeIsochronous | KUsbEpDirOut))
870 // This is going to be our Iso RX (OUT) endpoint
871 ifc().iEndpointData[ep_found].iType = KUsbEpTypeIsochronous;
872 ifc().iEndpointData[ep_found].iDir = KUsbEpDirOut;
873 ifc().iEndpointData[ep_found].iSize = mps;
874 ifc().iEndpointData[ep_found].iInterval = 0x01; // 2^(bInterval-1)ms, bInterval must be [1..16]
875 test.Printf(_L("ISO OUT size = %4d (ep %d)\n"), mps, ep_found + 1);
880 else if (!foundIntIN &&
881 (caps->iTypesAndDir & (KUsbEpTypeInterrupt | KUsbEpDirIn)) ==
882 (KUsbEpTypeInterrupt | KUsbEpDirIn))
884 // This is going to be our Interrupt TX (IN) endpoint
885 ifc().iEndpointData[ep_found].iType = KUsbEpTypeInterrupt;
886 ifc().iEndpointData[ep_found].iDir = KUsbEpDirIn;
887 ifc().iEndpointData[ep_found].iSize = mps;
888 ifc().iEndpointData[ep_found].iInterval = 10; // interval = 10ms, valid range [1..255]
889 ifc().iEndpointData[ep_found].iInterval_Hs = 4; // interval = 2^(bInterval-1)ms = 8ms
890 ifc().iEndpointData[ep_found].iExtra = 2; // 2 extra bytes for Audio Class EP descriptor
891 test.Printf(_L("INT IN size = %4d (ep %d)\n"), mps, ep_found + 1);
893 INT_IN_ep = ep_found + 1;
899 // Let's try to add some more Bulk endpoints up to the max # of 5.
900 for (TInt i = 0; i < n; i++)
902 TUsbcEndpointCaps& caps = data[i].iCaps;
903 const TUint mps = caps.MaxPacketSize();
904 if (caps.iTypesAndDir & KUsbEpTypeBulk)
906 const TUint dir = (caps.iTypesAndDir & KUsbEpDirIn) ? KUsbEpDirIn : KUsbEpDirOut;
907 ifc().iEndpointData[ep_found].iType = KUsbEpTypeBulk;
908 ifc().iEndpointData[ep_found].iDir = dir;
911 test.Printf(_L("Checking if correct Bulk packet size is reported in HS case\n"));
912 test(mps == KUsbEpSize512); // sane?
914 // The PSL should in any case also offer the 'legacy' FS size:
915 test(caps.iSizes & KUsbEpSize64);
916 ifc().iEndpointData[ep_found].iSize = mps;
917 test.Printf(_L("BULK %s size = %4d (ep %d)\n"),
918 dir == KUsbEpDirIn ? _S("IN ") : _S("OUT"), mps, ep_found + 1);
924 test.Printf(_L("Total: %d endpoints found for the alt. ifc setting\n"), ep_found);
927 test.Printf(_L("(3 endpoints are at least required. Skipping test...)\n"));
932 if (!foundIsoIN && !foundIsoOUT)
934 test.Printf(_L("(No Isochronous endpoints found)\n"));
939 test.Printf(_L("(No Interrupt endpoint found)\n"));
940 test.Printf(_L("Adjusting endpoint size for later test\n"));
941 // We want to make sure that at least one descriptor has the 2 extra bytes.
942 // It doesn't matter that this ep could be a Bulk one, or that the 2 Iso ep's might be missing -
943 // we just want to test some functionality and we're not going to use this interface in earnest.
944 ifc().iEndpointData[2].iExtra = 2; // 2 extra bytes for Audio Class Ep descriptor
945 INT_IN_ep = 3; // pretend it's an INT ep
948 test.Next(_L("Create alternate interface setting"));
949 _LIT16(string, "T_USBAPI Test Interface (Setting 1: Audio)");
950 ifc().iString = const_cast<TDesC16*>(&string);
951 ifc().iTotalEndpointsUsed = ep_found;
952 ifc().iClass.iClassNum = KUsbAudioInterfaceClassCode;
953 ifc().iClass.iSubClassNum = KUsbAudioInterfaceSubclassCode_Audiostreaming;
954 ifc().iClass.iProtocolNum = KUsbAudioInterfaceProtocolCode_Pr_Protocol_Undefined;
955 r = gPort.SetInterface(1, ifc);
958 test.Next(_L("Set alternate setting number to 8"));
959 TBuf8<KUsbDescSize_Interface> descriptor;
960 r = gPort.GetInterfaceDescriptor(1, descriptor);
962 descriptor[KIfcDesc_SettingOffset] = 8;
963 r = gPort.SetInterfaceDescriptor(1, descriptor);
966 test.Next(_L("Change ifc # in def setting whith alt ifcs"));
967 r = gPort.GetInterfaceDescriptor(0, descriptor);
969 descriptor[KIfcDesc_SettingOffset] = 8;
970 r = gPort.SetInterfaceDescriptor(0, descriptor);
973 test.Next(_L("Change the ifc # in default setting to 8"));
974 r = gPort.ReleaseInterface(1);
976 r = gPort.SetInterfaceDescriptor(0, descriptor);
979 test.Next(_L("Create new setting - this should also get #8"));
980 r = gPort.SetInterface(1, ifc);
982 r = gPort.GetInterfaceDescriptor(1, descriptor);
984 test(descriptor[KIfcDesc_SettingOffset] == 8);
986 test.Next(_L("Change the ifc # in default setting to 0"));
987 r = gPort.ReleaseInterface(1);
989 r = gPort.GetInterfaceDescriptor(0, descriptor);
991 descriptor[KIfcDesc_SettingOffset] = 0;
992 r = gPort.SetInterfaceDescriptor(0, descriptor);
995 test.Next(_L("Create new setting - this should also get #0"));
996 r = gPort.SetInterface(1, ifc);
998 r = gPort.GetInterfaceDescriptor(1, descriptor);
1000 test(descriptor[KIfcDesc_SettingOffset] == 0);
1006 static void TestEndpointDescriptor()
1008 test.Start(_L("Endpoint Descriptor Manipulation"));
1010 test.Next(_L("GetEndpointDescriptorSize(1)"));
1013 TInt r = gPort.GetEndpointDescriptorSize(0, epNumber, desc_size);
1014 test(r == KErrNone);
1015 test(static_cast<TUint>(desc_size) == KUsbDescSize_Endpoint);
1017 test.Next(_L("GetEndpointDescriptor(1)"));
1018 TBuf8<KUsbDescSize_Endpoint> descriptor;
1019 r = gPort.GetEndpointDescriptor(0, epNumber, descriptor);
1020 test(r == KErrNone);
1022 test.Next(_L("SetEndpointDescriptor(1)"));
1023 // Change the endpoint poll interval
1025 if (descriptor[KEpDesc_IntervalOffset] == ival)
1027 descriptor[KEpDesc_IntervalOffset] = ival;
1028 r = gPort.SetEndpointDescriptor(0, epNumber, descriptor);
1029 test(r == KErrNone);
1031 test.Next(_L("GetEndpointDescriptor(1)"));
1032 TBuf8<KUsbDescSize_Endpoint> descriptor2;
1033 r = gPort.GetEndpointDescriptor(0, epNumber, descriptor2);
1034 test(r == KErrNone);
1036 test.Next(_L("Compare endpoint descriptor with value set"));
1037 r = descriptor2.Compare(descriptor);
1038 test(r == KErrNone);
1040 test.Next(_L("Check endpoint max packet size"));
1041 const TUint16 ep_size = EpSize(descriptor[KEpDesc_PacketSizeOffset],
1042 descriptor[KEpDesc_PacketSizeOffset+1]);
1043 test.Printf(_L(" Size: %d\n"), ep_size);
1044 if (gUsingHighSpeed)
1046 // HS Bulk ep can only have one possible packet size.
1047 test(ep_size == 512);
1051 // FS Bulk ep cannot be larger than 64 bytes.
1052 test(ep_size <= 64);
1059 static void TestExtendedEndpointDescriptor()
1061 test.Start(_L("Extended Endpoint Descriptor Manipulation"));
1063 if (!SupportsAlternateInterfaces())
1065 test.Printf(_L("*** Not supported - skipping Extended Endpoint descriptor tests\n"));
1070 // Extended Endpoint Descriptor manipulation (Audio class endpoint)
1072 test.Next(_L("GetEndpointDescriptorSize()"));
1073 TInt epNumber = INT_IN_ep;
1075 TInt r = gPort.GetEndpointDescriptorSize(1, epNumber, desc_size);
1076 test(r == KErrNone);
1077 test(static_cast<TUint>(desc_size) == KUsbDescSize_AudioEndpoint);
1079 test.Next(_L("GetEndpointDescriptor()"));
1080 TBuf8<KUsbDescSize_AudioEndpoint> descriptor;
1081 r = gPort.GetEndpointDescriptor(1, epNumber, descriptor);
1082 test(r == KErrNone);
1084 test.Next(_L("SetEndpointDescriptor()"));
1085 // Change the Audio Endpoint bSynchAddress field
1086 TUint8 addr = 0x85; // bogus address
1087 if (descriptor[KEpDesc_SynchAddressOffset] == addr)
1089 descriptor[KEpDesc_SynchAddressOffset] = addr;
1090 r = gPort.SetEndpointDescriptor(1, epNumber, descriptor);
1091 test(r == KErrNone);
1093 test.Next(_L("GetEndpointDescriptor()"));
1094 TBuf8<KUsbDescSize_AudioEndpoint> descriptor2;
1095 r = gPort.GetEndpointDescriptor(1, epNumber, descriptor2);
1096 test(r == KErrNone);
1098 test.Next(_L("Compare endpoint descriptor with value set"));
1099 r = descriptor2.Compare(descriptor);
1100 test(r == KErrNone);
1102 test.Next(_L("Check endpoint max packet size"));
1103 const TUint16 ep_size = EpSize(descriptor[KEpDesc_PacketSizeOffset],
1104 descriptor[KEpDesc_PacketSizeOffset+1]);
1105 if (gUsingHighSpeed)
1108 test(ep_size <= 1024);
1112 // FS Interrupt ep cannot be larger than 64 bytes.
1113 test(ep_size <= 64);
1120 static void TestStandardStringDescriptors()
1122 test.Start(_L("String Descriptor Manipulation"));
1128 test.Next(_L("GetStringDescriptorLangId()"));
1129 TUint16 rd_langid_orig;
1130 TInt r = gPort.GetStringDescriptorLangId(rd_langid_orig);
1131 test(r == KErrNone);
1132 test.Printf(_L("Original LANGID code: 0x%04X\n"), rd_langid_orig);
1134 test.Next(_L("SetStringDescriptorLangId()"));
1135 TUint16 wr_langid = 0x0809; // English (UK) Language ID
1136 if (wr_langid == rd_langid_orig)
1137 wr_langid = 0x0444; // Tatar Language ID
1138 r = gPort.SetStringDescriptorLangId(wr_langid);
1139 test(r == KErrNone);
1141 test.Next(_L("GetStringDescriptorLangId()"));
1143 r = gPort.GetStringDescriptorLangId(rd_langid);
1144 test(r == KErrNone);
1145 test.Printf(_L("New LANGID code: 0x%04X\n"), rd_langid);
1147 test.Next(_L("Compare LANGID codes"));
1148 test(rd_langid == wr_langid);
1150 test.Next(_L("Restore original LANGID code"));
1151 r = gPort.SetStringDescriptorLangId(rd_langid_orig);
1152 test(r == KErrNone);
1153 r = gPort.GetStringDescriptorLangId(rd_langid);
1154 test(r == KErrNone);
1155 test(rd_langid == rd_langid_orig);
1158 // --- Manufacturer string
1161 test.Next(_L("GetManufacturerStringDescriptor()"));
1162 TBuf16<KUsbStringDescStringMaxSize / 2> rd_str_orig;
1163 r = gPort.GetManufacturerStringDescriptor(rd_str_orig);
1164 test(r == KErrNone || r == KErrNotFound);
1165 TBool restore_string;
1168 test.Printf(_L("Original Manufacturer string: \"%lS\"\n"), &rd_str_orig);
1169 restore_string = ETrue;
1173 test.Printf(_L("No Manufacturer string set\n"));
1174 restore_string = EFalse;
1177 test.Next(_L("SetManufacturerStringDescriptor()"));
1178 _LIT16(manufacturer, "Manufacturer Which Manufactures Devices");
1179 TBuf16<KUsbStringDescStringMaxSize / 2> wr_str(manufacturer);
1180 r = gPort.SetManufacturerStringDescriptor(wr_str);
1181 test(r == KErrNone);
1183 test.Next(_L("GetManufacturerStringDescriptor()"));
1184 TBuf16<KUsbStringDescStringMaxSize / 2> rd_str;
1185 r = gPort.GetManufacturerStringDescriptor(rd_str);
1186 test(r == KErrNone);
1187 test.Printf(_L("New Manufacturer string: \"%lS\"\n"), &rd_str);
1189 test.Next(_L("Compare Manufacturer strings"));
1190 r = rd_str.Compare(wr_str);
1191 test(r == KErrNone);
1193 test.Next(_L("SetManufacturerStringDescriptor()"));
1194 _LIT16(manufacturer2, "Different Manufacturer Which Manufactures Different Devices");
1195 wr_str.FillZ(wr_str.MaxLength());
1196 wr_str = manufacturer2;
1197 r = gPort.SetManufacturerStringDescriptor(wr_str);
1198 test(r == KErrNone);
1200 test.Next(_L("GetManufacturerStringDescriptor()"));
1201 rd_str.FillZ(rd_str.MaxLength());
1202 r = gPort.GetManufacturerStringDescriptor(rd_str);
1203 test(r == KErrNone);
1204 test.Printf(_L("New Manufacturer string: \"%lS\"\n"), &rd_str);
1206 test.Next(_L("Compare Manufacturer strings"));
1207 r = rd_str.Compare(wr_str);
1208 test(r == KErrNone);
1210 test.Next(_L("RemoveManufacturerStringDescriptor()"));
1211 r = gPort.RemoveManufacturerStringDescriptor();
1212 test(r == KErrNone);
1213 r = gPort.GetManufacturerStringDescriptor(rd_str);
1214 test(r == KErrNotFound);
1218 test.Next(_L("Restore original string"));
1219 r = gPort.SetManufacturerStringDescriptor(rd_str_orig);
1220 test(r == KErrNone);
1221 r = gPort.GetManufacturerStringDescriptor(rd_str);
1222 test(r == KErrNone);
1223 r = rd_str.Compare(rd_str_orig);
1224 test(r == KErrNone);
1228 // --- Product string
1231 test.Next(_L("GetProductStringDescriptor()"));
1232 rd_str_orig.FillZ(rd_str.MaxLength());
1233 r = gPort.GetProductStringDescriptor(rd_str_orig);
1234 test(r == KErrNone || r == KErrNotFound);
1237 test.Printf(_L("Old Product string: \"%lS\"\n"), &rd_str_orig);
1238 restore_string = ETrue;
1241 restore_string = EFalse;
1243 test.Next(_L("SetProductStringDescriptor()"));
1244 _LIT16(product, "Product That Was Produced By A Manufacturer");
1245 wr_str.FillZ(wr_str.MaxLength());
1247 r = gPort.SetProductStringDescriptor(wr_str);
1248 test(r == KErrNone);
1250 test.Next(_L("GetProductStringDescriptor()"));
1251 rd_str.FillZ(rd_str.MaxLength());
1252 r = gPort.GetProductStringDescriptor(rd_str);
1253 test(r == KErrNone);
1254 test.Printf(_L("New Product string: \"%lS\"\n"), &rd_str);
1256 test.Next(_L("Compare Product strings"));
1257 r = rd_str.Compare(wr_str);
1258 test(r == KErrNone);
1260 test.Next(_L("SetProductStringDescriptor()"));
1261 _LIT16(product2, "Different Product That Was Produced By A Different Manufacturer");
1262 wr_str.FillZ(wr_str.MaxLength());
1264 r = gPort.SetProductStringDescriptor(wr_str);
1265 test(r == KErrNone);
1267 test.Next(_L("GetProductStringDescriptor()"));
1268 rd_str.FillZ(rd_str.MaxLength());
1269 r = gPort.GetProductStringDescriptor(rd_str);
1270 test(r == KErrNone);
1271 test.Printf(_L("New Product string: \"%lS\"\n"), &rd_str);
1273 test.Next(_L("Compare Product strings"));
1274 r = rd_str.Compare(wr_str);
1275 test(r == KErrNone);
1277 test.Next(_L("RemoveProductStringDescriptor()"));
1278 r = gPort.RemoveProductStringDescriptor();
1279 test(r == KErrNone);
1280 r = gPort.GetProductStringDescriptor(rd_str);
1281 test(r == KErrNotFound);
1285 test.Next(_L("Restore original string"));
1286 r = gPort.SetProductStringDescriptor(rd_str_orig);
1287 test(r == KErrNone);
1288 r = gPort.GetProductStringDescriptor(rd_str);
1289 test(r == KErrNone);
1290 r = rd_str.Compare(rd_str_orig);
1291 test(r == KErrNone);
1295 // --- Serial Number string
1298 test.Next(_L("GetSerialNumberStringDescriptor()"));
1299 rd_str_orig.FillZ(rd_str.MaxLength());
1300 r = gPort.GetSerialNumberStringDescriptor(rd_str_orig);
1301 test(r == KErrNone || r == KErrNotFound);
1304 test.Printf(_L("Old Serial Number: \"%lS\"\n"), &rd_str_orig);
1305 restore_string = ETrue;
1308 restore_string = EFalse;
1310 test.Next(_L("SetSerialNumberStringDescriptor()"));
1311 _LIT16(serial, "000666000XYZ");
1312 wr_str.FillZ(wr_str.MaxLength());
1314 r = gPort.SetSerialNumberStringDescriptor(wr_str);
1315 test(r == KErrNone);
1317 test.Next(_L("GetSerialNumberStringDescriptor()"));
1318 rd_str.FillZ(rd_str.MaxLength());
1319 r = gPort.GetSerialNumberStringDescriptor(rd_str);
1320 test(r == KErrNone);
1321 test.Printf(_L("New Serial Number: \"%lS\"\n"), &rd_str);
1323 test.Next(_L("Compare Serial Number strings"));
1324 r = rd_str.Compare(wr_str);
1325 test(r == KErrNone);
1327 test.Next(_L("SetSerialNumberStringDescriptor()"));
1328 _LIT16(serial2, "Y11611193111711111Y");
1329 wr_str.FillZ(wr_str.MaxLength());
1331 r = gPort.SetSerialNumberStringDescriptor(wr_str);
1332 test(r == KErrNone);
1334 test.Next(_L("GetSerialNumberStringDescriptor()"));
1335 rd_str.FillZ(rd_str.MaxLength());
1336 r = gPort.GetSerialNumberStringDescriptor(rd_str);
1337 test(r == KErrNone);
1338 test.Printf(_L("New Serial Number: \"%lS\"\n"), &rd_str);
1340 test.Next(_L("Compare Serial Number strings"));
1341 r = rd_str.Compare(wr_str);
1342 test(r == KErrNone);
1344 test.Next(_L("RemoveSerialNumberStringDescriptor()"));
1345 r = gPort.RemoveSerialNumberStringDescriptor();
1346 test(r == KErrNone);
1347 r = gPort.GetSerialNumberStringDescriptor(rd_str);
1348 test(r == KErrNotFound);
1352 test.Next(_L("Restore original string"));
1353 r = gPort.SetSerialNumberStringDescriptor(rd_str_orig);
1354 test(r == KErrNone);
1355 r = gPort.GetSerialNumberStringDescriptor(rd_str);
1356 test(r == KErrNone);
1357 r = rd_str.Compare(rd_str_orig);
1358 test(r == KErrNone);
1362 // --- Configuration string
1365 test.Next(_L("GetConfigurationStringDescriptor()"));
1366 rd_str_orig.FillZ(rd_str.MaxLength());
1367 r = gPort.GetConfigurationStringDescriptor(rd_str_orig);
1368 test(r == KErrNone || r == KErrNotFound);
1371 test.Printf(_L("Old Configuration string: \"%lS\"\n"), &rd_str_orig);
1372 restore_string = ETrue;
1375 restore_string = EFalse;
1377 test.Next(_L("SetConfigurationStringDescriptor()"));
1378 _LIT16(config, "Relatively Simple Configuration That Is Still Useful");
1379 wr_str.FillZ(wr_str.MaxLength());
1381 r = gPort.SetConfigurationStringDescriptor(wr_str);
1382 test(r == KErrNone);
1384 test.Next(_L("GetConfigurationStringDescriptor()"));
1385 rd_str.FillZ(rd_str.MaxLength());
1386 r = gPort.GetConfigurationStringDescriptor(rd_str);
1387 test(r == KErrNone);
1388 test.Printf(_L("New Configuration string: \"%lS\"\n"), &rd_str);
1390 test.Next(_L("Compare Configuration strings"));
1391 r = rd_str.Compare(wr_str);
1392 test(r == KErrNone);
1394 test.Next(_L("SetConfigurationStringDescriptor()"));
1395 _LIT16(config2, "Convenient Configuration That Can Be Very Confusing");
1396 wr_str.FillZ(wr_str.MaxLength());
1398 r = gPort.SetConfigurationStringDescriptor(wr_str);
1399 test(r == KErrNone);
1401 test.Next(_L("GetConfigurationStringDescriptor()"));
1402 rd_str.FillZ(rd_str.MaxLength());
1403 r = gPort.GetConfigurationStringDescriptor(rd_str);
1404 test(r == KErrNone);
1405 test.Printf(_L("New Configuration string: \"%lS\"\n"), &rd_str);
1407 test.Next(_L("Compare Configuration strings"));
1408 r = rd_str.Compare(wr_str);
1409 test(r == KErrNone);
1411 test.Next(_L("RemoveConfigurationStringDescriptor()"));
1412 r = gPort.RemoveConfigurationStringDescriptor();
1413 test(r == KErrNone);
1414 r = gPort.GetConfigurationStringDescriptor(rd_str);
1415 test(r == KErrNotFound);
1419 test.Next(_L("Restore original string"));
1420 r = gPort.SetConfigurationStringDescriptor(rd_str_orig);
1421 test(r == KErrNone);
1422 r = gPort.GetConfigurationStringDescriptor(rd_str);
1423 test(r == KErrNone);
1424 r = rd_str.Compare(rd_str_orig);
1425 test(r == KErrNone);
1432 //---------------------------------------------
1433 //! @SYMTestCaseID KBASE-T_USBAPI-0041
1436 //! @SYMTestCaseDesc USB Device Driver API extension to support setting of a string descriptor at a specific index
1437 //! @SYMTestActions Tests GetStringDescriptor(), SetStringDescriptor() and RemoveStringDescriptor() to verify
1438 //! the right values are retrieved, set and deleted at specific positions
1439 //! @SYMTestExpectedResults KErrNone in positive testing and KErrNotFound in negative one
1440 //! @SYMTestPriority High
1441 //! @SYMTestStatus Implemented
1442 //---------------------------------------------
1443 static void TestArbitraryStringDescriptors()
1445 test.Start(_L("Arbitrary String Descriptor Manipulation"));
1447 const TUint8 stridx1 = 0xEE;
1448 const TUint8 stridx2 = 0xCC;
1449 const TUint8 stridx3 = 0xDD;
1450 const TUint8 stridx4 = 0xFF;
1452 // First test string
1454 test.Next(_L("GetStringDescriptor() 1"));
1455 TBuf16<KUsbStringDescStringMaxSize / 2> rd_str;
1456 TInt r = gPort.GetStringDescriptor(stridx1, rd_str);
1457 test(r == KErrNotFound);
1459 test.Next(_L("SetStringDescriptor() 1"));
1460 _LIT16(string_one, "Arbitrary String Descriptor Test String 1");
1461 TBuf16<KUsbStringDescStringMaxSize / 2> wr_str(string_one);
1462 r = gPort.SetStringDescriptor(stridx1, wr_str);
1463 test(r == KErrNone);
1465 test.Next(_L("GetStringDescriptor() 1"));
1466 r = gPort.GetStringDescriptor(stridx1, rd_str);
1467 test(r == KErrNone);
1468 test.Printf(_L("New test string @ idx %d: \"%lS\"\n"), stridx1, &rd_str);
1470 test.Next(_L("Compare test strings 1"));
1471 r = rd_str.Compare(wr_str);
1472 test(r == KErrNone);
1474 // Second test string
1476 test.Next(_L("GetStringDescriptor() 2"));
1477 rd_str.FillZ(rd_str.MaxLength());
1478 r = gPort.GetStringDescriptor(stridx2, rd_str);
1479 test(r == KErrNotFound);
1481 test.Next(_L("SetStringDescriptor() 2"));
1482 _LIT16(string_two, "Arbitrary String Descriptor Test String 2");
1483 wr_str.FillZ(wr_str.MaxLength());
1484 wr_str = string_two;
1485 r = gPort.SetStringDescriptor(stridx2, wr_str);
1486 test(r == KErrNone);
1488 // In between we create another interface setting to see what happens
1489 // to the existing string descriptor indices.
1490 // (We don't have to test this on every platform -
1491 // besides, those that don't support alt settings
1492 // are by now very rare.)
1493 if (SupportsAlternateInterfaces())
1495 TUsbcInterfaceInfoBuf ifc;
1496 _LIT16(string, "T_USBAPI Bogus Test Interface (Setting 2)");
1497 ifc().iString = const_cast<TDesC16*>(&string);
1498 ifc().iTotalEndpointsUsed = 0;
1499 TInt r = gPort.SetInterface(2, ifc);
1500 test(r == KErrNone);
1503 test.Next(_L("GetStringDescriptor() 2"));
1504 r = gPort.GetStringDescriptor(stridx2, rd_str);
1505 test(r == KErrNone);
1506 test.Printf(_L("New test string @ idx %d: \"%lS\"\n"), stridx2, &rd_str);
1508 test.Next(_L("Compare test strings 2"));
1509 r = rd_str.Compare(wr_str);
1510 test(r == KErrNone);
1512 // Third test string
1514 test.Next(_L("GetStringDescriptor() 3"));
1515 rd_str.FillZ(rd_str.MaxLength());
1516 r = gPort.GetStringDescriptor(stridx3, rd_str);
1517 test(r == KErrNotFound);
1519 test.Next(_L("SetStringDescriptor() 3"));
1520 _LIT16(string_three, "Arbitrary String Descriptor Test String 3");
1521 wr_str.FillZ(wr_str.MaxLength());
1522 wr_str = string_three;
1523 r = gPort.SetStringDescriptor(stridx3, wr_str);
1524 test(r == KErrNone);
1526 test.Next(_L("GetStringDescriptor() 3"));
1527 r = gPort.GetStringDescriptor(stridx3, rd_str);
1528 test(r == KErrNone);
1529 test.Printf(_L("New test string @ idx %d: \"%lS\"\n"), stridx3, &rd_str);
1531 test.Next(_L("Compare test strings 3"));
1532 r = rd_str.Compare(wr_str);
1533 test(r == KErrNone);
1535 // Remove string descriptors
1537 test.Next(_L("RemoveStringDescriptor() 4"));
1538 r = gPort.RemoveStringDescriptor(stridx4);
1539 test(r == KErrNotFound);
1541 test.Next(_L("RemoveStringDescriptor() 3"));
1542 r = gPort.RemoveStringDescriptor(stridx3);
1543 test(r == KErrNone);
1544 r = gPort.GetStringDescriptor(stridx3, rd_str);
1545 test(r == KErrNotFound);
1547 test.Next(_L("RemoveStringDescriptor() 2"));
1548 r = gPort.RemoveStringDescriptor(stridx2);
1549 test(r == KErrNone);
1550 r = gPort.GetStringDescriptor(stridx2, rd_str);
1551 test(r == KErrNotFound);
1553 test.Next(_L("RemoveStringDescriptor() 1"));
1554 r = gPort.RemoveStringDescriptor(stridx1);
1555 test(r == KErrNone);
1556 r = gPort.GetStringDescriptor(stridx1, rd_str);
1557 test(r == KErrNotFound);
1563 static void TestDescriptorManipulation()
1565 test.Start(_L("Test USB Descriptor Manipulation"));
1567 TestDeviceDescriptor();
1569 TestDeviceQualifierDescriptor();
1571 TestConfigurationDescriptor();
1573 TestOtherSpeedConfigurationDescriptor();
1575 TestInterfaceDescriptor();
1577 TestClassSpecificDescriptors();
1579 TestAlternateInterfaceManipulation();
1581 TestEndpointDescriptor();
1583 TestExtendedEndpointDescriptor();
1585 TestStandardStringDescriptors();
1587 TestArbitraryStringDescriptors();
1593 //---------------------------------------------
1594 //! @SYMTestCaseID KBASE-T_USBAPI-0040
1596 //! @SYMTestCaseDesc Test OTG extensions
1597 //! @SYMTestExpectedResults All APIs behave as expected
1598 //! @SYMTestPriority Medium
1599 //! @SYMTestStatus Implemented
1600 //---------------------------------------------
1601 static void TestOtgExtensions()
1603 test.Start(_L("Test Some OTG API Extensions"));
1605 // Test OTG descriptor manipulation
1606 test.Next(_L("Get OTG Descriptor Size"));
1608 gPort.GetOtgDescriptorSize(size);
1609 test(static_cast<TUint>(size) == KUsbDescSize_Otg);
1611 test.Next(_L("Get OTG Descriptor"));
1612 TBuf8<KUsbDescSize_Otg> otgDesc;
1613 TInt r = gPort.GetOtgDescriptor(otgDesc);
1614 test(r == KErrNotSupported || r == KErrNone);
1616 test.Next(_L("Set OTG Descriptor"));
1617 if (r == KErrNotSupported)
1619 r = gPort.SetOtgDescriptor(otgDesc);
1620 test(r == KErrNotSupported);
1624 otgDesc[0] = KUsbDescSize_Otg;
1625 otgDesc[1] = KUsbDescType_Otg;
1626 // The next step is likely to reset KUsbOtgAttr_HnpSupp
1627 otgDesc[2] = KUsbOtgAttr_SrpSupp;
1628 r = gPort.SetOtgDescriptor(otgDesc);
1629 test(r == KErrNone);
1630 TBuf8<KUsbDescSize_Otg> desc;
1631 r = gPort.GetOtgDescriptor(desc);
1632 test(r == KErrNone);
1633 test(desc.Compare(otgDesc) == 0);
1636 // Test get OTG features
1637 test.Next(_L("Get OTG Features"));
1639 r = gPort.GetOtgFeatures(features);
1642 test(r == KErrNone);
1643 TBool b_HnpEnable = (features & KUsbOtgAttr_B_HnpEnable) ? ETrue : EFalse;
1644 TBool a_HnpSupport = (features & KUsbOtgAttr_A_HnpSupport) ? ETrue : EFalse;
1645 TBool a_AltHnpSupport = (features & KUsbOtgAttr_A_AltHnpSupport) ? ETrue : EFalse;
1646 test.Printf(_L("### OTG Features:\nB_HnpEnable(%d)\nA_HnpSupport(%d)\nA_Alt_HnpSupport(%d)\n"),
1647 b_HnpEnable, a_HnpSupport, a_AltHnpSupport);
1651 test(r == KErrNotSupported);
1652 test.Printf(_L("GetOtgFeatures() not supported\n"));
1659 static void TestEndpoint0MaxPacketSizes()
1661 test.Start(_L("Test Endpoint0 MaxPacketSizes"));
1663 TUint32 sizes = gPort.EndpointZeroMaxPacketSizes();
1667 for (TInt i = 0; i < 32; i++)
1669 TUint bit = sizes & (1 << i);
1674 case KUsbEpSizeCont:
1696 case KUsbEpSize1023:
1703 test.Printf(_L("Ep0 supports %d bytes MaxPacketSize\n"), mpsize);
1707 test.Printf(_L("Bad Ep0 size: 0x%08x, failure will occur\n"), bit);
1712 test(r == KErrNone);
1718 static void TestDeviceControl()
1720 test.Start(_L("Test Device Control"));
1722 // This is a quick and crude test, to make sure that we don't get a steaming heap
1723 // as a result of calling the device control API's.
1724 test.Next(_L("SetDeviceControl()"));
1725 TInt r = gPort.SetDeviceControl();
1726 test(r == KErrNone);
1727 test.Next(_L("ReleaseDeviceControl()"));
1728 r = gPort.ReleaseDeviceControl();
1729 test(r == KErrNone);
1735 static void TestAlternateDeviceStatusNotify()
1737 test.Start(_L("Test Alternate Device Status Notification"));
1739 TRequestStatus dev_status;
1740 TUint deviceState = 0xffffffff; // put in a nonsense value
1741 test.Next(_L("AlternateDeviceStatusNotify()"));
1742 gPort.AlternateDeviceStatusNotify(dev_status, deviceState);
1743 test.Next(_L("AlternateDeviceStatusNotifyCancel()"));
1744 gPort.AlternateDeviceStatusNotifyCancel();
1745 User::WaitForRequest(dev_status);
1746 test(dev_status == KErrCancel || dev_status == KErrNone);
1747 if (deviceState & KUsbAlternateSetting)
1749 TUint setting = (deviceState & ~KUsbAlternateSetting);
1750 test.Printf(_L("Alternate setting change to setting %d - unexpected"), setting);
1755 switch (deviceState)
1757 case EUsbcDeviceStateUndefined:
1758 test.Printf(_L("TestAlternateDeviceStatusNotify: Undefined state\n"));
1760 case EUsbcDeviceStateAttached:
1761 test.Printf(_L("TestAlternateDeviceStatusNotify: Attached state\n"));
1763 case EUsbcDeviceStatePowered:
1764 test.Printf(_L("TestAlternateDeviceStatusNotify: Powered state\n"));
1766 case EUsbcDeviceStateDefault:
1767 test.Printf(_L("TestAlternateDeviceStatusNotify: Default state\n"));
1769 case EUsbcDeviceStateAddress:
1770 test.Printf(_L("TestAlternateDeviceStatusNotify: Address state\n"));
1772 case EUsbcDeviceStateConfigured:
1773 test.Printf(_L("TestAlternateDeviceStatusNotify: Configured state\n"));
1775 case EUsbcDeviceStateSuspended:
1776 test.Printf(_L("TestAlternateDeviceStatusNotify: Suspended state\n"));
1779 test.Printf(_L("TestAlternateDeviceStatusNotify: State buffering error\n"));
1783 test.Printf(_L("TestAlternateDeviceStatusNotify: Unknown state\n"));
1792 static void TestEndpointStatusNotify()
1794 test.Start(_L("Test Endpoint Status Notification"));
1796 TRequestStatus ep_status;
1797 TUint epStateBitmap = 0xffffffff; // put in a nonsense value
1798 test.Next(_L("EndpointStatusNotify()"));
1799 gPort.EndpointStatusNotify(ep_status, epStateBitmap);
1800 test.Next(_L("EndpointStatusNotifyCancel()"));
1801 gPort.EndpointStatusNotifyCancel();
1802 User::WaitForRequest(ep_status);
1803 test(ep_status.Int() == KErrCancel);
1804 test.Next(_L("Check endpoint state bitmap returned"));
1805 // Our ifc only uses 2 eps + ep0 is automatically granted:
1806 const TUint usedEpBitmap = (1 << EEndpoint0 | 1 << EEndpoint1 | 1 << EEndpoint2);
1807 // Must not return info about non existent Eps:
1808 test((epStateBitmap & ~usedEpBitmap) == 0);
1809 for (TInt i = 0; i <= 2; i++)
1811 if ((epStateBitmap & (1 << i)) == EEndpointStateNotStalled)
1813 test.Printf(_L("EndpointStatusNotify: Ep %d NOT STALLED\n"), i);
1817 test.Printf(_L("EndpointStatusNotify: Ep %d STALLED\n"), i);
1825 static void TestEndpointStallStatus()
1827 test.Start(_L("Test Endpoint Stall Status"));
1829 if (!SupportsEndpointStall())
1831 test.Printf(_L("*** Not supported - skipping endpoint stall status tests\n"));
1836 test.Next(_L("Endpoint stall status"));
1837 TEndpointState epState = EEndpointStateUnknown;
1838 QueryEndpointState(EEndpoint1);
1839 QueryEndpointState(EEndpoint2);
1841 test.Next(_L("Stall Ep1"));
1842 gPort.HaltEndpoint(EEndpoint1);
1843 epState = QueryEndpointState(EEndpoint1);
1844 test(epState == EEndpointStateStalled);
1846 test.Next(_L("Clear Stall Ep1"));
1847 gPort.ClearHaltEndpoint(EEndpoint1);
1848 epState = QueryEndpointState(EEndpoint1);
1849 test(epState == EEndpointStateNotStalled);
1851 test.Next(_L("Stall Ep2"));
1852 gPort.HaltEndpoint(EEndpoint2);
1853 epState = QueryEndpointState(EEndpoint2);
1854 test(epState == EEndpointStateStalled);
1856 test.Next(_L("Clear Stall Ep2"));
1857 gPort.ClearHaltEndpoint(EEndpoint2);
1858 epState = QueryEndpointState(EEndpoint2);
1859 test(epState == EEndpointStateNotStalled);
1865 static void CloseChannel()
1867 test.Start(_L("Close Channel"));
1869 test.Next(_L("Disconnect Device from Host"));
1870 TInt r = gPort.DeviceDisconnectFromHost();
1871 test(r != KErrGeneral);
1875 test.Next(_L("Stop OTG stack"));
1877 test.Next(_L("Close OTG Channel"));
1879 test.Next(_L("Free OTG LDD"));
1880 r = User::FreeLogicalDevice(RUsbOtgDriver::Name());
1881 test(r == KErrNone);
1884 test.Next(_L("Close USB Channel"));
1886 test.Next(_L("Free USB LDD"));
1887 r = User::FreeLogicalDevice(KUsbDeviceName);
1888 test(r == KErrNone);
1894 static const TInt KPrologue = 0;
1895 static const TInt KMain = 1;
1896 static const TInt KEpilogue = 2;
1898 static TInt RunTests(void* /*aArg*/)
1900 static TInt step = KPrologue;
1901 static TReal loops = 0;
1907 // outermost test begin
1908 test.Start(_L("Test of USB APIs not requiring a host connection\n"));
1916 test.Printf(_L("*** Test platform does not support USB - skipping all tests\n"));
1922 TestDescriptorManipulation();
1923 TestOtgExtensions();
1924 TestEndpoint0MaxPacketSizes();
1925 TestDeviceControl();
1926 TestAlternateDeviceStatusNotify();
1927 TestEndpointStatusNotify();
1928 TestEndpointStallStatus();
1931 if (gSoak && (gKeychar != EKeyEscape))
1941 test.Printf(_L("USBAPI tests were run %.0f time(s)\n"), loops);
1942 // outermost test end
1944 CActiveScheduler::Stop();
1951 static void RunAppL()
1953 // Create the active scheduler
1954 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
1955 // Push active scheduler onto the cleanup stack
1956 CleanupStack::PushL(scheduler);
1957 // Install as the active scheduler
1958 CActiveScheduler::Install(scheduler);
1960 // Create console handler
1961 CConsoleBase* console =
1962 Console::NewL(_L("T_USBAPI - USB Client Test Program"), TSize(KConsFullScreen, KConsFullScreen));
1963 CleanupStack::PushL(console);
1964 // Make this one also RTest's console
1965 test.SetConsole(console);
1967 // Create keypress notifier active object
1968 CActiveKeypressNotifier* keypress_notifier = CActiveKeypressNotifier::NewL(console);
1969 test(keypress_notifier != NULL);
1970 CleanupStack::PushL(keypress_notifier);
1971 keypress_notifier->RequestCharacter();
1973 // Create long-running test task active object
1974 CIdle* active_test = CIdle::NewL(CActive::EPriorityIdle);
1975 test(active_test != NULL);
1976 CleanupStack::PushL(active_test);
1977 active_test->Start(TCallBack(RunTests));
1979 // Start active scheduler
1980 CActiveScheduler::Start();
1982 // Suspend thread for a short while
1983 User::After(1000000);
1985 // active_test, keypress_notifier, console, scheduler
1986 CleanupStack::PopAndDestroy(4);
1992 GLDEF_C TInt E32Main()
1995 CTrapCleanup* cleanup = CTrapCleanup::New(); // get clean-up stack
2001 User::CommandLine(c);
2002 if (c.CompareF(KArg) == 0)
2006 TRAPD(r, RunAppL());
2007 __ASSERT_ALWAYS(!r, User::Panic(_L("E32EX"), r));
2011 delete cleanup; // destroy clean-up stack