author | mikek |
Sun, 27 Jun 2010 21:43:55 +0100 | |
branch | GCC_SURGE |
changeset 181 | bd8f1e65581b |
parent 0 | a41df078684a |
permissions | -rw-r--r-- |
// 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-