kernel/eka/drivers/usbcc/descriptors.cpp
changeset 0 a41df078684a
child 97 41f0cfe18c80
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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-