Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// f32test\testusbcldd\src\descriptors.cpp
// Platform independent USB client controller layer (PIL):
// USB descriptor handling and management.
//
//
#include "usbcdesc.h"
#include "dtestusblogdev.h"
// --- TUsbcDescriptorBase
TUsbcDescriptorBase::TUsbcDescriptorBase()
:
#ifdef USB_SUPPORTS_SET_DESCRIPTOR_REQUEST
iIndex(0),
#endif
iBufPtr(NULL, 0)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorBase::TUsbcDescriptorBase()")));
}
TUsbcDescriptorBase::~TUsbcDescriptorBase()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorBase::~TUsbcDescriptorBase()")));
}
void TUsbcDescriptorBase::SetByte(TUint aPosition, TUint8 aValue)
{
iBufPtr[aPosition] = aValue;
}
void TUsbcDescriptorBase::SetWord(TUint aPosition, TUint16 aValue)
{
*reinterpret_cast<TUint16*>(&iBufPtr[aPosition]) = SWAP_BYTES_16(aValue);
}
TUint8 TUsbcDescriptorBase::Byte(TUint aPosition) const
{
return iBufPtr[aPosition];
}
TUint16 TUsbcDescriptorBase::Word(TUint aPosition) const
{
return SWAP_BYTES_16(*reinterpret_cast<const TUint16*>(&iBufPtr[aPosition]));
}
void TUsbcDescriptorBase::GetDescriptorData(TDes8& aBuffer) const
{
aBuffer = iBufPtr;
}
TInt TUsbcDescriptorBase::GetDescriptorData(TUint8* aBuffer) const
{
__MEMCPY(aBuffer, iBufPtr.Ptr(), Size());
return Size();
}
TInt TUsbcDescriptorBase::GetDescriptorData(TUint8* aBuffer, TInt aMaxSize) const
{
if (aMaxSize < Size())
{
// No use to copy only half a descriptor
return 0;
}
return GetDescriptorData(aBuffer);
}
const TDes8& TUsbcDescriptorBase::DescriptorData() const
{
return iBufPtr;
}
TDes8& TUsbcDescriptorBase::DescriptorData()
{
return iBufPtr;
}
TInt TUsbcDescriptorBase::Size() const
{
return iBufPtr.Size();
}
TUint8 TUsbcDescriptorBase::Type() const
{
return iBufPtr[1];
}
void TUsbcDescriptorBase::SetBufferPointer(const TDesC8& aDes)
{
iBufPtr.Set(const_cast<TUint8*>(aDes.Ptr()), aDes.Size(), aDes.Size());
}
// --- TUsbcDeviceDescriptor
TUsbcDeviceDescriptor::TUsbcDeviceDescriptor()
: iBuf()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDeviceDescriptor::TUsbcDeviceDescriptor()")));
}
TUsbcDeviceDescriptor* TUsbcDeviceDescriptor::New(TUint8 aDeviceClass, TUint8 aDeviceSubClass,
TUint8 aDeviceProtocol, TUint8 aMaxPacketSize0,
TUint16 aVendorId, TUint16 aProductId,
TUint16 aDeviceRelease, TUint8 aNumConfigurations)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDeviceDescriptor::New()")));
TUsbcDeviceDescriptor* self = new TUsbcDeviceDescriptor();
if (self)
{
if (self->Construct(aDeviceClass, aDeviceSubClass, aDeviceProtocol, aMaxPacketSize0, aVendorId,
aProductId, aDeviceRelease, aNumConfigurations) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcDeviceDescriptor::Construct(TUint8 aDeviceClass, TUint8 aDeviceSubClass, TUint8 aDeviceProtocol,
TUint8 aMaxPacketSize0, TUint16 aVendorId, TUint16 aProductId,
TUint16 aDeviceRelease, TUint8 aNumConfigurations)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDeviceDescriptor::Construct()")));
iBuf.SetMax();
SetBufferPointer(iBuf);
iBuf[0] = (TUint8)iBuf.Size(); // bLength
iBuf[1] = KUsbDescType_Device; // bDescriptorType
SetWord(2, KUsbcUsbVersion); // bcdUSB
iBuf[4] = aDeviceClass; // bDeviceClass
iBuf[5] = aDeviceSubClass; // bDeviceSubClass
iBuf[6] = aDeviceProtocol; // bDeviceProtocol
iBuf[7] = aMaxPacketSize0; // bMaxPacketSize0
SetWord(8, aVendorId); // idVendor
SetWord(10, aProductId); // idProduct
SetWord(12, aDeviceRelease); // bcdDevice
iBuf[14] = 0; // iManufacturer
iBuf[15] = 0; // iProduct
iBuf[16] = 0; // iSerialNumber
iBuf[17] = aNumConfigurations; // bNumConfigurations
return KErrNone;
}
// --- TUsbcConfigDescriptor
TUsbcConfigDescriptor::TUsbcConfigDescriptor()
: iBuf()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcConfigDescriptor::TUsbcConfigDescriptor()")));
}
TUsbcConfigDescriptor* TUsbcConfigDescriptor::New(TUint8 aConfigurationValue, TBool aSelfPowered,
TBool aRemoteWakeup, TUint8 aMaxPower)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcConfigDescriptor::New()")));
TUsbcConfigDescriptor* self = new TUsbcConfigDescriptor();
if (self)
{
if (self->Construct(aConfigurationValue, aSelfPowered, aRemoteWakeup, aMaxPower) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcConfigDescriptor::Construct(TUint8 aConfigurationValue, TBool aSelfPowered,
TBool aRemoteWakeup, TUint8 aMaxPower)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcConfigDescriptor::Construct()")));
iBuf.SetMax();
SetBufferPointer(iBuf);
iBuf[0] = (TUint8)iBuf.Size(); // bLength
iBuf[1] = KUsbDescType_Config; // bDescriptorType
SetWord(2, KUsbDescSize_Config); // wTotalLength
iBuf[4] = 0; // bNumInterfaces
iBuf[5] = aConfigurationValue; // bConfigurationValue
iBuf[6] = 0; // iConfiguration
iBuf[7] = (TUint8)(0x80 | (aSelfPowered ? 0x40 : 0) | (aRemoteWakeup ? 0x20 : 0)); // bmAttributes (bit 7 always 1)
iBuf[8] = (TUint8)(aMaxPower / 2); // MaxPower (2mA units!)
return KErrNone;
}
// --- TUsbcInterfaceDescriptor
TUsbcInterfaceDescriptor::TUsbcInterfaceDescriptor()
: iBuf()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceDescriptor::TUsbcInterfaceDescriptor()")));
}
TUsbcInterfaceDescriptor* TUsbcInterfaceDescriptor::New(TUint8 aInterfaceNumber, TUint8 aAlternateSetting,
TInt aNumEndpoints, const TUsbcClassInfo& aClassInfo)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceDescriptor::New()")));
TUsbcInterfaceDescriptor* self = new TUsbcInterfaceDescriptor();
if (self)
{
if (self->Construct(aInterfaceNumber, aAlternateSetting, aNumEndpoints, aClassInfo) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcInterfaceDescriptor::Construct(TUint8 aInterfaceNumber, TUint8 aAlternateSetting,
TInt aNumEndpoints, const TUsbcClassInfo& aClassInfo)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcInterfaceDescriptor::Construct()")));
iBuf.SetMax();
SetBufferPointer(iBuf);
iBuf[0] = (TUint8)iBuf.Size(); // bLength
iBuf[1] = KUsbDescType_Interface; // bDescriptorType
iBuf[2] = aInterfaceNumber; // bInterfaceNumber
iBuf[3] = aAlternateSetting; // bAlternateSetting
iBuf[4] = (TUint8)aNumEndpoints; // bNumEndpoints
iBuf[5] = (TUint8)aClassInfo.iClassNum; // bInterfaceClass
iBuf[6] = (TUint8)aClassInfo.iSubClassNum; // bInterfaceSubClass
iBuf[7] = (TUint8)aClassInfo.iProtocolNum; // bInterfaceProtocol
iBuf[8] = 0; // iInterface
return KErrNone;
}
// --- TUsbcEndpointDescriptor
TUsbcEndpointDescriptor::TUsbcEndpointDescriptor()
: iBuf()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcEndpointDescriptor::TUsbcEndpointDescriptor()")));
}
TUsbcEndpointDescriptor* TUsbcEndpointDescriptor::New(TUint8 aEndpointAddress,
const TUsbcEndpointInfo& aEpInfo)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcEndpointDescriptor::New()")));
TUsbcEndpointDescriptor* self = new TUsbcEndpointDescriptor();
if (self)
{
if (self->Construct(aEndpointAddress, aEpInfo) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcEndpointDescriptor::Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcEndpointDescriptor::Construct()")));
iBuf.SetMax();
SetBufferPointer(iBuf);
iBuf[0] = (TUint8)iBuf.Size(); // bLength
iBuf[1] = KUsbDescType_Endpoint; // bDescriptorType
iBuf[2] = aEndpointAddress; // bEndpointAddress
iBuf[3] = (TUint8)EpTypeMask2Value(aEpInfo.iType); // bmAttributes
SetWord(4, (TUint8)aEpInfo.iSize); // wMaxPacketSize
iBuf[6] = (TUint8)aEpInfo.iInterval; // bInterval
return KErrNone;
}
// --- TUsbcAudioEndpointDescriptor
TUsbcAudioEndpointDescriptor::TUsbcAudioEndpointDescriptor()
: iBuf()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcAudioEndpointDescriptor::TUsbcAudioEndpointDescriptor()")));
}
TUsbcAudioEndpointDescriptor* TUsbcAudioEndpointDescriptor::New(TUint8 aEndpointAddress,
const TUsbcEndpointInfo& aEpInfo)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcAudioEndpointDescriptor::New()")));
TUsbcAudioEndpointDescriptor* self = new TUsbcAudioEndpointDescriptor();
if (self)
{
if (self->Construct(aEndpointAddress, aEpInfo) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcAudioEndpointDescriptor::Construct(TUint8 aEndpointAddress, const TUsbcEndpointInfo& aEpInfo)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcAudioEndpointDescriptor::Construct()")));
iBuf.SetMax();
SetBufferPointer(iBuf);
iBuf[0] = (TUint8)iBuf.Size(); // bLength
iBuf[1] = KUsbDescType_Endpoint; // bDescriptorType
iBuf[2] = aEndpointAddress; // bEndpointAddress
iBuf[3] = (TUint8)EpTypeMask2Value(aEpInfo.iType); // bmAttributes
SetWord(4, (TUint8)aEpInfo.iSize); // wMaxPacketSize
iBuf[6] = (TUint8)aEpInfo.iInterval; // bInterval
iBuf[7] = 0;
iBuf[8] = 0;
return KErrNone;
}
// --- TUsbcClassSpecificDescriptor
TUsbcClassSpecificDescriptor::TUsbcClassSpecificDescriptor()
: iBuf(NULL)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcClassSpecificDescriptor::TUsbcClassSpecificDescriptor()")));
}
TUsbcClassSpecificDescriptor::~TUsbcClassSpecificDescriptor()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcClassSpecificDescriptor::~TUsbcClassSpecificDescriptor()")));
delete iBuf;
}
TUsbcClassSpecificDescriptor* TUsbcClassSpecificDescriptor::New(TUint8 aType, TInt aSize)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcClassSpecificDescriptor::New()")));
TUsbcClassSpecificDescriptor* self = new TUsbcClassSpecificDescriptor();
if (self)
{
if (self->Construct(aType, aSize) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcClassSpecificDescriptor::Construct(TUint8 aType, TInt aSize)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcClassSpecificDescriptor::Construct()")));
__NEWPLATBUF(iBuf, aSize);
if (!iBuf)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Allocation of CS desc buffer failed")));
return KErrNoMemory;
}
SetBufferPointer(*iBuf);
SetByte(1, aType); // bDescriptorType
return KErrNone;
}
// --- TUsbcStringDescriptorBase
TUsbcStringDescriptorBase::TUsbcStringDescriptorBase()
: /*iIndex(0),*/ iSBuf(0), iBufPtr(NULL, 0)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcStringDescriptorBase::TUsbcStringDescriptorBase()")));
}
TUsbcStringDescriptorBase::~TUsbcStringDescriptorBase()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcStringDescriptorBase::~TUsbcStringDescriptorBase()")));
}
TUint16 TUsbcStringDescriptorBase::Word(TUint aPosition) const
{
if (aPosition <= 1)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("TUsbcStringDescriptorBase::Word: Error: Word(%d) in string descriptor!"), aPosition));
return 0;
}
else
{
// since iBufPtr[0] is actually string descriptor byte index 2,
// we have to subtract 2 from the absolute position.
return SWAP_BYTES_16(*reinterpret_cast<const TUint16*>(&iBufPtr[aPosition - 2]));
}
}
TInt TUsbcStringDescriptorBase::GetDescriptorData(TUint8* aBuffer) const
{
aBuffer[0] = iSBuf[0];
aBuffer[1] = iSBuf[1];
__MEMCPY(&aBuffer[2], iBufPtr.Ptr(), iBufPtr.Size());
return Size();
}
TInt TUsbcStringDescriptorBase::GetDescriptorData(TUint8* aBuffer, TInt aMaxSize) const
{
if (aMaxSize < Size())
{
// No use to copy only half a string
return 0;
}
return GetDescriptorData(aBuffer);
}
const TDes8& TUsbcStringDescriptorBase::StringData() const
{
return iBufPtr;
}
TDes8& TUsbcStringDescriptorBase::StringData()
{
return iBufPtr;
}
TInt TUsbcStringDescriptorBase::Size() const
{
return iSBuf[0];
}
void TUsbcStringDescriptorBase::SetBufferPointer(const TDesC8& aDes)
{
iBufPtr.Set(const_cast<TUint8*>(aDes.Ptr()), aDes.Size(), aDes.Size());
}
// --- TUsbcStringDescriptor
TUsbcStringDescriptor::TUsbcStringDescriptor()
: iBuf(NULL)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcStringDescriptor::TUsbcStringDescriptor()")));
}
TUsbcStringDescriptor::~TUsbcStringDescriptor()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcStringDescriptor::~TUsbcStringDescriptor()")));
delete iBuf;
}
TUsbcStringDescriptor* TUsbcStringDescriptor::New(const TDesC8& aString)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcStringDescriptor::New")));
TUsbcStringDescriptor* self = new TUsbcStringDescriptor();
if (self)
{
if (self->Construct(aString) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcStringDescriptor::Construct(const TDesC8& aString)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcStringDescriptor::Construct")));
__NEWPLATBUF(iBuf, aString.Size());
if (!iBuf)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Allocation of string buffer failed")));
return KErrNoMemory;
}
SetBufferPointer(*iBuf);
iBufPtr.Copy(aString);
iSBuf.SetMax();
iSBuf[0] = (TUint8)(iBuf->Size() + 2); // Bytes
iSBuf[1] = KUsbDescType_String;
return KErrNone;
}
// --- TUsbcLangIdDescriptor
TUsbcLangIdDescriptor::TUsbcLangIdDescriptor()
: iBuf(NULL)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLangIdDescriptor::TUsbcLangIdDescriptor()")));
}
TUsbcLangIdDescriptor::~TUsbcLangIdDescriptor()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLangIdDescriptor::~TUsbcLangIdDescriptor()")));
}
TUsbcLangIdDescriptor* TUsbcLangIdDescriptor::New(TUint16 aLangId)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLangIdDescriptor::New")));
TUsbcLangIdDescriptor* self = new TUsbcLangIdDescriptor();
if (self)
{
if (self->Construct(aLangId) != KErrNone)
{
delete self;
return NULL;
}
}
return self;
}
TInt TUsbcLangIdDescriptor::Construct(TUint16 aLangId)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcLangIdDescriptor::Construct")));
iBuf.SetMax();
SetBufferPointer(iBuf);
iBufPtr[0] = LowByte(SWAP_BYTES_16(aLangId)); // Language ID value
iBufPtr[1] = HighByte(SWAP_BYTES_16(aLangId));
iSBuf.SetMax();
iSBuf[0] = (TUint8)(iBuf.Size() + 2); // Bytes
iSBuf[1] = KUsbDescType_String;
return KErrNone;
}
// --- TUsbcDescriptorPool
TUsbcDescriptorPool::TUsbcDescriptorPool(TUint8* aEp0_TxBuf)
//
// The constructor for this class.
//
: iDescriptors(4), iStrings(4), iIfcIdx(0), iEp0_TxBuf(aEp0_TxBuf) // 4 = granularity
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::TUsbcDescriptorPool()")));
}
TUsbcDescriptorPool::~TUsbcDescriptorPool()
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::~TUsbcDescriptorPool()")));
// The destructor of each <class T> object is called before the objects themselves are destroyed.
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" iDescriptors.Count(): %d"), iDescriptors.Count()));
iDescriptors.ResetAndDestroy();
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" iStrings.Count(): %d"), iStrings.Count()));
iStrings.ResetAndDestroy();
}
TInt TUsbcDescriptorPool::Init(TUsbcDeviceDescriptor* aDeviceDesc, TUsbcConfigDescriptor* aConfigDesc,
TUsbcLangIdDescriptor* aLangId, TUsbcStringDescriptor* aManufacturer,
TUsbcStringDescriptor* aProduct, TUsbcStringDescriptor* aSerialNum,
TUsbcStringDescriptor* aConfig)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::Init()")));
iDescriptors.Insert(aDeviceDesc, 0);
iDescriptors.Insert(aConfigDesc, 1);
if (!aLangId || !aManufacturer || !aProduct || !aSerialNum || !aConfig)
{
// USB spec p. 202 says: "A USB device may omit all string descriptors."
// So, either ALL string descriptors are supplied or none at all.
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: No string descriptor(s)")));
return KErrArgument;
}
iStrings.Insert(aLangId, 0);
iStrings.Insert(aManufacturer, 1);
iStrings.Insert(aProduct, 2);
iStrings.Insert(aSerialNum, 3);
iStrings.Insert(aConfig, 4);
// set string indices
iDescriptors[0]->SetByte(14, 1); // Device.iManufacturer
iDescriptors[0]->SetByte(15, 2); // Device.iProduct
iDescriptors[0]->SetByte(16, 3); // Device.iSerialNumber
iDescriptors[1]->SetByte( 6, 4); // Config.iConfiguration
return KErrNone;
}
TInt TUsbcDescriptorPool::FindDescriptor(TUint8 aType, TUint8 aIndex, TUint16 aLangid, TInt& aSize) const
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::FindDescriptor()")));
TInt result = KErrGeneral;
switch(aType)
{
case KUsbDescType_Device:
if (aLangid != 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: bad langid: 0x%04x"), aLangid));
result = KErrGeneral; // bad langid
}
else if (aIndex > 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: bad device index: %d"), aIndex));
result = KErrGeneral; // we have only one device
}
else
{
aSize = GetDeviceDescriptor();
result = KErrNone;
}
break;
case KUsbDescType_Config:
if (aLangid != 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: bad langid: 0x%04x"), aLangid));
result = KErrGeneral; // bad langid
}
else if (aIndex > 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: bad config index: %d"), aIndex));
result = KErrGeneral; // we have only one configuration
}
else
{
aSize = GetConfigDescriptor();
result = KErrNone;
}
break;
case KUsbDescType_String:
if ((aLangid != 0) && // 0 addresses the LangId array
(aLangid != iStrings[0]->Word(2))) // we have just one (this) language
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: bad langid (0x%04x requested, 0x%04x supported)"),
aLangid, iStrings[0]->Word(2)));
result = KErrGeneral; // bad langid
}
else if (aIndex >= iStrings.Count())
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: bad string index: %d"), aIndex));
result = KErrGeneral;
}
else
{
aSize = GetStringDescriptor(aIndex);
result = KErrNone;
}
break;
case KUsbDescType_CS_Interface:
/* fall through */
case KUsbDescType_CS_Endpoint:
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Warning: finding of class specific descriptors not supported")));
break;
default:
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: unknown descriptor type requested: %d"), aType));
result = KErrGeneral;
break;
}
return result;
}
void TUsbcDescriptorPool::InsertDescriptor(TUsbcDescriptorBase* aDesc)
{
switch (aDesc->Type())
{
case KUsbDescType_Device:
InsertDevDesc(aDesc);
break;
case KUsbDescType_Config:
InsertConfigDesc(aDesc);
break;
case KUsbDescType_Interface:
InsertIfcDesc(aDesc);
break;
case KUsbDescType_Endpoint:
InsertEpDesc(aDesc);
break;
case KUsbDescType_CS_Interface:
/* fall through */
case KUsbDescType_CS_Endpoint:
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Warning: inserting class specific descriptors not supported")));
break;
default:
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::InsertDescriptor: Error: invalid type")));
break;
}
}
void TUsbcDescriptorPool::SetIfcStringDescriptor(TUsbcStringDescriptor* aDesc, TInt aNumber, TInt aSetting)
{
TInt i = FindIfcDescriptor(aNumber, aSetting);
if (i < 0)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::SetIfcStringDescriptor: error")));
return;
}
// Set (append) string descriptor for specified interface
iStrings.Append(aDesc);
// Update this ifc descriptors' string index field
const TInt str_idx = iStrings.Count() - 1;
iDescriptors[i]->SetByte(8, (TUint8)str_idx);
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" String for ifc %d/%d (@ pos %d): \"%S\""), aNumber, aSetting, str_idx,
&iStrings[str_idx]->StringData()));
}
void TUsbcDescriptorPool::DeleteIfcDescriptor(TInt aNumber, TInt aSetting)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::DeleteIfcDescriptor(%d, %d)"), aNumber, aSetting));
TInt i = FindIfcDescriptor(aNumber, aSetting);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" > Error: descriptor not found")));
return;
}
// Delete (if necessary) specified interface's string descriptor
TInt si = iDescriptors[i]->Byte(8);
if (si != 0)
{
DeleteString(si);
}
// Delete specified ifc setting + all its cs descriptors + all its endpoints + all their cs descriptors:
// find position of the next interface descriptor: we need to delete everything in between
const TInt count = iDescriptors.Count();
TInt j = i, n = 1;
while (++j < count && iDescriptors[j]->Type() != KUsbDescType_Interface)
++n;
DeleteDescriptors(i, n);
// Update all the following interfaces' bInterfaceNumber field if required
// (because these descriptors might have moved down by one position)
UpdateIfcNumbers(aNumber);
// Update (if necessary) all interfaces' string index field
if (si != 0)
{
UpdateIfcStringIndexes(si);
}
iIfcIdx = 0; // ifc index no longer valid
}
// The TC in many of the following functions stands for 'ThreadCopy',
// because that's what's happening there.
TInt TUsbcDescriptorPool::GetDeviceDescriptorTC(DThread* aThread, TDes8& aBuffer) const
{
return __THREADWRITE(aThread, &aBuffer, iDescriptors[0]->DescriptorData());
}
TInt TUsbcDescriptorPool::SetDeviceDescriptorTC(DThread* aThread, const TDes8& aBuffer)
{
TBuf8<KUsbDescSize_Device> device;
TInt r = __THREADREAD(aThread, &aBuffer, device);
if (r != KErrNone)
{
return r;
}
iDescriptors[0]->SetByte(2, device[2]); // bcdUSB
iDescriptors[0]->SetByte(3, device[3]); // bcdUSB (part II)
iDescriptors[0]->SetByte(4, device[4]); // bDeviceClass
iDescriptors[0]->SetByte(5, device[5]); // bDeviceSubClass
iDescriptors[0]->SetByte(6, device[6]); // bDeviceProtocol
iDescriptors[0]->SetByte(8, device[8]); // idVendor
iDescriptors[0]->SetByte(9, device[9]); // idVendor (part II)
iDescriptors[0]->SetByte(10, device[10]); // idProduct
iDescriptors[0]->SetByte(11, device[11]); // idProduct (part II)
iDescriptors[0]->SetByte(12, device[12]); // bcdDevice
iDescriptors[0]->SetByte(13, device[13]); // bcdDevice (part II)
return KErrNone;
}
TInt TUsbcDescriptorPool::GetConfigurationDescriptorTC(DThread* aThread, TDes8& aBuffer) const
{
return __THREADWRITE(aThread, &aBuffer, iDescriptors[1]->DescriptorData());
}
TInt TUsbcDescriptorPool::SetConfigurationDescriptorTC(DThread* aThread, const TDes8& aBuffer)
{
TBuf8<KUsbDescSize_Config> config;
TInt r = __THREADREAD(aThread, &aBuffer, config);
if (r != KErrNone)
{
return r;
}
iDescriptors[1]->SetByte(7, config[7]); // bmAttributes
iDescriptors[1]->SetByte(8, config[8]); // bMaxPower
return KErrNone;
}
TInt TUsbcDescriptorPool::GetInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer,
TInt aInterface, TInt aSetting) const
{
TInt i = FindIfcDescriptor(aInterface, aSetting);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such interface")));
return KErrNotFound;
}
return __THREADWRITE(aThread, &aBuffer, iDescriptors[i]->DescriptorData());
}
TInt TUsbcDescriptorPool::SetInterfaceDescriptor(const TDes8& aBuffer, TInt aInterface, TInt aSetting)
{
TInt i = FindIfcDescriptor(aInterface, aSetting);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such interface")));
return KErrNotFound;
}
iDescriptors[i]->SetByte(2, aBuffer[2]); // bInterfaceNumber
iDescriptors[i]->SetByte(5, aBuffer[5]); // bInterfaceClass
iDescriptors[i]->SetByte(6, aBuffer[6]); // bInterfaceSubClass
iDescriptors[i]->SetByte(7, aBuffer[7]); // bInterfaceProtocol
return KErrNone;
}
TInt TUsbcDescriptorPool::GetEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer,
TInt aInterface, TInt aSetting, TUint8 aEndpointAddress) const
{
TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint")));
return KErrNotFound;
}
return __THREADWRITE(aThread, &aBuffer, iDescriptors[i]->DescriptorData());
}
TInt TUsbcDescriptorPool::SetEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer,
TInt aInterface, TInt aSetting, TUint8 aEndpointAddress)
{
TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint")));
return KErrNotFound;
}
TBuf8<KUsbDescSize_AudioEndpoint> ep; // it could be an audio endpoint
TInt r = __THREADREAD(aThread, &aBuffer, ep);
if (r != KErrNone)
{
return r;
}
iDescriptors[i]->SetByte(3, ep[3]); // bmAttributes
iDescriptors[i]->SetByte(6, ep[6]); // bInterval
if (static_cast<TUint>(iDescriptors[i]->Size()) == KUsbDescSize_AudioEndpoint)
{
iDescriptors[i]->SetByte(7, ep[7]); // bRefresh
iDescriptors[i]->SetByte(8, ep[8]); // bSynchAddress
}
return KErrNone;
}
TInt TUsbcDescriptorPool::GetEndpointDescriptorSize(TInt aInterface, TInt aSetting, TUint8 aEndpointAddress,
TInt& aSize) const
{
TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint")));
return KErrNotFound;
}
aSize = iDescriptors[i]->Size();
return KErrNone;
}
TInt TUsbcDescriptorPool::GetCSInterfaceDescriptorTC(DThread* aThread, TDes8& aBuffer,
TInt aInterface, TInt aSetting) const
{
// first find the interface
TInt i = FindIfcDescriptor(aInterface, aSetting);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such interface")));
return KErrNotFound;
}
TInt r = KErrNotFound;
TInt offset = 0;
const TInt count = iDescriptors.Count();
while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
{
r = __THREADWRITEOFFSET(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), offset);
if (r != KErrNone)
break;
offset += iDescriptors[i]->Size();
}
return r;
}
TInt TUsbcDescriptorPool::SetCSInterfaceDescriptorTC(DThread* aThread, const TDes8& aBuffer,
TInt aInterface, TInt aSetting, TInt aSize)
{
// first find the interface
TInt i = FindIfcDescriptor(aInterface, aSetting);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such interface")));
return KErrNotFound;
}
// find a position where to insert the new class specific interface descriptor(s)
const TInt count = iDescriptors.Count();
while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
;
// create a new cs descriptor
TUsbcClassSpecificDescriptor* desc = TUsbcClassSpecificDescriptor::New(KUsbDescType_CS_Interface, aSize);
if (!desc)
{
return KErrNoMemory;
}
iDescriptors.Insert(desc, i);
if (iDescriptors[1])
{
// if there's a config descriptor (and not a NULL pointer), we update its wTotalLength field
iDescriptors[1]->SetWord(2, (TUint8)(iDescriptors[1]->Word(2) + aSize));
}
// copy contents from user side
return __THREADREAD(aThread, &aBuffer, iDescriptors[i]->DescriptorData());
}
TInt TUsbcDescriptorPool::GetCSInterfaceDescriptorSize(TInt aInterface, TInt aSetting, TInt& aSize) const
{
// first find the interface
TInt i = FindIfcDescriptor(aInterface, aSetting);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such interface")));
return KErrNotFound;
}
TInt r = KErrNotFound;
TInt size = 0;
const TInt count = iDescriptors.Count();
while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Interface)
{
size += iDescriptors[i]->Size();
r = KErrNone;
}
if (r == KErrNone)
aSize = size;
return r;
}
TInt TUsbcDescriptorPool::GetCSEndpointDescriptorTC(DThread* aThread, TDes8& aBuffer, TInt aInterface,
TInt aSetting, TUint8 aEndpointAddress) const
{
// first find the endpoint
TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint")));
return KErrNotFound;
}
TInt r = KErrNotFound;
TInt offset = 0;
const TInt count = iDescriptors.Count();
while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
{
__THREADWRITEOFFSET(aThread, &aBuffer, iDescriptors[i]->DescriptorData(), offset);
if (r != KErrNone)
break;
offset += iDescriptors[i]->Size();
}
return r;
}
TInt TUsbcDescriptorPool::SetCSEndpointDescriptorTC(DThread* aThread, const TDes8& aBuffer, TInt aInterface,
TInt aSetting, TUint8 aEndpointAddress, TInt aSize)
{
// first find the endpoint
TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint")));
return KErrNotFound;
}
// find a position where to insert the new class specific endpoint descriptor(s)
const TInt count = iDescriptors.Count();
while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
;
// create a new cs descriptor
TUsbcClassSpecificDescriptor* desc = TUsbcClassSpecificDescriptor::New(KUsbDescType_CS_Endpoint, aSize);
if (!desc)
{
return KErrNoMemory;
}
iDescriptors.Insert(desc, i);
if (iDescriptors[1])
{
// if there's a config descriptor (and not a NULL pointer), we update its wTotalLength field
iDescriptors[1]->SetWord(2, (TUint8)(iDescriptors[1]->Word(2) + aSize));
}
// copy contents from user side
return __THREADREAD(aThread, &aBuffer, iDescriptors[i]->DescriptorData());
}
TInt TUsbcDescriptorPool::GetCSEndpointDescriptorSize(TInt aInterface, TInt aSetting,
TUint8 aEndpointAddress, TInt& aSize) const
{
// first find the endpoint
TInt i = FindEpDescriptor(aInterface, aSetting, aEndpointAddress);
if (i < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint")));
return KErrNotFound;
}
TInt r = KErrNotFound;
TInt size = 0;
const TInt count = iDescriptors.Count();
while (++i < count && iDescriptors[i]->Type() == KUsbDescType_CS_Endpoint)
{
size += iDescriptors[i]->Size();
r = KErrNone;
}
if (r == KErrNone)
aSize = size;
return r;
}
TInt TUsbcDescriptorPool::GetManufacturerStringDescriptorTC(DThread* aThread, TDes8& aString) const
{
return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Manufact);
}
TInt TUsbcDescriptorPool::SetManufacturerStringDescriptorTC(DThread* aThread, const TDes8& aString)
{
return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Manufact);
}
TInt TUsbcDescriptorPool::GetProductStringDescriptorTC(DThread* aThread, TDes8& aString) const
{
return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Product);
}
TInt TUsbcDescriptorPool::SetProductStringDescriptorTC(DThread* aThread, const TDes8& aString)
{
return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Product);
}
TInt TUsbcDescriptorPool::GetSerialNumberStringDescriptorTC(DThread* aThread, TDes8& aString) const
{
return GetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Serial);
}
TInt TUsbcDescriptorPool::SetSerialNumberStringDescriptorTC(DThread* aThread, const TDes8& aString)
{
return SetDeviceStringDescriptorTC(aThread, aString, KUsbDescStringIndex_Serial);
}
TInt TUsbcDescriptorPool::GetConfigurationStringDescriptorTC(DThread* aThread, TDes8& aString) const
{
TBuf8<KUsbDescSize_Config> config_desc;
iDescriptors[1]->GetDescriptorData(config_desc);
const TInt str_idx = config_desc[KUsbDescStringIndex_Config];
if ((str_idx > 0) && iStrings[str_idx])
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" String @ pos %d (conf $): \"%S\""),
str_idx, &iStrings[str_idx]->StringData()));
return __THREADWRITE(aThread, &aString, iStrings[str_idx]->StringData());
}
else
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no string descriptor @ pos %d!"), str_idx));
return KErrNotFound;
}
}
TInt TUsbcDescriptorPool::SetConfigurationStringDescriptorTC(DThread* aThread, const TDes8& aString)
{
// we don't know the length of the string, so we have to allocate memory dynamically
TUint strlen = __THREADDESLEN(aThread, &aString);
if (strlen > KUsbStringDescStringMaxSize)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Warning: $ descriptor too long - string will be truncated")));
strlen = KUsbStringDescStringMaxSize;
}
HBuf8Plat* strbuf = NULL;
__NEWPLATBUF(strbuf, strlen);
if (!strbuf)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Memory allocation for config $ desc string failed (1)")));
return KErrNoMemory;
}
TInt r;
__THREADREADPLATBUF(aThread, &aString, strbuf, r);
if (r != KErrNone)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Thread read error")));
delete strbuf;
return r;
}
TUsbcStringDescriptor* sd = TUsbcStringDescriptor::New(*strbuf);
if (!sd)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Memory allocation for config $ desc failed (2)")));
delete strbuf;
return KErrNoMemory;
}
TBuf8<KUsbDescSize_Config> config_desc;
config_desc.FillZ(config_desc.MaxLength());
iDescriptors[1]->GetDescriptorData(config_desc);
ExchangeStringDescriptor(config_desc[KUsbDescStringIndex_Config], sd);
delete strbuf;
return r;
}
// --- private ---
void TUsbcDescriptorPool::InsertDevDesc(TUsbcDescriptorBase* aDesc)
{
TInt count = iDescriptors.Count();
if (count > 0)
{
DeleteDescriptors(0); // if there's already something at pos. 0, delete it
}
iDescriptors.Insert(aDesc, 0); // in any case: put the new descriptor at position 0
}
void TUsbcDescriptorPool::InsertConfigDesc(TUsbcDescriptorBase* aDesc)
{
TInt count = iDescriptors.Count();
if (count == 0)
{
TUsbcDescriptorBase* const iNullDesc = NULL;
iDescriptors.Append(iNullDesc); // if array's empty, put a dummy in position 0
}
else if (count > 1)
{
DeleteDescriptors(1); // if there's already something at pos. 1, delete it
}
iDescriptors.Insert(aDesc, 1); // in any case: put the new descriptor at position 1
// Currently this code assumes, that the config descriptor is inserted _before_ any interface
// or endpoint descriptors!
if (iDescriptors.Count() != 2)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("TUsbcDescriptorPool::InsertConfigDesc: config descriptor will be invalid!")));
}
}
void TUsbcDescriptorPool::InsertIfcDesc(TUsbcDescriptorBase* aDesc)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::InsertIfcDesc()")));
TInt count = iDescriptors.Count();
if (count < 2)
{
TUsbcDescriptorBase* const iNullDesc = NULL;
iDescriptors.Append(iNullDesc); // if array's too small, put some dummies in
iDescriptors.Append(iNullDesc);
}
TBool interface_exists = EFalse; // set to 'true' if we're adding an alternate
// setting to an already existing interface
TInt i = 2;
while (i < count)
{
if (iDescriptors[i]->Type() == KUsbDescType_Interface)
{
if (iDescriptors[i]->Byte(2) > aDesc->Byte(2))
{
// our interface number is less than the one's just found => insert before it (= here)
break;
}
else if (iDescriptors[i]->Byte(2) == aDesc->Byte(2))
{
interface_exists = ETrue;
// same interface number => look at settings number
if (iDescriptors[i]->Byte(3) > aDesc->Byte(3))
{
// our setting number is less than the one's found => insert before (= here)
break;
}
else if (iDescriptors[i]->Byte(3) == aDesc->Byte(3))
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("TUsbcDescriptorPool::InsertIfcDesc: error: first delete old one!")));
return;
}
}
}
++i;
}
iDescriptors.Insert(aDesc, i); // in any case: put the new descriptor at position i
if (iDescriptors[1])
{
// if there's a config descriptor (and not a NULL pointer), update its wTotalLength field...
iDescriptors[1]->SetWord(2, (TUint8)(iDescriptors[1]->Word(2) + KUsbDescSize_Interface));
// and increment bNumInterfaces if this is the first setting for the interface
if (!interface_exists)
iDescriptors[1]->SetByte(4, (TUint8)(iDescriptors[1]->Byte(4) + 1));
}
iIfcIdx = i;
}
void TUsbcDescriptorPool::InsertEpDesc(TUsbcDescriptorBase* aDesc)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::InsertEpDesc()")));
if (iIfcIdx == 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING("TUsbcDescriptorPool::InsertEpDesc: error: only after interface")));
return;
}
TInt count = iDescriptors.Count();
TInt i = iIfcIdx + 1;
while (i < count)
{
if (iDescriptors[i]->Type() != KUsbDescType_Endpoint)
break;
++i;
}
iDescriptors.Insert(aDesc, i); // put the new descriptor at position i
if (iDescriptors[1])
{
// if there's a config descriptor (and not a NULL pointer), update its wTotalLength field
iDescriptors[1]->SetWord(2, (TUint8)(iDescriptors[1]->Word(2) + aDesc->Size()));
}
}
TInt TUsbcDescriptorPool::FindIfcDescriptor(TInt aIfcNumber, TInt aIfcSetting) const
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::FindIfcDescriptor(%d, %d)"),
aIfcNumber, aIfcSetting));
TInt count = iDescriptors.Count();
for (TInt i = 2; i < count; ++i)
{
if ((iDescriptors[i]->Type() == KUsbDescType_Interface) &&
(iDescriptors[i]->Byte(2) == aIfcNumber) &&
(iDescriptors[i]->Byte(3) == aIfcSetting))
{
return i;
}
}
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such interface")));
return -1;
}
TInt TUsbcDescriptorPool::FindEpDescriptor(TInt aIfcNumber, TInt aIfcSetting, TUint8 aEpAddress) const
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::FindEpDescriptor(%d, %d, 0x%02x)"),
aIfcNumber, aIfcSetting, aEpAddress));
// first find the interface
TInt ifc = FindIfcDescriptor(aIfcNumber, aIfcSetting);
if (ifc < 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such interface")));
return ifc;
}
TInt count = iDescriptors.Count();
// then, before the next interface, try to locate the endpoint
for (TInt i = ifc + 1; i < count; ++i)
{
if (iDescriptors[i]->Type() == KUsbDescType_Interface)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint before next interface")));
return -1;
}
else if ((iDescriptors[i]->Type() == KUsbDescType_Endpoint) &&
(iDescriptors[i]->Byte(2) == aEpAddress))
{
return i; // found
}
}
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no such endpoint")));
return -1;
}
void TUsbcDescriptorPool::DeleteDescriptors(TInt aIndex, TInt aCount)
{
if (aCount <= 0)
{
return;
}
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" Removing descriptors at index %d:"), aIndex));
while (aCount--)
{
// in this loop we don't decrement aIndex, because after deleting an element
// aIndex is already indexing the next one!
TUsbcDescriptorBase* ptr = iDescriptors[aIndex];
if (iDescriptors[1])
{
// if there's a config descriptor (and not a NULL pointer),
if (ptr->Type() == KUsbDescType_Interface)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" - an interface descriptor")));
// if it's an interface descriptor:
// we update its wTotalLength field...
iDescriptors[1]->SetWord(2, (TUint8)(iDescriptors[1]->Word(2) - KUsbDescSize_Interface));
}
else if (ptr->Type() == KUsbDescType_Endpoint)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" - an endpoint descriptor")));
// if it's an endpoint descriptor:
// we only update its wTotalLength field
iDescriptors[1]->SetWord(2, (TUint8)(iDescriptors[1]->Word(2) - ptr->Size()));
}
else if (ptr->Type() == KUsbDescType_CS_Interface || ptr->Type() == KUsbDescType_CS_Endpoint)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" - a class specific descriptor")));
// if it's an class specific descriptor:
// we only update its wTotalLength field
iDescriptors[1]->SetWord(2, (TUint8)(iDescriptors[1]->Word(2) - ptr->Size()));
}
}
iDescriptors.Remove(aIndex);
delete ptr;
}
}
void TUsbcDescriptorPool::DeleteString(TInt aIndex)
{
TUsbcStringDescriptorBase* ptr = iStrings[aIndex];
iStrings.Remove(aIndex);
delete ptr;
}
void TUsbcDescriptorPool::UpdateIfcNumbers(TInt aNumber)
{
const TInt count = iDescriptors.Count();
for (TInt i = 2; i < count; ++i)
{
if ((iDescriptors[i]->Type() == KUsbDescType_Interface) &&
(iDescriptors[i]->Byte(2) == aNumber))
{
// there's still an interface with 'number' so we don't need to update anything
return;
}
}
// if we haven't returned yet, we decrement bNumInterfaces
iDescriptors[1]->SetByte(4, (TUint8)(iDescriptors[1]->Byte(4) - 1));
}
void TUsbcDescriptorPool::UpdateIfcStringIndexes(TInt aStringIndex)
{
// aStringIndex is the index value of the string descriptor that has just been removed.
// We update all ifc descriptors with a string index value that is greater than aStringIndex,
// because those strings moved all down by one position.
//
TInt count = iDescriptors.Count();
for (TInt i = 2; i < count; ++i)
{
if ((iDescriptors[i]->Type() == KUsbDescType_Interface) &&
(iDescriptors[i]->Byte(8) > aStringIndex))
{
iDescriptors[i]->SetByte(8, (TUint8)(iDescriptors[i]->Byte(8) - 1));
}
}
}
//
// Only used for Ep0 standard requests, so target buffer could be hard-wired.
//
TInt TUsbcDescriptorPool::GetDeviceDescriptor() const
{
return iDescriptors[0]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
}
//
// Only used for Ep0 standard requests, so target buffer could be hard-wired.
//
TInt TUsbcDescriptorPool::GetConfigDescriptor() const
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::GetConfigDescriptor()")));
TInt copied = 0;
TInt count = iDescriptors.Count();
TUint8* buf = iEp0_TxBuf;
for (TInt i = 1; i < count; ++i)
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" > desc[%02d]: type = 0x%02x size = %d "),
i, iDescriptors[i]->Type(), iDescriptors[i]->Size()));
const TInt size = iDescriptors[i]->GetDescriptorData(buf, KUsbcBufSz_Ep0Tx - copied);
if (size == 0)
{
// There was no buffer space to copy the descriptor -> no use to proceed
break;
}
copied += size;
if (copied >= KUsbcBufSz_Ep0Tx)
{
// There's no buffer space left -> we need to stop copying here
break;
}
buf += size;
}
return copied;
}
//
// Only used for Ep0 standard requests, so target buffer could be hard-wired.
//
TInt TUsbcDescriptorPool::GetStringDescriptor(TInt aIndex) const
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING("TUsbcDescriptorPool::GetStringDescriptor()")));
// I really would have liked to display here the descriptor contents, but without trailing zero
// we got a problem: how could we tell printf where the string ends? We would have to
// dynamically allocate memory (since we don't know the size in advance), copy the descriptor
// contents there, append a zero, and give this to printf. That's a bit too much effort...
if (iStrings[aIndex])
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" String @ pos %d"), aIndex));
TInt size = iStrings[aIndex]->GetDescriptorData(iEp0_TxBuf, KUsbcBufSz_Ep0Tx);
return size;
}
else
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no descriptor @ pos %d!"), aIndex));
return 0;
}
}
TInt TUsbcDescriptorPool::GetDeviceStringDescriptorTC(DThread* aThread, TDes8& aString, TInt aIndex) const
{
TBuf8<KUsbDescSize_Device> dev_desc;
iDescriptors[0]->GetDescriptorData(dev_desc);
const TInt str_idx = dev_desc[aIndex];
if ((str_idx > 0) && iStrings[str_idx])
{
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" String @ pos %d (device $): \"%S\""),
str_idx, &iStrings[str_idx]->StringData()));
return __THREADWRITE(aThread, &aString, iStrings[str_idx]->StringData());
}
else
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: no string descriptor @ pos %d!"), str_idx));
return KErrNotFound;
}
}
TInt TUsbcDescriptorPool::SetDeviceStringDescriptorTC(DThread* aThread, const TDes8& aString, TInt aIndex)
{
// we don't know the length of the string, so we have to allocate memory dynamically
TUint strlen = __THREADDESLEN(aThread, &aString);
if (strlen > KUsbStringDescStringMaxSize)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Warning: $ descriptor too long - string will be truncated")));
strlen = KUsbStringDescStringMaxSize;
}
HBuf8Plat* strbuf = NULL;
__NEWPLATBUF(strbuf, strlen);
if (!strbuf)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Memory allocation for dev $ desc string failed (1)")));
return KErrNoMemory;
}
TInt r;
__THREADREADPLATBUF(aThread, &aString, strbuf, r);
if (r != KErrNone)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Thread read error")));
delete strbuf;
return r;
}
TUsbcStringDescriptor* sd = TUsbcStringDescriptor::New(*strbuf);
if (!sd)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: Memory allocation for dev $ desc failed (2)")));
delete strbuf;
return KErrNoMemory;
}
TBuf8<KUsbDescSize_Device> dev_desc;
dev_desc.FillZ(dev_desc.MaxLength());
iDescriptors[0]->GetDescriptorData(dev_desc);
ExchangeStringDescriptor(dev_desc[aIndex], sd);
delete strbuf;
return r;
}
TInt TUsbcDescriptorPool::ExchangeStringDescriptor(TInt aIndex, const TUsbcStringDescriptor* aDesc)
{
if (aIndex <= 0)
{
__KTRACE_OPT(KPANIC, Kern::Printf(__KSTRING(" Error: invalid string descriptor index: %d!"), aIndex));
return KErrArgument;
}
__KTRACE_OPT(KUSB, Kern::Printf(__KSTRING(" Exchanging string descriptor @ index %d"), aIndex));
DeleteString(aIndex);
iStrings.Insert(aDesc, aIndex);
return KErrNone;
}
// -eof-