--- /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<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-