os/kernelhwsrv/kernel/eka/drivers/usbcc/descriptors.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32/drivers/usbcc/descriptors.cpp
    15 // Platform independent layer (PIL) of the USB Device controller driver:
    16 // USB descriptor handling and management.
    17 // 
    18 //
    19 
    20 /**
    21  @file descriptors.cpp
    22  @internalTechnology
    23 */
    24 
    25 #include <kernel/kern_priv.h>
    26 #include <drivers/usbc.h>
    27 
    28 
    29 // Debug Support
    30 static const char KUsbPanicCat[] = "USB PIL";
    31 
    32 
    33 // --- TUsbcDescriptorBase
    34 
    35 TUsbcDescriptorBase::TUsbcDescriptorBase()
    36 	:
    37 #ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
    38 	iIndex(0),
    39 #endif
    40 	iBufPtr(NULL, 0)
    41 	{
    42 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorBase::TUsbcDescriptorBase()"));
    43 	}
    44 
    45 
    46 TUsbcDescriptorBase::~TUsbcDescriptorBase()
    47 	{
    48 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorBase::~TUsbcDescriptorBase()"));
    49 	}
    50 
    51 
    52 void TUsbcDescriptorBase::SetByte(TInt aPosition, TUint8 aValue)
    53 	{
    54 	iBufPtr[aPosition] = aValue;
    55 	}
    56 
    57 
    58 void TUsbcDescriptorBase::SetWord(TInt aPosition, TUint16 aValue)
    59 	{
    60 	*reinterpret_cast<TUint16*>(&iBufPtr[aPosition]) = SWAP_BYTES_16(aValue);
    61 	}
    62 
    63 
    64 TUint8 TUsbcDescriptorBase::Byte(TInt aPosition) const
    65 	{
    66 	return iBufPtr[aPosition];
    67 	}
    68 
    69 
    70 TUint16 TUsbcDescriptorBase::Word(TInt aPosition) const
    71 	{
    72 	return SWAP_BYTES_16(*reinterpret_cast<const TUint16*>(&iBufPtr[aPosition]));
    73 	}
    74 
    75 
    76 void TUsbcDescriptorBase::GetDescriptorData(TDes8& aBuffer) const
    77 	{
    78 	aBuffer = iBufPtr;
    79 	}
    80 
    81 
    82 TInt TUsbcDescriptorBase::GetDescriptorData(TUint8* aBuffer) const
    83 	{
    84 	memcpy(aBuffer, iBufPtr.Ptr(), Size());
    85 	return Size();
    86 	}
    87 
    88 
    89 TInt TUsbcDescriptorBase::GetDescriptorData(TUint8* aBuffer, TUint aMaxSize) const
    90 	{
    91 	if (aMaxSize < Size())
    92 		{
    93 		// No use to copy only half a descriptor
    94 		return 0;
    95 		}
    96 	return GetDescriptorData(aBuffer);
    97 	}
    98 
    99 
   100 const TDes8& TUsbcDescriptorBase::DescriptorData() const
   101 	{
   102 	return iBufPtr;
   103 	}
   104 
   105 
   106 TDes8& TUsbcDescriptorBase::DescriptorData()
   107 	{
   108 	return iBufPtr;
   109 	}
   110 
   111 
   112 TUint TUsbcDescriptorBase::Size() const
   113 	{
   114 	return iBufPtr.Size();
   115 	}
   116 
   117 
   118 TUint8 TUsbcDescriptorBase::Type() const
   119 	{
   120 	return iBufPtr[1];
   121 	}
   122 
   123 
   124 void TUsbcDescriptorBase::UpdateFs()
   125 	{
   126 	// virtual function can be overridden in derived classes.
   127 	return;
   128 	}
   129 
   130 
   131 void TUsbcDescriptorBase::UpdateHs()
   132 	{
   133 	// virtual function can be overridden in derived classes.
   134 	return;
   135 	}
   136 
   137 
   138 void TUsbcDescriptorBase::SetBufferPointer(const TDesC8& aDes)
   139 	{
   140 	iBufPtr.Set(const_cast<TUint8*>(aDes.Ptr()), aDes.Size(), aDes.Size());
   141 	}
   142 
   143 
   144 // --- TUsbcDeviceDescriptor
   145 
   146 TUsbcDeviceDescriptor::TUsbcDeviceDescriptor()
   147 	: iBuf()
   148 	{
   149 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::TUsbcDeviceDescriptor()"));
   150 	}
   151 
   152 
   153 TUsbcDeviceDescriptor* TUsbcDeviceDescriptor::New(TUint8 aDeviceClass, TUint8 aDeviceSubClass,
   154 												  TUint8 aDeviceProtocol, TUint8 aMaxPacketSize0,
   155 												  TUint16 aVendorId, TUint16 aProductId,
   156 												  TUint16 aDeviceRelease, TUint8 aNumConfigurations)
   157 	{
   158 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::New()"));
   159 	TUsbcDeviceDescriptor* self = new TUsbcDeviceDescriptor();
   160 	if (self)
   161 		{
   162 		if (self->Construct(aDeviceClass, aDeviceSubClass, aDeviceProtocol, aMaxPacketSize0, aVendorId,
   163 							aProductId, aDeviceRelease, aNumConfigurations) != KErrNone)
   164 			{
   165 			delete self;
   166 			return NULL;
   167 			}
   168 		}
   169 	return self;
   170 	}
   171 
   172 
   173 TInt TUsbcDeviceDescriptor::Construct(TUint8 aDeviceClass, TUint8 aDeviceSubClass, TUint8 aDeviceProtocol,
   174 									  TUint8 aMaxPacketSize0, TUint16 aVendorId, TUint16 aProductId,
   175 									  TUint16 aDeviceRelease, TUint8 aNumConfigurations)
   176 	{
   177 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::Construct()"));
   178 	iBuf.SetMax();
   179 	SetBufferPointer(iBuf);
   180 	iBuf[0] = iBuf.Size();									// bLength
   181 	iBuf[1] = KUsbDescType_Device;							// bDescriptorType
   182 	SetWord(2, KUsbcUsbVersion);							// bcdUSB
   183 	iBuf[4] = aDeviceClass;									// bDeviceClass
   184 	iBuf[5] = aDeviceSubClass;								// bDeviceSubClass
   185 	iBuf[6] = aDeviceProtocol;								// bDeviceProtocol
   186 	iBuf[7] = aMaxPacketSize0;								// bMaxPacketSize0
   187 	SetWord(8, aVendorId);									// idVendor
   188 	SetWord(10, aProductId);								// idProduct
   189 	SetWord(12, aDeviceRelease);							// bcdDevice
   190 	iBuf[14] = 0;											// iManufacturer
   191 	iBuf[15] = 0;											// iProduct
   192 	iBuf[16] = 0;											// iSerialNumber
   193 	iBuf[17] = aNumConfigurations;							// bNumConfigurations
   194 	iEp0Size_Fs = aMaxPacketSize0;
   195 	return KErrNone;
   196 	}
   197 
   198 
   199 void TUsbcDeviceDescriptor::UpdateFs()
   200 	{
   201 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::UpdateFs()"));
   202 	SetByte(7, iEp0Size_Fs);								// bMaxPacketSize0
   203 	}
   204 
   205 
   206 void TUsbcDeviceDescriptor::UpdateHs()
   207 	{
   208 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::UpdateHs()"));
   209 	SetByte(7, 64);											// bMaxPacketSize0
   210 	}
   211 
   212 
   213 // --- TUsbcDeviceQualifierDescriptor
   214 
   215 TUsbcDeviceQualifierDescriptor::TUsbcDeviceQualifierDescriptor()
   216 	: iBuf()
   217 	{
   218 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceDescriptor::TUsbcDeviceQualifierDescriptor()"));
   219 	}
   220 
   221 
   222 TUsbcDeviceQualifierDescriptor* TUsbcDeviceQualifierDescriptor::New(TUint8 aDeviceClass,
   223 																	TUint8 aDeviceSubClass,
   224 																	TUint8 aDeviceProtocol,
   225 																	TUint8 aMaxPacketSize0,
   226 																	TUint8 aNumConfigurations,
   227 																	TUint8 aReserved)
   228 	{
   229 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::New()"));
   230 	TUsbcDeviceQualifierDescriptor* self = new TUsbcDeviceQualifierDescriptor();
   231 	if (self)
   232 		{
   233 		if (self->Construct(aDeviceClass, aDeviceSubClass, aDeviceProtocol, aMaxPacketSize0,
   234 							aNumConfigurations, aReserved) != KErrNone)
   235 			{
   236 			delete self;
   237 			return NULL;
   238 			}
   239 		}
   240 	return self;
   241 	}
   242 
   243 
   244 TInt TUsbcDeviceQualifierDescriptor::Construct(TUint8 aDeviceClass, TUint8 aDeviceSubClass,
   245 											   TUint8 aDeviceProtocol, TUint8 aMaxPacketSize0,
   246 											   TUint8 aNumConfigurations, TUint8 aReserved)
   247 	{
   248 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::Construct()"));
   249 	iBuf.SetMax();
   250 	SetBufferPointer(iBuf);
   251 	iBuf[0] = iBuf.Size();									// bLength
   252 	iBuf[1] = KUsbDescType_DeviceQualifier;					// bDescriptorType
   253 	SetWord(2, KUsbcUsbVersion);							// bcdUSB
   254 	iBuf[4] = aDeviceClass;									// bDeviceClass
   255 	iBuf[5] = aDeviceSubClass;								// bDeviceSubClass
   256 	iBuf[6] = aDeviceProtocol;								// bDeviceProtocol
   257 	iBuf[7] = aMaxPacketSize0;								// bMaxPacketSize0
   258 	iBuf[8] = aNumConfigurations;							// bNumConfigurations
   259 	if (aReserved) aReserved = 0;
   260 	iBuf[9] = aReserved;									// Reserved for future use, must be zero
   261 	iEp0Size_Fs = aMaxPacketSize0;
   262 	return KErrNone;
   263 	}
   264 
   265 
   266 void TUsbcDeviceQualifierDescriptor::UpdateFs()
   267 	{
   268 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::UpdateFs()"));
   269 	// Here we do exactly the opposite of what's done in the Device descriptor (as this one's
   270 	// documenting the 'other than the current speed').
   271 	SetByte(7, 64);											// bMaxPacketSize0
   272 	}
   273 
   274 
   275 void TUsbcDeviceQualifierDescriptor::UpdateHs()
   276 	{
   277 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDeviceQualifierDescriptor::UpdateHs()"));
   278 	// Here we do exactly the opposite of what's done in the Device descriptor (as this one's
   279 	// documenting the 'other than the current speed').
   280 	SetByte(7, iEp0Size_Fs);								// bMaxPacketSize0
   281 	}
   282 
   283 
   284 // --- TUsbcConfigDescriptor
   285 
   286 TUsbcConfigDescriptor::TUsbcConfigDescriptor()
   287 	: iBuf()
   288 	{
   289 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfigDescriptor::TUsbcConfigDescriptor()"));
   290 	}
   291 
   292 
   293 TUsbcConfigDescriptor* TUsbcConfigDescriptor::New(TUint8 aConfigurationValue, TBool aSelfPowered,
   294 												  TBool aRemoteWakeup, TUint16 aMaxPower)
   295 	{
   296 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfigDescriptor::New()"));
   297 	TUsbcConfigDescriptor* self = new TUsbcConfigDescriptor();
   298 	if (self)
   299 		{
   300 		if (self->Construct(aConfigurationValue, aSelfPowered, aRemoteWakeup, aMaxPower) != KErrNone)
   301 			{
   302 			delete self;
   303 			return NULL;
   304 			}
   305 		}
   306 	return self;
   307 	}
   308 
   309 
   310 TInt TUsbcConfigDescriptor::Construct(TUint8 aConfigurationValue, TBool aSelfPowered,
   311 									   TBool aRemoteWakeup, TUint16 aMaxPower)
   312 	{
   313 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcConfigDescriptor::Construct()"));
   314 	iBuf.SetMax();
   315 	SetBufferPointer(iBuf);
   316 	iBuf[0] = iBuf.Size();									// bLength
   317 	iBuf[1] = KUsbDescType_Config;							// bDescriptorType
   318 	SetWord(2, KUsbDescSize_Config);						// wTotalLength
   319 	iBuf[4] = 0;											// bNumInterfaces
   320 	iBuf[5] = aConfigurationValue;							// bConfigurationValue
   321 	iBuf[6] = 0;											// iConfiguration
   322 	iBuf[7] = 0x80 |
   323 		(aSelfPowered ? KUsbDevAttr_SelfPowered : 0) |
   324 		(aRemoteWakeup ? KUsbDevAttr_RemoteWakeup : 0);		// bmAttributes (bit 7 always 1)
   325 	if (aMaxPower > 510)
   326 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Invalid value for bMaxPower: %d", aMaxPower));
   327 	iBuf[8] = aMaxPower / 2;								// bMaxPower (2mA units!)
   328 	return KErrNone;
   329 	}
   330 
   331 
   332 // --- TUsbcInterfaceDescriptor
   333 
   334 TUsbcInterfaceDescriptor::TUsbcInterfaceDescriptor()
   335 	: iBuf()
   336 	{
   337 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceDescriptor::TUsbcInterfaceDescriptor()"));
   338 	}
   339 
   340 
   341 TUsbcInterfaceDescriptor* TUsbcInterfaceDescriptor::New(TUint8 aInterfaceNumber, TUint8 aAlternateSetting,
   342 														TInt aNumEndpoints, const TUsbcClassInfo& aClassInfo)
   343 	{
   344 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceDescriptor::New()"));
   345 	TUsbcInterfaceDescriptor* self = new TUsbcInterfaceDescriptor();
   346 	if (self)
   347 		{
   348 		if (self->Construct(aInterfaceNumber, aAlternateSetting, aNumEndpoints, aClassInfo) != KErrNone)
   349 			{
   350 			delete self;
   351 			return NULL;
   352 			}
   353 		}
   354 	return self;
   355 	}
   356 
   357 
   358 TInt TUsbcInterfaceDescriptor::Construct(TUint8 aInterfaceNumber, TUint8 aAlternateSetting,
   359 										 TInt aNumEndpoints, const TUsbcClassInfo& aClassInfo)
   360 	{
   361 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcInterfaceDescriptor::Construct()"));
   362 	iBuf.SetMax();
   363 	SetBufferPointer(iBuf);
   364 	iBuf[0] = iBuf.Size();									// bLength
   365 	iBuf[1] = KUsbDescType_Interface;						// bDescriptorType
   366 	iBuf[2] = aInterfaceNumber;								// bInterfaceNumber
   367 	iBuf[3] = aAlternateSetting;							// bAlternateSetting
   368 	iBuf[4] = aNumEndpoints;								// bNumEndpoints
   369 	iBuf[5] = aClassInfo.iClassNum;							// bInterfaceClass
   370 	iBuf[6] = aClassInfo.iSubClassNum;						// bInterfaceSubClass
   371 	iBuf[7] = aClassInfo.iProtocolNum;						// bInterfaceProtocol
   372 	iBuf[8] = 0;											// iInterface
   373 	return KErrNone;
   374 	}
   375 
   376 
   377 // --- TUsbcEndpointDescriptorBase
   378 
   379 TUsbcEndpointDescriptorBase::TUsbcEndpointDescriptorBase()
   380 	{
   381 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::TUsbcEndpointDescriptorBase()"));
   382 	}
   383 
   384 
   385 TInt TUsbcEndpointDescriptorBase::Construct(const TUsbcEndpointInfo& aEpInfo)
   386 	{
   387 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::Construct()"));
   388 	//  Adjust FS/HS endpoint sizes
   389 	if (aEpInfo.AdjustEpSizes(iEpSize_Fs, iEpSize_Hs) != KErrNone)
   390 		{
   391 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown endpoint type: %d", aEpInfo.iType));
   392 		}
   393 	__KTRACE_OPT(KUSB, Kern::Printf("  Now set: iEpSize_Fs=%d iEpSize_Hs=%d (aEpInfo.iSize=%d)",
   394 									iEpSize_Fs, iEpSize_Hs, aEpInfo.iSize));
   395 
   396 	//  Adjust HS endpoint size for additional transactions
   397 	if ((aEpInfo.iType == KUsbEpTypeIsochronous) || (aEpInfo.iType == KUsbEpTypeInterrupt))
   398 		{
   399 		if ((aEpInfo.iTransactions > 0) && (aEpInfo.iTransactions < 3))
   400 			{
   401 			// Bits 12..11 specify the number of additional transactions per microframe
   402 			iEpSize_Hs |= (aEpInfo.iTransactions << 12);
   403 			__KTRACE_OPT(KUSB, Kern::Printf("  Adjusted for add. transact.: iEpSize_Hs=0x%02x "
   404 											"(aEpInfo.iTransactions=%d)",
   405 											iEpSize_Hs, aEpInfo.iTransactions));
   406 			}
   407 		else if (aEpInfo.iTransactions != 0)
   408 			{
   409 			__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Invalid iTransactions value: %d (ignored)",
   410 											  aEpInfo.iTransactions));
   411 			}
   412 		}
   413 
   414 	//  Adjust HS polling interval
   415 	TUsbcEndpointInfo info(aEpInfo);						// create local writeable copy
   416 	if (info.AdjustPollInterval() != KErrNone)
   417 		{
   418 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Unknown ep type (%d) or invalid interval value (%d)",
   419 										  info.iType, info.iInterval));
   420 		}
   421 	iInterval_Fs = info.iInterval;
   422 	iInterval_Hs = info.iInterval_Hs;
   423 	__KTRACE_OPT(KUSB, Kern::Printf("  Now set: iInterval_Fs=%d iInterval_Hs=%d",
   424 									iInterval_Fs, iInterval_Hs));
   425 	return KErrNone;
   426 	}
   427 
   428 
   429 void TUsbcEndpointDescriptorBase::UpdateFs()
   430 	{
   431 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::UpdateFs()"));
   432 	// (TUsbcEndpointDescriptorBase's FS/HS endpoint sizes and interval values got
   433 	//  adjusted in its Construct() method.)
   434 	SetWord(4, iEpSize_Fs);									// wMaxPacketSize
   435 	SetByte(6, iInterval_Fs);								// bInterval
   436 	}
   437 
   438 
   439 void TUsbcEndpointDescriptorBase::UpdateHs()
   440 	{
   441 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptorBase::UpdateHs()"));
   442 	// (TUsbcEndpointDescriptorBase's FS/HS endpoint sizes and interval values get
   443 	//  adjusted in its Construct() method.)
   444 	SetWord(4, iEpSize_Hs);									// wMaxPacketSize
   445 	SetByte(6, iInterval_Hs);								// bInterval
   446 	}
   447 
   448 
   449 // --- TUsbcEndpointDescriptor
   450 
   451 TUsbcEndpointDescriptor::TUsbcEndpointDescriptor()
   452 	: iBuf()
   453 	{
   454 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptor::TUsbcEndpointDescriptor()"));
   455 	}
   456 
   457 
   458 TUsbcEndpointDescriptor* TUsbcEndpointDescriptor::New(TUint8 aEndpointAddress,
   459 													  const TUsbcEndpointInfo& aEpInfo)
   460 	{
   461 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptor::New()"));
   462 	TUsbcEndpointDescriptor* self = new TUsbcEndpointDescriptor();
   463 	if (self)
   464 		{
   465 		if (self->Construct(aEndpointAddress, aEpInfo) != KErrNone)
   466 			{
   467 			delete self;
   468 			return NULL;
   469 			}
   470 		}
   471 	return self;
   472 	}
   473 
   474 
   475 TInt TUsbcEndpointDescriptor::Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo)
   476 	{
   477 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcEndpointDescriptor::Construct()"));
   478 	(void) TUsbcEndpointDescriptorBase::Construct(aEpInfo);	// Init Base class
   479 	iBuf.SetMax();
   480 	SetBufferPointer(iBuf);
   481 	iBuf[0] = iBuf.Size();									// bLength
   482 	iBuf[1] = KUsbDescType_Endpoint;						// bDescriptorType
   483 	iBuf[2] = aEndpointAddress;								// bEndpointAddress
   484 	iBuf[3] = EpTypeMask2Value(aEpInfo.iType);				// bmAttributes
   485 	SetWord(4, iEpSize_Fs);									// wMaxPacketSize (default is FS)
   486 	iBuf[6] = iInterval_Fs;									// bInterval (default is FS)
   487 	return KErrNone;
   488 	}
   489 
   490 
   491 // --- TUsbcAudioEndpointDescriptor
   492 
   493 TUsbcAudioEndpointDescriptor::TUsbcAudioEndpointDescriptor()
   494 	: iBuf()
   495 	{
   496 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcAudioEndpointDescriptor::TUsbcAudioEndpointDescriptor()"));
   497 	}
   498 
   499 
   500 TUsbcAudioEndpointDescriptor* TUsbcAudioEndpointDescriptor::New(TUint8 aEndpointAddress,
   501 																const TUsbcEndpointInfo& aEpInfo)
   502 	{
   503 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcAudioEndpointDescriptor::New()"));
   504 	TUsbcAudioEndpointDescriptor* self = new TUsbcAudioEndpointDescriptor();
   505 	if (self)
   506 		{
   507 		if (self->Construct(aEndpointAddress, aEpInfo) != KErrNone)
   508 			{
   509 			delete self;
   510 			return NULL;
   511 			}
   512 		}
   513 	return self;
   514 	}
   515 
   516 
   517 TInt TUsbcAudioEndpointDescriptor::Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo)
   518 	{
   519 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcAudioEndpointDescriptor::Construct()"));
   520 	(void) TUsbcEndpointDescriptorBase::Construct(aEpInfo);	// Init Base class
   521 	iBuf.SetMax();
   522 	SetBufferPointer(iBuf);
   523 	iBuf[0] = iBuf.Size();									// bLength
   524 	iBuf[1] = KUsbDescType_Endpoint;						// bDescriptorType
   525 	iBuf[2] = aEndpointAddress;								// bEndpointAddress
   526 	iBuf[3] = EpTypeMask2Value(aEpInfo.iType);				// bmAttributes
   527 	SetWord(4, iEpSize_Fs);									// wMaxPacketSize (default is FS)
   528 	iBuf[6] = iInterval_Fs;									// bInterval (default is FS)
   529 	iBuf[7] = 0;
   530 	iBuf[8] = 0;
   531 	return KErrNone;
   532 	}
   533 
   534 
   535 // --- TUsbcOtgDescriptor
   536 
   537 TUsbcOtgDescriptor* TUsbcOtgDescriptor::New(TBool aHnpSupport, TBool aSrpSupport)
   538 	{
   539 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcOtgDescriptor::New()"));
   540 	TUsbcOtgDescriptor* self = new TUsbcOtgDescriptor();
   541 	if (self && (self->Construct(aHnpSupport, aSrpSupport) != KErrNone))
   542 		{
   543 		delete self;
   544 		return NULL;
   545 		}
   546 	return self;
   547 	}
   548 
   549 
   550 TUsbcOtgDescriptor::TUsbcOtgDescriptor()
   551 	: iBuf()
   552 	{
   553 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcOtgDescriptor::TUsbcOtgDescriptor()"));
   554 	}
   555 
   556 
   557 TInt TUsbcOtgDescriptor::Construct(TBool aHnpSupport, TBool aSrpSupport)
   558 	{
   559 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcOtgDescriptor::Construct()"));
   560 	iBuf.SetMax();
   561 	SetBufferPointer(iBuf);
   562 	iBuf[0] = iBuf.Size();									// bLength
   563 	iBuf[1] = KUsbDescType_Otg;								// bDescriptorType
   564 	iBuf[2] = (aHnpSupport ? KUsbOtgAttr_HnpSupp : 0) |
   565 		(aSrpSupport ? KUsbOtgAttr_SrpSupp : 0);			// bmAttributes
   566 	return KErrNone;
   567     }
   568 
   569 
   570 // --- TUsbcClassSpecificDescriptor
   571 
   572 TUsbcClassSpecificDescriptor::TUsbcClassSpecificDescriptor()
   573 	: iBuf(NULL)
   574 	{
   575 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::TUsbcClassSpecificDescriptor()"));
   576 	}
   577 
   578 
   579 TUsbcClassSpecificDescriptor::~TUsbcClassSpecificDescriptor()
   580 	{
   581 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::~TUsbcClassSpecificDescriptor()"));
   582 	delete iBuf;
   583 	}
   584 
   585 
   586 TUsbcClassSpecificDescriptor* TUsbcClassSpecificDescriptor::New(TUint8 aType, TInt aSize)
   587 	{
   588 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::New()"));
   589 	TUsbcClassSpecificDescriptor* self = new TUsbcClassSpecificDescriptor();
   590 	if (self)
   591 		{
   592 		if (self->Construct(aType, aSize) != KErrNone)
   593 			{
   594 			delete self;
   595 			return NULL;
   596 			}
   597 		}
   598 	return self;
   599 	}
   600 
   601 
   602 TInt TUsbcClassSpecificDescriptor::Construct(TUint8 aType, TInt aSize)
   603 	{
   604 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcClassSpecificDescriptor::Construct()"));
   605 	iBuf = HBuf8::New(aSize);
   606 	if (!iBuf)
   607 		{
   608 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Allocation of CS desc buffer failed"));
   609 		return KErrNoMemory;
   610 		}
   611 	iBuf->SetMax();
   612 	SetBufferPointer(*iBuf);
   613 	SetByte(1, aType);										// bDescriptorType
   614 	return KErrNone;
   615 	}
   616 
   617 
   618 // --- TUsbcStringDescriptorBase
   619 
   620 TUsbcStringDescriptorBase::TUsbcStringDescriptorBase()
   621 	: /*iIndex(0),*/ iSBuf(0), iBufPtr(NULL, 0)
   622 	{
   623 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptorBase::TUsbcStringDescriptorBase()"));
   624 	}
   625 
   626 
   627 TUsbcStringDescriptorBase::~TUsbcStringDescriptorBase()
   628 	{
   629 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptorBase::~TUsbcStringDescriptorBase()"));
   630 	}
   631 
   632 
   633 TUint16 TUsbcStringDescriptorBase::Word(TInt aPosition) const
   634 	{
   635 	if (aPosition <= 1)
   636 		{
   637 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Word(%d) in string descriptor "
   638 										  "(TUsbcStringDescriptorBase::Word)", aPosition));
   639 		return 0;
   640 		}
   641 	else
   642 		{
   643 		// since iBufPtr[0] is actually string descriptor byte index 2,
   644 		// we have to subtract 2 from the absolute position.
   645 		return SWAP_BYTES_16(*reinterpret_cast<const TUint16*>(&iBufPtr[aPosition - 2]));
   646 		}
   647 	}
   648 
   649 
   650 void TUsbcStringDescriptorBase::SetWord(TInt aPosition, TUint16 aValue)
   651 	{
   652 	if (aPosition <= 1)
   653 		{
   654 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: SetWord(%d) in string descriptor "
   655 										  "(TUsbcStringDescriptorBase::SetWord)", aPosition));
   656 		return;
   657 		}
   658 	else
   659 		{
   660 		// since iBufPtr[0] is actually string descriptor byte index 2,
   661 		// we have to subtract 2 from the absolute position.
   662 		*reinterpret_cast<TUint16*>(&iBufPtr[aPosition - 2]) = SWAP_BYTES_16(aValue);
   663 		}
   664 	}
   665 
   666 
   667 TInt TUsbcStringDescriptorBase::GetDescriptorData(TUint8* aBuffer) const
   668 	{
   669 	aBuffer[0] = iSBuf[0];
   670 	aBuffer[1] = iSBuf[1];
   671 	memcpy(&aBuffer[2], iBufPtr.Ptr(), iBufPtr.Size());
   672 	return Size();
   673 	}
   674 
   675 
   676 TInt TUsbcStringDescriptorBase::GetDescriptorData(TUint8* aBuffer, TUint aMaxSize) const
   677 	{
   678 	if (aMaxSize < Size())
   679 		{
   680 		// No use to copy only half a string
   681 		return 0;
   682 		}
   683 	return GetDescriptorData(aBuffer);
   684 	}
   685 
   686 
   687 const TDes8& TUsbcStringDescriptorBase::StringData() const
   688 	{
   689 	return iBufPtr;
   690 	}
   691 
   692 
   693 TDes8& TUsbcStringDescriptorBase::StringData()
   694 	{
   695 	return iBufPtr;
   696 	}
   697 
   698 
   699 TUint TUsbcStringDescriptorBase::Size() const
   700 	{
   701 	return iSBuf[0];
   702 	}
   703 
   704 
   705 void TUsbcStringDescriptorBase::SetBufferPointer(const TDesC8& aDes)
   706 	{
   707 	iBufPtr.Set(const_cast<TUint8*>(aDes.Ptr()), aDes.Size(), aDes.Size());
   708 	}
   709 
   710 
   711 // --- TUsbcStringDescriptor
   712 
   713 TUsbcStringDescriptor::TUsbcStringDescriptor()
   714 	: iBuf(NULL)
   715 	{
   716 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::TUsbcStringDescriptor()"));
   717 	}
   718 
   719 
   720 TUsbcStringDescriptor::~TUsbcStringDescriptor()
   721 	{
   722 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::~TUsbcStringDescriptor()"));
   723 	delete iBuf;
   724 	}
   725 
   726 
   727 TUsbcStringDescriptor* TUsbcStringDescriptor::New(const TDesC8& aString)
   728 	{
   729 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::New"));
   730 	TUsbcStringDescriptor* self = new TUsbcStringDescriptor();
   731 	if (self)
   732 		{
   733 		if (self->Construct(aString) != KErrNone)
   734 			{
   735 			delete self;
   736 			return NULL;
   737 			}
   738 		}
   739 	return self;
   740 	}
   741 
   742 
   743 TInt TUsbcStringDescriptor::Construct(const TDesC8& aString)
   744 	{
   745 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcStringDescriptor::Construct"));
   746 	iBuf = HBuf8::New(aString.Size());						// bytes, not UNICODE chars
   747 	if (!iBuf)
   748 		{
   749 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Allocation of string buffer failed"));
   750 		return KErrNoMemory;
   751 		}
   752 	iBuf->SetMax();
   753 	SetBufferPointer(*iBuf);
   754 	iBufPtr.Copy(aString);
   755 	iSBuf.SetMax();
   756 	iSBuf[0] = iBuf->Size() + 2;							// Bytes
   757 	iSBuf[1] = KUsbDescType_String;
   758 	return KErrNone;
   759 	}
   760 
   761 
   762 // --- TUsbcLangIdDescriptor
   763 
   764 TUsbcLangIdDescriptor::TUsbcLangIdDescriptor()
   765 	: iBuf(NULL)
   766 	{
   767 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::TUsbcLangIdDescriptor()"));
   768 	}
   769 
   770 
   771 TUsbcLangIdDescriptor::~TUsbcLangIdDescriptor()
   772 	{
   773 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::~TUsbcLangIdDescriptor()"));
   774 	}
   775 
   776 
   777 TUsbcLangIdDescriptor* TUsbcLangIdDescriptor::New(TUint16 aLangId)
   778 	{
   779 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::New"));
   780 	TUsbcLangIdDescriptor* self = new TUsbcLangIdDescriptor();
   781 	if (self)
   782 		{
   783 		if (self->Construct(aLangId) != KErrNone)
   784 			{
   785 			delete self;
   786 			return NULL;
   787 			}
   788 		}
   789 	return self;
   790 	}
   791 
   792 
   793 TInt TUsbcLangIdDescriptor::Construct(TUint16 aLangId)
   794 	{
   795 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcLangIdDescriptor::Construct"));
   796 	iBuf.SetMax();
   797 	SetBufferPointer(iBuf);
   798 	iBufPtr[0] = LowByte(SWAP_BYTES_16(aLangId));			// Language ID value
   799 	iBufPtr[1] = HighByte(SWAP_BYTES_16(aLangId));
   800 	iSBuf.SetMax();
   801 	iSBuf[0] = iBuf.Size() + 2;								// Bytes
   802 	iSBuf[1] = KUsbDescType_String;
   803 	return KErrNone;
   804 	}
   805 
   806 
   807 // --- TUsbcDescriptorPool
   808 
   809 TUsbcDescriptorPool::TUsbcDescriptorPool(TUint8* aEp0_TxBuf)
   810 //
   811 //	The constructor for this class.
   812 //
   813 	: iDescriptors(), iStrings(), iIfcIdx(0), iEp0_TxBuf(aEp0_TxBuf), iHighSpeed(EFalse)
   814 	{
   815 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::TUsbcDescriptorPool()"));
   816 	}
   817 
   818 
   819 TUsbcDescriptorPool::~TUsbcDescriptorPool()
   820 	{
   821 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::~TUsbcDescriptorPool()"));
   822 	// The destructor of each <class T> object is called before the objects themselves are destroyed.
   823 	__KTRACE_OPT(KUSB, Kern::Printf("  iDescriptors.Count(): %d", iDescriptors.Count()));
   824 	iDescriptors.ResetAndDestroy();
   825 	__KTRACE_OPT(KUSB, Kern::Printf("  iStrings.Count(): %d", iStrings.Count()));
   826 	iStrings.ResetAndDestroy();
   827 	}
   828 
   829 
   830 TInt TUsbcDescriptorPool::Init(TUsbcDeviceDescriptor* aDeviceDesc, TUsbcConfigDescriptor* aConfigDesc,
   831 							   TUsbcLangIdDescriptor* aLangId, TUsbcStringDescriptor* aManufacturer,
   832 							   TUsbcStringDescriptor* aProduct, TUsbcStringDescriptor* aSerialNum,
   833 							   TUsbcStringDescriptor* aConfig, TUsbcOtgDescriptor* aOtgDesc)
   834 	{
   835 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::Init()"));
   836 	if (!aDeviceDesc || !aConfigDesc)
   837 		{
   838 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: No Device or Config descriptor specified"));
   839 		return KErrArgument;
   840 		}
   841 	for (TInt n = 0; n < KDescPosition_FirstAvailable; n++)
   842 		{
   843 		iDescriptors.Append(NULL);
   844 		}
   845 	__ASSERT_DEBUG((iDescriptors.Count() == KDescPosition_FirstAvailable),
   846 				   Kern::Printf("  Error: iDescriptors.Count() (%d) != KDescPosition_FirstAvailable (%d)",
   847 								iDescriptors.Count(), KDescPosition_FirstAvailable));
   848 	iDescriptors[KDescPosition_Device] = aDeviceDesc;
   849 	iDescriptors[KDescPosition_Config] = aConfigDesc;
   850 	if (aOtgDesc)
   851 		{
   852 		iDescriptors[KDescPosition_Otg] = aOtgDesc;
   853 		// Update the config descriptor's wTotalLength field
   854 		UpdateConfigDescriptorLength(KUsbDescSize_Otg);
   855 		}
   856 	if (!aLangId)
   857 		{
   858 		// USB spec 9.6.7 says: "String index zero for all languages returns a string descriptor
   859 		// that contains an array of two-byte LANGID codes supported by the device. ...
   860 		// USB devices that omit all string descriptors must not return an array of LANGID codes."
   861 		// So if we have at least one string descriptor, we must also have a LANGID descriptor.
   862 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: No LANGID string descriptor specified"));
   863 		return KErrArgument;
   864 		}
   865 	iStrings.Insert(aLangId, KStringPosition_Langid);
   866 	iStrings.Insert(aManufacturer, KStringPosition_Manufact);
   867 	iStrings.Insert(aProduct, KStringPosition_Product);
   868 	iStrings.Insert(aSerialNum, KStringPosition_Serial);
   869 	iStrings.Insert(aConfig, KStringPosition_Config);
   870 	__ASSERT_DEBUG((iStrings.Count() == 5),
   871 				   Kern::Printf("  Error: iStrings.Count() != 5 (%d)", iStrings.Count()));
   872 #ifdef _DEBUG
   873 	for (TInt i = KStringPosition_Langid; i <= KStringPosition_Config; i++)
   874 		{
   875 		__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool.iStrings[%d] = 0x%x", i, iStrings[i]));
   876 		}
   877 #endif
   878 	// Set string indices
   879 	if (aManufacturer)
   880 		iDescriptors[KDescPosition_Device]->SetByte(KUsbDescStringIndex_Manufact,
   881 													KStringPosition_Manufact);
   882 	if (aProduct)
   883 		iDescriptors[KDescPosition_Device]->SetByte(KUsbDescStringIndex_Product,
   884 													KStringPosition_Product);
   885 	if (aSerialNum)
   886 		iDescriptors[KDescPosition_Device]->SetByte(KUsbDescStringIndex_Serial,
   887 													KStringPosition_Serial);
   888 	if (aConfig)
   889 		iDescriptors[KDescPosition_Config]->SetByte(KUsbDescStringIndex_Config,
   890 													KStringPosition_Config);
   891 	return KErrNone;
   892 	}
   893 
   894 
   895 TInt TUsbcDescriptorPool::InitHs()
   896 	{
   897 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InitHs()"));
   898 	__ASSERT_DEBUG((iDescriptors.Count() >= KDescPosition_FirstAvailable),
   899 				   Kern::Printf("  Error: Call Init() first)"));
   900 
   901 	TUsbcDeviceQualifierDescriptor* const dq_desc = TUsbcDeviceQualifierDescriptor::New(
   902 		iDescriptors[KDescPosition_Device]->Byte(4),		// aDeviceClass
   903 		iDescriptors[KDescPosition_Device]->Byte(5),		// aDeviceSubClass
   904 		iDescriptors[KDescPosition_Device]->Byte(6),		// aDeviceProtocol
   905 		iDescriptors[KDescPosition_Device]->Byte(7),		// aMaxPacketSize0
   906 		iDescriptors[KDescPosition_Device]->Byte(17));		// aNumConfigurations
   907 	if (!dq_desc)
   908 		{
   909 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for dev qualif desc failed."));
   910 		return KErrGeneral;
   911 		}
   912 	iDescriptors[KDescPosition_DeviceQualifier] = dq_desc;
   913 
   914 	TUsbcOtherSpeedConfigDescriptor* const osc_desc = TUsbcOtherSpeedConfigDescriptor::New(
   915 		iDescriptors[KDescPosition_Config]->Byte(5),		// aConfigurationValue
   916 		iDescriptors[KDescPosition_Config]->Byte(7) & KUsbDevAttr_SelfPowered, // aSelfPowered
   917 		iDescriptors[KDescPosition_Config]->Byte(7) & KUsbDevAttr_RemoteWakeup,	// aRemoteWakeup
   918 		iDescriptors[KDescPosition_Config]->Byte(8) * 2);	// aMaxPower (mA)
   919 	if (!osc_desc)
   920 		{
   921 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for other speed conf desc failed."));
   922 		return KErrGeneral;
   923 		}
   924 
   925 	// We need to set the bDescriptorType field manually, as that's the only one
   926 	// that differs from a Configuration descriptor.
   927 	osc_desc->SetByte(1, KUsbDescType_OtherSpeedConfig);
   928 
   929 	// Also, initially we set the iConfiguration string index to the same value as
   930 	// in the Configuration descriptor.
   931 	osc_desc->SetByte(KUsbDescStringIndex_Config,
   932 					  iDescriptors[KDescPosition_Config]->Byte(KUsbDescStringIndex_Config));
   933 
   934 	iDescriptors[KDescPosition_OtherSpeedConfig] = osc_desc;
   935 
   936 	return KErrNone;
   937 	}
   938 
   939 
   940 TInt TUsbcDescriptorPool::UpdateDescriptorsFs()
   941 	{
   942 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateDescriptorsFs()"));
   943 	const TInt count = iDescriptors.Count();
   944 	for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
   945 		{
   946 		TUsbcDescriptorBase* const ptr = iDescriptors[i];
   947 		ptr->UpdateFs();
   948 		}
   949 	iHighSpeed = EFalse;
   950 	return KErrNone;
   951 	}
   952 
   953 
   954 TInt TUsbcDescriptorPool::UpdateDescriptorsHs()
   955 	{
   956 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateDescriptorsHs()"));
   957 	const TInt count = iDescriptors.Count();
   958 	for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
   959 		{
   960 		TUsbcDescriptorBase* const ptr = iDescriptors[i];
   961 		ptr->UpdateHs();
   962 		}
   963 	iHighSpeed = ETrue;
   964 	return KErrNone;
   965 	}
   966 
   967 
   968 //
   969 // An error can be indicated by either a return value != KErrNone or by a descriptor size == 0.
   970 //
   971 TInt TUsbcDescriptorPool::FindDescriptor(TUint8 aType, TUint8 aIndex, TUint16 aLangid, TInt& aSize) const
   972 	{
   973 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindDescriptor()"));
   974 	TInt result = KErrGeneral;
   975 	switch (aType)
   976 		{
   977 	case KUsbDescType_Device:
   978 		if (aLangid != 0)
   979 			{
   980 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
   981 			}
   982 		else if (aIndex > 0)
   983 			{
   984 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad device index: %d", aIndex));
   985 			}
   986 		else
   987 			{
   988 			aSize = GetDeviceDescriptor(KDescPosition_Device);
   989 			result = KErrNone;
   990 			}
   991 		break;
   992 	case KUsbDescType_Config:
   993 		if (aLangid != 0)
   994 			{
   995 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
   996 			}
   997 		else if (aIndex > 0)
   998 			{
   999 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad config index: %d", aIndex));
  1000 			}
  1001 		else
  1002 			{
  1003 			aSize = GetConfigurationDescriptor(KDescPosition_Config);
  1004 			result = KErrNone;
  1005 			}
  1006 		break;
  1007 	case KUsbDescType_DeviceQualifier:
  1008 		if (aLangid != 0)
  1009 			{
  1010 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
  1011 			}
  1012 		else if (aIndex > 0)
  1013 			{
  1014 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad device index: %d", aIndex));
  1015 			}
  1016 		else
  1017 			{
  1018 			aSize = GetDeviceDescriptor(KDescPosition_DeviceQualifier);
  1019 			result = KErrNone;
  1020 			}
  1021 		break;
  1022 	case KUsbDescType_OtherSpeedConfig:
  1023 		if (aLangid != 0)
  1024 			{
  1025 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad langid: 0x%04x", aLangid));
  1026 			}
  1027 		else if (aIndex > 0)
  1028 			{
  1029 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bad config index: %d", aIndex));
  1030 			}
  1031 		else
  1032 			{
  1033 			aSize = GetConfigurationDescriptor(KDescPosition_OtherSpeedConfig);
  1034 			result = KErrNone;
  1035 			}
  1036 		break;
  1037 	case KUsbDescType_Otg:
  1038 		aSize = GetOtgDescriptor();
  1039 		result = KErrNone;
  1040 		break;
  1041 	case KUsbDescType_String:
  1042 		if (aIndex == 0)									// 0 addresses the LangId array
  1043 			{
  1044 			if (AnyStringDescriptors())
  1045 				{
  1046 				aSize = GetStringDescriptor(aIndex);
  1047 				result = KErrNone;
  1048 				}
  1049 			else
  1050 				{
  1051 				__KTRACE_OPT(KUSB, Kern::Printf("  No string descriptors: not returning LANGID array"));
  1052 				}
  1053 			}
  1054 		else
  1055 			{
  1056    			if (!aLangid)
  1057    				{
  1058    				__KTRACE_OPT(KUSB,
  1059  							 Kern::Printf("  Strange: LANGID=0 for a $ descriptor (ignoring LANGID)"));
  1060 				// The USB spec doesn't really say what to do in this case, but as there are host apps
  1061 				// that fail if we return an error here, we choose to ignore the issue.
  1062    				}
  1063 			else if (aLangid != iStrings[KStringPosition_Langid]->Word(2))
  1064 				{
  1065 				// We have only one (this) language
  1066 				__KTRACE_OPT(KUSB,
  1067 							 Kern::Printf("  Bad LANGID: 0x%04X requested, 0x%04X supported (ignoring LANGID)",
  1068 										  aLangid, iStrings[KStringPosition_Langid]->Word(2)));
  1069 				// We could return an error here, but rather choose to ignore the discrepancy
  1070 				// (the USB spec is not very clear what to do in such a case anyway).
  1071 				}
  1072 			aSize = GetStringDescriptor(aIndex);
  1073 			result = KErrNone;
  1074 			}
  1075 		break;
  1076 	case KUsbDescType_CS_Interface:
  1077 		/* fall through */
  1078 	case KUsbDescType_CS_Endpoint:
  1079 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: finding of class specific descriptors not supported"));
  1080 		break;
  1081 	default:
  1082 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: unknown descriptor type requested: %d", aType));
  1083 		break;
  1084 		}
  1085 	return result;
  1086 	}
  1087 
  1088 
  1089 void TUsbcDescriptorPool::InsertDescriptor(TUsbcDescriptorBase* aDesc)
  1090 	{
  1091 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InsertDescriptor()"));
  1092 	switch (aDesc->Type())
  1093 		{
  1094 	case KUsbDescType_Interface:
  1095 		InsertIfcDesc(aDesc);
  1096 		break;
  1097 	case KUsbDescType_Endpoint:
  1098 		InsertEpDesc(aDesc);
  1099 		break;
  1100 	default:
  1101 		__KTRACE_OPT(KUSB, Kern::Printf("  Error: unsupported descriptor type"));
  1102 		}
  1103 	}
  1104 
  1105 
  1106 void TUsbcDescriptorPool::SetIfcStringDescriptor(TUsbcStringDescriptor* aDesc, TInt aNumber, TInt aSetting)
  1107 	{
  1108 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetIfcDescriptor(%d, %d)", aNumber, aSetting));
  1109 	const TInt i = FindIfcDescriptor(aNumber, aSetting);
  1110 	if (i < 0)
  1111 		{
  1112 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Ifc descriptor not found (%d, %d)",
  1113 										  aNumber, aSetting));
  1114 		return;
  1115 		}
  1116 	// Try to find available NULL postition
  1117 	TInt str_idx = FindAvailableStringPos();
  1118 	if (str_idx >= 0)
  1119 		{
  1120 		// Insert string descriptor for specified interface
  1121 		ExchangeStringDescriptor(str_idx, aDesc);
  1122 		}
  1123 	else
  1124 		{
  1125 		// No NULL found - expand array
  1126 		str_idx = iStrings.Count();
  1127 		if (str_idx > 0xff)
  1128 			{
  1129 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: $ descriptor array full (idx=%d)", str_idx));
  1130 			return;
  1131 			}
  1132 		while (str_idx < KStringPosition_FirstAvailable)
  1133 			{
  1134 			iStrings.Append(NULL);
  1135 			str_idx = iStrings.Count();
  1136 			}
  1137 		// Append string descriptor for specified interface
  1138 		iStrings.Append(aDesc);
  1139 		}
  1140 	// Update this ifc descriptor's string index field
  1141 	iDescriptors[i]->SetByte(8, str_idx);
  1142 	__KTRACE_OPT(KUSB, Kern::Printf("  String for ifc %d/%d (@ pos %d): \"%S\"", aNumber, aSetting, str_idx,
  1143 									&iStrings[str_idx]->StringData()));
  1144 	}
  1145 
  1146 
  1147 void TUsbcDescriptorPool::DeleteIfcDescriptor(TInt aNumber, TInt aSetting)
  1148 	{
  1149 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::DeleteIfcDescriptor(%d, %d)", aNumber, aSetting));
  1150 	const TInt i = FindIfcDescriptor(aNumber, aSetting);
  1151 	if (i < 0)
  1152 		{
  1153 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: DeleteIfcDescriptor - descriptor not found (%d, %d)",
  1154 										  aNumber, aSetting));
  1155 		return;
  1156 		}
  1157 	// Delete (if necessary) specified interface's string descriptor
  1158 	const TInt si = iDescriptors[i]->Byte(8);
  1159 	if (si != 0)
  1160 		{
  1161 		ExchangeStringDescriptor(si, NULL);
  1162 		}
  1163 	// Delete specified ifc setting + all its cs descriptors + all its endpoints + all their cs descriptors:
  1164 	// find position of the next interface descriptor: we need to delete everything in between
  1165 	const TInt count = iDescriptors.Count();
  1166 	TInt j = i, n = 1;
  1167 	while (++j < count && iDescriptors[j]->Type() != KUsbDescType_Interface)
  1168 		++n;
  1169 	DeleteDescriptors(i, n);
  1170 	// Update all the following interfaces' bInterfaceNumber field if required
  1171 	// (because those descriptors might have moved down by one position)
  1172 	UpdateIfcNumbers(aNumber);
  1173 	iIfcIdx = 0;											// ifc index no longer valid
  1174 	}
  1175 
  1176 
  1177 // The TC in many of the following functions stands for 'ThreadCopy',
  1178 // because that's what's happening there.
  1179 
  1180 TInt TUsbcDescriptorPool::GetDeviceDescriptorTC(DThread* aThread, TDes8& aBuffer) const
  1181 	{
  1182 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceDescriptorTC()"));
  1183 	return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[KDescPosition_Device]->DescriptorData(), 0);
  1184 	}
  1185 
  1186 
  1187 TInt TUsbcDescriptorPool::SetDeviceDescriptorTC(DThread* aThread, const TDes8& aBuffer)
  1188 	{
  1189 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetDeviceDescriptorTC()"));
  1190 	TBuf8<KUsbDescSize_Device> device;
  1191 	const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, device, 0);
  1192 	if (r != KErrNone)
  1193 		{
  1194 		return r;
  1195 		}
  1196 	iDescriptors[KDescPosition_Device]->SetByte(2, device[2]); // bcdUSB
  1197 	iDescriptors[KDescPosition_Device]->SetByte(3, device[3]); // bcdUSB (part II)
  1198 	iDescriptors[KDescPosition_Device]->SetByte(4, device[4]); // bDeviceClass
  1199 	iDescriptors[KDescPosition_Device]->SetByte(5, device[5]); // bDeviceSubClass
  1200 	iDescriptors[KDescPosition_Device]->SetByte(6, device[6]); // bDeviceProtocol
  1201 	iDescriptors[KDescPosition_Device]->SetByte(8, device[8]); // idVendor
  1202 	iDescriptors[KDescPosition_Device]->SetByte(9, device[9]); // idVendor (part II)
  1203 	iDescriptors[KDescPosition_Device]->SetByte(10, device[10]); // idProduct
  1204 	iDescriptors[KDescPosition_Device]->SetByte(11, device[11]); // idProduct (part II)
  1205 	iDescriptors[KDescPosition_Device]->SetByte(12, device[12]); // bcdDevice
  1206 	iDescriptors[KDescPosition_Device]->SetByte(13, device[13]); // bcdDevice (part II)
  1207 	return KErrNone;
  1208 	}
  1209 
  1210 
  1211 TInt TUsbcDescriptorPool::GetConfigurationDescriptorTC(DThread* aThread, TDes8& aBuffer) const
  1212 	{
  1213 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetConfigurationDescriptorTC()"));
  1214 	return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[KDescPosition_Config]->DescriptorData(), 0);
  1215 	}
  1216 
  1217 
  1218 TInt TUsbcDescriptorPool::SetConfigurationDescriptorTC(DThread* aThread, const TDes8& aBuffer)
  1219 	{
  1220 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetConfigurationDescriptorTC()"));
  1221 	TBuf8<KUsbDescSize_Config> config;
  1222 	const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, config, 0);
  1223 	if (r != KErrNone)
  1224 		{
  1225 		return r;
  1226 		}
  1227 	iDescriptors[KDescPosition_Config]->SetByte(7, config[7]); // bmAttributes
  1228 	iDescriptors[KDescPosition_Config]->SetByte(8, config[8]); // bMaxPower
  1229 	return KErrNone;
  1230 	}
  1231 
  1232 
  1233 TInt TUsbcDescriptorPool::GetOtgDescriptorTC(DThread* aThread, TDes8& aBuffer) const
  1234 	{
  1235 	return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[KDescPosition_Otg]->DescriptorData(), 0);
  1236 	}
  1237 
  1238 
  1239 TInt TUsbcDescriptorPool::SetOtgDescriptor(const TDesC8& aBuffer)
  1240 	{
  1241 	iDescriptors[KDescPosition_Otg]->SetByte(2, aBuffer[2]); // bmAttributes
  1242 	return KErrNone;
  1243 	}
  1244 
  1245 
  1246 TInt TUsbcDescriptorPool::GetInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer,
  1247 												   TInt aInterface, TInt aSetting) const
  1248 	{
  1249 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetInterfaceDescriptorTC()"));
  1250 	const TInt i = FindIfcDescriptor(aInterface, aSetting);
  1251 	if (i < 0)
  1252 		{
  1253 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
  1254 		return KErrNotFound;
  1255 		}
  1256 	return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
  1257 	}
  1258 
  1259 
  1260 TInt TUsbcDescriptorPool::SetInterfaceDescriptor(const TDes8& aBuffer, TInt aInterface, TInt aSetting)
  1261 	{
  1262 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetInterfaceDescriptor()"));
  1263 	const TInt i = FindIfcDescriptor(aInterface, aSetting);
  1264 	if (i < 0)
  1265 		{
  1266 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
  1267 		return KErrNotFound;
  1268 		}
  1269 	iDescriptors[i]->SetByte(2, aBuffer[2]);				// bInterfaceNumber
  1270 	iDescriptors[i]->SetByte(5, aBuffer[5]);				// bInterfaceClass
  1271 	iDescriptors[i]->SetByte(6, aBuffer[6]);				// bInterfaceSubClass
  1272 	iDescriptors[i]->SetByte(7, aBuffer[7]);				// bInterfaceProtocol
  1273 	return KErrNone;
  1274 	}
  1275 
  1276 
  1277 TInt TUsbcDescriptorPool::GetEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer,
  1278 												  TInt aInterface, TInt aSetting, TUint8 aEndpointAddress) const
  1279 	{
  1280 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetEndpointDescriptorTC()"));
  1281 	const TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
  1282 	if (i < 0)
  1283 		{
  1284 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
  1285 		return KErrNotFound;
  1286 		}
  1287 	return Kern::ThreadDesWrite(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
  1288 	}
  1289 
  1290 
  1291 TInt TUsbcDescriptorPool::SetEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer,
  1292 												  TInt aInterface, TInt aSetting, TUint8 aEndpointAddress)
  1293 	{
  1294 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetEndpointDescriptorTC()"));
  1295 	const TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
  1296 	if (i < 0)
  1297 		{
  1298 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
  1299 		return KErrNotFound;
  1300 		}
  1301 	TBuf8<KUsbDescSize_AudioEndpoint> ep;					// it could be an audio endpoint
  1302 	const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, ep, 0);
  1303 	if (r != KErrNone)
  1304 		{
  1305 		return r;
  1306 		}
  1307 	iDescriptors[i]->SetByte(3, ep[3]);						// bmAttributes
  1308 	iDescriptors[i]->SetByte(6, ep[6]);						// bInterval
  1309 	if (iDescriptors[i]->Size() == KUsbDescSize_AudioEndpoint)
  1310 		{
  1311 		iDescriptors[i]->SetByte(7, ep[7]);					// bRefresh
  1312 		iDescriptors[i]->SetByte(8, ep[8]);					// bSynchAddress
  1313 		}
  1314 	return KErrNone;
  1315 	}
  1316 
  1317 
  1318 TInt TUsbcDescriptorPool::GetEndpointDescriptorSize(TInt aInterface, TInt aSetting, TUint8 aEndpointAddress,
  1319 													TInt& aSize) const
  1320 	{
  1321 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetEndpointDescriptorSize()"));
  1322 	const TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
  1323 	if (i < 0)
  1324 		{
  1325 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
  1326 		return KErrNotFound;
  1327 		}
  1328 	aSize = iDescriptors[i]->Size();
  1329 	return KErrNone;
  1330 	}
  1331 
  1332 
  1333 TInt TUsbcDescriptorPool::GetDeviceQualifierDescriptorTC(DThread* aThread, TDes8& aBuffer) const
  1334 	{
  1335 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceQualifierDescriptorTC()"));
  1336 	if (iDescriptors[KDescPosition_DeviceQualifier] == NULL)
  1337 		{
  1338 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Device_Qualifier descriptor not supported"));
  1339 		return KErrNotSupported;
  1340 		}
  1341 	return Kern::ThreadDesWrite(aThread, &aBuffer,
  1342 								iDescriptors[KDescPosition_DeviceQualifier]->DescriptorData(), 0);
  1343 	}
  1344 
  1345 
  1346 TInt TUsbcDescriptorPool::SetDeviceQualifierDescriptorTC(DThread* aThread, const TDes8& aBuffer)
  1347 	{
  1348 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetDeviceQualifierDescriptorTC()"));
  1349 	if (iDescriptors[KDescPosition_DeviceQualifier] == NULL)
  1350 		{
  1351 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Device_Qualifier descriptor not supported"));
  1352 		return KErrNotSupported;
  1353 		}
  1354 	TBuf8<KUsbDescSize_DeviceQualifier> device;
  1355 	const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, device, 0);
  1356 	if (r != KErrNone)
  1357 		{
  1358 		return r;
  1359 		}
  1360 	iDescriptors[KDescPosition_DeviceQualifier]->SetByte(2, device[2]); // bcdUSB
  1361 	iDescriptors[KDescPosition_DeviceQualifier]->SetByte(3, device[3]); // bcdUSB (part II)
  1362 	iDescriptors[KDescPosition_DeviceQualifier]->SetByte(4, device[4]); // bDeviceClass
  1363 	iDescriptors[KDescPosition_DeviceQualifier]->SetByte(5, device[5]); // bDeviceSubClass
  1364 	iDescriptors[KDescPosition_DeviceQualifier]->SetByte(6, device[6]); // bDeviceProtocol
  1365 	return KErrNone;
  1366 	}
  1367 
  1368 
  1369 TInt TUsbcDescriptorPool::GetOtherSpeedConfigurationDescriptorTC(DThread* aThread, TDes8& aBuffer) const
  1370 	{
  1371 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetOtherSpeedConfigurationDescriptorTC()"));
  1372 	if (iDescriptors[KDescPosition_OtherSpeedConfig] == NULL)
  1373 		{
  1374 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Other_Speed_Configuration descriptor not supported"));
  1375 		return KErrNotSupported;
  1376 		}
  1377 	return Kern::ThreadDesWrite(aThread, &aBuffer,
  1378 								iDescriptors[KDescPosition_OtherSpeedConfig]->DescriptorData(), 0);
  1379 	}
  1380 
  1381 
  1382 TInt TUsbcDescriptorPool::SetOtherSpeedConfigurationDescriptorTC(DThread* aThread, const TDes8& aBuffer)
  1383 	{
  1384 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetOtherSpeedConfigurationDescriptorTC()"));
  1385 	if (iDescriptors[KDescPosition_OtherSpeedConfig] == NULL)
  1386 		{
  1387 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Other_Speed_Configuration descriptor not supported"));
  1388 		return KErrNotSupported;
  1389 		}
  1390 	TBuf8<KUsbDescSize_OtherSpeedConfig> config;
  1391 	const TInt r = Kern::ThreadDesRead(aThread, &aBuffer, config, 0);
  1392 	if (r != KErrNone)
  1393 		{
  1394 		return r;
  1395 		}
  1396 	iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(7, config[7]); // bmAttributes
  1397 	iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(8, config[8]); // bMaxPower
  1398 	return KErrNone;
  1399 	}
  1400 
  1401 
  1402 TInt TUsbcDescriptorPool::GetCSInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer,
  1403 													 TInt aInterface, TInt aSetting) const
  1404 	{
  1405 	// first find the interface
  1406 	TInt i = FindIfcDescriptor(aInterface, aSetting);
  1407 	if (i < 0)
  1408 		{
  1409 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
  1410 		return KErrNotFound;
  1411 		}
  1412 	TInt r = KErrNotFound;
  1413 	TInt offset = 0;
  1414 	const TInt count = iDescriptors.Count();
  1415 	while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
  1416 		{
  1417 		r = Kern::ThreadDesWrite(aThread, &aBuffer,
  1418 								 iDescriptors[i]->DescriptorData(), offset);
  1419 		if (r != KErrNone)
  1420 			break;
  1421 		offset += iDescriptors[i]->Size();
  1422 		}
  1423 	return r;
  1424 	}
  1425 
  1426 
  1427 TInt TUsbcDescriptorPool::SetCSInterfaceDescriptorTC(DThread* aThread, const TDes8& aBuffer,
  1428 													 TInt aInterface, TInt aSetting, TInt aSize)
  1429 	{
  1430 	// First find the interface
  1431 	TInt i = FindIfcDescriptor(aInterface, aSetting);
  1432 	if (i < 0)
  1433 		{
  1434 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
  1435 		return KErrNotFound;
  1436 		}
  1437 	// Find a position where to insert the new class specific interface descriptor(s)
  1438 	const TInt count = iDescriptors.Count();
  1439 	while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
  1440 		;
  1441 	// Create a new cs descriptor
  1442 	TUsbcClassSpecificDescriptor* desc = TUsbcClassSpecificDescriptor::New(KUsbDescType_CS_Interface, aSize);
  1443 	if (!desc)
  1444 		{
  1445 		return KErrNoMemory;
  1446 		}
  1447 	__KTRACE_OPT(KUSB, Kern::Printf("  inserting descriptor at position %d", i));
  1448 	iDescriptors.Insert(desc, i);
  1449 
  1450 	// Update the config descriptor's wTotalLength field
  1451 	UpdateConfigDescriptorLength(aSize);
  1452 
  1453 	// Copy contents from the user side
  1454 	return Kern::ThreadDesRead(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
  1455 	}
  1456 
  1457 
  1458 TInt TUsbcDescriptorPool::GetCSInterfaceDescriptorSize(TInt aInterface, TInt aSetting, TInt& aSize) const
  1459 	{
  1460 	// first find the interface
  1461 	TInt i = FindIfcDescriptor(aInterface, aSetting);
  1462 	if (i < 0)
  1463 		{
  1464 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
  1465 		return KErrNotFound;
  1466 		}
  1467 	TInt r = KErrNotFound;
  1468 	TInt size = 0;
  1469 	const TInt count = iDescriptors.Count();
  1470 	while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
  1471 		{
  1472 		size += iDescriptors[i]->Size();
  1473 		r = KErrNone;
  1474 		}
  1475 	if (r == KErrNone)
  1476 		aSize = size;
  1477 	return r;
  1478 	}
  1479 
  1480 
  1481 TInt TUsbcDescriptorPool::GetCSEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer, TInt aInterface,
  1482 													TInt aSetting, TUint8 aEndpointAddress) const
  1483 	{
  1484 	// first find the endpoint
  1485 	TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
  1486 	if (i < 0)
  1487 		{
  1488 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
  1489 		return KErrNotFound;
  1490 		}
  1491 	TInt r = KErrNotFound;
  1492 	TInt offset = 0;
  1493 	const TInt count = iDescriptors.Count();
  1494 	while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
  1495 		{
  1496 		r = Kern::ThreadDesWrite(aThread, &aBuffer,
  1497 								 iDescriptors[i]->DescriptorData(), offset);
  1498 		if (r != KErrNone)
  1499 			break;
  1500 		offset += iDescriptors[i]->Size();
  1501 		}
  1502 	return r;
  1503 	}
  1504 
  1505 
  1506 TInt TUsbcDescriptorPool::SetCSEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer, TInt aInterface,
  1507 													TInt aSetting, TUint8 aEndpointAddress, TInt aSize)
  1508 	{
  1509 	// first find the endpoint
  1510 	TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
  1511 	if (i < 0)
  1512 		{
  1513 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
  1514 		return KErrNotFound;
  1515 		}
  1516 	// find a position where to insert the new class specific endpoint descriptor(s)
  1517 	const TInt count = iDescriptors.Count();
  1518 	while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
  1519 		;
  1520 	// create a new cs descriptor
  1521 	TUsbcClassSpecificDescriptor* desc = TUsbcClassSpecificDescriptor::New(KUsbDescType_CS_Endpoint, aSize);
  1522 	if (!desc)
  1523 		{
  1524 		return KErrNoMemory;
  1525 		}
  1526 	iDescriptors.Insert(desc, i);
  1527 	// update the config descriptor's wTotalLength field
  1528 	UpdateConfigDescriptorLength(aSize);
  1529 	// copy contents from user side
  1530 	return Kern::ThreadDesRead(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), 0);
  1531 	}
  1532 
  1533 
  1534 TInt TUsbcDescriptorPool::GetCSEndpointDescriptorSize(TInt aInterface, TInt aSetting,
  1535 													  TUint8 aEndpointAddress, TInt& aSize) const
  1536 	{
  1537 	// first find the endpoint
  1538 	TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
  1539 	if (i < 0)
  1540 		{
  1541 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
  1542 		return KErrNotFound;
  1543 		}
  1544 	TInt r = KErrNotFound;
  1545 	TInt size = 0;
  1546 	const TInt count = iDescriptors.Count();
  1547 	while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
  1548 		{
  1549 		size += iDescriptors[i]->Size();
  1550 		r = KErrNone;
  1551 		}
  1552 	if (r == KErrNone)
  1553 		aSize = size;
  1554 	return r;
  1555 	}
  1556 
  1557 
  1558 TInt TUsbcDescriptorPool::GetStringDescriptorLangIdTC(DThread* aThread, TDes8& aLangId) const
  1559 	{
  1560 	const TUint16 id = iStrings[KStringPosition_Langid]->Word(2);
  1561 	const TPtrC8 id_des(reinterpret_cast<const TUint8*>(&id), sizeof(id));
  1562 	return Kern::ThreadDesWrite(aThread, &aLangId, id_des, 0);
  1563 	}
  1564 
  1565 
  1566 TInt TUsbcDescriptorPool::SetStringDescriptorLangId(TUint16 aLangId)
  1567 	{
  1568 	iStrings[KStringPosition_Langid]->SetWord(2, aLangId);
  1569 	return KErrNone;
  1570 	}
  1571 
  1572 
  1573 TInt TUsbcDescriptorPool::GetManufacturerStringDescriptorTC(DThread* aThread, TDes8& aString) const
  1574 	{
  1575 	return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Manufact,
  1576 									   KStringPosition_Manufact);
  1577 	}
  1578 
  1579 
  1580 TInt TUsbcDescriptorPool::SetManufacturerStringDescriptorTC(DThread* aThread, const TDes8& aString)
  1581 	{
  1582 	return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Manufact,
  1583 									   KStringPosition_Manufact);
  1584 	}
  1585 
  1586 
  1587 TInt TUsbcDescriptorPool::RemoveManufacturerStringDescriptor()
  1588 	{
  1589 	return RemoveDeviceStringDescriptor(KUsbDescStringIndex_Manufact, KStringPosition_Manufact);
  1590 	}
  1591 
  1592 
  1593 TInt TUsbcDescriptorPool::GetProductStringDescriptorTC(DThread* aThread, TDes8& aString) const
  1594 	{
  1595 	return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Product,
  1596 									   KStringPosition_Product);
  1597 	}
  1598 
  1599 
  1600 TInt TUsbcDescriptorPool::SetProductStringDescriptorTC(DThread* aThread, const TDes8& aString)
  1601 	{
  1602 	return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Product,
  1603 									   KStringPosition_Product);
  1604 	}
  1605 
  1606 
  1607 TInt TUsbcDescriptorPool::RemoveProductStringDescriptor()
  1608 	{
  1609 	return RemoveDeviceStringDescriptor(KUsbDescStringIndex_Product, KStringPosition_Product);
  1610 	}
  1611 
  1612 
  1613 TInt TUsbcDescriptorPool::GetSerialNumberStringDescriptorTC(DThread* aThread, TDes8& aString) const
  1614 	{
  1615 	return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Serial,
  1616 									   KStringPosition_Serial);
  1617 	}
  1618 
  1619 
  1620 TInt TUsbcDescriptorPool::SetSerialNumberStringDescriptorTC(DThread* aThread, const TDes8& aString)
  1621 	{
  1622 	return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Serial,
  1623 									   KStringPosition_Serial);
  1624 	}
  1625 
  1626 
  1627 TInt TUsbcDescriptorPool::RemoveSerialNumberStringDescriptor()
  1628 	{
  1629 	return RemoveDeviceStringDescriptor(KUsbDescStringIndex_Serial, KStringPosition_Serial);
  1630 	}
  1631 
  1632 
  1633 TInt TUsbcDescriptorPool::GetConfigurationStringDescriptorTC(DThread* aThread, TDes8& aString) const
  1634 	{
  1635 	const TInt str_idx = iDescriptors[KDescPosition_Config]->Byte(KUsbDescStringIndex_Config);
  1636 	if (str_idx)
  1637 		{
  1638 		__ASSERT_ALWAYS((str_idx == KStringPosition_Config), Kern::Fault(KUsbPanicCat, __LINE__));
  1639 		__KTRACE_OPT(KUSB, Kern::Printf("  String @ pos %d (conf $): \"%S\"",
  1640 										str_idx, &iStrings[str_idx]->StringData()));
  1641 		return Kern::ThreadDesWrite(aThread, &aString,
  1642 									iStrings[str_idx]->StringData(), 0);
  1643 		}
  1644 	else
  1645 		{
  1646 		__KTRACE_OPT(KUSB, Kern::Printf("  No config string descriptor @ pos %d", str_idx));
  1647 		return KErrNotFound;
  1648 		}
  1649 	}
  1650 
  1651 
  1652 TInt TUsbcDescriptorPool::SetConfigurationStringDescriptorTC(DThread* aThread, const TDes8& aString)
  1653 	{
  1654 	// we don't know the length of the string, so we have to allocate memory dynamically
  1655 	TUint strlen = Kern::ThreadGetDesLength(aThread, &aString);
  1656 	if (strlen > KUsbStringDescStringMaxSize)
  1657 		{
  1658 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: config $ descriptor too long - will be truncated"));
  1659 		strlen = KUsbStringDescStringMaxSize;
  1660 		}
  1661 	HBuf8* const strbuf = HBuf8::New(strlen);
  1662 	if (!strbuf)
  1663 		{
  1664 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for config $ desc string failed (1)"));
  1665 		return KErrNoMemory;
  1666 		}
  1667 	strbuf->SetMax();
  1668 	// the aString points to data that lives in user memory, so we have to copy it:
  1669 	const TInt r = Kern::ThreadDesRead(aThread, &aString, *strbuf, 0);
  1670 	if (r != KErrNone)
  1671 		{
  1672 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
  1673 		delete strbuf;
  1674 		return r;
  1675 		}
  1676 	TUsbcStringDescriptor* sd = TUsbcStringDescriptor::New(*strbuf);
  1677 	if (!sd)
  1678 		{
  1679 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for config $ desc failed (2)"));
  1680 		delete strbuf;
  1681 		return KErrNoMemory;
  1682 		}
  1683 	// Delete old string, put in new one
  1684 	ExchangeStringDescriptor(KStringPosition_Config, sd);
  1685 	// Update Config descriptor string index field
  1686 	iDescriptors[KDescPosition_Config]->SetByte(KUsbDescStringIndex_Config, KStringPosition_Config);
  1687 	// Update Other_Speed_Config descriptor string index field as well, if applicable
  1688 	if (iDescriptors[KDescPosition_OtherSpeedConfig])
  1689 		iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(KUsbDescStringIndex_Config,
  1690 															  KStringPosition_Config);
  1691 	delete strbuf;
  1692 	return KErrNone;
  1693 	}
  1694 
  1695 
  1696 TInt TUsbcDescriptorPool::RemoveConfigurationStringDescriptor()
  1697 	{
  1698 	if (iDescriptors[KDescPosition_Config]->Byte(KUsbDescStringIndex_Config) == 0)
  1699 		{
  1700 		__KTRACE_OPT(KUSB, Kern::Printf("  RemoveConfigurationStringDescriptor: no $ desc @ index %d",
  1701 										KUsbDescStringIndex_Config));
  1702 		return KErrNotFound;
  1703 		}
  1704 	// Delete old string, put in NULL pointer
  1705 	ExchangeStringDescriptor(KStringPosition_Config, NULL);
  1706 	// Update Config descriptor string index field
  1707 	iDescriptors[KDescPosition_Config]->SetByte(KUsbDescStringIndex_Config, 0);
  1708 	// Update Other_Speed_Config descriptor string index field as well, if applicable
  1709 	if (iDescriptors[KDescPosition_OtherSpeedConfig])
  1710 		iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(KUsbDescStringIndex_Config, 0);
  1711 	return KErrNone;
  1712 	}
  1713 
  1714 
  1715 TInt TUsbcDescriptorPool::GetStringDescriptorTC(DThread* aThread, TInt aIndex, TDes8& aString) const
  1716 	{
  1717 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetStringDescriptorTC()"));
  1718 	if (!StringDescriptorExists(aIndex))
  1719 		{
  1720 		return KErrNotFound;
  1721 		}
  1722 	__KTRACE_OPT(KUSB, Kern::Printf("  String @ pos %d: \"%S\"",
  1723 									aIndex, &iStrings[aIndex]->StringData()));
  1724 	return Kern::ThreadDesWrite(aThread, &aString, iStrings[aIndex]->StringData(), 0);
  1725 	}
  1726 
  1727 
  1728 TInt TUsbcDescriptorPool::SetStringDescriptorTC(DThread* aThread, TInt aIndex, const TDes8& aString)
  1729 	{
  1730 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetStringDescriptorTC()"));
  1731 	// we don't know the length of the string, so we have to allocate memory dynamically
  1732 	TUint strlen = Kern::ThreadGetDesLength(aThread, &aString);
  1733 	if (strlen > KUsbStringDescStringMaxSize)
  1734 		{
  1735 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: $ descriptor too long - will be truncated"));
  1736 		strlen = KUsbStringDescStringMaxSize;
  1737 		}
  1738 	HBuf8* strbuf = HBuf8::New(strlen);
  1739 	if (!strbuf)
  1740 		{
  1741 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Mem alloc for $ desc string failed (1)"));
  1742 		return KErrNoMemory;
  1743 		}
  1744 	strbuf->SetMax();
  1745 	// the aString points to data that lives in user memory, so we have to copy it over:
  1746 	const TInt r = Kern::ThreadDesRead(aThread, &aString, *strbuf, 0);
  1747 	if (r != KErrNone)
  1748 		{
  1749 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
  1750 		delete strbuf;
  1751 		return r;
  1752 		}
  1753 	TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*strbuf);
  1754 	if (!sd)
  1755 		{
  1756 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Mem alloc for $ desc failed (2)"));
  1757 		delete strbuf;
  1758 		return KErrNoMemory;
  1759 		}
  1760 	if (aIndex < iStrings.Count())
  1761 		{
  1762 		ExchangeStringDescriptor(aIndex, sd);
  1763 		}
  1764 	else // if (aIndex >= iStrings.Count())
  1765 		{
  1766 		while (aIndex > iStrings.Count())
  1767 			{
  1768 			iStrings.Append(NULL);
  1769 			}
  1770 		iStrings.Append(sd);
  1771 		}
  1772 	delete strbuf;
  1773 	return KErrNone;
  1774 	}
  1775 
  1776 
  1777 TInt TUsbcDescriptorPool::RemoveStringDescriptor(TInt aIndex)
  1778 	{
  1779 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::RemoveStringDescriptor()"));
  1780 	if (!StringDescriptorExists(aIndex))
  1781 		{
  1782 		return KErrNotFound;
  1783 		}
  1784 	__KTRACE_OPT(KUSB, Kern::Printf("  Removing string @ pos %d: \"%S\"",
  1785 									aIndex, &iStrings[aIndex]->StringData()));
  1786 	ExchangeStringDescriptor(aIndex, NULL);
  1787 
  1788 	// Make sure there's no $ after aIndex.
  1789 	const TInt n = iStrings.Count();
  1790 	for (TInt i = aIndex; i < n; i++)
  1791 		{
  1792 		if (iStrings[i] != NULL)
  1793 			{
  1794 			__KTRACE_OPT(KUSB, Kern::Printf("  Found $ @ idx %d - not compressing", i));
  1795 			return KErrNone;
  1796 			}
  1797 		}
  1798 
  1799 	__KTRACE_OPT(KUSB, Kern::Printf("  No $ found after idx %d - compressing array", aIndex));
  1800 	// Move aIndex back just before the first !NULL element.
  1801 	while (iStrings[--aIndex] == NULL)
  1802 		;
  1803 	// Let aIndex point to first NULL.
  1804 	aIndex++;
  1805 	__KTRACE_OPT(KUSB, Kern::Printf("  Starting at index %d", aIndex));
  1806 	// Now remove NULL pointers until (Count() == aIndex).
  1807 	__KTRACE_OPT(KUSB, Kern::Printf("  iStrings.Count() before: %d", iStrings.Count()));
  1808 	do
  1809 		{
  1810 		iStrings.Remove(aIndex);
  1811 		__KTRACE_OPT(KUSB, Kern::Printf("  Removing $"));
  1812 		}
  1813 	while (iStrings.Count() > aIndex);
  1814 	__KTRACE_OPT(KUSB, Kern::Printf("  iStrings.Count() after: %d", iStrings.Count()));
  1815 
  1816 	// Regain some memory.
  1817 	iStrings.Compress();
  1818 
  1819 	return KErrNone;
  1820 	}
  1821 
  1822 
  1823 // ===================================================================
  1824 // --- private ---
  1825 // ===================================================================
  1826 
  1827 //
  1828 // Insert an Interface descriptor into the descriptor array at the appropriate index.
  1829 //
  1830 void TUsbcDescriptorPool::InsertIfcDesc(TUsbcDescriptorBase* aDesc)
  1831 	{
  1832 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InsertIfcDesc()"));
  1833 
  1834 	const TInt count = iDescriptors.Count();
  1835 	TBool ifc_exists = EFalse;								// set to 'true' if we're adding an alternate
  1836 															// setting to an already existing interface
  1837 	TInt i = KDescPosition_FirstAvailable;
  1838 	while (i < count)
  1839 		{
  1840 		__KTRACE_OPT(KUSB, Kern::Printf("  already descriptors there (%d)...", count));
  1841 		if (iDescriptors[i]->Type() == KUsbDescType_Interface)
  1842 			{
  1843 			if (iDescriptors[i]->Byte(2) > aDesc->Byte(2))
  1844 				{
  1845 				// our interface number is less than the one's just found => insert before it (= here)
  1846 				break;
  1847 				}
  1848 			else if (iDescriptors[i]->Byte(2) == aDesc->Byte(2))
  1849 				{
  1850 				ifc_exists = ETrue;
  1851 				// same interface number => look at settings number
  1852 				if (iDescriptors[i]->Byte(3) > aDesc->Byte(3))
  1853 					{
  1854 					// our setting number is less than the one's found => insert before (= here)
  1855 					break;
  1856 					}
  1857 				else if (iDescriptors[i]->Byte(3) == aDesc->Byte(3))
  1858 					{
  1859 					__KTRACE_OPT(KPANIC, Kern::Printf("  Error: first delete old desc "
  1860 													  "(TUsbcDescriptorPool::InsertIfcDesc)"));
  1861 					return;
  1862 					}
  1863 				}
  1864 			}
  1865 		++i;
  1866 		}
  1867 	// In any case: put the new descriptor at position i.
  1868 	__KTRACE_OPT(KUSB, Kern::Printf("  inserting descriptor at position %d", i));
  1869 	iDescriptors.Insert(aDesc, i);
  1870 
  1871 	// Update the config descriptor's wTotalLength field.
  1872 	UpdateConfigDescriptorLength(KUsbDescSize_Interface);
  1873 
  1874 	if (!ifc_exists)
  1875 		{
  1876 		// If this is the first setting for the interface, increment bNumInterfaces.
  1877 		UpdateConfigDescriptorNumIfcs(1);
  1878 		}
  1879 
  1880 	iIfcIdx = i;
  1881 	}
  1882 
  1883 
  1884 //
  1885 // Insert an Endpoint descriptor into the descriptor array at the appropriate index.
  1886 //
  1887 void TUsbcDescriptorPool::InsertEpDesc(TUsbcDescriptorBase* aDesc)
  1888 	{
  1889 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::InsertEpDesc()"));
  1890 	if (iIfcIdx == 0)
  1891 		{
  1892 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: only after interface "
  1893 										  "(TUsbcDescriptorPool::InsertEpDesc)"));
  1894 		return;
  1895 		}
  1896 	const TInt count = iDescriptors.Count();
  1897 	TInt i = iIfcIdx + 1;
  1898 	while (i < count)
  1899 		{
  1900 		if (iDescriptors[i]->Type() != KUsbDescType_Endpoint)
  1901 			break;
  1902 		++i;
  1903 		}
  1904 	// put the new descriptor at position i
  1905 	iDescriptors.Insert(aDesc, i);
  1906 	// update the config descriptor's wTotalLength field
  1907 	UpdateConfigDescriptorLength(aDesc->Size());
  1908 	}
  1909 
  1910 
  1911 //
  1912 // Find the index of the Interface descriptor for a given interface setting.
  1913 //
  1914 TInt TUsbcDescriptorPool::FindIfcDescriptor(TInt aIfcNumber, TInt aIfcSetting) const
  1915 	{
  1916 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindIfcDescriptor(%d, %d)",
  1917 									aIfcNumber, aIfcSetting));
  1918 	const TInt count = iDescriptors.Count();
  1919 	for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
  1920 		{
  1921 		if ((iDescriptors[i]->Type() == KUsbDescType_Interface) &&
  1922 			(iDescriptors[i]->Byte(2) == aIfcNumber) &&
  1923 			(iDescriptors[i]->Byte(3) == aIfcSetting))
  1924 			{
  1925 			return i;
  1926 			}
  1927 		}
  1928 	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
  1929 	return -1;
  1930 	}
  1931 
  1932 
  1933 //
  1934 // Find the index of the Endpoint descriptor for a given endpoint on a given interface setting.
  1935 //
  1936 TInt TUsbcDescriptorPool::FindEpDescriptor(TInt aIfcNumber, TInt aIfcSetting, TUint8 aEpAddress) const
  1937 	{
  1938 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindEpDescriptor(%d, %d, 0x%02x)",
  1939 									aIfcNumber, aIfcSetting, aEpAddress));
  1940 	// first find the interface
  1941 	const TInt ifc = FindIfcDescriptor(aIfcNumber, aIfcSetting);
  1942 	if (ifc < 0)
  1943 		{
  1944 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such interface"));
  1945 		return ifc;
  1946 		}
  1947 	const TInt count = iDescriptors.Count();
  1948 	// then, before the next interface, try to locate the endpoint
  1949 	for (TInt i = ifc + 1; i < count; i++)
  1950 		{
  1951 		if (iDescriptors[i]->Type() == KUsbDescType_Interface)
  1952 			{
  1953 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint before next interface"));
  1954 			return -1;
  1955 			}
  1956 		else if ((iDescriptors[i]->Type() == KUsbDescType_Endpoint) &&
  1957 				 (iDescriptors[i]->Byte(2) == aEpAddress))
  1958 			{
  1959 			// found
  1960 			return i;
  1961 			}
  1962 		}
  1963 	__KTRACE_OPT(KPANIC, Kern::Printf("  Error: no such endpoint"));
  1964 	return -1;
  1965 	}
  1966 
  1967 
  1968 //
  1969 // Delete n descriptors starting from aIndex and remove their pointers from the array.
  1970 //
  1971 void TUsbcDescriptorPool::DeleteDescriptors(TInt aIndex, TInt aCount)
  1972 	{
  1973 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::DeleteDescriptors()"));
  1974 	if (aIndex < KDescPosition_FirstAvailable)
  1975 		{
  1976 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aIndex < KDescPosition_FirstAvailable"));
  1977 		return;
  1978 		}
  1979 	if (aCount <= 0)
  1980 		{
  1981 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: aCount <= 0"));
  1982 		return;
  1983 		}
  1984 	__KTRACE_OPT(KUSB, Kern::Printf("  Removing descriptors at index %d:", aIndex));
  1985 	// Try to update wTotalLength field in Config descriptor
  1986 	while (aCount--)
  1987 		{
  1988 		// In this loop we don't decrement aIndex, because after deleting an element
  1989 		// aIndex is already indexing the next one.
  1990 		TUsbcDescriptorBase* const ptr = iDescriptors[aIndex];
  1991 		switch (ptr->Type())
  1992 			{
  1993 		case KUsbDescType_Interface:
  1994 			__KTRACE_OPT(KUSB, Kern::Printf("  - an interface descriptor"));
  1995 			UpdateConfigDescriptorLength(-KUsbDescSize_Interface);
  1996 			break;
  1997 		case KUsbDescType_Endpoint:
  1998 			__KTRACE_OPT(KUSB, Kern::Printf("  - an endpoint descriptor"));
  1999 			UpdateConfigDescriptorLength(-ptr->Size());
  2000 			break;
  2001 		case KUsbDescType_CS_Interface:
  2002 			/* fall through */
  2003 		case KUsbDescType_CS_Endpoint:
  2004 			__KTRACE_OPT(KUSB, Kern::Printf("  - a class specific descriptor"));
  2005 			UpdateConfigDescriptorLength(-ptr->Size());
  2006 			break;
  2007 		default:
  2008 			__KTRACE_OPT(KUSB, Kern::Printf("  - an unknown descriptor"));
  2009 			__KTRACE_OPT(KPANIC, Kern::Printf("  Error: unknown descriptor type"));
  2010 			}
  2011 		iDescriptors.Remove(aIndex);
  2012 		delete ptr;
  2013 		}
  2014 	}
  2015 
  2016 
  2017 //
  2018 // Update the wTotalLength field in the Configuration descriptor (aLength can be negative).
  2019 //
  2020 void TUsbcDescriptorPool::UpdateConfigDescriptorLength(TInt aLength)
  2021 	{
  2022 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateConfigDescriptorLength(%d)", aLength));
  2023 	TUsbcDescriptorBase* const cnf = iDescriptors[KDescPosition_Config];
  2024 	__KTRACE_OPT(KUSB, Kern::Printf("  wTotalLength old: %d", cnf->Word(2)));
  2025 	// Update Config descriptor
  2026 	cnf->SetWord(2, cnf->Word(2) + aLength);
  2027 	__KTRACE_OPT(KUSB, Kern::Printf("  wTotalLength new: %d", cnf->Word(2)));
  2028 	// Update Other_Speed_Config descriptor as well, if applicable
  2029 	if (iDescriptors[KDescPosition_OtherSpeedConfig])
  2030 		iDescriptors[KDescPosition_OtherSpeedConfig]->SetWord(2, cnf->Word(2));
  2031 	}
  2032 
  2033 
  2034 //
  2035 // Update the bNumInterfaces field in the Configuration descriptor (aNumber can be negative).
  2036 //
  2037 void TUsbcDescriptorPool::UpdateConfigDescriptorNumIfcs(TInt aNumber)
  2038 	{
  2039 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateConfigDescriptorNumIfcs(%d)", aNumber));
  2040 	TUsbcDescriptorBase* const cnf = iDescriptors[KDescPosition_Config];
  2041 	__KTRACE_OPT(KUSB, Kern::Printf("  bNumInterfaces old: %d", cnf->Byte(4)));
  2042 	const TInt n = cnf->Byte(4) + aNumber;
  2043 	if (n < 0)
  2044 		{
  2045 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: bNumInterfaces + aNumber < 0"));
  2046 		return;
  2047 		}
  2048 	// Update Config descriptor
  2049 	cnf->SetByte(4, n);
  2050 	__KTRACE_OPT(KUSB, Kern::Printf("  bNumInterfaces new: %d", cnf->Byte(4)));
  2051 	// Update Other_Speed_Config descriptor as well, if applicable
  2052 	if (iDescriptors[KDescPosition_OtherSpeedConfig])
  2053 		iDescriptors[KDescPosition_OtherSpeedConfig]->SetByte(4, n);
  2054 	}
  2055 
  2056 
  2057 //
  2058 // Update the bNumInterfaces field in the Configuration descriptor if necessary.
  2059 //
  2060 void TUsbcDescriptorPool::UpdateIfcNumbers(TInt aNumber)
  2061 	{
  2062 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::UpdateIfcNumbers(%d)", aNumber));
  2063 	const TInt count = iDescriptors.Count();
  2064 	for (TInt i = KDescPosition_FirstAvailable; i < count; i++)
  2065 		{
  2066 		if ((iDescriptors[i]->Type() == KUsbDescType_Interface) &&
  2067 			(iDescriptors[i]->Byte(2) == aNumber))
  2068 			{
  2069 			// there's still an interface with 'number' so we don't need to update anything
  2070 			return;
  2071 			}
  2072 		}
  2073 	// if we haven't returned yet, we decrement bNumInterfaces
  2074 	UpdateConfigDescriptorNumIfcs(-1);
  2075 	}
  2076 
  2077 
  2078 //
  2079 // Put the current Device or Device_Qualifier descriptor in the Ep0 Tx buffer.
  2080 // Only used for Ep0 standard requests, so target buffer can be hard-wired.
  2081 //
  2082 TInt TUsbcDescriptorPool::GetDeviceDescriptor(TInt aIndex) const
  2083 	{
  2084 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceDescriptor()"));
  2085 	__ASSERT_DEBUG((aIndex == KDescPosition_Device) || (aIndex == KDescPosition_DeviceQualifier),
  2086 				   Kern::Printf("  Error: invalid descriptor index: %d", aIndex));
  2087 	if (iDescriptors[aIndex] == NULL)
  2088 		{
  2089 		// This doesn't have to be an error - we might get asked here for the Device_Qualifier descriptor
  2090 		// on a FS-only device.
  2091 		__KTRACE_OPT(KUSB, Kern::Printf("  Descriptor #%d requested but not available", aIndex));
  2092 		return 0;
  2093 		}
  2094 	return iDescriptors[aIndex]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
  2095 	}
  2096 
  2097 
  2098 //
  2099 // Put the current Configuration or Other_Speed_Configuration descriptor + all the following
  2100 // descriptors in the Ep0 Tx buffer.
  2101 // Only used for Ep0 standard requests, so target buffer can be hard-wired.
  2102 //
  2103 TInt TUsbcDescriptorPool::GetConfigurationDescriptor(TInt aIndex) const
  2104 	{
  2105 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetConfigDescriptor(%d)", aIndex));
  2106 	__ASSERT_DEBUG((aIndex == KDescPosition_Config) || (aIndex == KDescPosition_OtherSpeedConfig),
  2107 				   Kern::Printf("  Error: invalid descriptor index: %d", aIndex));
  2108 	if (iDescriptors[aIndex] == NULL)
  2109 		{
  2110 		// This is always an error: We should always have a Configuration descriptor and we should never
  2111 		// get asked for the Other_Speed_Configuration descriptor if we don't have one (9.6.2).
  2112 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: Descriptor %d requested but not available", aIndex));
  2113 		return 0;
  2114 		}
  2115 	const TInt count = iDescriptors.Count();
  2116 	TInt copied = 0;
  2117 	TUint8* buf = iEp0_TxBuf;
  2118 	for (TInt i = aIndex; i < count; i++)
  2119 		{
  2120 		TUsbcDescriptorBase* const ptr = iDescriptors[i];
  2121 		if ((aIndex == KDescPosition_OtherSpeedConfig) && (i == KDescPosition_Config))
  2122 			{
  2123 			// Skip Config descriptor when returning Other_Speed_Config
  2124 			continue;
  2125 			}
  2126 		if ((i == KDescPosition_Otg) && (iDescriptors[i] == NULL))
  2127 			{
  2128 			__KTRACE_OPT(KUSB, Kern::Printf("  no OTG descriptor -> next"));
  2129 			continue;
  2130 			}
  2131 		// We need to edit endpoint descriptors on the fly because we have only one copy
  2132 		// of each and that copy has to contain different information, depending on the
  2133 		// current speed and the type of descriptor requested.
  2134 		if (ptr->Type() == KUsbDescType_Endpoint)
  2135 			{
  2136 			if ((iHighSpeed && (aIndex == KDescPosition_Config)) ||
  2137 				(!iHighSpeed && (aIndex == KDescPosition_OtherSpeedConfig)))
  2138 				{
  2139 				ptr->UpdateHs();
  2140 				}
  2141 			else
  2142 				{
  2143 				ptr->UpdateFs();
  2144 				}
  2145 			}
  2146 		__KTRACE_OPT(KUSB, Kern::Printf("  desc[%02d]: type = 0x%02x size = %d ",
  2147 										i, ptr->Type(), ptr->Size()));
  2148 		const TInt size = ptr->GetDescriptorData(buf, KUsbcBufSz_Ep0Tx - copied);
  2149 		if (size == 0)
  2150 			{
  2151 			__KTRACE_OPT(KPANIC,
  2152 						 Kern::Printf("  Error: No Tx buffer space to copy this descriptor -> exiting"));
  2153 			break;
  2154 			}
  2155 		copied += size;
  2156 		if (copied >= KUsbcBufSz_Ep0Tx)
  2157 			{
  2158 			__KTRACE_OPT(KPANIC,
  2159 						 Kern::Printf("  Error: No Tx buffer space left -> stopping here"));
  2160 			break;
  2161 			}
  2162 		buf += size;
  2163 		}
  2164 	__KTRACE_OPT(KUSB, Kern::Printf("  copied %d bytes", copied));
  2165 	return copied;
  2166 	}
  2167 
  2168 
  2169 //
  2170 // Put the current OTG descriptor in the Ep0 Tx buffer.
  2171 // Only used for Ep0 standard requests, so target buffer can be hard-wired.
  2172 //
  2173 TInt TUsbcDescriptorPool::GetOtgDescriptor() const
  2174 	{
  2175 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetOtgDescriptor()"));
  2176 	if (iDescriptors[KDescPosition_Otg] == NULL)
  2177 		{
  2178 		__KTRACE_OPT(KUSB, Kern::Printf("  OTG Descriptor not set"));
  2179 		return 0;
  2180 		}
  2181 	return iDescriptors[KDescPosition_Otg]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
  2182 	}
  2183 
  2184 
  2185 //
  2186 // Put a specific String descriptor in the Ep0 Tx buffer.
  2187 // Only used for Ep0 standard requests, so target buffer can be hard-wired.
  2188 //
  2189 TInt TUsbcDescriptorPool::GetStringDescriptor(TInt aIndex) const
  2190 	{
  2191 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetStringDescriptor(%d)", aIndex));
  2192 	// I really would have liked to display the descriptor contents here, but without trailing zero
  2193 	// we got a problem: how can we tell printf where the string ends? We would have to
  2194 	// dynamically allocate memory (since we don't know the size in advance), copy the descriptor
  2195 	// contents there, append a zero, and give this to printf. That's a bit too much effort...
  2196 	if (!StringDescriptorExists(aIndex))
  2197 		{
  2198 		return 0;
  2199 		}
  2200 	return iStrings[aIndex]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
  2201 	}
  2202 
  2203 
  2204 //
  2205 // Write a String descriptor pointed to by the Device descriptor to the user side
  2206 // (one of Manufacturer, Product, SerialNumber).
  2207 //
  2208 TInt TUsbcDescriptorPool::GetDeviceStringDescriptorTC(DThread* aThread, TDes8& aString,
  2209 													  TInt aIndex, TInt aPosition) const
  2210 	{
  2211 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::GetDeviceStringDescriptorTC()"));
  2212 	const TInt str_idx = iDescriptors[KDescPosition_Device]->Byte(aIndex);
  2213 	if (str_idx)
  2214 		{
  2215 		__ASSERT_ALWAYS((str_idx == aPosition), Kern::Fault(KUsbPanicCat, __LINE__));
  2216 		__KTRACE_OPT(KUSB, Kern::Printf("  String @ pos %d (device $): \"%S\"",
  2217 										str_idx, &iStrings[str_idx]->StringData()));
  2218 		return Kern::ThreadDesWrite(aThread, &aString,
  2219 									iStrings[str_idx]->StringData(), 0);
  2220 		}
  2221 	else
  2222 		{
  2223 		__KTRACE_OPT(KUSB, Kern::Printf("  No string descriptor @ pos %d", aIndex));
  2224 		return KErrNotFound;
  2225 		}
  2226 	}
  2227 
  2228 
  2229 //
  2230 // Read a Device String descriptor from the user side and put in the descriptor arrays
  2231 // (one of Manufacturer, Product, SerialNumber).
  2232 //
  2233 TInt TUsbcDescriptorPool::SetDeviceStringDescriptorTC(DThread* aThread, const TDes8& aString,
  2234 													  TInt aIndex, TInt aPosition)
  2235 	{
  2236 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::SetDeviceStringDescriptorTC()"));
  2237 	// we don't know the length of the string, so we have to allocate memory dynamically
  2238 	TUint strlen = Kern::ThreadGetDesLength(aThread, &aString);
  2239 	if (strlen > KUsbStringDescStringMaxSize)
  2240 		{
  2241 		__KTRACE_OPT(KPANIC, Kern::Printf("  Warning: $ descriptor too long - will be truncated"));
  2242 		strlen = KUsbStringDescStringMaxSize;
  2243 		}
  2244 	HBuf8* const strbuf = HBuf8::New(strlen);
  2245 	if (!strbuf)
  2246 		{
  2247 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for dev $ desc string failed (1)"));
  2248 		return KErrNoMemory;
  2249 		}
  2250 	strbuf->SetMax();
  2251 	// the aString points to data that lives in user memory, so we have to copy it:
  2252 	const TInt r = Kern::ThreadDesRead(aThread, &aString, *strbuf, 0);
  2253 	if (r != KErrNone)
  2254 		{
  2255 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Thread read error"));
  2256 		delete strbuf;
  2257 		return r;
  2258 		}
  2259 	TUsbcStringDescriptor* const sd = TUsbcStringDescriptor::New(*strbuf);
  2260 	if (!sd)
  2261 		{
  2262 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Memory allocation for dev $ desc failed (2)"));
  2263 		delete strbuf;
  2264 		return KErrNoMemory;
  2265 		}
  2266 	ExchangeStringDescriptor(aPosition, sd);
  2267 	iDescriptors[KDescPosition_Device]->SetByte(aIndex, aPosition);
  2268 	delete strbuf;
  2269 	return r;
  2270 	}
  2271 
  2272 
  2273 //
  2274 // Remove a Device String descriptor from the descriptor arrays
  2275 // (one of Manufacturer, Product, SerialNumber).
  2276 //
  2277 TInt TUsbcDescriptorPool::RemoveDeviceStringDescriptor(TInt aIndex, TInt aPosition)
  2278 	{
  2279 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::RemoveDeviceStringDescriptor()"));
  2280 	if (iDescriptors[KDescPosition_Device]->Byte(aIndex) == 0)
  2281 		{
  2282 		__KTRACE_OPT(KUSB, Kern::Printf("  RemoveDeviceStringDescriptor: no $ desc @ index %d", aIndex));
  2283 		return KErrNotFound;
  2284 		}
  2285 	ExchangeStringDescriptor(aPosition, NULL);
  2286 	iDescriptors[KDescPosition_Device]->SetByte(aIndex, 0);
  2287 	return KErrNone;
  2288 	}
  2289 
  2290 
  2291 //
  2292 // Puts aDesc at postion aIndex in the string descriptor array, after deleting what was (possibly) there.
  2293 //
  2294 void TUsbcDescriptorPool::ExchangeStringDescriptor(TInt aIndex, const TUsbcStringDescriptor* aDesc)
  2295 	{
  2296 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::ExchangeStringDescriptor()"));
  2297 	TUsbcStringDescriptorBase* const ptr = iStrings[aIndex];
  2298 	__KTRACE_OPT(KUSB, Kern::Printf("  Deleting string descriptor at index %d: 0x%x", aIndex, ptr));
  2299 	iStrings.Remove(aIndex);
  2300 	delete ptr;
  2301 	__KTRACE_OPT(KUSB, Kern::Printf("  Inserting string descriptor at index %d: 0x%x", aIndex, aDesc));
  2302 	iStrings.Insert(aDesc, aIndex);
  2303 	}
  2304 
  2305 
  2306 //
  2307 // Checks whether there are any string descriptors in the array (apart from LangID).
  2308 //
  2309 TBool TUsbcDescriptorPool::AnyStringDescriptors() const
  2310 	{
  2311 	const TInt n = iStrings.Count();
  2312 	for (TInt i = 1; i < n; i++)
  2313 		{
  2314 		if (iStrings[i] != NULL)
  2315 			return ETrue;
  2316 		}
  2317 	return EFalse;
  2318 	}
  2319 
  2320 
  2321 //
  2322 // Returns true if aIndex exists and what is at that positition is not a NULL pointer.
  2323 //
  2324 TBool TUsbcDescriptorPool::StringDescriptorExists(TInt aIndex) const
  2325 	{
  2326 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::StringDescriptorExists()"));
  2327 	if (aIndex >= iStrings.Count())
  2328 		{
  2329 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: Bad string index: %d", aIndex));
  2330 		return EFalse;
  2331 		}
  2332 	else if (iStrings[aIndex] == NULL)
  2333 		{
  2334 		__KTRACE_OPT(KPANIC, Kern::Printf("  Error: No $ descriptor @ pos %d", aIndex));
  2335 		return EFalse;
  2336 		}
  2337 	return ETrue;
  2338 	}
  2339 
  2340 
  2341 //
  2342 //
  2343 //
  2344 TInt TUsbcDescriptorPool::FindAvailableStringPos() const
  2345 	{
  2346 	__KTRACE_OPT(KUSB, Kern::Printf("TUsbcDescriptorPool::FindAvailableStringPos()"));
  2347 	const TInt n = iStrings.Count();
  2348 	// We don't start from 0 because the first few locations are 'reserved'.
  2349 	for (TInt i = KStringPosition_FirstAvailable; i < n; i++)
  2350 		{
  2351 		if (iStrings[i] == NULL)
  2352 			{
  2353 			__KTRACE_OPT(KUSB, Kern::Printf(" Found available NULL position: %d", i));
  2354 			return i;
  2355 			}
  2356 		}
  2357 	return -1;
  2358 	}
  2359 
  2360 
  2361 // -eof-