diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32utils/testusbcldd/src/descriptors.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32utils/testusbcldd/src/descriptors.cpp Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,1546 @@ +// 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(&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(&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(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(&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(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 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 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 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 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(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 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 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 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 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-